summaryrefslogtreecommitdiffstats
path: root/libaudio
diff options
context:
space:
mode:
Diffstat (limited to 'libaudio')
-rw-r--r--libaudio/AudioHardware.cpp146
-rw-r--r--libaudio/AudioHardware.h5
-rw-r--r--libaudio/EchoReference.cpp180
-rw-r--r--libaudio/EchoReference.h33
4 files changed, 225 insertions, 139 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;
diff --git a/libaudio/AudioHardware.h b/libaudio/AudioHardware.h
index 8824ca5..1fb848e 100644
--- a/libaudio/AudioHardware.h
+++ b/libaudio/AudioHardware.h
@@ -254,6 +254,7 @@ private:
private:
int computeEchoReferenceDelay(size_t frames, struct timespec *echoRefRenderTime);
+ int getPlaybackDelay(size_t frames, EchoReference::Buffer *buffer);
Mutex mLock;
AudioHardware* mHardware;
@@ -320,9 +321,10 @@ private:
ssize_t readFrames(void* buffer, ssize_t frames);
ssize_t processFrames(void* buffer, ssize_t frames);
- void updateEchoReference(size_t frames);
+ int32_t updateEchoReference(size_t frames);
void pushEchoReference(size_t frames);
void updateEchoDelay(size_t frames, struct timespec *echoRefRenderTime);
+ void getCaptureDelay(size_t frames, EchoReference::Buffer *buffer);
status_t setPreProcessorEchoDelay(effect_handle_t handle, int32_t delayUs);
status_t setPreprocessorParam(effect_handle_t handle, effect_param_t *param);
@@ -355,7 +357,6 @@ private:
size_t mRefFramesIn;
EchoReference *mEchoReference;
bool mNeedEchoReference;
- int32_t mEchoDelayUs;
};
};
diff --git a/libaudio/EchoReference.cpp b/libaudio/EchoReference.cpp
index cfd07de..2c10062 100644
--- a/libaudio/EchoReference.cpp
+++ b/libaudio/EchoReference.cpp
@@ -60,7 +60,6 @@ EchoReference::EchoReference(audio_format_t rdFormat,
mRdFrameSize = audio_bytes_per_sample(rdFormat) * rdChannelCount;
mWrFrameSize = audio_bytes_per_sample(wrFormat) * wrChannelCount;
-
mStatus = NO_ERROR;
}
@@ -71,9 +70,10 @@ EchoReference::~EchoReference() {
delete mDownSampler;
}
-status_t EchoReference::write(EchoReference::Buffer *buffer)
+status_t EchoReference::write(Buffer *buffer)
{
if (mStatus != NO_ERROR) {
+ LOGV("EchoReference::write() ERROR, exiting early");
return mStatus;
}
@@ -86,7 +86,18 @@ status_t EchoReference::write(EchoReference::Buffer *buffer)
return NO_ERROR;
}
-// LOGV("EchoReference::write() %d frames", buffer->frameCount);
+ LOGV("EchoReference::write() START trying to write %d frames", buffer->frameCount);
+ LOGV("EchoReference::write() playbackTimestamp:[%lld].[%lld], mPlaybackDelay:[%ld]",
+ (int64_t)buffer->timeStamp.tv_sec,
+ (int64_t)buffer->timeStamp.tv_nsec, mPlaybackDelay);
+
+ //LOGV("EchoReference::write() %d frames", buffer->frameCount);
+ // discard writes until a valid time stamp is provided.
+
+ if ((buffer->timeStamp.tv_sec == 0) && (buffer->timeStamp.tv_nsec == 0) &&
+ (mWrRenderTime.tv_sec == 0) && (mWrRenderTime.tv_nsec == 0)) {
+ return NO_ERROR;
+ }
if ((mState & ECHOREF_WRITING) == 0) {
LOGV("EchoReference::write() start write");
@@ -100,17 +111,10 @@ status_t EchoReference::write(EchoReference::Buffer *buffer)
return NO_ERROR;
}
+ mWrRenderTime.tv_sec = buffer->timeStamp.tv_sec;
+ mWrRenderTime.tv_nsec = buffer->timeStamp.tv_nsec;
- // discard writes until a valid time stamp is provided. Once a valid TS has been received
- // reuse last good TS if none is provided.
- if (buffer->tstamp.tv_sec == 0 && buffer->tstamp.tv_nsec == 0 ) {
- if (mWrRenderTime.tv_sec == 0 && mWrRenderTime.tv_nsec == 0) {
- return NO_ERROR;
- }
- } else {
- mWrRenderTime.tv_sec = buffer->tstamp.tv_sec;
- mWrRenderTime.tv_nsec = buffer->tstamp.tv_nsec;
- }
+ mPlaybackDelay = buffer->delayNs;
void *srcBuf;
size_t inFrames;
@@ -119,8 +123,8 @@ status_t EchoReference::write(EchoReference::Buffer *buffer)
mRdSamplingRate != mWrSamplingRate) {
if (mWrBufSize < buffer->frameCount) {
mWrBufSize = buffer->frameCount;
- // max buffer size is normally function of read sampling rate but as write sampling rate
- // is always more than read sampling rate this works
+ //max buffer size is normally function of read sampling rate but as write sampling rate
+ //is always more than read sampling rate this works
mWrBuf = realloc(mWrBuf, mWrBufSize * mRdFrameSize);
}
@@ -137,7 +141,8 @@ status_t EchoReference::write(EchoReference::Buffer *buffer)
}
if (mWrSamplingRate != mRdSamplingRate) {
if (mDownSampler == NULL) {
- LOGV("EchoReference::write() new ReSampler(%d, %d)", mWrSamplingRate, mRdSamplingRate);
+ LOGV("EchoReference::write() new ReSampler(%d, %d)",
+ mWrSamplingRate, mRdSamplingRate);
mDownSampler = new ReSampler(mWrSamplingRate,
mRdSamplingRate,
mRdChannelCount,
@@ -154,9 +159,12 @@ status_t EchoReference::write(EchoReference::Buffer *buffer)
mWrFramesIn = buffer->frameCount;
// inFrames is always more than we need here to get frames remaining from previous runs
// inFrames is updated by resample() with the number of frames produced
+ LOGV("EchoReference::write() ReSampling(%d, %d)",
+ mWrSamplingRate, mRdSamplingRate);
mDownSampler->resample((int16_t *)mWrBuf, &inFrames);
LOGV_IF(mWrFramesIn != 0,
- "EchoReference::write() mWrFramesIn not 0 (%d) after resampler", mWrFramesIn);
+ "EchoReference::write() mWrFramesIn not 0 (%d) after resampler",
+ mWrFramesIn);
}
srcBuf = mWrBuf;
} else {
@@ -164,20 +172,24 @@ status_t EchoReference::write(EchoReference::Buffer *buffer)
srcBuf = buffer->raw;
}
-
if (mFramesIn + inFrames > mBufSize) {
+ LOGV("EchoReference::write() increasing buffer size from %d to %d",
+ mBufSize, mFramesIn + inFrames);
mBufSize = mFramesIn + inFrames;
mBuffer = realloc(mBuffer, mBufSize * mRdFrameSize);
- LOGV("EchoReference::write() increasing buffer size to %d", mBufSize);
}
memcpy((char *)mBuffer + mFramesIn * mRdFrameSize,
srcBuf,
inFrames * mRdFrameSize);
mFramesIn += inFrames;
- LOGV("EchoReference::write() frames %d, total frames in %d", inFrames, mFramesIn);
+ LOGV("EchoReference::write_log() inFrames:[%d], mFramesInOld:[%d], "\
+ "mFramesInNew:[%d], mBufSize:[%d], mWrRenderTime:[%lld].[%lld], mPlaybackDelay:[%ld]",
+ inFrames, mFramesIn - inFrames, mFramesIn, mBufSize, (int64_t)mWrRenderTime.tv_sec,
+ (int64_t)mWrRenderTime.tv_nsec, mPlaybackDelay);
mCond.signal();
+ LOGV("EchoReference::write() END");
return NO_ERROR;
}
@@ -194,6 +206,9 @@ status_t EchoReference::read(EchoReference::Buffer *buffer)
return NO_ERROR;
}
+ LOGV("EchoReference::read() START, delayCapture:[%ld],mFramesIn:[%d],buffer->frameCount:[%d]",
+ buffer->delayNs, mFramesIn, buffer->frameCount);
+
if ((mState & ECHOREF_READING) == 0) {
LOGV("EchoReference::read() start read");
reset_l();
@@ -202,8 +217,7 @@ status_t EchoReference::read(EchoReference::Buffer *buffer)
if ((mState & ECHOREF_WRITING) == 0) {
memset(buffer->raw, 0, mRdFrameSize * buffer->frameCount);
- buffer->tstamp.tv_sec = 0;
- buffer->tstamp.tv_nsec = 0;
+ buffer->delayNs = 0;
return NO_ERROR;
}
@@ -215,17 +229,97 @@ status_t EchoReference::read(EchoReference::Buffer *buffer)
mCond.waitRelative(mLock, milliseconds(timeoutMs));
if (mFramesIn < buffer->frameCount) {
+ LOGV("EchoReference::read() waited %d ms but still not enough frames"\
+ " mFramesIn: %d, buffer->frameCount = %d",
+ timeoutMs, mFramesIn, buffer->frameCount);
buffer->frameCount = mFramesIn;
- LOGV("EchoReference::read() waited %d ms but still not enough frames", timeoutMs);
}
}
- // computeRenderTime() must be called before subtracting frames read from mFramesIn because
- // we subtract the duration of the whole echo reference buffer including the buffer being read.
- // This is because the time stamp stored in mWrRenderTime corresponds to the last sample written
- // to the echo reference buffer and we want to return the render time of the first sample of
- // the buffer being read.
- computeRenderTime(&buffer->tstamp);
+ int64_t timeDiff;
+ struct timespec tmp;
+
+ if ((mWrRenderTime.tv_sec == 0 && mWrRenderTime.tv_nsec == 0) ||
+ (buffer->timeStamp.tv_sec == 0 && buffer->timeStamp.tv_nsec == 0)) {
+ LOGV("read: NEW:timestamp is zero---------setting timeDiff = 0, "\
+ "not updating delay this time");
+ timeDiff = 0;
+ } else {
+ if (buffer->timeStamp.tv_nsec < mWrRenderTime.tv_nsec) {
+ tmp.tv_sec = buffer->timeStamp.tv_sec - mWrRenderTime.tv_sec - 1;
+ tmp.tv_nsec = 1000000000 + buffer->timeStamp.tv_nsec - mWrRenderTime.tv_nsec;
+ } else {
+ tmp.tv_sec = buffer->timeStamp.tv_sec - mWrRenderTime.tv_sec;
+ tmp.tv_nsec = buffer->timeStamp.tv_nsec - mWrRenderTime.tv_nsec;
+ }
+ timeDiff = (((int64_t)tmp.tv_sec * 1000000000 + tmp.tv_nsec));
+
+ int64_t expectedDelayNs = mPlaybackDelay + buffer->delayNs - timeDiff;
+
+ LOGV("expectedDelayNs[%lld] = mPlaybackDelay[%ld] + delayCapture[%ld] - timeDiff[%lld]",
+ expectedDelayNs, mPlaybackDelay, buffer->delayNs, timeDiff);
+
+ if (expectedDelayNs > 0) {
+ int64_t delayNs = ((int64_t)mFramesIn * 1000000000) / mRdSamplingRate;
+
+ delayNs -= expectedDelayNs;
+
+ if (abs(delayNs) >= sMinDelayUpdate) {
+ if (delayNs < 0) {
+ size_t previousFrameIn = mFramesIn;
+ mFramesIn = (expectedDelayNs * mRdSamplingRate)/1000000000;
+ int offset = mFramesIn - previousFrameIn;
+ LOGV("EchoReference::readlog: delayNs = NEGATIVE and ENOUGH : "\
+ "setting %d frames to zero mFramesIn: %d, previousFrameIn = %d",
+ offset, mFramesIn, previousFrameIn);
+
+ if (mFramesIn > mBufSize) {
+ mBufSize = mFramesIn;
+ mBuffer = realloc(mBuffer, mFramesIn * mRdFrameSize);
+ LOGV("EchoReference::read: increasing buffer size to %d", mBufSize);
+ }
+
+ if (offset > 0)
+ memset((char *)mBuffer + previousFrameIn * mRdFrameSize,
+ 0, offset * mRdFrameSize);
+ } else {
+ size_t previousFrameIn = mFramesIn;
+ int framesInInt = (int)(((int64_t)expectedDelayNs *
+ (int64_t)mRdSamplingRate)/1000000000);
+ int offset = previousFrameIn - framesInInt;
+
+ LOGV("EchoReference::readlog: delayNs = POSITIVE/ENOUGH :previousFrameIn: %d,"\
+ "framesInInt: [%d], offset:[%d], buffer->frameCount:[%d]",
+ previousFrameIn, framesInInt, offset, buffer->frameCount);
+
+ if (framesInInt < (int)buffer->frameCount) {
+ if (framesInInt > 0) {
+ memset((char *)mBuffer + framesInInt * mRdFrameSize,
+ 0, (buffer->frameCount-framesInInt) * mRdFrameSize);
+ LOGV("EchoReference::read: pushing [%d] zeros into ref buffer",
+ (buffer->frameCount-framesInInt));
+ } else {
+ LOGV("framesInInt = %d", framesInInt);
+ }
+ framesInInt = buffer->frameCount;
+ } else {
+ if (offset > 0) {
+ memcpy(mBuffer, (char *)mBuffer + (offset * mRdFrameSize),
+ framesInInt * mRdFrameSize);
+ LOGV("EchoReference::read: shifting ref buffer by [%d]",framesInInt);
+ }
+ }
+ mFramesIn = (size_t)framesInInt;
+ }
+ } else {
+ LOGV("EchoReference::read: NOT ENOUGH samples to update %lld", delayNs);
+ }
+ } else {
+ LOGV("NEGATIVE expectedDelayNs[%lld] = "\
+ "mPlaybackDelay[%ld] + delayCapture[%ld] - timeDiff[%lld]",
+ expectedDelayNs, mPlaybackDelay, buffer->delayNs, timeDiff);
+ }
+ }
memcpy(buffer->raw,
(char *)mBuffer,
@@ -236,34 +330,16 @@ status_t EchoReference::read(EchoReference::Buffer *buffer)
(char *)mBuffer + buffer->frameCount * mRdFrameSize,
mFramesIn * mRdFrameSize);
- LOGV("EchoReference::read() %d frames, total frames in %d", buffer->frameCount, mFramesIn);
+ // As the reference buffer is now time aligned to the microphone signal there is a zero delay
+ buffer->delayNs = 0;
+
+ LOGV("EchoReference::read() END %d frames, total frames in %d",
+ buffer->frameCount, mFramesIn);
mCond.signal();
return NO_ERROR;
}
-void EchoReference::computeRenderTime(struct timespec *renderTime)
-{
- int64_t delayNs = ((int64_t)mFramesIn * 1000000000) / mRdSamplingRate;
-
- if (mDownSampler != NULL) {
- delayNs += mDownSampler->delayNs();
- }
-
- struct timespec tmp;
- tmp.tv_nsec = delayNs % 1000000000;
- tmp.tv_sec = delayNs / 1000000000;
-
- if (mWrRenderTime.tv_nsec < tmp.tv_nsec)
- {
- renderTime->tv_sec = mWrRenderTime.tv_sec - tmp.tv_sec - 1;
- renderTime->tv_nsec = 1000000000 + mWrRenderTime.tv_nsec - tmp.tv_nsec;
- } else {
- renderTime->tv_sec = mWrRenderTime.tv_sec - tmp.tv_sec;
- renderTime->tv_nsec = mWrRenderTime.tv_nsec - tmp.tv_nsec;
- }
-}
-
void EchoReference::reset_l() {
LOGV("EchoReference::reset_l()");
free(mBuffer);
diff --git a/libaudio/EchoReference.h b/libaudio/EchoReference.h
index 5d54fac..b82cd11 100644
--- a/libaudio/EchoReference.h
+++ b/libaudio/EchoReference.h
@@ -46,15 +46,29 @@ public:
ECHOREF_WRITING = 0x02 // writing is active
};
- // Buffer descriptor used by read() and write() methods, including the render time stamp.
- // for write(), The time stamp is the render time for the last sample in the buffer written
- // for read(), the time stamp is the render time for the first sample in the buffer read
+ // Buffer descriptor used by read() and write() methods, including the time stamp and delay.
class Buffer {
public:
- void *raw;
- size_t frameCount;
- struct timespec tstamp; // render time stamp of buffer. 0.0 means if unknown
+ void *raw; // pointer to audio frame
+ size_t frameCount; // number of frames in buffer
+ int32_t delayNs; // delay for this buffer (see comment below)
+ struct timespec timeStamp; // time stamp for this buffer (see comment below)
};
+ // when used for EchoReference::write():
+ // + as input:
+ // - delayNs is the delay introduced by playback buffers
+ // - timeStamp is the time stamp corresponding to the delay calculation
+ // + as output:
+ // unused
+ // when used for EchoReference::read():
+ // + as input:
+ // - delayNs is the delay introduced by capture buffers
+ // - timeStamp is the time stamp corresponding to the delay calculation
+ // + as output:
+ // - delayNs is the delay between the returned frames and the capture time derived from
+ // delay and time stamp indicated as input. This delay is to be communicated to the AEC.
+ // - frameCount is updated with the actual number of frames returned
+
// BufferProvider
status_t getNextBuffer(ReSampler::BufferProvider::Buffer* buffer);
@@ -65,10 +79,10 @@ public:
status_t read(Buffer *buffer);
status_t write(Buffer *buffer);
+
private:
void reset_l();
- void computeRenderTime(struct timespec *renderTime);
status_t mStatus; // init status
uint32_t mState; // active state: reading, writing or both
@@ -88,10 +102,15 @@ private:
size_t mWrFramesIn; // number of frames in conversion buffer
void *mWrSrcBuf; // resampler input buf (either mWrBuf or buffer used by write()
struct timespec mWrRenderTime; // latest render time indicated by write()
+ int32_t mPlaybackDelay;
+
uint32_t mRdDurationUs; // Duration of last buffer read (used for mCond wait timeout)
android::Mutex mLock; // Mutex protecting read/write concurrency
android::Condition mCond; // Condition signaled when data is ready to read
ReSampler *mDownSampler; // input resampler
+
+ static const int sMinDelayUpdate = 62500; // delay jump threshold to update ref buffer
+ // 0.5 samples at 8kHz in nsecs
};
}; // namespace android