📄 paec.cxx
字号:
/*
* paec.cxx
*
* Open Phone Abstraction Library (OPAL)
* Formally known as the Open H323 project.
*
* Copyright (c) 2001 Post Increment
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Open Phone Abstraction Library.
*
* The author of this code is Damien Sandras
*
* rewritten amd made generic ptlib by Simon Horne
*
* Contributor(s): Miguel Rodriguez Perez.
*
* $Revision: 19008 $
* $Author: rjongbloed $
* $Date: 2007-11-29 09:17:41 +0000 (Thu, 29 Nov 2007) $
*/
#include <ptlib.h>
#include "ptclib/paec.h"
extern "C" {
#include "speex_echo.h"
#include "speex_preprocess.h"
}
///////////////////////////////////////////////////////////////////////////////
PAec::PAec(int _clock, int _sampletime)
: clockrate(_clock), sampleTime(_sampletime)
{
echoState = NULL;
preprocessState = NULL;
e_buf = NULL;
echo_buf = NULL;
ref_buf = NULL;
noise = NULL;
receiveReady = PFalse;
bufferTime = sampleTime*2; // Indicating it takes sampletime to play and sampletime to record
minbuffer = bufferTime - sampleTime;
maxbuffer = bufferTime + 2*sampleTime; // Indicating that
lastTimeStamp = PTimer::Tick();
echo_chan = new PQueueChannel();
echo_chan->Open(10000);
echo_chan->SetReadTimeout(10);
echo_chan->SetWriteTimeout(10);
PTRACE(3, "AEC\tcreated AEC " << clockrate << " hz " << " buffer Size " << bufferTime << " ms." );
}
PAec::~PAec()
{
PWaitAndSignal m(readwritemute);
if (echoState) {
speex_echo_state_destroy(echoState);
echoState = NULL;
}
if (preprocessState) {
speex_preprocess_state_destroy(preprocessState);
preprocessState = NULL;
}
if (ref_buf)
free(ref_buf);
if (e_buf)
free(e_buf);
if (echo_buf)
free(echo_buf);
if (noise)
free(noise);
echo_chan->Close();
delete(echo_chan);
}
void PAec::Receive(BYTE * buffer, unsigned & length)
{
// PWaitAndSignal m(readwritemute);
if (length == 0)
return;
/* Buffer has run dry adjust the timestamp to now */
if (echo_chan->GetSize() == 0)
lastTimeStamp = PTimer::Tick();
/* Write to the soundcard, and write the frame to the PQueueChannel */
if (echo_chan->Write(buffer, length))
rectime.Enqueue(new PTimeInterval(PTimer::Tick()));
if (!receiveReady)
receiveReady = PTrue;
}
void PAec::Send(BYTE * buffer, unsigned & length)
{
// PWaitAndSignal m(readwritemute);
// Audio Recording to send
// Inialise the Echo Canceller
if (echoState == NULL) {
echoState = speex_echo_state_init(length/sizeof(short), 32*length);
echo_buf = (spx_int16_t *) malloc(length);
noise = (spx_int16_t *) malloc((length/sizeof(short)+1)*sizeof(float));
e_buf = (spx_int16_t *) malloc(length);
ref_buf = (spx_int16_t *) malloc(length);
int k=1;
preprocessState = speex_preprocess_state_init(length/sizeof(short), clockrate);
speex_preprocess_ctl(preprocessState, SPEEX_PREPROCESS_SET_DENOISE, &k);
speex_preprocess_ctl(preprocessState, SPEEX_PREPROCESS_SET_DEREVERB, &k);
}
if (!receiveReady)
return;
if (echo_chan->GetSize() == 0)
return;
memcpy((spx_int16_t*)ref_buf, buffer, length);
// Read from the PQueueChannel a reference echo frame
PTimeInterval rec = lastTimeStamp;
PInt64 time = (PTimer::Tick()).GetMilliSeconds();
PInt64 diff = time - rec.GetMilliSeconds();
if (diff < minbuffer) {
PTRACE(6,"AEC\tBuffer Time too short ignoring " << diff << " ms ");
return;
}
if (diff > maxbuffer) {
do {
if (rectime.GetSize() == 0)
return;
rec = *(rectime.Dequeue());
if (time > rec.GetMilliSeconds()) {
PTRACE(6,"AEC\tBuffer Time too large " << diff << " ms Max:" << maxbuffer << " Ignoring Packet!");
diff = time - rec.GetMilliSeconds();
if (!echo_chan->Read((short *)echo_buf, length)) {
speex_preprocess(preprocessState, (spx_int16_t*)ref_buf, NULL);
memcpy(buffer, (spx_int16_t*)ref_buf, length);
PTRACE(3,"AEC\tExiting Buffer Read error.");
return;
}
} else return;
} while (diff > maxbuffer);
} else {
if (!echo_chan->Read((short *)echo_buf, length)) {
speex_preprocess(preprocessState, (spx_int16_t*)ref_buf, NULL);
memcpy(buffer, (spx_int16_t*)ref_buf, length);
PTRACE(6,"AEC\tExiting Buffer Read error.");
return;
}
if (rectime.GetSize() == 0)
return;
rec = *(rectime.Dequeue());
}
PTRACE(6,"AEC\tBuffer Time difference " << diff << " ms ");
lastTimeStamp = rec;
// Cancel the echo in this frame
speex_echo_cancel(echoState, (short *)ref_buf, (short *)echo_buf, (short *)e_buf, (float *)noise);
// Suppress the noise & reverb
speex_preprocess(preprocessState, (spx_int16_t*)e_buf, (float *)noise);
lastTimeStamp = rec;
// Use the result of the echo cancelation as capture frame
memcpy(buffer, e_buf, length);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -