Skip to content
Snippets Groups Projects
Commit 7ba369bb authored by Alexandre Savard's avatar Alexandre Savard
Browse files

#5915: Implement different slope for attack tme and release time for gain control

parent 65088111
No related branches found
No related tags found
No related merge requests found
...@@ -371,6 +371,7 @@ void AudioRtpRecordHandler::processDataDecode (unsigned char *spkrData, unsigned ...@@ -371,6 +371,7 @@ void AudioRtpRecordHandler::processDataDecode (unsigned char *spkrData, unsigned
_audioRtpRecord._spkrFadeInComplete = fadeIn (spkrDataDecoded, nbSample, &_audioRtpRecord._micAmplFactor); _audioRtpRecord._spkrFadeInComplete = fadeIn (spkrDataDecoded, nbSample, &_audioRtpRecord._micAmplFactor);
} }
// Normalize incomming signal
gainController.process(spkrDataDecoded, nbSample); gainController.process(spkrDataDecoded, nbSample);
// test if resampling is required // test if resampling is required
......
...@@ -6,14 +6,17 @@ ...@@ -6,14 +6,17 @@
#include "global.h" #include "global.h"
#include "gaincontrol.h" #include "gaincontrol.h"
#define SFL_GAIN_ATTACK_RELEASE_TIME 10 #define SFL_GAIN_ATTACK_TIME 10
#define SFL_GAIN_RELEASE_TIME 300
#define SFL_GAIN_LIMITER_RATIO 0.1 #define SFL_GAIN_LIMITER_RATIO 0.1
#define SFL_GAIN_LIMITER_THRESHOLD 0.6 #define SFL_GAIN_LIMITER_THRESHOLD 0.6
#define SFL_GAIN_LOGe10 2.30258509299404568402 #define SFL_GAIN_LOGe10 2.30258509299404568402
GainControl::GainControl(double sr, double target) : averager(sr, SFL_GAIN_ATTACK_RELEASE_TIME) #define DUMP_GAIN_CONTROL_SIGNAL
GainControl::GainControl(double sr, double target) : averager(sr, SFL_GAIN_ATTACK_TIME, SFL_GAIN_RELEASE_TIME)
, limiter(SFL_GAIN_LIMITER_RATIO, SFL_GAIN_LIMITER_THRESHOLD) , limiter(SFL_GAIN_LIMITER_RATIO, SFL_GAIN_LIMITER_THRESHOLD)
, targetGaindB(target) , targetGaindB(target)
, targetGainLinear(0.0) , targetGainLinear(0.0)
...@@ -48,7 +51,7 @@ void GainControl::process(SFLDataFormat *buf, int bufLength) ...@@ -48,7 +51,7 @@ void GainControl::process(SFLDataFormat *buf, int bufLength)
out = limiter.limit(in); out = limiter.limit(in);
#ifdef DUMP_GAIN_CONTROL_SIGNAL #ifdef DUMP_GAIN_CONTROL_SIGNAL
tmpRms.write(retinterpret_cast<char *>(&out), sizeof(double)); tmpOut.write(reinterpret_cast<char *>(&out), sizeof(double));
#endif #endif
buf[i] = (short)(out * (double)SHRT_MAX); buf[i] = (short)(out * (double)SHRT_MAX);
...@@ -62,17 +65,24 @@ double GainControl::RmsDetection::getRms(double in) ...@@ -62,17 +65,24 @@ double GainControl::RmsDetection::getRms(double in)
return in * in; return in * in;
} }
GainControl::DetectionAverage::DetectionAverage(double sr, double t) : GainControl::DetectionAverage::DetectionAverage(double sr, double ta, double tr) :
g(0.0), teta(t), samplingRate(sr), previous_y(0.0) g_a(0.0), teta_a(ta), g_r(0.0), teta_r(tr), samplingRate(sr), previous_y(0.0)
{ {
g = exp(-1.0 / (samplingRate * (teta / 1000.0))); g_a = exp(-1.0 / (samplingRate * (teta_a / 1000.0)));
g_r = exp(-1.0 / (samplingRate * (teta_r / 1000.0)));
std::cout << "GainControl: g: " << g << ", teta: " << teta << std::endl; std::cout << "GainControl: g_attack: " << g_a << ", teta_attack: " << teta_a
<< ", g_release: " << g_r << ", teta_release: " << teta_r << std::endl;
} }
double GainControl::DetectionAverage::getAverage(double in) double GainControl::DetectionAverage::getAverage(double in)
{ {
previous_y = ((1.0 - g) * in) + (g * previous_y); if(in > previous_y) {
previous_y = ((1.0 - g_a) * in) + (g_a * previous_y);
}
else {
previous_y = ((1.0 - g_r) * in) + (g_r * previous_y);
}
return previous_y; return previous_y;
} }
......
...@@ -51,8 +51,11 @@ private: ...@@ -51,8 +51,11 @@ private:
public: public:
/** /**
* Constructor for this class * Constructor for this class
* /param Sampling rate
* /param Attack ramping time
* /param Release ramping time
*/ */
DetectionAverage(double, double); DetectionAverage(double, double, double);
/** /**
* Process average * Process average
...@@ -61,14 +64,24 @@ private: ...@@ -61,14 +64,24 @@ private:
private: private:
/** /**
* Average factor * Average factor for attack
*/
double g_a;
/**
* Attack ramp time (in ms)
*/
double teta_a;
/**
* Average factor for release
*/ */
double g; double g_r;
/** /**
* Attack and release ramp time (in ms) * Release ramp time (in ms)
*/ */
double teta; double teta_r;
/** /**
* Samplig rate * Samplig rate
......
...@@ -55,11 +55,13 @@ SpeexEchoCancel::SpeexEchoCancel() ...@@ -55,11 +55,13 @@ SpeexEchoCancel::SpeexEchoCancel()
_micData->createReadPointer(); _micData->createReadPointer();
_spkrData->createReadPointer(); _spkrData->createReadPointer();
#ifdef DUMP_ECHOCANCEL_INTERNAL_DATA
micFile = new ofstream("test_mic_data.raw"); micFile = new ofstream("test_mic_data.raw");
spkrFile = new ofstream("test_spkr_data.raw"); spkrFile = new ofstream("test_spkr_data.raw");
micProcessFile = new ofstream("test_mic_data_process.raw", std::ofstream::out); micProcessFile = new ofstream("test_mic_data_process.raw", std::ofstream::out);
spkrProcessFile = new ofstream("test_spkr_data_process.raw", std::ofstream::out); spkrProcessFile = new ofstream("test_spkr_data_process.raw", std::ofstream::out);
echoFile = new ofstream("test_echo_data.raw"); echoFile = new ofstream("test_echo_data.raw");
#endif
_spkrStopped = true; _spkrStopped = true;
} }
...@@ -80,11 +82,13 @@ SpeexEchoCancel::~SpeexEchoCancel() ...@@ -80,11 +82,13 @@ SpeexEchoCancel::~SpeexEchoCancel()
delete _spkrData; delete _spkrData;
_spkrData = NULL; _spkrData = NULL;
#ifdef DUMP_ECHOCANCEL_INTERNAL_DATA
delete micFile; delete micFile;
delete spkrFile; delete spkrFile;
delete micProcessFile; delete micProcessFile;
delete spkrProcessFile; delete spkrProcessFile;
delete echoFile; delete echoFile;
#endif
} }
...@@ -101,7 +105,9 @@ void SpeexEchoCancel::putData (SFLDataFormat *inputData, int nbBytes) ...@@ -101,7 +105,9 @@ void SpeexEchoCancel::putData (SFLDataFormat *inputData, int nbBytes)
_spkrStopped = false; _spkrStopped = false;
} }
#ifdef DUMP_ECHOCANCEL_INTERNAL_DATA
spkrFile->write(reinterpret_cast<char *>(inputData), nbBytes); spkrFile->write(reinterpret_cast<char *>(inputData), nbBytes);
#endif
// Put data in speaker ring buffer // Put data in speaker ring buffer
_spkrData->Put (inputData, nbBytes); _spkrData->Put (inputData, nbBytes);
...@@ -131,7 +137,9 @@ int SpeexEchoCancel::process (SFLDataFormat *inputData, SFLDataFormat *outputDat ...@@ -131,7 +137,9 @@ int SpeexEchoCancel::process (SFLDataFormat *inputData, SFLDataFormat *outputDat
memset (_tmpMic, 0, 5000 * sizeof(SFLDataFormat)); memset (_tmpMic, 0, 5000 * sizeof(SFLDataFormat));
memset (_tmpOut, 0, 5000 * sizeof(SFLDataFormat)); memset (_tmpOut, 0, 5000 * sizeof(SFLDataFormat));
#ifdef DUMP_ECHOCANCEL_INTERNAL_DATA
micFile->write(reinterpret_cast<char *>(inputData), nbBytes); micFile->write(reinterpret_cast<char *>(inputData), nbBytes);
#endif
// Put mic data in ringbuffer // Put mic data in ringbuffer
_micData->Put (inputData, nbBytes); _micData->Put (inputData, nbBytes);
...@@ -153,8 +161,10 @@ int SpeexEchoCancel::process (SFLDataFormat *inputData, SFLDataFormat *outputDat ...@@ -153,8 +161,10 @@ int SpeexEchoCancel::process (SFLDataFormat *inputData, SFLDataFormat *outputDat
_spkrData->Get (_tmpSpkr, byteSize); _spkrData->Get (_tmpSpkr, byteSize);
_micData->Get (_tmpMic, byteSize); _micData->Get (_tmpMic, byteSize);
#ifdef DUMP_ECHOCANCEL_INTERNAL_DATA
micProcessFile->write(reinterpret_cast<char *>(_tmpMic), byteSize); micProcessFile->write(reinterpret_cast<char *>(_tmpMic), byteSize);
spkrProcessFile->write(reinterpret_cast<char *>(_tmpSpkr), byteSize); spkrProcessFile->write(reinterpret_cast<char *>(_tmpSpkr), byteSize);
#endif
int32_t tmp; int32_t tmp;
for(int i = 0; i < nbSamples; i++) { for(int i = 0; i < nbSamples; i++) {
...@@ -172,7 +182,9 @@ int SpeexEchoCancel::process (SFLDataFormat *inputData, SFLDataFormat *outputDat ...@@ -172,7 +182,9 @@ int SpeexEchoCancel::process (SFLDataFormat *inputData, SFLDataFormat *outputDat
speex_echo_cancellation (_echoState, _tmpMic, _tmpSpkr, _tmpOut); speex_echo_cancellation (_echoState, _tmpMic, _tmpSpkr, _tmpOut);
speex_preprocess_run(_preState, reinterpret_cast<short *>(_tmpOut)); speex_preprocess_run(_preState, reinterpret_cast<short *>(_tmpOut));
#ifdef DUMP_ECHOCANCEL_INTERNAL_DATA
echoFile->write(reinterpret_cast<char *>(_tmpOut), byteSize); echoFile->write(reinterpret_cast<char *>(_tmpOut), byteSize);
#endif
for(int i = 0; i < nbSamples; i++) { for(int i = 0; i < nbSamples; i++) {
_tmpOut[i] *= 3; _tmpOut[i] *= 3;
......
...@@ -85,11 +85,13 @@ class SpeexEchoCancel : public Algorithm ...@@ -85,11 +85,13 @@ class SpeexEchoCancel : public Algorithm
SFLDataFormat _tmpMic[5000]; SFLDataFormat _tmpMic[5000];
SFLDataFormat _tmpOut[5000]; SFLDataFormat _tmpOut[5000];
#ifdef DUMP_ECHOCANCEL_INTERNAL_DATA
ofstream *micFile; ofstream *micFile;
ofstream *spkrFile; ofstream *spkrFile;
ofstream *micProcessFile; ofstream *micProcessFile;
ofstream *spkrProcessFile; ofstream *spkrProcessFile;
ofstream *echoFile; ofstream *echoFile;
#endif
}; };
#endif #endif
...@@ -40,7 +40,9 @@ void GainControlTest::testGainProcessing() ...@@ -40,7 +40,9 @@ void GainControlTest::testGainProcessing()
int fileSize; int fileSize;
SFLDataFormat buf[SFL_GAIN_BUFFER_LENGTH]; SFLDataFormat buf[SFL_GAIN_BUFFER_LENGTH];
GainControl gcontrol(8000); // Sampling rate is 8000
// Target level is 0 dB
GainControl gcontrol(8000, 0.0);
/* /*
fstream inputFile("testgaininput.raw", fstream::in); fstream inputFile("testgaininput.raw", fstream::in);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment