Chromium Code Reviews| 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 1b5f03fec4e7a255f25c681218bbb7470ebc0770..9f11fb8530442521ab2f735a9132933ddd9cc745 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) { |
| @@ -568,28 +574,18 @@ static float CalculatePower(const float* in, size_t num_samples) { |
| return energy / num_samples; |
| } |
| -static void UpdateLevel(PowerLevel* level, float energy) { |
| - level->sfrsum += energy; |
| - level->sfrcounter++; |
| - |
| - if (level->sfrcounter > subCountLen) { |
| - level->framelevel = level->sfrsum / (subCountLen * PART_LEN); |
| - level->sfrsum = 0; |
| - level->sfrcounter = 0; |
| - if (level->framelevel > 0) { |
| - if (level->framelevel < level->minlevel) { |
| - level->minlevel = level->framelevel; // New minimum. |
| +static void UpdateLevel(PowerLevel* level, float power) { |
| + level->framelevel.AddSample(power); |
| + if (level->framelevel.GetNumberNewSamples() == 0) { |
|
peah-webrtc
2016/03/18 09:18:34
I see what you want to achieve with the GetNumberN
minyue-webrtc
2016/03/21 15:27:51
I changed to a similar but slightly shorter name.
|
| + const float new_frame_level = level->framelevel.GetLatestMean(); |
| + if (new_frame_level > 0) { |
|
peah-webrtc
2016/03/18 09:18:34
Why is this if statement there? The result is that
minyue-webrtc
2016/03/21 15:27:51
Good question, this is the way it was. I guess it
|
| + 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.AddSample(new_frame_level); |
| } |
| } |
| @@ -600,11 +596,7 @@ static void UpdateMetrics(AecCore* aec) { |
| const float actThresholdClean = 40.0f; |
| const float safety = 0.99995f; |
| - // To make noisePower consistent with the legacy code, a factor of |
| - // 2.0f / PART_LEN2 is applied to noisyPower, since the legacy code uses |
| - // the energy of a frame as the audio levels, while the new code uses a |
| - // a per-sample energy (i.e., power). |
| - const float noisyPower = 300000.0f * 2.0f / PART_LEN2; |
| + const float noisyPower = 300000.0f; |
| float actThreshold; |
| float echo, suppressedEcho; |
| @@ -613,29 +605,34 @@ static void UpdateMetrics(AecCore* aec) { |
| aec->stateCounter++; |
| } |
| - if (aec->farlevel.frcounter == 0) { |
| + if (aec->farlevel.averagelevel.GetNumberNewSamples() == 0) { |
| + const float far_average_level = aec->farlevel.averagelevel.GetLatestMean(); |
| + |
| if (aec->farlevel.minlevel < noisyPower) { |
| actThreshold = actThresholdClean; |
| } else { |
| actThreshold = actThresholdNoisy; |
| } |
| - if ((aec->stateCounter > (0.5f * countLen * subCountLen)) && |
| - (aec->farlevel.sfrcounter == 0) |
| - |
| + if ((aec->stateCounter > (0.5f * kCountLen * kSubCountLen)) && |
| + (aec->farlevel.framelevel.GetNumberNewSamples() == 0) |
| // Estimate in active far-end segments only |
| - && (aec->farlevel.averagelevel > |
| - (actThreshold * aec->farlevel.minlevel))) { |
| + && (far_average_level > (actThreshold * aec->farlevel.minlevel))) { |
| + |
| + const float near_average_level = |
| + aec->nearlevel.averagelevel.GetLatestMean(); |
| + const float linout_average_level = |
| + aec->linoutlevel.averagelevel.GetLatestMean(); |
| + const float nlpout_average_level = |
| + aec->nlpoutlevel.averagelevel.GetLatestMean(); |
| + |
| // 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) { |
| @@ -658,13 +655,12 @@ static void UpdateMetrics(AecCore* aec) { |
| } |
| // A_NLP |
| - dtmp = 10 * static_cast<float>(log10(aec->nearlevel.averagelevel / |
| - aec->linoutlevel.averagelevel + |
| - 1e-10f)); |
| + 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)); |
| @@ -691,11 +687,11 @@ static void UpdateMetrics(AecCore* aec) { |
| // ERLE |
| // 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; |
| @@ -1365,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; |
| } |
| @@ -1429,6 +1425,7 @@ AecCore* WebRtcAec_CreateAec() { |
| WebRtcAec_FreeAec(aec); |
| return NULL; |
| } |
| + |
|
peah-webrtc
2016/03/18 09:18:34
Intended new line?
minyue-webrtc
2016/03/21 15:27:51
no, I guess it was due to mistake or formatter.
|
| #ifdef WEBRTC_ANDROID |
| aec->delay_agnostic_enabled = 1; // DA-AEC enabled by default. |
| // DA-AEC assumes the system is causal from the beginning and will self adjust |