1#include "SineSource.h"
2
3#include <math.h>
4
5#include <media/stagefright/MediaBufferGroup.h>
6#include <media/stagefright/foundation/ADebug.h>
7#include <media/stagefright/MediaDefs.h>
8#include <media/stagefright/MetaData.h>
9
10namespace android {
11
12SineSource::SineSource(int32_t sampleRate, int32_t numChannels)
13    : mStarted(false),
14      mSampleRate(sampleRate),
15      mNumChannels(numChannels),
16      mPhase(0),
17      mGroup(NULL) {
18    CHECK(numChannels == 1 || numChannels == 2);
19}
20
21SineSource::~SineSource() {
22    if (mStarted) {
23        stop();
24    }
25}
26
27status_t SineSource::start(MetaData * /* params */) {
28    CHECK(!mStarted);
29
30    mGroup = new MediaBufferGroup;
31    mGroup->add_buffer(new MediaBuffer(kBufferSize));
32
33    mPhase = 0;
34    mStarted = true;
35
36    return OK;
37}
38
39status_t SineSource::stop() {
40    CHECK(mStarted);
41
42    delete mGroup;
43    mGroup = NULL;
44
45    mStarted = false;
46
47    return OK;
48}
49
50sp<MetaData> SineSource::getFormat() {
51    sp<MetaData> meta = new MetaData;
52    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
53    meta->setInt32(kKeyChannelCount, mNumChannels);
54    meta->setInt32(kKeySampleRate, mSampleRate);
55    meta->setInt32(kKeyMaxInputSize, kBufferSize);
56
57    return meta;
58}
59
60status_t SineSource::read(
61        MediaBuffer **out, const ReadOptions * /* options */) {
62    *out = NULL;
63
64    MediaBuffer *buffer;
65    status_t err = mGroup->acquire_buffer(&buffer);
66
67    if (err != OK) {
68        return err;
69    }
70
71    size_t frameSize = mNumChannels * sizeof(int16_t);
72    size_t numFramesPerBuffer = buffer->size() / frameSize;
73
74    int16_t *ptr = (int16_t *)buffer->data();
75
76    const double k = kFrequency / mSampleRate * (2.0 * M_PI);
77
78    double x = mPhase * k;
79    for (size_t i = 0; i < numFramesPerBuffer; ++i) {
80        int16_t amplitude = (int16_t)(32767.0 * sin(x));
81
82        *ptr++ = amplitude;
83        if (mNumChannels == 2) {
84            *ptr++ = amplitude;
85        }
86
87        x += k;
88    }
89
90    buffer->meta_data()->setInt64(
91            kKeyTime, ((int64_t)mPhase * 1000000) / mSampleRate);
92
93    mPhase += numFramesPerBuffer;
94
95    buffer->set_range(0, numFramesPerBuffer * frameSize);
96
97    *out = buffer;
98
99    return OK;
100}
101
102}  // namespace android
103