Changed to new ring buffer in AECM.

Replaced the old ring buffer in AECM with the new one. Also removed the old one from ring_buffer.
Changes are bit exact according to audioproc_unittest fixed.

TEST=audioproc_unittest
Review URL: http://webrtc-codereview.appspot.com/331022

git-svn-id: http://webrtc.googlecode.com/svn/trunk@1327 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
bjornv@webrtc.org 2012-01-04 09:55:09 +00:00
parent 226c5a1a95
commit 80d28b22b9
4 changed files with 83 additions and 291 deletions

View File

@ -280,28 +280,32 @@ int WebRtcAecm_CreateCore(AecmCore_t **aecmInst)
return -1;
}
if (WebRtcApm_CreateBuffer(&aecm->farFrameBuf, FRAME_LEN + PART_LEN) == -1)
if (WebRtc_CreateBuffer(&aecm->farFrameBuf, FRAME_LEN + PART_LEN,
sizeof(int16_t)) == -1)
{
WebRtcAecm_FreeCore(aecm);
aecm = NULL;
return -1;
}
if (WebRtcApm_CreateBuffer(&aecm->nearNoisyFrameBuf, FRAME_LEN + PART_LEN) == -1)
if (WebRtc_CreateBuffer(&aecm->nearNoisyFrameBuf, FRAME_LEN + PART_LEN,
sizeof(int16_t)) == -1)
{
WebRtcAecm_FreeCore(aecm);
aecm = NULL;
return -1;
}
if (WebRtcApm_CreateBuffer(&aecm->nearCleanFrameBuf, FRAME_LEN + PART_LEN) == -1)
if (WebRtc_CreateBuffer(&aecm->nearCleanFrameBuf, FRAME_LEN + PART_LEN,
sizeof(int16_t)) == -1)
{
WebRtcAecm_FreeCore(aecm);
aecm = NULL;
return -1;
}
if (WebRtcApm_CreateBuffer(&aecm->outFrameBuf, FRAME_LEN + PART_LEN) == -1)
if (WebRtc_CreateBuffer(&aecm->outFrameBuf, FRAME_LEN + PART_LEN,
sizeof(int16_t)) == -1)
{
WebRtcAecm_FreeCore(aecm);
aecm = NULL;
@ -574,10 +578,10 @@ int WebRtcAecm_InitCore(AecmCore_t * const aecm, int samplingFreq)
aecm->knownDelay = 0;
aecm->lastKnownDelay = 0;
WebRtcApm_InitBuffer(aecm->farFrameBuf);
WebRtcApm_InitBuffer(aecm->nearNoisyFrameBuf);
WebRtcApm_InitBuffer(aecm->nearCleanFrameBuf);
WebRtcApm_InitBuffer(aecm->outFrameBuf);
WebRtc_InitBuffer(aecm->farFrameBuf);
WebRtc_InitBuffer(aecm->nearNoisyFrameBuf);
WebRtc_InitBuffer(aecm->nearCleanFrameBuf);
WebRtc_InitBuffer(aecm->outFrameBuf);
memset(aecm->xBuf_buf, 0, sizeof(aecm->xBuf_buf));
memset(aecm->dBufClean_buf, 0, sizeof(aecm->dBufClean_buf));
@ -696,10 +700,10 @@ int WebRtcAecm_FreeCore(AecmCore_t *aecm)
return -1;
}
WebRtcApm_FreeBuffer(aecm->farFrameBuf);
WebRtcApm_FreeBuffer(aecm->nearNoisyFrameBuf);
WebRtcApm_FreeBuffer(aecm->nearCleanFrameBuf);
WebRtcApm_FreeBuffer(aecm->outFrameBuf);
WebRtc_FreeBuffer(aecm->farFrameBuf);
WebRtc_FreeBuffer(aecm->nearNoisyFrameBuf);
WebRtc_FreeBuffer(aecm->nearCleanFrameBuf);
WebRtc_FreeBuffer(aecm->outFrameBuf);
WebRtc_FreeDelayEstimator(aecm->delay_estimator);
free(aecm);
@ -713,13 +717,11 @@ int WebRtcAecm_ProcessFrame(AecmCore_t * aecm,
const WebRtc_Word16 * nearendClean,
WebRtc_Word16 * out)
{
WebRtc_Word16 farBlock[PART_LEN];
WebRtc_Word16 nearNoisyBlock[PART_LEN];
WebRtc_Word16 nearCleanBlock[PART_LEN];
WebRtc_Word16 outBlock_buf[PART_LEN + 8]; // Align buffer to 8-byte boundary.
WebRtc_Word16* outBlock = (WebRtc_Word16*) (((uintptr_t) outBlock_buf + 15) & ~ 15);
WebRtc_Word16 farFrame[FRAME_LEN];
const int16_t* out_ptr = NULL;
int size = 0;
// Buffer the current frame.
@ -729,25 +731,40 @@ int WebRtcAecm_ProcessFrame(AecmCore_t * aecm,
// Buffer the synchronized far and near frames,
// to pass the smaller blocks individually.
WebRtcApm_WriteBuffer(aecm->farFrameBuf, farFrame, FRAME_LEN);
WebRtcApm_WriteBuffer(aecm->nearNoisyFrameBuf, nearendNoisy, FRAME_LEN);
WebRtc_WriteBuffer(aecm->farFrameBuf, farFrame, FRAME_LEN);
WebRtc_WriteBuffer(aecm->nearNoisyFrameBuf, nearendNoisy, FRAME_LEN);
if (nearendClean != NULL)
{
WebRtcApm_WriteBuffer(aecm->nearCleanFrameBuf, nearendClean, FRAME_LEN);
WebRtc_WriteBuffer(aecm->nearCleanFrameBuf, nearendClean, FRAME_LEN);
}
// Process as many blocks as possible.
while (WebRtcApm_get_buffer_size(aecm->farFrameBuf) >= PART_LEN)
while (WebRtc_available_read(aecm->farFrameBuf) >= PART_LEN)
{
WebRtcApm_ReadBuffer(aecm->farFrameBuf, farBlock, PART_LEN);
WebRtcApm_ReadBuffer(aecm->nearNoisyFrameBuf, nearNoisyBlock, PART_LEN);
int16_t far_block[PART_LEN];
const int16_t* far_block_ptr = NULL;
int16_t near_noisy_block[PART_LEN];
const int16_t* near_noisy_block_ptr = NULL;
WebRtc_ReadBuffer(aecm->farFrameBuf, (void**) &far_block_ptr, far_block,
PART_LEN);
WebRtc_ReadBuffer(aecm->nearNoisyFrameBuf,
(void**) &near_noisy_block_ptr,
near_noisy_block,
PART_LEN);
if (nearendClean != NULL)
{
WebRtcApm_ReadBuffer(aecm->nearCleanFrameBuf, nearCleanBlock, PART_LEN);
int16_t near_clean_block[PART_LEN];
const int16_t* near_clean_block_ptr = NULL;
WebRtc_ReadBuffer(aecm->nearCleanFrameBuf,
(void**) &near_clean_block_ptr,
near_clean_block,
PART_LEN);
if (WebRtcAecm_ProcessBlock(aecm,
farBlock,
nearNoisyBlock,
nearCleanBlock,
far_block_ptr,
near_noisy_block_ptr,
near_clean_block_ptr,
outBlock) == -1)
{
return -1;
@ -755,8 +772,8 @@ int WebRtcAecm_ProcessFrame(AecmCore_t * aecm,
} else
{
if (WebRtcAecm_ProcessBlock(aecm,
farBlock,
nearNoisyBlock,
far_block_ptr,
near_noisy_block_ptr,
NULL,
outBlock) == -1)
{
@ -764,19 +781,23 @@ int WebRtcAecm_ProcessFrame(AecmCore_t * aecm,
}
}
WebRtcApm_WriteBuffer(aecm->outFrameBuf, outBlock, PART_LEN);
WebRtc_WriteBuffer(aecm->outFrameBuf, outBlock, PART_LEN);
}
// Stuff the out buffer if we have less than a frame to output.
// This should only happen for the first frame.
size = WebRtcApm_get_buffer_size(aecm->outFrameBuf);
size = (int) WebRtc_available_read(aecm->outFrameBuf);
if (size < FRAME_LEN)
{
WebRtcApm_StuffBuffer(aecm->outFrameBuf, FRAME_LEN - size);
WebRtc_MoveReadPtr(aecm->outFrameBuf, size - FRAME_LEN);
}
// Obtain an output frame.
WebRtcApm_ReadBuffer(aecm->outFrameBuf, out, FRAME_LEN);
WebRtc_ReadBuffer(aecm->outFrameBuf, (void**) &out_ptr, out, FRAME_LEN);
if (out_ptr != out) {
// ReadBuffer() hasn't copied to |out| in this case.
memcpy(out, out_ptr, FRAME_LEN * sizeof(int16_t));
}
return 0;
}

View File

@ -31,7 +31,7 @@ extern HANDLE logFile;
// The factor of 2 handles wb, and the + 1 is as a safety margin
#define MAX_RESAMP_LEN (5 * FRAME_LEN)
static const int kBufSizeSamp = BUF_SIZE_FRAMES * FRAME_LEN; // buffer size (samples)
static const size_t kBufSizeSamp = BUF_SIZE_FRAMES * FRAME_LEN; // buffer size (samples)
static const int kSampMsNb = 8; // samples per ms in nb
// Target suppression levels for nlp modes
// log{0.001, 0.00001, 0.00000001}
@ -108,7 +108,8 @@ WebRtc_Word32 WebRtcAecm_Create(void **aecmInst)
return -1;
}
if (WebRtcApm_CreateBuffer(&aecm->farendBuf, kBufSizeSamp) == -1)
if (WebRtc_CreateBuffer(&aecm->farendBuf, kBufSizeSamp,
sizeof(int16_t)) == -1)
{
WebRtcAecm_Free(aecm);
aecm = NULL;
@ -153,7 +154,7 @@ WebRtc_Word32 WebRtcAecm_Free(void *aecmInst)
fclose(aecm->postCompFile);
#endif // AEC_DEBUG
WebRtcAecm_FreeCore(aecm->aecmCore);
WebRtcApm_FreeBuffer(aecm->farendBuf);
WebRtc_FreeBuffer(aecm->farendBuf);
free(aecm);
return 0;
@ -184,7 +185,7 @@ WebRtc_Word32 WebRtcAecm_Init(void *aecmInst, WebRtc_Word32 sampFreq)
}
// Initialize farend buffer
if (WebRtcApm_InitBuffer(aecm->farendBuf) == -1)
if (WebRtc_InitBuffer(aecm->farendBuf) == -1)
{
aecm->lastError = AECM_UNSPECIFIED_ERROR;
return -1;
@ -257,7 +258,7 @@ WebRtc_Word32 WebRtcAecm_BufferFarend(void *aecmInst, const WebRtc_Word16 *faren
WebRtcAecm_DelayComp(aecm);
}
WebRtcApm_WriteBuffer(aecm->farendBuf, farend, nrOfSamples);
WebRtc_WriteBuffer(aecm->farendBuf, farend, (size_t) nrOfSamples);
return retVal;
}
@ -269,7 +270,6 @@ WebRtc_Word32 WebRtcAecm_Process(void *aecmInst, const WebRtc_Word16 *nearendNoi
aecmob_t *aecm = aecmInst;
WebRtc_Word32 retVal = 0;
short i;
short farend[FRAME_LEN];
short nmbrOfFilledBuffers;
short nBlocks10ms;
short nFrames;
@ -345,7 +345,8 @@ WebRtc_Word32 WebRtcAecm_Process(void *aecmInst, const WebRtc_Word16 *nearendNoi
memcpy(out, nearendClean, sizeof(short) * nrOfSamples);
}
nmbrOfFilledBuffers = WebRtcApm_get_buffer_size(aecm->farendBuf) / FRAME_LEN;
nmbrOfFilledBuffers =
(short) WebRtc_available_read(aecm->farendBuf) / FRAME_LEN;
// The AECM is in the start up mode
// AECM is disabled until the soundcard buffer and farend buffers are OK
@ -407,10 +408,9 @@ WebRtc_Word32 WebRtcAecm_Process(void *aecmInst, const WebRtc_Word16 *nearendNoi
aecm->ECstartup = 0; // Enable the AECM
} else if (nmbrOfFilledBuffers > aecm->bufSizeStart)
{
WebRtcApm_FlushBuffer(
aecm->farendBuf,
WebRtcApm_get_buffer_size(aecm->farendBuf)
- aecm->bufSizeStart * FRAME_LEN);
WebRtc_MoveReadPtr(aecm->farendBuf,
(int) WebRtc_available_read(aecm->farendBuf)
- (int) aecm->bufSizeStart * FRAME_LEN);
aecm->ECstartup = 0;
}
}
@ -422,20 +422,27 @@ WebRtc_Word32 WebRtcAecm_Process(void *aecmInst, const WebRtc_Word16 *nearendNoi
// Note only 1 block supported for nb and 2 blocks for wb
for (i = 0; i < nFrames; i++)
{
nmbrOfFilledBuffers = WebRtcApm_get_buffer_size(aecm->farendBuf) / FRAME_LEN;
int16_t farend[FRAME_LEN];
const int16_t* farend_ptr = NULL;
nmbrOfFilledBuffers =
(short) WebRtc_available_read(aecm->farendBuf) / FRAME_LEN;
// Check that there is data in the far end buffer
if (nmbrOfFilledBuffers > 0)
{
// Get the next 80 samples from the farend buffer
WebRtcApm_ReadBuffer(aecm->farendBuf, farend, FRAME_LEN);
WebRtc_ReadBuffer(aecm->farendBuf, (void**) &farend_ptr, farend,
FRAME_LEN);
// Always store the last frame for use when we run out of data
memcpy(&(aecm->farendOld[i][0]), farend, FRAME_LEN * sizeof(short));
memcpy(&(aecm->farendOld[i][0]), farend_ptr,
FRAME_LEN * sizeof(short));
} else
{
// We have no data so we use the last played frame
memcpy(farend, &(aecm->farendOld[i][0]), FRAME_LEN * sizeof(short));
farend_ptr = farend;
}
// Call buffer delay estimator when all data is extracted,
@ -459,7 +466,7 @@ WebRtc_Word32 WebRtcAecm_Process(void *aecmInst, const WebRtc_Word16 *nearendNoi
if (nearendClean == NULL)
{
if (WebRtcAecm_ProcessFrame(aecm->aecmCore,
farend,
farend_ptr,
&nearendNoisy[FRAME_LEN * i],
NULL,
&out[FRAME_LEN * i]) == -1)
@ -469,7 +476,7 @@ WebRtc_Word32 WebRtcAecm_Process(void *aecmInst, const WebRtc_Word16 *nearendNoi
} else
{
if (WebRtcAecm_ProcessFrame(aecm->aecmCore,
farend,
farend_ptr,
&nearendNoisy[FRAME_LEN * i],
&nearendClean[FRAME_LEN * i],
&out[FRAME_LEN * i]) == -1)
@ -515,7 +522,8 @@ WebRtc_Word32 WebRtcAecm_Process(void *aecmInst, const WebRtc_Word16 *nearendNoi
}
#ifdef AEC_DEBUG
msInAECBuf = WebRtcApm_get_buffer_size(aecm->farendBuf) / (kSampMsNb*aecm->aecmCore->mult);
msInAECBuf = (short) WebRtc_available_read(aecm->farendBuf) /
(kSampMsNb * aecm->aecmCore->mult);
fwrite(&msInAECBuf, 2, 1, aecm->bufFile);
fwrite(&(aecm->knownDelay), sizeof(aecm->knownDelay), 1, aecm->delayFile);
#endif
@ -727,17 +735,17 @@ WebRtc_Word32 WebRtcAecm_get_error_code(void *aecmInst)
static int WebRtcAecm_EstBufDelay(aecmob_t *aecm, short msInSndCardBuf)
{
short delayNew, nSampFar, nSampSndCard;
short delayNew, nSampSndCard;
short nSampFar = (short) WebRtc_available_read(aecm->farendBuf);
short diff;
nSampFar = WebRtcApm_get_buffer_size(aecm->farendBuf);
nSampSndCard = msInSndCardBuf * kSampMsNb * aecm->aecmCore->mult;
delayNew = nSampSndCard - nSampFar;
if (delayNew < FRAME_LEN)
{
WebRtcApm_FlushBuffer(aecm->farendBuf, FRAME_LEN);
WebRtc_MoveReadPtr(aecm->farendBuf, FRAME_LEN);
delayNew += FRAME_LEN;
}
@ -777,10 +785,10 @@ static int WebRtcAecm_EstBufDelay(aecmob_t *aecm, short msInSndCardBuf)
static int WebRtcAecm_DelayComp(aecmob_t *aecm)
{
int nSampFar, nSampSndCard, delayNew, nSampAdd;
int nSampFar = (int) WebRtc_available_read(aecm->farendBuf);
int nSampSndCard, delayNew, nSampAdd;
const int maxStuffSamp = 10 * FRAME_LEN;
nSampFar = WebRtcApm_get_buffer_size(aecm->farendBuf);
nSampSndCard = aecm->msInSndCardBuf * kSampMsNb * aecm->aecmCore->mult;
delayNew = nSampSndCard - nSampFar;
@ -792,7 +800,7 @@ static int WebRtcAecm_DelayComp(aecmob_t *aecm)
FRAME_LEN));
nSampAdd = WEBRTC_SPL_MIN(nSampAdd, maxStuffSamp);
WebRtcApm_StuffBuffer(aecm->farendBuf, nSampAdd);
WebRtc_MoveReadPtr(aecm->farendBuf, -nSampAdd);
aecm->delayChange = 1; // the delay needs to be updated
}

View File

@ -17,17 +17,6 @@
#include <stdlib.h>
#include <string.h>
// TODO(bjornv): Remove tmp_buf_t once old buffer function has been replaced in
// APM.
typedef struct {
int readPos;
int writePos;
int size;
int element_size;
char rwWrap;
bufdata_t *data;
} tmp_buf_t;
enum Wrap {
SAME_WRAP,
DIFF_WRAP
@ -76,203 +65,6 @@ static size_t GetBufferReadRegions(buf_t* buf,
return read_elements;
}
int WebRtcApm_CreateBuffer(void **bufInst, int size) {
tmp_buf_t *buf = NULL;
if (size < 0) {
return -1;
}
buf = malloc(sizeof(tmp_buf_t));
*bufInst = buf;
if (buf == NULL) {
return -1;
}
buf->data = malloc(size * sizeof(bufdata_t));
if (buf->data == NULL) {
free(buf);
buf = NULL;
return -1;
}
buf->size = size;
buf->element_size = 1;
return 0;
}
int WebRtcApm_InitBuffer(void *bufInst) {
tmp_buf_t *buf = (tmp_buf_t*)bufInst;
buf->readPos = 0;
buf->writePos = 0;
buf->rwWrap = SAME_WRAP;
// Initialize buffer to zeros
memset(buf->data, 0, sizeof(bufdata_t) * buf->size);
return 0;
}
int WebRtcApm_FreeBuffer(void *bufInst) {
tmp_buf_t *buf = (tmp_buf_t*)bufInst;
if (buf == NULL) {
return -1;
}
free(buf->data);
free(buf);
return 0;
}
int WebRtcApm_ReadBuffer(void *bufInst, bufdata_t *data, int size) {
tmp_buf_t *buf = (tmp_buf_t*)bufInst;
int n = 0, margin = 0;
if (size <= 0 || size > buf->size) {
return -1;
}
n = size;
if (buf->rwWrap == DIFF_WRAP) {
margin = buf->size - buf->readPos;
if (n > margin) {
buf->rwWrap = SAME_WRAP;
memcpy(data, buf->data + buf->readPos, sizeof(bufdata_t) * margin);
buf->readPos = 0;
n = size - margin;
} else {
memcpy(data, buf->data + buf->readPos, sizeof(bufdata_t) * n);
buf->readPos += n;
return n;
}
}
if (buf->rwWrap == SAME_WRAP) {
margin = buf->writePos - buf->readPos;
if (margin > n)
margin = n;
memcpy(data + size - n, buf->data + buf->readPos,
sizeof(bufdata_t) * margin);
buf->readPos += margin;
n -= margin;
}
return size - n;
}
int WebRtcApm_WriteBuffer(void *bufInst, const bufdata_t *data, int size) {
tmp_buf_t *buf = (tmp_buf_t*)bufInst;
int n = 0, margin = 0;
if (size < 0 || size > buf->size) {
return -1;
}
n = size;
if (buf->rwWrap == SAME_WRAP) {
margin = buf->size - buf->writePos;
if (n > margin) {
buf->rwWrap = DIFF_WRAP;
memcpy(buf->data + buf->writePos, data, sizeof(bufdata_t) * margin);
buf->writePos = 0;
n = size - margin;
} else {
memcpy(buf->data + buf->writePos, data, sizeof(bufdata_t) * n);
buf->writePos += n;
return n;
}
}
if (buf->rwWrap == DIFF_WRAP) {
margin = buf->readPos - buf->writePos;
if (margin > n)
margin = n;
memcpy(buf->data + buf->writePos, data + size - n,
sizeof(bufdata_t) * margin);
buf->writePos += margin;
n -= margin;
}
return size - n;
}
int WebRtcApm_FlushBuffer(void *bufInst, int size) {
tmp_buf_t *buf = (tmp_buf_t*)bufInst;
int n = 0, margin = 0;
if (size <= 0 || size > buf->size) {
return -1;
}
n = size;
if (buf->rwWrap == DIFF_WRAP) {
margin = buf->size - buf->readPos;
if (n > margin) {
buf->rwWrap = SAME_WRAP;
buf->readPos = 0;
n = size - margin;
} else {
buf->readPos += n;
return n;
}
}
if (buf->rwWrap == SAME_WRAP) {
margin = buf->writePos - buf->readPos;
if (margin > n)
margin = n;
buf->readPos += margin;
n -= margin;
}
return size - n;
}
int WebRtcApm_StuffBuffer(void *bufInst, int size) {
tmp_buf_t *buf = (tmp_buf_t*)bufInst;
int n = 0, margin = 0;
if (size <= 0 || size > buf->size) {
return -1;
}
n = size;
if (buf->rwWrap == SAME_WRAP) {
margin = buf->readPos;
if (n > margin) {
buf->rwWrap = DIFF_WRAP;
buf->readPos = buf->size - 1;
n -= margin + 1;
} else {
buf->readPos -= n;
return n;
}
}
if (buf->rwWrap == DIFF_WRAP) {
margin = buf->readPos - buf->writePos;
if (margin > n)
margin = n;
buf->readPos -= margin;
n -= margin;
}
return size - n;
}
int WebRtcApm_get_buffer_size(const void *bufInst) {
const tmp_buf_t *buf = (tmp_buf_t*)bufInst;
if (buf->rwWrap == SAME_WRAP)
return buf->writePos - buf->readPos;
else
return buf->size - buf->readPos + buf->writePos;
}
int WebRtc_CreateBuffer(void** handle,
size_t element_count,
size_t element_size) {

View File

@ -16,35 +16,6 @@
#include <stddef.h> // size_t
// Determines buffer datatype
typedef short bufdata_t; // TODO(bjornv): Remove together with the below.
// TODO(bjornv): Remove WebRtcApm_CreateBuffer, WebRtcApm_InitBuffer and
// WebRtcApm_FreeBuffer when replaced in APM.
// Rename WebRtcApm_FreeBuffer to WebRtc_FreeBuffer() and replace.
// Replace WebRtcApm_FlushBuffer and WebRtcApm_StuffBuffer with
// WebRtc_MoveReadPtr and Read/Write-Buffer with its new versions.
int WebRtcApm_CreateBuffer(void **bufInst, int size);
int WebRtcApm_InitBuffer(void *bufInst);
int WebRtcApm_FreeBuffer(void *bufInst);
// Returns number of samples read
int WebRtcApm_ReadBuffer(void *bufInst, bufdata_t *data, int size);
// Returns number of samples written
int WebRtcApm_WriteBuffer(void *bufInst, const bufdata_t *data, int size);
// Returns number of samples flushed
int WebRtcApm_FlushBuffer(void *bufInst, int size);
// Returns number of samples stuffed
int WebRtcApm_StuffBuffer(void *bufInst, int size);
// Returns number of samples in buffer
int WebRtcApm_get_buffer_size(const void *bufInst);
// TODO(bjornv): Below are the new functions, to replace the older ones above.
int WebRtc_CreateBuffer(void** handle,
size_t element_count,
size_t element_size);