AudioSource.cpp revision eaae38445a340c4857c1c5569475879a728e63b7
1e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber/*
2e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * Copyright (C) 2010 The Android Open Source Project
3e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber *
4e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * you may not use this file except in compliance with the License.
6e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * You may obtain a copy of the License at
7e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber *
8e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber *
10e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * Unless required by applicable law or agreed to in writing, software
11e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * See the License for the specific language governing permissions and
14e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber * limitations under the License.
15e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber */
16e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
17050b28a593350047845a45a14cc5026221ac1620James Dong//#define LOG_NDEBUG 0
18050b28a593350047845a45a14cc5026221ac1620James Dong#define LOG_TAG "AudioSource"
19050b28a593350047845a45a14cc5026221ac1620James Dong#include <utils/Log.h>
20050b28a593350047845a45a14cc5026221ac1620James Dong
21e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/AudioSource.h>
22e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
23e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/AudioRecord.h>
24e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MediaBufferGroup.h>
25e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MediaDebug.h>
26e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MediaDefs.h>
27e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MetaData.h>
28365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <cutils/properties.h>
2946292fb347d72a314d985e34e5e3743d846cb9b6James Dong#include <stdlib.h>
30e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
31e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Hubernamespace android {
32e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
33e7c9cb48fec02697227bd847cd2e69432659adfdAndreas HuberAudioSource::AudioSource(
34e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        int inputSource, uint32_t sampleRate, uint32_t channels)
35be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong    : mStarted(false),
36365a963142093a1cd8efdcea76b5f65096a5b115James Dong      mCollectStats(false),
3746292fb347d72a314d985e34e5e3743d846cb9b6James Dong      mPrevSampleTimeUs(0),
3847204e1806da9f849464d0cef936851d7e561607James Dong      mTotalLostFrames(0),
3947204e1806da9f849464d0cef936851d7e561607James Dong      mPrevLostBytes(0),
40e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber      mGroup(NULL) {
41be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong
42be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong    LOGV("sampleRate: %d, channels: %d", sampleRate, channels);
43f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    CHECK(channels == 1 || channels == 2);
44be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong    uint32_t flags = AudioRecord::RECORD_AGC_ENABLE |
45be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                     AudioRecord::RECORD_NS_ENABLE  |
46be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                     AudioRecord::RECORD_IIR_ENABLE;
47be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong
48be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong    mRecord = new AudioRecord(
49be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                inputSource, sampleRate, AudioSystem::PCM_16_BIT,
50be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                channels > 1? AudioSystem::CHANNEL_IN_STEREO: AudioSystem::CHANNEL_IN_MONO,
51be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                4 * kMaxBufferSize / sizeof(int16_t), /* Enable ping-pong buffers */
52be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong                flags);
53be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong
54be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong    mInitCheck = mRecord->initCheck();
55e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
56e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
57e7c9cb48fec02697227bd847cd2e69432659adfdAndreas HuberAudioSource::~AudioSource() {
58e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (mStarted) {
59e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        stop();
60e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
61e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
62e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    delete mRecord;
63e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    mRecord = NULL;
64e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
65e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
66e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::initCheck() const {
67e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return mInitCheck;
68e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
69e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
70e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::start(MetaData *params) {
71e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (mStarted) {
72e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        return UNKNOWN_ERROR;
73e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
74e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
756e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    if (mInitCheck != OK) {
766e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong        return NO_INIT;
776e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    }
786e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
79365a963142093a1cd8efdcea76b5f65096a5b115James Dong    char value[PROPERTY_VALUE_MAX];
80365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (property_get("media.stagefright.record-stats", value, NULL)
81365a963142093a1cd8efdcea76b5f65096a5b115James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
82365a963142093a1cd8efdcea76b5f65096a5b115James Dong        mCollectStats = true;
83365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
84f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
85d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    mTrackMaxAmplitude = false;
86d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    mMaxAmplitude = 0;
87d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mInitialReadTimeUs = 0;
88f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mStartTimeUs = 0;
89f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t startTimeUs;
90f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (params && params->findInt64(kKeyTime, &startTimeUs)) {
91f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimeUs = startTimeUs;
92f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
93e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    status_t err = mRecord->start();
94e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (err == OK) {
95e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        mGroup = new MediaBufferGroup;
96e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        mGroup->add_buffer(new MediaBuffer(kMaxBufferSize));
97e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
98e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        mStarted = true;
99eaae38445a340c4857c1c5569475879a728e63b7James Dong    } else {
100eaae38445a340c4857c1c5569475879a728e63b7James Dong        delete mRecord;
101eaae38445a340c4857c1c5569475879a728e63b7James Dong        mRecord = NULL;
102e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
103e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
104eaae38445a340c4857c1c5569475879a728e63b7James Dong
105e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return err;
106e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
107e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
108e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::stop() {
109e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (!mStarted) {
110e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        return UNKNOWN_ERROR;
111e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
112e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
1136e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    if (mInitCheck != OK) {
1146e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong        return NO_INIT;
1156e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    }
1166e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
117e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    mRecord->stop();
118e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
119e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    delete mGroup;
120e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    mGroup = NULL;
121e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
122e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    mStarted = false;
123e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
124365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (mCollectStats) {
12547204e1806da9f849464d0cef936851d7e561607James Dong        LOGI("Total lost audio frames: %lld",
12647204e1806da9f849464d0cef936851d7e561607James Dong            mTotalLostFrames + (mPrevLostBytes >> 1));
127365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
128365a963142093a1cd8efdcea76b5f65096a5b115James Dong
129e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return OK;
130e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
131e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
132e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Hubersp<MetaData> AudioSource::getFormat() {
1336e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    if (mInitCheck != OK) {
1346e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong        return 0;
1356e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    }
1366e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
137e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    sp<MetaData> meta = new MetaData;
138e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
139e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setInt32(kKeySampleRate, mRecord->getSampleRate());
140e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setInt32(kKeyChannelCount, mRecord->channelCount());
141e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setInt32(kKeyMaxInputSize, kMaxBufferSize);
142e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
143e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return meta;
144e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
145e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
146f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dongvoid AudioSource::rampVolume(
147f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        int32_t startFrame, int32_t rampDurationFrames,
148f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        uint8_t *data,   size_t bytes) {
149f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
150f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    const int32_t kShift = 14;
151f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    int32_t fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
152f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    const int32_t nChannels = mRecord->channelCount();
153f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    int32_t stopFrame = startFrame + bytes / sizeof(int16_t);
154f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    int16_t *frame = (int16_t *) data;
155f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    if (stopFrame > rampDurationFrames) {
156f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        stopFrame = rampDurationFrames;
157f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    }
158f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
159f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    while (startFrame < stopFrame) {
160f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        if (nChannels == 1) {  // mono
161f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame[0] = (frame[0] * fixedMultiplier) >> kShift;
162f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            ++frame;
163f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            ++startFrame;
164f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        } else {               // stereo
165f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame[0] = (frame[0] * fixedMultiplier) >> kShift;
166f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame[1] = (frame[1] * fixedMultiplier) >> kShift;
167f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame += 2;
168f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            startFrame += 2;
169f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        }
170f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
171f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        // Update the multiplier every 4 frames
172f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        if ((startFrame & 3) == 0) {
173f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
174f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        }
175f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    }
176f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong}
177f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
178e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::read(
179e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        MediaBuffer **out, const ReadOptions *options) {
1806e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
1816e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    if (mInitCheck != OK) {
1826e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong        return NO_INIT;
1836e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    }
1846e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
185d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    int64_t readTimeUs = systemTime() / 1000;
186e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    *out = NULL;
187e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
188e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    MediaBuffer *buffer;
189e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    CHECK_EQ(mGroup->acquire_buffer(&buffer), OK);
190e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
19146292fb347d72a314d985e34e5e3743d846cb9b6James Dong    int err = 0;
19279e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong    if (mStarted) {
19346292fb347d72a314d985e34e5e3743d846cb9b6James Dong
194542db5d438988360d491a5add1040a2df9aa90c9James Dong        uint32_t numFramesRecorded;
195542db5d438988360d491a5add1040a2df9aa90c9James Dong        mRecord->getPosition(&numFramesRecorded);
196542db5d438988360d491a5add1040a2df9aa90c9James Dong
197542db5d438988360d491a5add1040a2df9aa90c9James Dong
19846292fb347d72a314d985e34e5e3743d846cb9b6James Dong        if (numFramesRecorded == 0 && mPrevSampleTimeUs == 0) {
199d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong            mInitialReadTimeUs = readTimeUs;
200542db5d438988360d491a5add1040a2df9aa90c9James Dong            // Initial delay
201542db5d438988360d491a5add1040a2df9aa90c9James Dong            if (mStartTimeUs > 0) {
202d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong                mStartTimeUs = readTimeUs - mStartTimeUs;
203542db5d438988360d491a5add1040a2df9aa90c9James Dong            } else {
20446292fb347d72a314d985e34e5e3743d846cb9b6James Dong                // Assume latency is constant.
20546292fb347d72a314d985e34e5e3743d846cb9b6James Dong                mStartTimeUs += mRecord->latency() * 1000;
206542db5d438988360d491a5add1040a2df9aa90c9James Dong            }
20746292fb347d72a314d985e34e5e3743d846cb9b6James Dong            mPrevSampleTimeUs = mStartTimeUs;
208542db5d438988360d491a5add1040a2df9aa90c9James Dong        }
209542db5d438988360d491a5add1040a2df9aa90c9James Dong
21046292fb347d72a314d985e34e5e3743d846cb9b6James Dong        uint32_t sampleRate = mRecord->getSampleRate();
21146292fb347d72a314d985e34e5e3743d846cb9b6James Dong
21246292fb347d72a314d985e34e5e3743d846cb9b6James Dong        // Insert null frames when lost frames are detected.
21346292fb347d72a314d985e34e5e3743d846cb9b6James Dong        int64_t timestampUs = mPrevSampleTimeUs;
21446292fb347d72a314d985e34e5e3743d846cb9b6James Dong        uint32_t numLostBytes = mRecord->getInputFramesLost() << 1;
21547204e1806da9f849464d0cef936851d7e561607James Dong        numLostBytes += mPrevLostBytes;
21646292fb347d72a314d985e34e5e3743d846cb9b6James Dong#if 0
21746292fb347d72a314d985e34e5e3743d846cb9b6James Dong        // Simulate lost frames
21847204e1806da9f849464d0cef936851d7e561607James Dong        numLostBytes = ((rand() * 1.0 / RAND_MAX)) * 2 * kMaxBufferSize;
21947204e1806da9f849464d0cef936851d7e561607James Dong        numLostBytes &= 0xFFFFFFFE; // Alignment requirement
22046292fb347d72a314d985e34e5e3743d846cb9b6James Dong
22146292fb347d72a314d985e34e5e3743d846cb9b6James Dong        // Reduce the chance to lose
22246292fb347d72a314d985e34e5e3743d846cb9b6James Dong        if (rand() * 1.0 / RAND_MAX >= 0.05) {
22346292fb347d72a314d985e34e5e3743d846cb9b6James Dong            numLostBytes = 0;
22446292fb347d72a314d985e34e5e3743d846cb9b6James Dong        }
22546292fb347d72a314d985e34e5e3743d846cb9b6James Dong#endif
22646292fb347d72a314d985e34e5e3743d846cb9b6James Dong        if (numLostBytes > 0) {
22747204e1806da9f849464d0cef936851d7e561607James Dong            if (numLostBytes > kMaxBufferSize) {
22847204e1806da9f849464d0cef936851d7e561607James Dong                mPrevLostBytes = numLostBytes - kMaxBufferSize;
22947204e1806da9f849464d0cef936851d7e561607James Dong                numLostBytes = kMaxBufferSize;
23067e9269eaeab41a6c9a18794ebb32cbd1414381cJames Dong            } else {
23167e9269eaeab41a6c9a18794ebb32cbd1414381cJames Dong                mPrevLostBytes = 0;
23247204e1806da9f849464d0cef936851d7e561607James Dong            }
23347204e1806da9f849464d0cef936851d7e561607James Dong
23447204e1806da9f849464d0cef936851d7e561607James Dong            CHECK_EQ(numLostBytes & 1, 0);
23547204e1806da9f849464d0cef936851d7e561607James Dong            timestampUs += ((1000000LL * (numLostBytes >> 1)) +
23647204e1806da9f849464d0cef936851d7e561607James Dong                    (sampleRate >> 1)) / sampleRate;
23746292fb347d72a314d985e34e5e3743d846cb9b6James Dong
23846292fb347d72a314d985e34e5e3743d846cb9b6James Dong            CHECK(timestampUs > mPrevSampleTimeUs);
23946292fb347d72a314d985e34e5e3743d846cb9b6James Dong            if (mCollectStats) {
24047204e1806da9f849464d0cef936851d7e561607James Dong                mTotalLostFrames += (numLostBytes >> 1);
24146292fb347d72a314d985e34e5e3743d846cb9b6James Dong            }
24246292fb347d72a314d985e34e5e3743d846cb9b6James Dong            memset(buffer->data(), 0, numLostBytes);
24346292fb347d72a314d985e34e5e3743d846cb9b6James Dong            buffer->set_range(0, numLostBytes);
244d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong            if (numFramesRecorded == 0) {
24567e9269eaeab41a6c9a18794ebb32cbd1414381cJames Dong                buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs);
246d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong            }
24767e9269eaeab41a6c9a18794ebb32cbd1414381cJames Dong            buffer->meta_data()->setInt64(kKeyTime, mStartTimeUs + mPrevSampleTimeUs);
248d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong            buffer->meta_data()->setInt64(kKeyDriftTime, readTimeUs - mInitialReadTimeUs);
24946292fb347d72a314d985e34e5e3743d846cb9b6James Dong            mPrevSampleTimeUs = timestampUs;
25046292fb347d72a314d985e34e5e3743d846cb9b6James Dong            *out = buffer;
25146292fb347d72a314d985e34e5e3743d846cb9b6James Dong            return OK;
252f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        }
253e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
25446292fb347d72a314d985e34e5e3743d846cb9b6James Dong        ssize_t n = mRecord->read(buffer->data(), buffer->size());
255542db5d438988360d491a5add1040a2df9aa90c9James Dong        if (n < 0) {
256542db5d438988360d491a5add1040a2df9aa90c9James Dong            buffer->release();
257542db5d438988360d491a5add1040a2df9aa90c9James Dong            return (status_t)n;
258365a963142093a1cd8efdcea76b5f65096a5b115James Dong        }
259e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
26046292fb347d72a314d985e34e5e3743d846cb9b6James Dong        int64_t recordDurationUs = (1000000LL * n >> 1) / sampleRate;
26146292fb347d72a314d985e34e5e3743d846cb9b6James Dong        timestampUs += recordDurationUs;
262e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
263f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        if (mPrevSampleTimeUs - mStartTimeUs < kAutoRampStartUs) {
264f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            // Mute the initial video recording signal
265f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            memset((uint8_t *) buffer->data(), 0, n);
266f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        } else if (mPrevSampleTimeUs - mStartTimeUs < kAutoRampStartUs + kAutoRampDurationUs) {
267f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            int32_t autoRampDurationFrames =
268f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong                    (kAutoRampDurationUs * sampleRate + 500000LL) / 1000000LL;
269f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
270f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            int32_t autoRampStartFrames =
271f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong                    (kAutoRampStartUs * sampleRate + 500000LL) / 1000000LL;
272f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
273f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            int32_t nFrames = numFramesRecorded - autoRampStartFrames;
274f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            rampVolume(nFrames, autoRampDurationFrames, (uint8_t *) buffer->data(), n);
275f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        }
276542db5d438988360d491a5add1040a2df9aa90c9James Dong        if (mTrackMaxAmplitude) {
277542db5d438988360d491a5add1040a2df9aa90c9James Dong            trackMaxAmplitude((int16_t *) buffer->data(), n >> 1);
278542db5d438988360d491a5add1040a2df9aa90c9James Dong        }
279d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong
280d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong        if (numFramesRecorded == 0) {
2813c3763d2ee1cd1fba7fe522fbaf0faca315d8c2aJames Dong            buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs);
282d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong        }
2833c3763d2ee1cd1fba7fe522fbaf0faca315d8c2aJames Dong
2843c3763d2ee1cd1fba7fe522fbaf0faca315d8c2aJames Dong        buffer->meta_data()->setInt64(kKeyTime, mStartTimeUs + mPrevSampleTimeUs);
285d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong        buffer->meta_data()->setInt64(kKeyDriftTime, readTimeUs - mInitialReadTimeUs);
28646292fb347d72a314d985e34e5e3743d846cb9b6James Dong        CHECK(timestampUs > mPrevSampleTimeUs);
28746292fb347d72a314d985e34e5e3743d846cb9b6James Dong        mPrevSampleTimeUs = timestampUs;
288542db5d438988360d491a5add1040a2df9aa90c9James Dong        LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld",
289542db5d438988360d491a5add1040a2df9aa90c9James Dong                mStartTimeUs, sampleRate, timestampUs);
290f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
291542db5d438988360d491a5add1040a2df9aa90c9James Dong        buffer->set_range(0, n);
292e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
293542db5d438988360d491a5add1040a2df9aa90c9James Dong        *out = buffer;
294542db5d438988360d491a5add1040a2df9aa90c9James Dong        return OK;
295542db5d438988360d491a5add1040a2df9aa90c9James Dong    }
296e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
297e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return OK;
298e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
299e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
300d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dongvoid AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) {
301d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    for (int i = nSamples; i > 0; --i) {
302d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        int16_t value = *data++;
303d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        if (value < 0) {
304d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong            value = -value;
305d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        }
306d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        if (mMaxAmplitude < value) {
307d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong            mMaxAmplitude = value;
308d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        }
309d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    }
310d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong}
311d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong
312d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dongint16_t AudioSource::getMaxAmplitude() {
313d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    // First call activates the tracking.
314d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    if (!mTrackMaxAmplitude) {
315d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        mTrackMaxAmplitude = true;
316d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    }
317d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    int16_t value = mMaxAmplitude;
318d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    mMaxAmplitude = 0;
319d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    LOGV("max amplitude since last call: %d", value);
320d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    return value;
321d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong}
322d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong
323e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}  // namespace android
324