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..e0d0baef3a732e158b6b73f8438b76c40c3a0c79 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.SamplesSinceLastUpdate() == 0) { |
+ 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.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.SamplesSinceLastUpdate() == 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.SamplesSinceLastUpdate() == 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 = |
peah-webrtc
2016/03/24 07:18:41
Please move this closer to where it is used.
minyue-webrtc
2016/03/24 09:13:57
Done.
|
+ aec->linoutlevel.averagelevel.GetLatestMean(); |
+ const float nlpout_average_level = |
peah-webrtc
2016/03/24 07:18:41
Please move this closer to where it is used.
minyue-webrtc
2016/03/24 09:13:57
Done.
|
+ 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; |
} |