diff --git a/sflphone-common/src/audio/echocancel.cpp b/sflphone-common/src/audio/echocancel.cpp index 977b7d4a2c5be5febd3ed3fd43b44c7e563564e5..c3c2ae4d68c20efc4e3fe5b924ef778692986af5 100644 --- a/sflphone-common/src/audio/echocancel.cpp +++ b/sflphone-common/src/audio/echocancel.cpp @@ -32,7 +32,17 @@ EchoCancel::EchoCancel(int smplRate, int frameLength) : _samplingRate(smplRate), _spkrHistCnt(0), _micHistCnt(0), _amplFactor(0.0), - _lastAmplFactor(0.0) + _lastAmplFactor(0.0), + _amplDelayIndexIn(0), + _amplDelayIndexOut(0), + _adaptDone(false), + _adaptStarted(false), + _adaptCnt(0), + _spkrAdaptCnt(0), + _micAdaptCnt(0), + _spkrAdaptSize(SPKR_ADAPT_SIZE), + _micAdaptSize(MIC_ADAPT_SIZE), + _correlationSize(0) { _debug("EchoCancel: Instantiate echo canceller"); @@ -48,6 +58,7 @@ EchoCancel::EchoCancel(int smplRate, int frameLength) : _samplingRate(smplRate), _micData->createReadPointer(); _spkrData->createReadPointer(); + // variable used to sync mic and spkr _spkrStoped = true; _smplPerFrame = (_samplingRate * _frameLength) / MS_PER_SEC; @@ -55,6 +66,7 @@ EchoCancel::EchoCancel(int smplRate, int frameLength) : _samplingRate(smplRate), _historyLength = ECHO_LENGTH / SEGMENT_LENGTH; _nbSegmentPerFrame = _frameLength / SEGMENT_LENGTH; + _noiseState = speex_preprocess_state_init(_smplPerFrame, _samplingRate); int i=1; speex_preprocess_ctl(_noiseState, SPEEX_PREPROCESS_SET_DENOISE, &i); @@ -72,10 +84,10 @@ EchoCancel::EchoCancel(int smplRate, int frameLength) : _samplingRate(smplRate), memset(_avgSpkrLevelHist, 0, BUFF_SIZE*sizeof(int)); memset(_avgMicLevelHist, 0, BUFF_SIZE*sizeof(int)); - memset(_delayedAmplify, 0, MAX_DELAY*sizeof(float)); + memset(_delayLineAmplify, 0, MAX_DELAY_LINE_AMPL*sizeof(float)); - _amplIndexIn = 0; - _amplIndexOut = DELAY_AMPLIFY / SEGMENT_LENGTH; + _amplDelayIndexIn = 0; + _amplDelayIndexOut = 0;; } @@ -122,10 +134,10 @@ void EchoCancel::reset() _historyLength = ECHO_LENGTH / SEGMENT_LENGTH; _nbSegmentPerFrame = _frameLength / SEGMENT_LENGTH; - memset(_delayedAmplify, 0, MAX_DELAY*sizeof(float)); + memset(_delayLineAmplify, 0, MAX_DELAY_LINE_AMPL*sizeof(float)); - _amplIndexIn = 0; - _amplIndexOut = DELAY_AMPLIFY / SEGMENT_LENGTH; + _amplDelayIndexIn = 0; + _amplDelayIndexOut = DELAY_AMPLIFY / SEGMENT_LENGTH; _micData->flushAll(); _spkrData->flushAll(); @@ -146,12 +158,6 @@ void EchoCancel::reset() f=.0; speex_preprocess_ctl(_noiseState, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &f); - /* - std::cout << "EchoCancel: _smplPerFrame " << _smplPerFrame - << ", _smplPerSeg " << _smplPerSeg - << ", _historyLength " << _historyLength - << ", _nbSegmentPerFrame " << _nbSegmentPerFrame << std::endl; - */ _spkrStoped = true; } @@ -169,11 +175,6 @@ void EchoCancel::putData(SFLDataFormat *inputData, int nbBytes) // Put data in speaker ring buffer _spkrData->Put(inputData, nbBytes); - // std::cout << "EchoCancel: spkrDataAvail " << _spkrData->AvailForGet() << std::endl; - - // In case we use libspeex internal buffer - // (require capture and playback stream to be synchronized) - // speex_echo_playback(_echoState, inputData); } void EchoCancel::process(SFLDataFormat *data, int nbBytes) {} @@ -199,23 +200,16 @@ int EchoCancel::process(SFLDataFormat *inputData, SFLDataFormat *outputData, int int spkrAvail = _spkrData->AvailForGet(); int micAvail = _micData->AvailForGet(); - // std::cout << "Process echo: spkrAvail " << spkrAvail << ", micAvail " << micAvail << ", byteSize " << byteSize << std::endl; - // Init number of frame processed int nbFrame = 0; // Get data from mic and speaker internal buffer while((spkrAvail >= byteSize) && (micAvail >= byteSize)) { - // std::cout << "perform echocancel" << std::endl; - // get synchronized data _spkrData->Get(_tmpSpkr, byteSize); _micData->Get(_tmpMic, byteSize); - // micFile->write ((const char *)_tmpMic, byteSize); - // spkrFile->write ((const char *)_tmpSpkr, byteSize); - // Processed echo cancellation performEchoCancel(_tmpMic, _tmpSpkr, _tmpOut); @@ -229,8 +223,6 @@ int EchoCancel::process(SFLDataFormat *inputData, SFLDataFormat *outputData, int spkrAvail = _spkrData->AvailForGet(); micAvail = _micData->AvailForGet(); - // std::cout << "Process echo remaining: spkrAvail " << spkrAvail << ", micAvail " << micAvail << std::endl; - // increment nb of frame processed ++nbFrame; } @@ -247,13 +239,6 @@ void EchoCancel::setSamplingRate(int smplRate) { if (smplRate != _samplingRate) { _samplingRate = smplRate; - /* - if(smplRate == 16000) - _frameLength = 10; - else - _frameLength = 20; - */ - reset(); } } @@ -293,8 +278,6 @@ void EchoCancel::performEchoCancel(SFLDataFormat *micData, SFLDataFormat *spkrDa _lastAmplFactor = _amplFactor; - // std::cout << "Amplitude: " << amplify << ", spkrLevel: " << _spkrLevel << ", micLevel: " << _micLevel << std::endl; - amplifySignal(micData+(k*_smplPerSeg), outputData+(k*_smplPerSeg), amplify); } @@ -317,6 +300,8 @@ void EchoCancel::updateEchoCancel(SFLDataFormat *micData, SFLDataFormat *spkrDat if(_spkrHistCnt >= _historyLength) _spkrHistCnt = 0; + + } @@ -355,17 +340,17 @@ void EchoCancel::amplifySignal(SFLDataFormat *micData, SFLDataFormat *outputData // Use delayed amplification factor due to sound card latency for(int i = 0; i < _smplPerSeg; i++) { - outputData[i] = (SFLDataFormat)(((float)micData[i])*_delayedAmplify[_amplIndexOut]); + outputData[i] = (SFLDataFormat)(((float)micData[i])*_delayLineAmplify[_amplDelayIndexOut]); } - _amplIndexOut++; - _delayedAmplify[_amplIndexIn++] = amplify; + _amplDelayIndexOut++; + _delayLineAmplify[_amplDelayIndexIn++] = amplify; - if(_amplIndexOut >= MAX_DELAY) - _amplIndexOut = 0; + if(_amplDelayIndexOut >= MAX_DELAY_LINE_AMPL) + _amplDelayIndexOut = 0; - if(_amplIndexIn >= MAX_DELAY) - _amplIndexIn = 0; + if(_amplDelayIndexIn >= MAX_DELAY_LINE_AMPL) + _amplDelayIndexIn = 0; } diff --git a/sflphone-common/src/audio/echocancel.h b/sflphone-common/src/audio/echocancel.h index 8312ac5afbee1aae5efc15304ddecd272a0f9d96..c559e6a6f6095bb9f7393af8be64109a3c4c91c3 100644 --- a/sflphone-common/src/audio/echocancel.h +++ b/sflphone-common/src/audio/echocancel.h @@ -41,7 +41,7 @@ #define DELAY_AMPLIFY 60 // maximum in segment size (segment are SEGMENT_LENGTH long) -#define MAX_DELAY 10 +#define MAX_DELAY_LINE_AMPL 100 // Internal buffer size #define BUFF_SIZE 10000 @@ -50,6 +50,9 @@ #define DEFAULT_FRAME_LENGTH 20 +#define MIC_ADAPT_SIZE 100 +#define SPKR_ADAPT_SIZE 50 + class EchoCancel : public Algorithm { public: @@ -228,13 +231,44 @@ class EchoCancel : public Algorithm { /** * Linear gain factor buffer to adjust to system's latency */ - float _delayedAmplify[MAX_DELAY]; + float _delayLineAmplify[MAX_DELAY_LINE_AMPL]; /** * read/write for mic gain delay */ - int _amplIndexIn; - int _amplIndexOut; + int _amplDelayIndexIn; + int _amplDelayIndexOut; + + /** + * State variable to determine if adaptation must be performed + */ + bool _adaptDone; + + /** + * State variable to specify if adaptation is started + */ + bool _adaptStarted; + + /** + * Adaptation index + */ + int _adaptCnt; + + int _spkrAdaptCnt; + + int _micAdaptCnt; + + int _spkrAdaptSize; + + int _micAdaptSize; + + int _spkrAdaptArray[BUFF_SIZE]; + + int _micAdaptArray[BUFF_SIZE]; + + int _correlationSize; + + int _correlationArray[BUFF_SIZE]; /* ofstream *micFile;