summaryrefslogtreecommitdiffstats
path: root/libaudio/AudioHardware.cpp
diff options
context:
space:
mode:
authorAndy Gough <andygough@google.com>2011-08-04 11:59:44 -0700
committerEric Laurent <elaurent@google.com>2011-08-12 19:04:47 -0700
commit86a47e3912531066f6b81ee078e78eccc853ad2f (patch)
tree23f569ea1e49a1a36101bef50c4af37638be9729 /libaudio/AudioHardware.cpp
parent19b413d3c87b2f5c8b610192979ff26efe736d27 (diff)
downloaddevice_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.cpp146
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;