diff options
author | Andy Gough <andygough@google.com> | 2011-08-04 11:59:44 -0700 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2011-08-12 19:04:47 -0700 |
commit | 86a47e3912531066f6b81ee078e78eccc853ad2f (patch) | |
tree | 23f569ea1e49a1a36101bef50c4af37638be9729 /libaudio/AudioHardware.cpp | |
parent | 19b413d3c87b2f5c8b610192979ff26efe736d27 (diff) | |
download | device_samsung_crespo-86a47e3912531066f6b81ee078e78eccc853ad2f.zip device_samsung_crespo-86a47e3912531066f6b81ee078e78eccc853ad2f.tar.gz device_samsung_crespo-86a47e3912531066f6b81ee078e78eccc853ad2f.tar.bz2 |
audio HAL: new echo reference design
The echo reference discards or inserts (silent) frames according to underruns
or overruns.
It always returns an echo buffer which delay from current capture buffer is 0.
Change-Id: Ifea06a47fe87f2b75d4d04737c495a9867d1c4bd
Diffstat (limited to 'libaudio/AudioHardware.cpp')
-rw-r--r-- | libaudio/AudioHardware.cpp | 146 |
1 files changed, 68 insertions, 78 deletions
diff --git a/libaudio/AudioHardware.cpp b/libaudio/AudioHardware.cpp index faa8a14..d1160ba 100644 --- a/libaudio/AudioHardware.cpp +++ b/libaudio/AudioHardware.cpp @@ -1085,16 +1085,17 @@ AudioHardware::AudioStreamOutALSA::~AudioStreamOutALSA() standby(); } -int AudioHardware::AudioStreamOutALSA::computeEchoReferenceDelay(size_t frames, - struct timespec *echoRefRenderTime) +int AudioHardware::AudioStreamOutALSA::getPlaybackDelay(size_t frames, + EchoReference::Buffer *buffer) { size_t kernelFr; - int rc = pcm_get_htimestamp(mPcm, &kernelFr, echoRefRenderTime); + int rc = pcm_get_htimestamp(mPcm, &kernelFr, &buffer->timeStamp); if (rc < 0) { - LOGV("computeEchoReferenceDelay(): pcm_get_htimestamp error"); - echoRefRenderTime->tv_sec = 0; - echoRefRenderTime->tv_nsec = 0; + buffer->timeStamp.tv_sec = 0; + buffer->timeStamp.tv_nsec = 0; + buffer->delayNs = 0; + LOGV("getPlaybackDelay(): pcm_get_htimestamp error, setting playbackTimestamp to 0"); return rc; } @@ -1103,19 +1104,23 @@ int AudioHardware::AudioStreamOutALSA::computeEchoReferenceDelay(size_t frames, // adjust render time stamp with delay added by current driver buffer. // Add the duration of current frame as we want the render time of the last // sample being written. - long delayNs = (long)(((int64_t)(kernelFr + frames)* 1000000000) / - AUDIO_HW_OUT_SAMPLERATE); - delayNs += echoRefRenderTime->tv_nsec; + long delayNs = (long)(((int64_t)(kernelFr + frames)* 1000000000) /AUDIO_HW_OUT_SAMPLERATE); - echoRefRenderTime->tv_nsec = delayNs % 1000000000; - echoRefRenderTime->tv_sec += delayNs / 1000000000; + LOGV("AudioStreamOutALSA::getPlaybackDelay2 delayNs: [%ld], "\ + "kernelFr:[%d], frames:[%d], buffSize:[%d], timeStamp:[%ld].[%ld]", + delayNs, (int)kernelFr, (int)frames, pcm_get_buffer_size(mPcm), + (long)buffer->timeStamp.tv_sec, buffer->timeStamp.tv_nsec); + + buffer->delayNs = delayNs; + LOGV("NXPWritehTimestamps: FrameAvailable = [%d], hTimestamps = [%d]s.[%d]ns", + (int)kernelFr, (int)buffer->timeStamp.tv_sec, (int)(buffer->timeStamp.tv_nsec/1000)); return 0; } ssize_t AudioHardware::AudioStreamOutALSA::write(const void* buffer, size_t bytes) { - // LOGV("AudioStreamOutALSA::write(%p, %u)", buffer, bytes); + LOGV("-----AudioStreamInALSA::write(%p, %d) START", buffer, (int)bytes); status_t status = NO_INIT; const uint8_t* p = static_cast<const uint8_t*>(buffer); int ret; @@ -1176,7 +1181,8 @@ ssize_t AudioHardware::AudioStreamOutALSA::write(const void* buffer, size_t byte EchoReference::Buffer b; b.raw = (void *)buffer; b.frameCount = bytes / frameSize(); - computeEchoReferenceDelay(bytes / frameSize(), &b.tstamp); + + getPlaybackDelay(bytes / frameSize(), &b); mEchoReference->write(&b); } @@ -1185,18 +1191,18 @@ ssize_t AudioHardware::AudioStreamOutALSA::write(const void* buffer, size_t byte TRACE_DRIVER_OUT if (ret == 0) { + LOGV("-----AudioStreamInALSA::write(%p, %d) END", buffer, (int)bytes); return bytes; } LOGW("write error: %d", errno); status = -errno; } Error: - standby(); // Simulate audio output timing in case of error usleep((((bytes * 1000) / frameSize()) * 1000) / sampleRate()); - + LOGE("AudioStreamOutALSA::write END WITH ERROR !!!!!!!!!(%p, %u)", buffer, bytes); return status; } @@ -1549,8 +1555,8 @@ ssize_t AudioHardware::AudioStreamInALSA::processFrames(void* buffer, ssize_t fr pushEchoReference(mProcFramesIn); } - // inBuf.frameCount and outBuf.frameCount indicate respectively the maximum number of frames - // to be consumed and produced by process() + //inBuf.frameCount and outBuf.frameCount indicate respectively the maximum number of frames + //to be consumed and produced by process() audio_buffer_t inBuf = { mProcFramesIn, {mProcBuf} @@ -1585,8 +1591,13 @@ ssize_t AudioHardware::AudioStreamInALSA::processFrames(void* buffer, ssize_t fr return framesWr; } -void AudioHardware::AudioStreamInALSA::updateEchoReference(size_t frames) +int32_t AudioHardware::AudioStreamInALSA::updateEchoReference(size_t frames) { + EchoReference::Buffer b; + b.delayNs = 0; + + LOGV("updateEchoReference1 START, frames = [%d], mRefFramesIn = [%d], b.frameCount = [%d]", + frames, mRefFramesIn, frames - mRefFramesIn); if (mRefFramesIn < frames) { if (mRefBufSize < frames) { mRefBufSize = frames; @@ -1594,24 +1605,29 @@ void AudioHardware::AudioStreamInALSA::updateEchoReference(size_t frames) mRefBufSize * mChannelCount * sizeof(int16_t)); } - EchoReference::Buffer b; b.frameCount = frames - mRefFramesIn; b.raw = (void *)(mRefBuf + mRefFramesIn * mChannelCount); - if (mEchoReference->read(&b) == NO_ERROR) { + + getCaptureDelay(frames, &b); + + if (mEchoReference->read(&b) == NO_ERROR) + { mRefFramesIn += b.frameCount; - // Echo delay calculation: updates mEchoDelayUs - updateEchoDelay(frames, &b.tstamp); - } else { - mEchoDelayUs = 0; + LOGV("updateEchoReference2: mRefFramesIn:[%d], mRefBufSize:[%d], "\ + "frames:[%d], b.frameCount:[%d]", mRefFramesIn, mRefBufSize,frames,b.frameCount); } + + }else{ + LOGV("updateEchoReference3: NOT enough frames to read ref buffer"); } + return b.delayNs; } void AudioHardware::AudioStreamInALSA::pushEchoReference(size_t frames) { // read frames from echo reference buffer and update echo delay // mRefFramesIn is updated with frames available in mRefBuf - updateEchoReference(frames); + int32_t delayUs = (int32_t)(updateEchoReference(frames)/1000); if (mRefFramesIn < frames) { frames = mRefFramesIn; @@ -1629,11 +1645,12 @@ void AudioHardware::AudioStreamInALSA::pushEchoReference(size_t frames) (*mPreprocessors[i])->process_reverse(mPreprocessors[i], &refBuf, NULL); - setPreProcessorEchoDelay(mPreprocessors[i], mEchoDelayUs); + setPreProcessorEchoDelay(mPreprocessors[i], delayUs); } mRefFramesIn -= refBuf.frameCount; if (mRefFramesIn) { + LOGV("pushEchoReference5: shifting mRefBuf down by = %d frames", mRefFramesIn); memcpy(mRefBuf, mRefBuf + refBuf.frameCount * mChannelCount, mRefFramesIn * mChannelCount * sizeof(int16_t)); @@ -1674,81 +1691,54 @@ status_t AudioHardware::AudioStreamInALSA::setPreprocessorParam(effect_handle_t return status; } -void AudioHardware::AudioStreamInALSA::updateEchoDelay(size_t frames, - struct timespec *echoRefRenderTime) +void AudioHardware::AudioStreamInALSA::getCaptureDelay(size_t frames, + EchoReference::Buffer *buffer) { + // read frames available in kernel driver buffer size_t kernelFr; struct timespec tstamp; - if (pcm_get_htimestamp(mPcm, &kernelFr, &tstamp) < 0) { - mEchoDelayUs = 0; - LOGW("read updateEchoDelay(): pcm_get_htimestamp error"); - return; - } - if (echoRefRenderTime->tv_sec == 0 && echoRefRenderTime->tv_nsec == 0) { - mEchoDelayUs = 0; - LOGV("read updateEchoDelay(): echo ref render time is 0"); + if (pcm_get_htimestamp(mPcm, &kernelFr, &tstamp) < 0) { + buffer->timeStamp.tv_sec = 0; + buffer->timeStamp.tv_nsec = 0; + buffer->delayNs = 0; + LOGW("read getCaptureDelay(): pcm_htimestamp error"); return; } - long kernelDelay = (long)(((int64_t)kernelFr * 1000000000) / AUDIO_HW_IN_SAMPLERATE); - // read frames available in audio HAL input buffer // add number of frames being read as we want the capture time of first sample in current // buffer - long bufDelay = (long)(((int64_t)(mInputFramesIn + mProcFramesIn + frames) * 1000000000) + long bufDelay = (long)(((int64_t)(mInputFramesIn + mProcFramesIn) * 1000000000) / AUDIO_HW_IN_SAMPLERATE); - // add delay introduced by resampler long rsmpDelay = 0; if (mDownSampler) { rsmpDelay = mDownSampler->delayNs(); } - // correct capture time stamp - long delay = kernelDelay + bufDelay + rsmpDelay; - struct timespec tmp; - tmp.tv_sec = delay / 1000000000; - tmp.tv_nsec = delay % 1000000000; - - if (tstamp.tv_nsec < tmp.tv_nsec) - { - tmp.tv_sec = tstamp.tv_sec - tmp.tv_sec - 1; - tmp.tv_nsec = 1000000000 + tstamp.tv_nsec - tmp.tv_nsec; - } else { - tmp.tv_sec = tstamp.tv_sec - tmp.tv_sec; - tmp.tv_nsec = tstamp.tv_nsec - tmp.tv_nsec; - } + long kernelDelay = (long)(((int64_t)kernelFr * 1000000000) / AUDIO_HW_IN_SAMPLERATE); - // caculate echo delay = echo reference render time - capture time - if (echoRefRenderTime->tv_nsec < tmp.tv_nsec) - { - tmp.tv_sec = echoRefRenderTime->tv_sec - tmp.tv_sec - 1; - tmp.tv_nsec = 1000000000 + echoRefRenderTime->tv_nsec - tmp.tv_nsec; - } else { - tmp.tv_sec = echoRefRenderTime->tv_sec - tmp.tv_sec; - tmp.tv_nsec = echoRefRenderTime->tv_nsec - tmp.tv_nsec; - } + // correct capture time stamp + long delayNs = kernelDelay + bufDelay + rsmpDelay; - mEchoDelayUs = (int32_t)(((int64_t)tmp.tv_sec * 1000000000 + tmp.tv_nsec) / 1000); + buffer->timeStamp = tstamp; + buffer->delayNs = delayNs; + LOGV("AudioStreamInALSA::getCaptureDelay2 TimeStamp = [%lld].[%lld], delayCaptureNs: [%ld],"\ + " kernelDelay:[%ld], bufDelay:[%ld], rsmpDelay:[%ld], kernelFr:[%d], "\ + "mInputFramesIn:[%d], mProcFramesIn:[%d], frames:[%d]", + (int64_t)buffer->timeStamp.tv_sec , (int64_t)buffer->timeStamp.tv_nsec, buffer->delayNs, + kernelDelay, bufDelay, rsmpDelay, kernelFr, mInputFramesIn,mProcFramesIn,frames); - if (mEchoDelayUs < 0) { - LOGW("negative echo delay !!! %d", mEchoDelayUs); - mEchoDelayUs = 0; - } + LOGV("NXPReadhTimestamps: FrameAvailable = [%d], hTimestamps = [%d]s.[%d]ns", + (int)kernelFr, (int)buffer->timeStamp.tv_sec, (int)(buffer->timeStamp.tv_nsec/1000)); -// LOGV("updateEchoDelay() ref render TS %d.%d capture TS %d.%d delta TS %d.%d" -// " mEchoDelayUs %d kernelDelay %d bufDelay %d rsmpDelay %d", -// (int)echoRefRenderTime->tv_sec, (int)echoRefRenderTime->tv_nsec, -// (int)tstamp.tv_sec, (int)tstamp.tv_nsec, -// (int)tmp.tv_sec, (int)tmp.tv_nsec, -// mEchoDelayUs, (int)kernelDelay, (int)bufDelay, (int)rsmpDelay); } ssize_t AudioHardware::AudioStreamInALSA::read(void* buffer, ssize_t bytes) { - // LOGV("AudioStreamInALSA::read(%p, %d)", buffer, (int)bytes); + LOGV("-----AudioStreamInALSA::read(%p, %d) START", buffer, (int)bytes); status_t status = NO_INIT; if (mHardware == NULL) return NO_INIT; @@ -1820,6 +1810,7 @@ ssize_t AudioHardware::AudioStreamInALSA::read(void* buffer, ssize_t bytes) } if (framesRd >= 0) { + LOGV("-----AudioStreamInALSA::read(%p, %d) END", buffer, (int)bytes); return framesRd * mChannelCount * sizeof(int16_t); } @@ -1833,7 +1824,7 @@ Error: // Simulate audio output timing in case of error usleep((((bytes * 1000) / frameSize()) * 1000) / sampleRate()); - + LOGE("-----AudioStreamInALSA::read(%p, %d) END ERROR", buffer, (int)bytes); return status; } @@ -1944,7 +1935,6 @@ status_t AudioHardware::AudioStreamInALSA::open_l() mProcFramesIn = 0; mRefBufSize = 0; mRefFramesIn = 0; - mEchoDelayUs = 0; mMixer = mHardware->openMixer_l(); if (mMixer) { @@ -2143,7 +2133,7 @@ status_t AudioHardware::AudioStreamInALSA::getNextBuffer(ReSampler::BufferProvid mInputFramesIn = AUDIO_HW_IN_PERIOD_SZ; } - buffer->frameCount = (buffer->frameCount > mInputFramesIn) ? mInputFramesIn : buffer->frameCount; + buffer->frameCount = (buffer->frameCount > mInputFramesIn) ? mInputFramesIn:buffer->frameCount; buffer->i16 = mInputBuf + (AUDIO_HW_IN_PERIOD_SZ - mInputFramesIn) * mChannelCount; return mReadStatus; |