| Index: webrtc/modules/audio_processing/aec/aec_core.cc
|
| diff --git a/webrtc/modules/audio_processing/aec/aec_core.cc b/webrtc/modules/audio_processing/aec/aec_core.cc
|
| index 4de7812a528c4b24edfbb07ec868e799d79a6b49..e23a79312b05beb9c7904c103c605a5d454b3e69 100644
|
| --- a/webrtc/modules/audio_processing/aec/aec_core.cc
|
| +++ b/webrtc/modules/audio_processing/aec/aec_core.cc
|
| @@ -46,8 +46,8 @@ namespace webrtc {
|
| static const size_t kBufSizePartitions = 250; // 1 second of audio in 16 kHz.
|
|
|
| // Metrics
|
| -static const int subCountLen = 4;
|
| -static const int countLen = 50;
|
| +static const size_t kSubCountLen = 4;
|
| +static const size_t kCountLen = 50;
|
| static const int kDelayMetricsAggregationWindow = 1250; // 5 seconds at 16 kHz.
|
|
|
| // Quantities to control H band scaling for SWB input
|
| @@ -150,6 +150,17 @@ __inline static float MulIm(float aRe, float aIm, float bRe, float bIm) {
|
| return aRe * bIm + aIm * bRe;
|
| }
|
|
|
| +PowerLevel::PowerLevel()
|
| +// TODO(minyue): Due to a legacy bug, |framelevel| and |averagelevel| use a
|
| +// window, of which the length is 1 unit longer than indicated. Remove "+1"
|
| +// when the code is refactored.
|
| +: framelevel(kSubCountLen + 1),
|
| + averagelevel(kCountLen + 1) {
|
| +}
|
| +
|
| +// TODO(minyue): Moving some initialization from WebRtcAec_CreateAec() to ctor.
|
| +AecCore::AecCore() = default;
|
| +
|
| static int CmpFloat(const void* a, const void* b) {
|
| const float* da = (const float*)a;
|
| const float* db = (const float*)b;
|
| @@ -523,14 +534,9 @@ static void ComfortNoise(AecCore* aec,
|
|
|
| static void InitLevel(PowerLevel* level) {
|
| const float kBigFloat = 1E17f;
|
| -
|
| - level->averagelevel = 0;
|
| - level->framelevel = 0;
|
| + level->averagelevel.Reset();
|
| + level->framelevel.Reset();
|
| level->minlevel = kBigFloat;
|
| - level->frsum = 0;
|
| - level->sfrsum = 0;
|
| - level->frcounter = 0;
|
| - level->sfrcounter = 0;
|
| }
|
|
|
| static void InitStats(Stats* stats) {
|
| @@ -569,27 +575,17 @@ static float CalculatePower(const float* in, size_t num_samples) {
|
| }
|
|
|
| static void UpdateLevel(PowerLevel* level, float power) {
|
| - level->sfrsum += power;
|
| - level->sfrcounter++;
|
| -
|
| - if (level->sfrcounter > subCountLen) {
|
| - level->framelevel = level->sfrsum / subCountLen;
|
| - level->sfrsum = 0;
|
| - level->sfrcounter = 0;
|
| - if (level->framelevel > 0) {
|
| - if (level->framelevel < level->minlevel) {
|
| - level->minlevel = level->framelevel; // New minimum.
|
| + level->framelevel.AddValue(power);
|
| + if (level->framelevel.EndOfBlock()) {
|
| + const float new_frame_level = level->framelevel.GetLatestMean();
|
| + if (new_frame_level > 0) {
|
| + if (new_frame_level < level->minlevel) {
|
| + level->minlevel = new_frame_level; // New minimum.
|
| } else {
|
| level->minlevel *= (1 + 0.001f); // Small increase.
|
| }
|
| }
|
| - level->frcounter++;
|
| - level->frsum += level->framelevel;
|
| - if (level->frcounter > countLen) {
|
| - level->averagelevel = level->frsum / countLen;
|
| - level->frsum = 0;
|
| - level->frcounter = 0;
|
| - }
|
| + level->averagelevel.AddValue(new_frame_level);
|
| }
|
| }
|
|
|
| @@ -609,29 +605,31 @@ static void UpdateMetrics(AecCore* aec) {
|
| aec->stateCounter++;
|
| }
|
|
|
| - if (aec->farlevel.frcounter == 0) {
|
| + if (aec->farlevel.averagelevel.EndOfBlock()) {
|
| if (aec->farlevel.minlevel < noisyPower) {
|
| actThreshold = actThresholdClean;
|
| } else {
|
| actThreshold = actThresholdNoisy;
|
| }
|
|
|
| - if ((aec->stateCounter > (0.5f * countLen * subCountLen)) &&
|
| - (aec->farlevel.sfrcounter == 0)
|
| + const float far_average_level = aec->farlevel.averagelevel.GetLatestMean();
|
| +
|
| + // The last condition is to let estimation be made in active far-end
|
| + // segments only.
|
| + if ((aec->stateCounter > (0.5f * kCountLen * kSubCountLen)) &&
|
| + (aec->farlevel.framelevel.EndOfBlock()) &&
|
| + (far_average_level > (actThreshold * aec->farlevel.minlevel))) {
|
| +
|
| + const float near_average_level =
|
| + aec->nearlevel.averagelevel.GetLatestMean();
|
|
|
| - // Estimate in active far-end segments only
|
| - && (aec->farlevel.averagelevel >
|
| - (actThreshold * aec->farlevel.minlevel))) {
|
| // Subtract noise power
|
| - echo = aec->nearlevel.averagelevel - safety * aec->nearlevel.minlevel;
|
| + echo = near_average_level - safety * aec->nearlevel.minlevel;
|
|
|
| // ERL
|
| - dtmp = 10 * static_cast<float>(log10(aec->farlevel.averagelevel /
|
| - aec->nearlevel.averagelevel +
|
| - 1e-10f));
|
| - dtmp2 = 10 * static_cast<float>(log10(aec->farlevel.averagelevel /
|
| - echo +
|
| - 1e-10f));
|
| + dtmp = 10 * static_cast<float>(log10(far_average_level /
|
| + near_average_level + 1e-10f));
|
| + dtmp2 = 10 * static_cast<float>(log10(far_average_level / echo + 1e-10f));
|
|
|
| aec->erl.instant = dtmp;
|
| if (dtmp > aec->erl.max) {
|
| @@ -654,13 +652,14 @@ static void UpdateMetrics(AecCore* aec) {
|
| }
|
|
|
| // A_NLP
|
| - dtmp = 10 * static_cast<float>(log10(aec->nearlevel.averagelevel /
|
| - aec->linoutlevel.averagelevel +
|
| - 1e-10f));
|
| + const float linout_average_level =
|
| + aec->linoutlevel.averagelevel.GetLatestMean();
|
| + dtmp = 10 * static_cast<float>(log10(near_average_level /
|
| + linout_average_level + 1e-10f));
|
|
|
| // subtract noise power
|
| - suppressedEcho = aec->linoutlevel.averagelevel -
|
| - safety * aec->linoutlevel.minlevel;
|
| + suppressedEcho =
|
| + linout_average_level - safety * aec->linoutlevel.minlevel;
|
|
|
| dtmp2 = 10 * static_cast<float>(log10(echo / suppressedEcho + 1e-10f));
|
|
|
| @@ -685,13 +684,14 @@ static void UpdateMetrics(AecCore* aec) {
|
| }
|
|
|
| // ERLE
|
| -
|
| + const float nlpout_average_level =
|
| + aec->nlpoutlevel.averagelevel.GetLatestMean();
|
| // subtract noise power
|
| - suppressedEcho = aec->nlpoutlevel.averagelevel -
|
| - safety * aec->nlpoutlevel.minlevel;
|
| + suppressedEcho =
|
| + nlpout_average_level - safety * aec->nlpoutlevel.minlevel;
|
|
|
| - dtmp = 10 * static_cast<float>(log10(aec->nearlevel.averagelevel /
|
| - aec->nlpoutlevel.averagelevel + 1e-10f));
|
| + dtmp = 10 * static_cast<float>(log10(near_average_level /
|
| + nlpout_average_level + 1e-10f));
|
| dtmp2 = 10 * static_cast<float>(log10(echo / suppressedEcho + 1e-10f));
|
|
|
| dtmp = dtmp2;
|
| @@ -1361,7 +1361,7 @@ static void ProcessBlock(AecCore* aec) {
|
|
|
| AecCore* WebRtcAec_CreateAec() {
|
| int i;
|
| - AecCore* aec = reinterpret_cast<AecCore*>(malloc(sizeof(AecCore)));
|
| + AecCore* aec = new AecCore;
|
| if (!aec) {
|
| return NULL;
|
| }
|
| @@ -1496,7 +1496,7 @@ void WebRtcAec_FreeAec(AecCore* aec) {
|
| WebRtc_FreeDelayEstimator(aec->delay_estimator);
|
| WebRtc_FreeDelayEstimatorFarend(aec->delay_estimator_farend);
|
|
|
| - free(aec);
|
| + delete aec;
|
| }
|
|
|
| int WebRtcAec_InitAec(AecCore* aec, int sampFreq) {
|
|
|