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    meta->setInt32(kKeyPcmEncoding, kAudioEncodingPcm16bit);
57
58    return meta;
59}
60
61status_t SineSource::read(
62        MediaBuffer **out, const ReadOptions * /* options */) {
63    *out = NULL;
64
65    MediaBuffer *buffer;
66    status_t err = mGroup->acquire_buffer(&buffer);
67
68    if (err != OK) {
69        return err;
70    }
71
72    size_t frameSize = mNumChannels * sizeof(int16_t);
73    size_t numFramesPerBuffer = buffer->size() / frameSize;
74
75    int16_t *ptr = (int16_t *)buffer->data();
76
77    const double k = kFrequency / mSampleRate * (2.0 * M_PI);
78
79    double x = mPhase * k;
80    for (size_t i = 0; i < numFramesPerBuffer; ++i) {
81        int16_t amplitude = (int16_t)(32767.0 * sin(x));
82
83        *ptr++ = amplitude;
84        if (mNumChannels == 2) {
85            *ptr++ = amplitude;
86        }
87
88        x += k;
89    }
90
91    buffer->meta_data()->setInt64(
92            kKeyTime, ((int64_t)mPhase * 1000000) / mSampleRate);
93
94    mPhase += numFramesPerBuffer;
95
96    buffer->set_range(0, numFramesPerBuffer * frameSize);
97
98    *out = buffer;
99
100    return OK;
101}
102
103}  // namespace android
104