OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
43 namespace webrtc { | 43 namespace webrtc { |
44 | 44 |
45 // Buffer size (samples) | 45 // Buffer size (samples) |
46 static const size_t kBufSizePartitions = 250; // 1 second of audio in 16 kHz. | 46 static const size_t kBufSizePartitions = 250; // 1 second of audio in 16 kHz. |
47 | 47 |
48 // Metrics | 48 // Metrics |
49 static const size_t kSubCountLen = 4; | 49 static const size_t kSubCountLen = 4; |
50 static const size_t kCountLen = 50; | 50 static const size_t kCountLen = 50; |
51 static const int kDelayMetricsAggregationWindow = 1250; // 5 seconds at 16 kHz. | 51 static const int kDelayMetricsAggregationWindow = 1250; // 5 seconds at 16 kHz. |
52 | 52 |
53 // Divergence metric is based on audio level, which gets updated every | |
54 // |kCountLen + 1| * 10 milliseconds. Divergence metric takes the statistics of | |
55 // |kDivergeMetricAggregationWindow| samples. Current value corresponds to 0.5 | |
56 // seconds at 16 kHz. | |
57 static const int kDivergeMetricAggregationWindow = 25; | |
peah-webrtc
2016/04/06 11:01:10
This should probably be called kDivergeMetricAggre
minyue-webrtc
2016/04/06 13:35:37
Done.
| |
58 | |
53 // Quantities to control H band scaling for SWB input | 59 // Quantities to control H band scaling for SWB input |
54 static const float cnScaleHband = 0.4f; // scale for comfort noise in H band. | 60 static const float cnScaleHband = 0.4f; // scale for comfort noise in H band. |
55 // Initial bin for averaging nlp gain in low band | 61 // Initial bin for averaging nlp gain in low band |
56 static const int freqAvgIc = PART_LEN / 2; | 62 static const int freqAvgIc = PART_LEN / 2; |
57 | 63 |
58 // Matlab code to produce table: | 64 // Matlab code to produce table: |
59 // win = sqrt(hanning(63)); win = [0 ; win(1:32)]; | 65 // win = sqrt(hanning(63)); win = [0 ; win(1:32)]; |
60 // fprintf(1, '\t%.14f, %.14f, %.14f,\n', win); | 66 // fprintf(1, '\t%.14f, %.14f, %.14f,\n', win); |
61 ALIGN16_BEG const float ALIGN16_END WebRtcAec_sqrtHanning[65] = { | 67 ALIGN16_BEG const float ALIGN16_END WebRtcAec_sqrtHanning[65] = { |
62 0.00000000000000f, 0.02454122852291f, 0.04906767432742f, 0.07356456359967f, | 68 0.00000000000000f, 0.02454122852291f, 0.04906767432742f, 0.07356456359967f, |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
143 WebRtcAecWindowData WebRtcAec_WindowData; | 149 WebRtcAecWindowData WebRtcAec_WindowData; |
144 | 150 |
145 __inline static float MulRe(float aRe, float aIm, float bRe, float bIm) { | 151 __inline static float MulRe(float aRe, float aIm, float bRe, float bIm) { |
146 return aRe * bRe - aIm * bIm; | 152 return aRe * bRe - aIm * bIm; |
147 } | 153 } |
148 | 154 |
149 __inline static float MulIm(float aRe, float aIm, float bRe, float bIm) { | 155 __inline static float MulIm(float aRe, float aIm, float bRe, float bIm) { |
150 return aRe * bIm + aIm * bRe; | 156 return aRe * bIm + aIm * bRe; |
151 } | 157 } |
152 | 158 |
159 // TODO(minyue): Due to a legacy bug, |framelevel| and |averagelevel| use a | |
160 // window, of which the length is 1 unit longer than indicated. Remove "+1" when | |
161 // the code is refactored. | |
153 PowerLevel::PowerLevel() | 162 PowerLevel::PowerLevel() |
154 // TODO(minyue): Due to a legacy bug, |framelevel| and |averagelevel| use a | 163 : framelevel(kSubCountLen + 1), |
155 // window, of which the length is 1 unit longer than indicated. Remove "+1" | 164 averagelevel(kCountLen + 1) { |
156 // when the code is refactored. | |
157 : framelevel(kSubCountLen + 1), | |
158 averagelevel(kCountLen + 1) { | |
159 } | 165 } |
160 | 166 |
161 // TODO(minyue): Moving some initialization from WebRtcAec_CreateAec() to ctor. | 167 // TODO(minyue): Moving some initialization from WebRtcAec_CreateAec() to ctor. |
162 AecCore::AecCore() = default; | 168 AecCore::AecCore() |
169 : divergent_filter_fraction(kDivergeMetricAggregationWindow) { | |
170 } | |
163 | 171 |
164 static int CmpFloat(const void* a, const void* b) { | 172 static int CmpFloat(const void* a, const void* b) { |
165 const float* da = (const float*)a; | 173 const float* da = (const float*)a; |
166 const float* db = (const float*)b; | 174 const float* db = (const float*)b; |
167 | 175 |
168 return (*da > *db) - (*da < *db); | 176 return (*da > *db) - (*da < *db); |
169 } | 177 } |
170 | 178 |
171 static void FilterFar(int num_partitions, | 179 static void FilterFar(int num_partitions, |
172 int x_fft_buf_block_pos, | 180 int x_fft_buf_block_pos, |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
555 self->stateCounter = 0; | 563 self->stateCounter = 0; |
556 InitLevel(&self->farlevel); | 564 InitLevel(&self->farlevel); |
557 InitLevel(&self->nearlevel); | 565 InitLevel(&self->nearlevel); |
558 InitLevel(&self->linoutlevel); | 566 InitLevel(&self->linoutlevel); |
559 InitLevel(&self->nlpoutlevel); | 567 InitLevel(&self->nlpoutlevel); |
560 | 568 |
561 InitStats(&self->erl); | 569 InitStats(&self->erl); |
562 InitStats(&self->erle); | 570 InitStats(&self->erle); |
563 InitStats(&self->aNlp); | 571 InitStats(&self->aNlp); |
564 InitStats(&self->rerl); | 572 InitStats(&self->rerl); |
573 | |
574 self->divergent_filter_fraction.Reset(); | |
565 } | 575 } |
566 | 576 |
567 static float CalculatePower(const float* in, size_t num_samples) { | 577 static float CalculatePower(const float* in, size_t num_samples) { |
568 size_t k; | 578 size_t k; |
569 float energy = 0.0f; | 579 float energy = 0.0f; |
570 | 580 |
571 for (k = 0; k < num_samples; ++k) { | 581 for (k = 0; k < num_samples; ++k) { |
572 energy += in[k] * in[k]; | 582 energy += in[k] * in[k]; |
573 } | 583 } |
574 return energy / num_samples; | 584 return energy / num_samples; |
(...skipping 23 matching lines...) Expand all Loading... | |
598 | 608 |
599 const float noisyPower = 300000.0f; | 609 const float noisyPower = 300000.0f; |
600 | 610 |
601 float actThreshold; | 611 float actThreshold; |
602 float echo, suppressedEcho; | 612 float echo, suppressedEcho; |
603 | 613 |
604 if (aec->echoState) { // Check if echo is likely present | 614 if (aec->echoState) { // Check if echo is likely present |
605 aec->stateCounter++; | 615 aec->stateCounter++; |
606 } | 616 } |
607 | 617 |
618 if (aec->linoutlevel.framelevel.EndOfBlock()) { | |
619 const float near_level = aec->nearlevel.framelevel.GetLatestMean(); | |
620 const float level_increase = | |
621 aec->linoutlevel.framelevel.GetLatestMean() - near_level; | |
622 const bool output_signal_active = | |
623 aec->nlpoutlevel.framelevel.GetLatestMean() > | |
624 actThresholdClean * aec->nlpoutlevel.minlevel; | |
625 // Level increase should be, in principle, negative, when the filter | |
626 // does not diverge. Here we allow some margin (0.01 * near end level) and | |
627 // numerical error (1.0). We count divergence only when the AEC output | |
628 // signal is active. | |
629 aec->divergent_filter_fraction.AddObservation(output_signal_active && | |
630 level_increase > std::max(0.01 * near_level, 1.0)); | |
peah-webrtc
2016/04/06 11:01:10
If this would be a general and common task maybe a
minyue-webrtc
2016/04/06 13:35:37
Done.
| |
631 } | |
632 | |
608 if (aec->farlevel.averagelevel.EndOfBlock()) { | 633 if (aec->farlevel.averagelevel.EndOfBlock()) { |
609 if (aec->farlevel.minlevel < noisyPower) { | 634 if (aec->farlevel.minlevel < noisyPower) { |
610 actThreshold = actThresholdClean; | 635 actThreshold = actThresholdClean; |
611 } else { | 636 } else { |
612 actThreshold = actThresholdNoisy; | 637 actThreshold = actThresholdNoisy; |
613 } | 638 } |
614 | 639 |
615 const float far_average_level = aec->farlevel.averagelevel.GetLatestMean(); | 640 const float far_average_level = aec->farlevel.averagelevel.GetLatestMean(); |
616 | 641 |
617 // The last condition is to let estimation be made in active far-end | 642 // The last condition is to let estimation be made in active far-end |
(...skipping 1274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1892 | 1917 |
1893 int WebRtcAec_system_delay(AecCore* self) { | 1918 int WebRtcAec_system_delay(AecCore* self) { |
1894 return self->system_delay; | 1919 return self->system_delay; |
1895 } | 1920 } |
1896 | 1921 |
1897 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { | 1922 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { |
1898 assert(delay >= 0); | 1923 assert(delay >= 0); |
1899 self->system_delay = delay; | 1924 self->system_delay = delay; |
1900 } | 1925 } |
1901 } // namespace webrtc | 1926 } // namespace webrtc |
OLD | NEW |