summaryrefslogtreecommitdiffstats
path: root/cmds/stagefright/SineSource.cpp
blob: 14b43061c1d8d43af1809f7b30cda96f397c197a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include "SineSource.h"

#include <math.h>

#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaData.h>

namespace android {

SineSource::SineSource(int32_t sampleRate, int32_t numChannels)
    : mStarted(false),
      mSampleRate(sampleRate),
      mNumChannels(numChannels),
      mPhase(0),
      mGroup(NULL) {
    CHECK(numChannels == 1 || numChannels == 2);
}

SineSource::~SineSource() {
    if (mStarted) {
        stop();
    }
}

status_t SineSource::start(MetaData *params) {
    CHECK(!mStarted);

    mGroup = new MediaBufferGroup;
    mGroup->add_buffer(new MediaBuffer(kBufferSize));

    mPhase = 0;
    mStarted = true;

    return OK;
}

status_t SineSource::stop() {
    CHECK(mStarted);

    delete mGroup;
    mGroup = NULL;

    mStarted = false;

    return OK;
}

sp<MetaData> SineSource::getFormat() {
    sp<MetaData> meta = new MetaData;
    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
    meta->setInt32(kKeyChannelCount, mNumChannels);
    meta->setInt32(kKeySampleRate, mSampleRate);
    meta->setInt32(kKeyMaxInputSize, kBufferSize);

    return meta;
}

status_t SineSource::read(
        MediaBuffer **out, const ReadOptions *options) {
    *out = NULL;

    MediaBuffer *buffer;
    status_t err = mGroup->acquire_buffer(&buffer);

    if (err != OK) {
        return err;
    }

    size_t frameSize = mNumChannels * sizeof(int16_t);
    size_t numFramesPerBuffer = buffer->size() / frameSize;

    int16_t *ptr = (int16_t *)buffer->data();

    const double k = kFrequency / mSampleRate * (2.0 * M_PI);

    double x = mPhase * k;
    for (size_t i = 0; i < numFramesPerBuffer; ++i) {
        int16_t amplitude = (int16_t)(32767.0 * sin(x));
        
        *ptr++ = amplitude;
        if (mNumChannels == 2) {
            *ptr++ = amplitude;
        }

        x += k;
    }

    buffer->meta_data()->setInt64(
            kKeyTime, ((int64_t)mPhase * 1000000) / mSampleRate);

    mPhase += numFramesPerBuffer;

    buffer->set_range(0, numFramesPerBuffer * frameSize);

    *out = buffer;

    return OK;
}

}  // namespace android