diff --git a/sflphone-common/src/audio/echocancel.cpp b/sflphone-common/src/audio/echocancel.cpp index d957853560520930b15f8d7c1d147f933baba81f..ea5441bb47937a63e56b78b61033231dc1e1d0ec 100644 --- a/sflphone-common/src/audio/echocancel.cpp +++ b/sflphone-common/src/audio/echocancel.cpp @@ -32,12 +32,15 @@ // #include <fstream> +#define MICDELAY 32000 + EchoCancel::EchoCancel(int smplRate, int frameLength) : _samplingRate(smplRate), _frameLength(frameLength), _smplPerFrame(0), _smplPerSeg(0), _nbSegmentPerFrame(0), - _historyLength(0), + _micHistoryLength(0), + _spkrHistoryLength(0), _spkrLevel(0), _micLevel(0), _spkrHistCnt(0), @@ -62,11 +65,11 @@ EchoCancel::EchoCancel(int smplRate, int frameLength) : _samplingRate(smplRate), micFile = new ofstream("micData", ofstream::binary); echoFile = new ofstream("echoData", ofstream::binary); spkrFile = new ofstream("spkrData", ofstream::binary); + + micLevelData = new ofstream("micLevelData", ofstream::binary); + spkrLevelData = new ofstream("spkrLevelData", ofstream::binary); */ - micLearningData = new ofstream("micLearningData", ofstream::binary); - spkrLearningData = new ofstream("spkrLearningData", ofstream::binary); - _micData = new RingBuffer(50000); _spkrData = new RingBuffer(50000); _spkrDataOut = new RingBuffer(50000); @@ -80,7 +83,8 @@ EchoCancel::EchoCancel(int smplRate, int frameLength) : _samplingRate(smplRate), _smplPerFrame = (_samplingRate * _frameLength) / MS_PER_SEC; _smplPerSeg = (_samplingRate * SEGMENT_LENGTH) / MS_PER_SEC; - _historyLength = ECHO_LENGTH / SEGMENT_LENGTH; + _micHistoryLength = MIC_LENGTH / SEGMENT_LENGTH; + _spkrHistoryLength = SPKR_LENGTH / SEGMENT_LENGTH; _nbSegmentPerFrame = _frameLength / SEGMENT_LENGTH; @@ -130,12 +134,13 @@ EchoCancel::~EchoCancel() delete micFile; delete spkrFile; delete echoFile; + + micLevelData->close(); + spkrLevelData->close(); + delete micLevelData; + delete spkrLevelData; */ - micLearningData->close(); - spkrLearningData->close(); - delete micLearningData; - delete spkrLearningData; } @@ -156,7 +161,8 @@ void EchoCancel::reset() _smplPerFrame = (_samplingRate * _frameLength) / MS_PER_SEC; _smplPerSeg = (_samplingRate * SEGMENT_LENGTH) / MS_PER_SEC; - _historyLength = ECHO_LENGTH / SEGMENT_LENGTH; + _micHistoryLength = MIC_LENGTH / SEGMENT_LENGTH; + _spkrHistoryLength = SPKR_LENGTH / SEGMENT_LENGTH; _nbSegmentPerFrame = _frameLength / SEGMENT_LENGTH; memset(_delayLineAmplify, 0, MAX_DELAY_LINE_AMPL*sizeof(float)); @@ -174,10 +180,12 @@ void EchoCancel::reset() _spkrData->flushAll(); _spkrDataOut->flushAll(); - // SFLDataFormat delay[960]; - // memset(delay, 0, sizeof(SFLDataFormat)); + /* + SFLDataFormat delay[MICDELAY]; + memset(delay, 0, sizeof(SFLDataFormat)); - // _micData->Put(delay, 960*2); + _micData->Put(delay, MICDELAY*2); + */ speex_preprocess_state_destroy(_noiseState); @@ -202,19 +210,21 @@ void EchoCancel::putData(SFLDataFormat *inputData, int nbBytes) { // std::cout << "putData nbBytes: " << nbBytes << std::endl; - /* + if(_spkrStoped) { _debug("EchoCancel: Flush data"); _micData->flushAll(); _spkrData->flushAll(); _spkrStoped = false; } - */ // Put data in speaker ring buffer _spkrData->Put(inputData, nbBytes); _spkrDataOut->Put(inputData, nbBytes); + // _debug("********************** signal event *****************"); + // _event.signal(); + } int EchoCancel::getData(SFLDataFormat *outputData) @@ -235,11 +245,16 @@ void EchoCancel::process(SFLDataFormat *data, int nbBytes) {} int EchoCancel::process(SFLDataFormat *inputData, SFLDataFormat *outputData, int nbBytes) { - /* + if(_spkrStoped) { return 0; } - */ + + // _debug("****************************** wait signal ********************************"); + + // _event.wait(); + + // _debug("****************************** process ************************ ********"); int byteSize = _smplPerFrame*sizeof(SFLDataFormat); @@ -260,16 +275,32 @@ int EchoCancel::process(SFLDataFormat *inputData, SFLDataFormat *outputData, int // Init number of frame processed int nbFrame = 0; + // Get data from mic and speaker internal buffer - while((spkrAvail >= byteSize) && (micAvail >= byteSize)) { + // while((spkrAvail >= byteSize) && (micAvail >= byteSize)) { + if ((spkrAvail >= byteSize) && (micAvail >= byteSize)) { + + _debug("----------- ProcessData ----------"); // get synchronized data _spkrData->Get(_tmpSpkr, byteSize); _micData->Get(_tmpMic, byteSize); + // micFile->write((const char *)_tmpMic, byteSize); + // spkrFile->write((const char *)_tmpSpkr, byteSize); + + /* + while((computeAmplitudeLevel(_tmpSpkr, _smplPerFrame) < MIN_SIG_LEVEL) && (spkrAvail >= byteSize)) { + _spkrData->Get(_tmpSpkr, byteSize); + spkrAvail = _spkrData->AvailForGet(); + } + */ + // Processed echo cancellation performEchoCancel(_tmpMic, _tmpSpkr, _tmpOut); + // echoFile->write((const char *)_tmpOut, byteSize); + // Remove noise speex_preprocess_run(_noiseState, _tmpOut); @@ -287,6 +318,10 @@ int EchoCancel::process(SFLDataFormat *inputData, SFLDataFormat *outputData, int ++nbFrame; } + + + // _event.reset(); + return nbFrame * _smplPerFrame; } @@ -306,13 +341,23 @@ void EchoCancel::setSamplingRate(int smplRate) { void EchoCancel::performEchoCancel(SFLDataFormat *micData, SFLDataFormat *spkrData, SFLDataFormat *outputData) { - for(int k = 0; k < _nbSegmentPerFrame; k++) { + // int tempmiclevel[_nbSegmentPerFrame]; + // int tempspkrlevel[_nbSegmentPerFrame]; + for(int k = 0; k < _nbSegmentPerFrame; k++) { + /* updateEchoCancel(micData+(k*_smplPerSeg), spkrData+(k*_smplPerSeg)); - _spkrLevel = getMaxAmplitude(_avgSpkrLevelHist); - _micLevel = getMaxAmplitude(_avgMicLevelHist); + _spkrLevel = getMaxAmplitude(_avgSpkrLevelHist, _spkrHistoryLength); + _micLevel = getMaxAmplitude(_avgMicLevelHist, _micHistoryLength); + + // _debug("_spkrLevel: (max): %d", _spkrLevel); + // _debug("_micLevel: (min): %d", _micLevel); + tempspkrlevel[k] = _spkrLevel; + tempmiclevel[k] = _micLevel; + */ + /* if(_micLevel >= MIN_SIG_LEVEL) { if(_spkrLevel < MIN_SIG_LEVEL) { increaseFactor(0.02); @@ -323,46 +368,73 @@ void EchoCancel::performEchoCancel(SFLDataFormat *micData, SFLDataFormat *spkrDa else { // decreaseFactor(); _amplFactor = 0.0; + _debug("CANCELECHO AAAAAA"); } } else { if(_spkrLevel < MIN_SIG_LEVEL) { increaseFactor(0.02); + // _amplFactor = 0.0; + // _debug("CANCELECHO BBBBBBB"); } else { // decreaseFactor(); _amplFactor = 0.0; + _debug("CANCELECHO CCCCCCCC"); } } + */ + /* + if(_spkrLevel >= MIN_SIG_LEVEL) { + _amplFactor = 0.0; + // _debug("------------------------------------------ echocancel"); + } + else { + increaseFactor(0.02); + } // lowpass filtering float amplify = (_lastAmplFactor + _amplFactor) / 2; _lastAmplFactor = _amplFactor; - amplifySignal(micData+(k*_smplPerSeg), outputData+(k*_smplPerSeg), amplify); + + */ + amplifySignal(micData+(k*_smplPerSeg), outputData+(k*_smplPerSeg), 1.0); } + + // micLevelData->write((const char *)tempmiclevel, sizeof(int)*_nbSegmentPerFrame); + // spkrLevelData->write((const char *)tempspkrlevel, sizeof(int)*_nbSegmentPerFrame); } void EchoCancel::updateEchoCancel(SFLDataFormat *micData, SFLDataFormat *spkrData) { - int micLvl = computeAmplitudeLevel(micData); - int spkrLvl = computeAmplitudeLevel(spkrData); + int micLvl = computeAmplitudeLevel(micData, _smplPerSeg); + int spkrLvl = computeAmplitudeLevel(spkrData, _smplPerSeg); // Add 1 to make sure we are not dividing by 0 _avgMicLevelHist[_micHistCnt++] = micLvl+1; _avgSpkrLevelHist[_spkrHistCnt++] = spkrLvl+1; + + // spkrLevelData->write((const char *)_spkrAdaptArray, _spkrAdaptSize*sizeof(int)); + // micLevelData->write((const char *)_micAdaptArray, _micAdaptSize*sizeof(int)); - if(_micHistCnt >= _historyLength) + + // _debug("micLevel: %d", micLvl); + // _debug("spkrLevel: %d", spkrLvl); + + if(_micHistCnt >= _micHistoryLength) _micHistCnt = 0; - if(_spkrHistCnt >= _historyLength) + if(_spkrHistCnt >= _spkrHistoryLength) _spkrHistCnt = 0; + /* // if adaptation done, stop here - if(_adaptDone) + // if(_adaptDone) + if(true) return; // start learning only if there is data played through speaker @@ -383,7 +455,7 @@ void EchoCancel::updateEchoCancel(SFLDataFormat *micData, SFLDataFormat *spkrDat if(_adaptCnt > _spkrAdaptSize) { int k = _adaptCnt - _spkrAdaptSize; _correlationArray[k] = performCorrelation(_spkrAdaptArray, _micAdaptArray+k, _correlationSize); - _debug("EchoCancel: Correlation: %d", _correlationArray[k]); + // _debug("EchoCancel: Correlation: %d", _correlationArray[k]); } _adaptCnt++; @@ -394,18 +466,16 @@ void EchoCancel::updateEchoCancel(SFLDataFormat *micData, SFLDataFormat *spkrDat _adaptDone = true; _amplDelayIndexOut = 0;// getMaximumIndex(_correlationArray, _correlationSize); _debug("EchoCancel: Echo length %d", _amplDelayIndexOut); - spkrLearningData->write((const char *)_spkrAdaptArray, _spkrAdaptSize*sizeof(int)); - micLearningData->write((const char *)_micAdaptArray, _micAdaptSize*sizeof(int)); } - + */ } -int EchoCancel::computeAmplitudeLevel(SFLDataFormat *data) { +int EchoCancel::computeAmplitudeLevel(SFLDataFormat *data, int size) { int level = 0; - for(int i = 0; i < _smplPerSeg; i++) { + for(int i = 0; i < size; i++) { if(data[i] >= 0.0) level += (int)data[i]; else @@ -418,11 +488,11 @@ int EchoCancel::computeAmplitudeLevel(SFLDataFormat *data) { } -int EchoCancel::getMaxAmplitude(int *data) { +int EchoCancel::getMaxAmplitude(int *data, int size) { SFLDataFormat level = 0.0; - for(int i = 0; i < _historyLength; i++) { + for(int i = 0; i < size; i++) { if(data[i] >= level) level = data[i]; } @@ -433,17 +503,19 @@ int EchoCancel::getMaxAmplitude(int *data) { void EchoCancel::amplifySignal(SFLDataFormat *micData, SFLDataFormat *outputData, float amplify) { + for(int i = 0; i < _smplPerSeg; i++) + outputData[i] = micData[i]; // Use delayed amplification factor due to sound card latency - for(int i = 0; i < _smplPerSeg; i++) { - outputData[i] = (SFLDataFormat)(((float)micData[i])*_delayLineAmplify[_amplDelayIndexOut]); - } - // do not increment amplitude array if adaptation is not done - if (_adaptDone) { + // if (_adaptDone) { + /* + if (true) { for(int i = 0; i < _smplPerSeg; i++) { outputData[i] = (SFLDataFormat)(((float)micData[i])*_delayLineAmplify[_amplDelayIndexOut]); } + _amplDelayIndexOut++; + _delayLineAmplify[_amplDelayIndexIn++] = amplify; } else { for(int i = 0; i < _smplPerSeg; i++) { @@ -452,15 +524,12 @@ void EchoCancel::amplifySignal(SFLDataFormat *micData, SFLDataFormat *outputData return; } - - _amplDelayIndexOut++; - _delayLineAmplify[_amplDelayIndexIn++] = amplify; - if(_amplDelayIndexOut >= MAX_DELAY_LINE_AMPL) _amplDelayIndexOut = 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 e397f49e22c14cbc0dc19b565d88a9314b30ce12..abf5ba8d222cb5f3e0ba0a1845fe012c9862241a 100644 --- a/sflphone-common/src/audio/echocancel.h +++ b/sflphone-common/src/audio/echocancel.h @@ -31,9 +31,10 @@ #ifndef ECHOCANCEL_H #define ECHOCANCEL_H -#include "audioprocessing.h" +#include <cc++/thread.h> #include <speex/speex_preprocess.h> +#include "audioprocessing.h" #include "ringbuffer.h" // Number of ms in sec @@ -44,9 +45,11 @@ // Length of the echo tail in ms #define ECHO_LENGTH 50 +#define SPKR_LENGTH 50 +#define MIC_LENGTH 50 // Voice level threashold -#define MIN_SIG_LEVEL 1000 +#define MIN_SIG_LEVEL 75 // Delay between mic and speaker #define DELAY_AMPLIFY 60 @@ -129,12 +132,12 @@ class EchoCancel : public Algorithm { * Compute the average amplitude of the signal. * \param data must be of SEGMENT_LENGTH long. */ - int computeAmplitudeLevel(SFLDataFormat *data); + int computeAmplitudeLevel(SFLDataFormat *data, int size); /** * Return the max amplitude provided any of _avgSpkrLevelHist or _avgMicLevelHist */ - int getMaxAmplitude(int *data); + int getMaxAmplitude(int *data, int size); /** * Apply gain factor on input buffer and copy result in output buffer. @@ -211,7 +214,9 @@ class EchoCancel : public Algorithm { * Number of segment considered in history * Mainly used to compute signal level */ - int _historyLength; + int _micHistoryLength; + + int _spkrHistoryLength; /** * Current playback level @@ -294,20 +299,20 @@ class EchoCancel : public Algorithm { int _processedByte; - /* ofstream *micFile; ofstream *spkrFile; ofstream *echoFile; - */ - ofstream *micLearningData; - ofstream *spkrLearningData; + ofstream *micLevelData; + ofstream *spkrLevelData; /** * Noise reduction processing state */ SpeexPreprocessState *_noiseState; + ost::Event _event; + }; #endif diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp index 16cf22bb1ded8750ea134b198068b29a85aad69e..1c76ef3a40753b280af0c1bfac139ef0ed4ec5b1 100644 --- a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp +++ b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp @@ -951,7 +951,6 @@ void PulseLayer::readFromMic (void) // echo cancellation processing int sampleready = _echoCanceller->processAudio(rsmpl_out, echoCancelledMic, nbSample*sizeof(SFLDataFormat)); - _debug("sampleready: %d", sampleready); // getMainBuffer()->putData ( (void*) rsmpl_out, nbSample*sizeof (SFLDataFormat), 100); if(sampleready) getMainBuffer()->putData ( echoCancelledMic, sampleready*sizeof (SFLDataFormat), 100);