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
17a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h>
18a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <stdlib.h>
19a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
20050b28a593350047845a45a14cc5026221ac1620James Dong//#define LOG_NDEBUG 0
21050b28a593350047845a45a14cc5026221ac1620James Dong#define LOG_TAG "AudioSource"
22050b28a593350047845a45a14cc5026221ac1620James Dong#include <utils/Log.h>
23050b28a593350047845a45a14cc5026221ac1620James Dong
24e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/AudioRecord.h>
256b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong#include <media/stagefright/AudioSource.h>
266b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong#include <media/stagefright/MediaBuffer.h>
27e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MediaDefs.h>
28e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber#include <media/stagefright/MetaData.h>
296b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong#include <media/stagefright/foundation/ADebug.h>
30082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber#include <media/stagefright/foundation/ALooper.h>
31365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <cutils/properties.h>
32e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
33e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Hubernamespace android {
34e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
356b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dongstatic void AudioRecordCallbackFunction(int event, void *user, void *info) {
366b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    AudioSource *source = (AudioSource *) user;
376b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    switch (event) {
386b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        case AudioRecord::EVENT_MORE_DATA: {
39082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber            source->dataCallback(*((AudioRecord::Buffer *) info));
406b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong            break;
416b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        }
426b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        case AudioRecord::EVENT_OVERRUN: {
435ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("AudioRecord reported overrun!");
446b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong            break;
456b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        }
466b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        default:
476b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong            // does nothing
486b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong            break;
496b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
506b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong}
516b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong
52e7c9cb48fec02697227bd847cd2e69432659adfdAndreas HuberAudioSource::AudioSource(
5346d26dd29195450db15704e84d65740628a821fbChong Zhang        audio_source_t inputSource, const String16 &opPackageName,
54b2379ba0a32638bae2ea0460644f68cf5a0967ceEric Laurent        uint32_t sampleRate, uint32_t channelCount, uint32_t outSampleRate,
55b2379ba0a32638bae2ea0460644f68cf5a0967ceEric Laurent        uid_t uid, pid_t pid)
56e2ffd5b583da9d30d96710b0e8879e90b2b51d30Glenn Kasten    : mStarted(false),
576b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong      mSampleRate(sampleRate),
5846d26dd29195450db15704e84d65740628a821fbChong Zhang      mOutSampleRate(outSampleRate > 0 ? outSampleRate : sampleRate),
59f88d1d8e63442d09303ca1090e1ee12e22040500Marco Nelissen      mTrackMaxAmplitude(false),
60f88d1d8e63442d09303ca1090e1ee12e22040500Marco Nelissen      mStartTimeUs(0),
61f88d1d8e63442d09303ca1090e1ee12e22040500Marco Nelissen      mMaxAmplitude(0),
6246292fb347d72a314d985e34e5e3743d846cb9b6James Dong      mPrevSampleTimeUs(0),
63f88d1d8e63442d09303ca1090e1ee12e22040500Marco Nelissen      mInitialReadTimeUs(0),
646b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong      mNumFramesReceived(0),
654f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang      mNumFramesSkipped(0),
664f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang      mNumFramesLost(0),
67af5dd7753e62353411cf0daf3b513c38818e9662Andreas Huber      mNumClientOwnedBuffers(0) {
6846d26dd29195450db15704e84d65740628a821fbChong Zhang    ALOGV("sampleRate: %u, outSampleRate: %u, channelCount: %u",
6946d26dd29195450db15704e84d65740628a821fbChong Zhang            sampleRate, outSampleRate, channelCount);
70ab334fd351ae5a0e18903da123d63e565b536874Glenn Kasten    CHECK(channelCount == 1 || channelCount == 2);
7146d26dd29195450db15704e84d65740628a821fbChong Zhang    CHECK(sampleRate > 0);
72be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong
73e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten    size_t minFrameCount;
74e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent    status_t status = AudioRecord::getMinFrameCount(&minFrameCount,
75e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent                                           sampleRate,
76e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent                                           AUDIO_FORMAT_PCM_16_BIT,
77dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten                                           audio_channel_in_mask_from_count(channelCount));
78e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent    if (status == OK) {
79e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent        // make sure that the AudioRecord callback never returns more than the maximum
80e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent        // buffer size
81838b3d8bafa4a781e277870dee4e0390165cff52Glenn Kasten        uint32_t frameCount = kMaxBufferSize / sizeof(int16_t) / channelCount;
82e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent
83e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent        // make sure that the AudioRecord total buffer size is large enough
8484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        size_t bufCount = 2;
85e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent        while ((bufCount * frameCount) < minFrameCount) {
86e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent            bufCount++;
87e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent        }
88e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent
89e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent        mRecord = new AudioRecord(
90e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent                    inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT,
91e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent                    audio_channel_in_mask_from_count(channelCount),
92be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov                    opPackageName,
93bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten                    (size_t) (bufCount * frameCount),
94e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent                    AudioRecordCallbackFunction,
95e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent                    this,
96b2379ba0a32638bae2ea0460644f68cf5a0967ceEric Laurent                    frameCount /*notificationFrames*/,
97b2379ba0a32638bae2ea0460644f68cf5a0967ceEric Laurent                    AUDIO_SESSION_ALLOCATE,
98b2379ba0a32638bae2ea0460644f68cf5a0967ceEric Laurent                    AudioRecord::TRANSFER_DEFAULT,
99b2379ba0a32638bae2ea0460644f68cf5a0967ceEric Laurent                    AUDIO_INPUT_FLAG_NONE,
100b2379ba0a32638bae2ea0460644f68cf5a0967ceEric Laurent                    uid,
101b2379ba0a32638bae2ea0460644f68cf5a0967ceEric Laurent                    pid);
102e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent        mInitCheck = mRecord->initCheck();
1033e98ecd18c906dc3ac2ff1a890f0b3163447272dGlenn Kasten        if (mInitCheck != OK) {
1043e98ecd18c906dc3ac2ff1a890f0b3163447272dGlenn Kasten            mRecord.clear();
1053e98ecd18c906dc3ac2ff1a890f0b3163447272dGlenn Kasten        }
106e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent    } else {
107e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent        mInitCheck = status;
108e49f2b424318aa8e830e7a1338e5e32ab82992f9Eric Laurent    }
109e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
110e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
111e7c9cb48fec02697227bd847cd2e69432659adfdAndreas HuberAudioSource::~AudioSource() {
112e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (mStarted) {
113b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dong        reset();
114e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
115e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
116e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
117e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::initCheck() const {
118e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return mInitCheck;
119e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
120e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
121e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::start(MetaData *params) {
1226b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    Mutex::Autolock autoLock(mLock);
123e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (mStarted) {
124e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        return UNKNOWN_ERROR;
125e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
126e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
1276e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    if (mInitCheck != OK) {
1286e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong        return NO_INIT;
1296e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    }
1306e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
131d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    mTrackMaxAmplitude = false;
132d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    mMaxAmplitude = 0;
133d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong    mInitialReadTimeUs = 0;
134f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mStartTimeUs = 0;
135f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t startTimeUs;
136f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (params && params->findInt64(kKeyTime, &startTimeUs)) {
137f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimeUs = startTimeUs;
138f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
139e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    status_t err = mRecord->start();
140e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (err == OK) {
141e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        mStarted = true;
142eaae38445a340c4857c1c5569475879a728e63b7James Dong    } else {
143e2ffd5b583da9d30d96710b0e8879e90b2b51d30Glenn Kasten        mRecord.clear();
144e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
145e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
146eaae38445a340c4857c1c5569475879a728e63b7James Dong
147e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return err;
148e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
149e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
1506b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dongvoid AudioSource::releaseQueuedFrames_l() {
1513856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("releaseQueuedFrames_l");
1526b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    List<MediaBuffer *>::iterator it;
1536b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    while (!mBuffersReceived.empty()) {
1546b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        it = mBuffersReceived.begin();
1556b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        (*it)->release();
1566b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        mBuffersReceived.erase(it);
1576b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
1586b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong}
1596b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong
1606b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dongvoid AudioSource::waitOutstandingEncodingFrames_l() {
161a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("waitOutstandingEncodingFrames_l: %" PRId64, mNumClientOwnedBuffers);
1626b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    while (mNumClientOwnedBuffers > 0) {
1636b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        mFrameEncodingCompletionCondition.wait(mLock);
1646b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
1656b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong}
1666b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong
167b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dongstatus_t AudioSource::reset() {
1686b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    Mutex::Autolock autoLock(mLock);
169e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    if (!mStarted) {
170e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber        return UNKNOWN_ERROR;
171e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    }
172e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
1736e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    if (mInitCheck != OK) {
1746e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong        return NO_INIT;
1756e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    }
1766e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
177e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    mStarted = false;
17816e79115e497386eaf010af388627f94314a55a3Chong Zhang    mFrameAvailableCondition.signal();
17916e79115e497386eaf010af388627f94314a55a3Chong Zhang
1806b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    mRecord->stop();
1816b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    waitOutstandingEncodingFrames_l();
1826b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    releaseQueuedFrames_l();
183365a963142093a1cd8efdcea76b5f65096a5b115James Dong
184e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return OK;
185e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
186e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
187e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Hubersp<MetaData> AudioSource::getFormat() {
1886b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    Mutex::Autolock autoLock(mLock);
1896e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    if (mInitCheck != OK) {
1906e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong        return 0;
1916e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    }
1926e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
193e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    sp<MetaData> meta = new MetaData;
194e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
1956b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    meta->setInt32(kKeySampleRate, mSampleRate);
196e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setInt32(kKeyChannelCount, mRecord->channelCount());
197e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    meta->setInt32(kKeyMaxInputSize, kMaxBufferSize);
19878bd91b15ee8ea5aa2ab5a8cad7e892cb2d01c1bLajos Molnar    meta->setInt32(kKeyPcmEncoding, kAudioEncodingPcm16bit);
199e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
200e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber    return meta;
201e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
202e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
203f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dongvoid AudioSource::rampVolume(
204f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        int32_t startFrame, int32_t rampDurationFrames,
205f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        uint8_t *data,   size_t bytes) {
206f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
207f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    const int32_t kShift = 14;
208f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    int32_t fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
209f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    const int32_t nChannels = mRecord->channelCount();
210f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    int32_t stopFrame = startFrame + bytes / sizeof(int16_t);
211f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    int16_t *frame = (int16_t *) data;
212f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    if (stopFrame > rampDurationFrames) {
213f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        stopFrame = rampDurationFrames;
214f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    }
215f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
216f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    while (startFrame < stopFrame) {
217f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        if (nChannels == 1) {  // mono
218f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame[0] = (frame[0] * fixedMultiplier) >> kShift;
219f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            ++frame;
220f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            ++startFrame;
221f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        } else {               // stereo
222f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame[0] = (frame[0] * fixedMultiplier) >> kShift;
223f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame[1] = (frame[1] * fixedMultiplier) >> kShift;
224f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            frame += 2;
225f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            startFrame += 2;
226f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        }
227f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
228f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        // Update the multiplier every 4 frames
229f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        if ((startFrame & 3) == 0) {
230f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong            fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
231f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong        }
232f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong    }
233f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong}
234f1ae1963f5028a670573b50a9c1cfb504fc426b4James Dong
235e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huberstatus_t AudioSource::read(
23684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        MediaBuffer **out, const ReadOptions * /* options */) {
2376b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    Mutex::Autolock autoLock(mLock);
2386b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    *out = NULL;
2396e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
2406e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    if (mInitCheck != OK) {
2416e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong        return NO_INIT;
2426e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong    }
2436e20bdf799a6f4efa6c42121a958634ea32ed5ccJames Dong
2446b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    while (mStarted && mBuffersReceived.empty()) {
2456b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        mFrameAvailableCondition.wait(mLock);
2466b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
2476b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    if (!mStarted) {
2486b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        return OK;
2496b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
2506b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    MediaBuffer *buffer = *mBuffersReceived.begin();
2516b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    mBuffersReceived.erase(mBuffersReceived.begin());
2526b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    ++mNumClientOwnedBuffers;
2536b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    buffer->setObserver(this);
2546b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    buffer->add_ref();
2556b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong
2566b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    // Mute/suppress the recording sound
2576b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    int64_t timeUs;
2586b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
2596b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    int64_t elapsedTimeUs = timeUs - mStartTimeUs;
2606b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    if (elapsedTimeUs < kAutoRampStartUs) {
2616b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        memset((uint8_t *) buffer->data(), 0, buffer->range_length());
2626b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    } else if (elapsedTimeUs < kAutoRampStartUs + kAutoRampDurationUs) {
2636b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        int32_t autoRampDurationFrames =
264b65473f4f881ee7c0a24217ceac69514f6c127d5Vineeta Srivastava                    ((int64_t)kAutoRampDurationUs * mSampleRate + 500000LL) / 1000000LL; //Need type casting
2656b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong
2666b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        int32_t autoRampStartFrames =
267b65473f4f881ee7c0a24217ceac69514f6c127d5Vineeta Srivastava                    ((int64_t)kAutoRampStartUs * mSampleRate + 500000LL) / 1000000LL; //Need type casting
2686b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong
2696b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        int32_t nFrames = mNumFramesReceived - autoRampStartFrames;
2706b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        rampVolume(nFrames, autoRampDurationFrames,
2716b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong                (uint8_t *) buffer->data(), buffer->range_length());
2726b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
273542db5d438988360d491a5add1040a2df9aa90c9James Dong
2746b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    // Track the max recording signal amplitude.
2756b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    if (mTrackMaxAmplitude) {
2766b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        trackMaxAmplitude(
2776b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong            (int16_t *) buffer->data(), buffer->range_length() >> 1);
2786b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
279542db5d438988360d491a5add1040a2df9aa90c9James Dong
28046d26dd29195450db15704e84d65740628a821fbChong Zhang    if (mSampleRate != mOutSampleRate) {
281bd83e4b3e77b31e089832bcfbebde086392216c9Hangyu Kuang            timeUs *= (int64_t)mSampleRate / (int64_t)mOutSampleRate;
282bd83e4b3e77b31e089832bcfbebde086392216c9Hangyu Kuang            buffer->meta_data()->setInt64(kKeyTime, timeUs);
28346d26dd29195450db15704e84d65740628a821fbChong Zhang    }
28446d26dd29195450db15704e84d65740628a821fbChong Zhang
2856b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    *out = buffer;
2866b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    return OK;
2876b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong}
288542db5d438988360d491a5add1040a2df9aa90c9James Dong
2896b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dongvoid AudioSource::signalBufferReturned(MediaBuffer *buffer) {
2903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("signalBufferReturned: %p", buffer->data());
2916b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    Mutex::Autolock autoLock(mLock);
2926b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    --mNumClientOwnedBuffers;
2936b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    buffer->setObserver(0);
2946b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    buffer->release();
2956b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    mFrameEncodingCompletionCondition.signal();
2966b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    return;
2976b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong}
29846292fb347d72a314d985e34e5e3743d846cb9b6James Dong
299082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huberstatus_t AudioSource::dataCallback(const AudioRecord::Buffer& audioBuffer) {
3004f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang    int64_t timeUs, position, timeNs;
3014f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang    ExtendedTimestamp ts;
3024f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang    ExtendedTimestamp::Location location;
3034f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang    const int32_t usPerSec = 1000000;
3044f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang
3054f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang    if (mRecord->getTimestamp(&ts) == OK &&
3064f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang            ts.getBestTimestamp(&position, &timeNs, ExtendedTimestamp::TIMEBASE_MONOTONIC,
3074f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang            &location) == OK) {
3084f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang        // Use audio timestamp.
3094f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang        timeUs = timeNs / 1000 -
3104f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang                (position - mNumFramesSkipped -
3114f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang                mNumFramesReceived + mNumFramesLost) * usPerSec / mSampleRate;
3124f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang    } else {
3134f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang        // This should not happen in normal case.
3144f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang        ALOGW("Failed to get audio timestamp, fallback to use systemclock");
3154f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang        timeUs = systemTime() / 1000ll;
3164f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang        // Estimate the real sampling time of the 1st sample in this buffer
3174f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang        // from AudioRecord's latency. (Apply this adjustment first so that
3184f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang        // the start time logic is not affected.)
3194f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang        timeUs -= mRecord->latency() * 1000LL;
3204f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang    }
321082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber
322a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("dataCallbackTimestamp: %" PRId64 " us", timeUs);
3236b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    Mutex::Autolock autoLock(mLock);
3246b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    if (!mStarted) {
3255ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Spurious callback from AudioRecord. Drop the audio data.");
3266b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        return OK;
3276b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
32846292fb347d72a314d985e34e5e3743d846cb9b6James Dong
3294f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang    const size_t bufferSize = audioBuffer.size;
3304f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang
331a472613aec322e25891abf5c77bf3f7e3c244920James Dong    // Drop retrieved and previously lost audio data.
332a472613aec322e25891abf5c77bf3f7e3c244920James Dong    if (mNumFramesReceived == 0 && timeUs < mStartTimeUs) {
3335f972c031d4061f4f037c9fda1ea4bd9b6a756cdGlenn Kasten        (void) mRecord->getInputFramesLost();
3344f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang        int64_t receievedFrames = bufferSize / mRecord->frameSize();
3354f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang        ALOGV("Drop audio data(%" PRId64 " frames) at %" PRId64 "/%" PRId64 " us",
3364f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang                receievedFrames, timeUs, mStartTimeUs);
3374f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang        mNumFramesSkipped += receievedFrames;
338a472613aec322e25891abf5c77bf3f7e3c244920James Dong        return OK;
339a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
340a472613aec322e25891abf5c77bf3f7e3c244920James Dong
3416b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    if (mNumFramesReceived == 0 && mPrevSampleTimeUs == 0) {
3426b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        mInitialReadTimeUs = timeUs;
3436b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        // Initial delay
344af5dd7753e62353411cf0daf3b513c38818e9662Andreas Huber        if (mStartTimeUs > 0) {
3456b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong            mStartTimeUs = timeUs - mStartTimeUs;
346f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        }
3476b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        mPrevSampleTimeUs = mStartTimeUs;
3486b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
349e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
350a472613aec322e25891abf5c77bf3f7e3c244920James Dong    size_t numLostBytes = 0;
351a472613aec322e25891abf5c77bf3f7e3c244920James Dong    if (mNumFramesReceived > 0) {  // Ignore earlier frame lost
352a472613aec322e25891abf5c77bf3f7e3c244920James Dong        // getInputFramesLost() returns the number of lost frames.
353a472613aec322e25891abf5c77bf3f7e3c244920James Dong        // Convert number of frames lost to number of bytes lost.
354a472613aec322e25891abf5c77bf3f7e3c244920James Dong        numLostBytes = mRecord->getInputFramesLost() * mRecord->frameSize();
355a472613aec322e25891abf5c77bf3f7e3c244920James Dong    }
356a472613aec322e25891abf5c77bf3f7e3c244920James Dong
3576b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    CHECK_EQ(numLostBytes & 1, 0u);
3586b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    CHECK_EQ(audioBuffer.size & 1, 0u);
3596b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    if (numLostBytes > 0) {
360b575ddce78d266fa218006f90306158dda5c8f56James Dong        // Loss of audio frames should happen rarely; thus the LOGW should
361b575ddce78d266fa218006f90306158dda5c8f56James Dong        // not cause a logging spam
362377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        ALOGW("Lost audio record data: %zu bytes", numLostBytes);
363b575ddce78d266fa218006f90306158dda5c8f56James Dong    }
364b575ddce78d266fa218006f90306158dda5c8f56James Dong
365b575ddce78d266fa218006f90306158dda5c8f56James Dong    while (numLostBytes > 0) {
366b575ddce78d266fa218006f90306158dda5c8f56James Dong        size_t bufferSize = numLostBytes;
367b575ddce78d266fa218006f90306158dda5c8f56James Dong        if (numLostBytes > kMaxBufferSize) {
368b575ddce78d266fa218006f90306158dda5c8f56James Dong            numLostBytes -= kMaxBufferSize;
369b575ddce78d266fa218006f90306158dda5c8f56James Dong            bufferSize = kMaxBufferSize;
370b575ddce78d266fa218006f90306158dda5c8f56James Dong        } else {
371b575ddce78d266fa218006f90306158dda5c8f56James Dong            numLostBytes = 0;
372d707fcb3e29707ca4a5935c294ef0b38eb5aba5fJames Dong        }
373b575ddce78d266fa218006f90306158dda5c8f56James Dong        MediaBuffer *lostAudioBuffer = new MediaBuffer(bufferSize);
374b575ddce78d266fa218006f90306158dda5c8f56James Dong        memset(lostAudioBuffer->data(), 0, bufferSize);
375b575ddce78d266fa218006f90306158dda5c8f56James Dong        lostAudioBuffer->set_range(0, bufferSize);
3764f998cdef97b9c027f145b2da5c48278e19c3d33Hangyu Kuang        mNumFramesLost += bufferSize / mRecord->frameSize();
377b575ddce78d266fa218006f90306158dda5c8f56James Dong        queueInputBuffer_l(lostAudioBuffer, timeUs);
378b575ddce78d266fa218006f90306158dda5c8f56James Dong    }
379b575ddce78d266fa218006f90306158dda5c8f56James Dong
380b575ddce78d266fa218006f90306158dda5c8f56James Dong    if (audioBuffer.size == 0) {
381b575ddce78d266fa218006f90306158dda5c8f56James Dong        ALOGW("Nothing is available from AudioRecord callback buffer");
382b575ddce78d266fa218006f90306158dda5c8f56James Dong        return OK;
3836b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    }
3843c3763d2ee1cd1fba7fe522fbaf0faca315d8c2aJames Dong
385b575ddce78d266fa218006f90306158dda5c8f56James Dong    MediaBuffer *buffer = new MediaBuffer(bufferSize);
386b575ddce78d266fa218006f90306158dda5c8f56James Dong    memcpy((uint8_t *) buffer->data(),
387b575ddce78d266fa218006f90306158dda5c8f56James Dong            audioBuffer.i16, audioBuffer.size);
3886b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    buffer->set_range(0, bufferSize);
389b575ddce78d266fa218006f90306158dda5c8f56James Dong    queueInputBuffer_l(buffer, timeUs);
390b575ddce78d266fa218006f90306158dda5c8f56James Dong    return OK;
391b575ddce78d266fa218006f90306158dda5c8f56James Dong}
392b575ddce78d266fa218006f90306158dda5c8f56James Dong
393b575ddce78d266fa218006f90306158dda5c8f56James Dongvoid AudioSource::queueInputBuffer_l(MediaBuffer *buffer, int64_t timeUs) {
394b575ddce78d266fa218006f90306158dda5c8f56James Dong    const size_t bufferSize = buffer->range_length();
395b575ddce78d266fa218006f90306158dda5c8f56James Dong    const size_t frameSize = mRecord->frameSize();
396b575ddce78d266fa218006f90306158dda5c8f56James Dong    const int64_t timestampUs =
397b575ddce78d266fa218006f90306158dda5c8f56James Dong                mPrevSampleTimeUs +
398b575ddce78d266fa218006f90306158dda5c8f56James Dong                    ((1000000LL * (bufferSize / frameSize)) +
399b575ddce78d266fa218006f90306158dda5c8f56James Dong                        (mSampleRate >> 1)) / mSampleRate;
400e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
4016b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    if (mNumFramesReceived == 0) {
4026b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong        buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs);
403542db5d438988360d491a5add1040a2df9aa90c9James Dong    }
404b575ddce78d266fa218006f90306158dda5c8f56James Dong
4056b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs);
4066b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    buffer->meta_data()->setInt64(kKeyDriftTime, timeUs - mInitialReadTimeUs);
4076b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    mPrevSampleTimeUs = timestampUs;
408b575ddce78d266fa218006f90306158dda5c8f56James Dong    mNumFramesReceived += bufferSize / frameSize;
4096b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    mBuffersReceived.push_back(buffer);
4106b61f4355db1974cd0f0dfaa4effdd7117b9f09bJames Dong    mFrameAvailableCondition.signal();
411e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}
412e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber
413d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dongvoid AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) {
414d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    for (int i = nSamples; i > 0; --i) {
415d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        int16_t value = *data++;
416d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        if (value < 0) {
417d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong            value = -value;
418d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        }
419d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        if (mMaxAmplitude < value) {
420d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong            mMaxAmplitude = value;
421d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        }
422d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    }
423d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong}
424d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong
425d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dongint16_t AudioSource::getMaxAmplitude() {
426d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    // First call activates the tracking.
427d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    if (!mTrackMaxAmplitude) {
428d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong        mTrackMaxAmplitude = true;
429d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    }
430d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    int16_t value = mMaxAmplitude;
431d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    mMaxAmplitude = 0;
4323856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("max amplitude since last call: %d", value);
433d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong    return value;
434d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong}
435d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong
436e7c9cb48fec02697227bd847cd2e69432659adfdAndreas Huber}  // namespace android
437