| 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 | 
| 11 /* | 11 /* | 
| 12  * The core AEC algorithm, which is presented with time-aligned signals. | 12  * The core AEC algorithm, which is presented with time-aligned signals. | 
| 13  */ | 13  */ | 
| 14 | 14 | 
| 15 #include "webrtc/modules/audio_processing/aec/aec_core.h" | 15 #include "webrtc/modules/audio_processing/aec/aec_core.h" | 
| 16 | 16 | 
| 17 #ifdef WEBRTC_AEC_DEBUG_DUMP | 17 #ifdef WEBRTC_AEC_DEBUG_DUMP | 
| 18 #include <stdio.h> | 18 #include <stdio.h> | 
| 19 #endif | 19 #endif | 
| 20 | 20 | 
|  | 21 #include <algorithm> | 
| 21 #include <assert.h> | 22 #include <assert.h> | 
| 22 #include <math.h> | 23 #include <math.h> | 
| 23 #include <stddef.h>  // size_t | 24 #include <stddef.h>  // size_t | 
| 24 #include <stdlib.h> | 25 #include <stdlib.h> | 
| 25 #include <string.h> | 26 #include <string.h> | 
| 26 | 27 | 
| 27 extern "C" { | 28 extern "C" { | 
| 28 #include "webrtc/common_audio/ring_buffer.h" | 29 #include "webrtc/common_audio/ring_buffer.h" | 
| 29 } | 30 } | 
| 30 #include "webrtc/common_audio/signal_processing/include/signal_processing_librar
      y.h" | 31 #include "webrtc/common_audio/signal_processing/include/signal_processing_librar
      y.h" | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
| 43 namespace webrtc { | 44 namespace webrtc { | 
| 44 | 45 | 
| 45 // Buffer size (samples) | 46 // Buffer size (samples) | 
| 46 static const size_t kBufSizePartitions = 250;  // 1 second of audio in 16 kHz. | 47 static const size_t kBufSizePartitions = 250;  // 1 second of audio in 16 kHz. | 
| 47 | 48 | 
| 48 // Metrics | 49 // Metrics | 
| 49 static const size_t kSubCountLen = 4; | 50 static const size_t kSubCountLen = 4; | 
| 50 static const size_t kCountLen = 50; | 51 static const size_t kCountLen = 50; | 
| 51 static const int kDelayMetricsAggregationWindow = 1250;  // 5 seconds at 16 kHz. | 52 static const int kDelayMetricsAggregationWindow = 1250;  // 5 seconds at 16 kHz. | 
| 52 | 53 | 
|  | 54 // Divergence metric is based on audio level, which gets updated every | 
|  | 55 // |kCountLen + 1| * 10 milliseconds. Divergence metric takes the statistics of | 
|  | 56 // |kDivergentFilterFractionAggregationWindowSize| samples. Current value | 
|  | 57 // corresponds to 0.5 seconds at 16 kHz. | 
|  | 58 static const int kDivergentFilterFractionAggregationWindowSize = 25; | 
|  | 59 | 
| 53 // Quantities to control H band scaling for SWB input | 60 // Quantities to control H band scaling for SWB input | 
| 54 static const float cnScaleHband = 0.4f;  // scale for comfort noise in H band. | 61 static const float cnScaleHband = 0.4f;  // scale for comfort noise in H band. | 
| 55 // Initial bin for averaging nlp gain in low band | 62 // Initial bin for averaging nlp gain in low band | 
| 56 static const int freqAvgIc = PART_LEN / 2; | 63 static const int freqAvgIc = PART_LEN / 2; | 
| 57 | 64 | 
| 58 // Matlab code to produce table: | 65 // Matlab code to produce table: | 
| 59 // win = sqrt(hanning(63)); win = [0 ; win(1:32)]; | 66 // win = sqrt(hanning(63)); win = [0 ; win(1:32)]; | 
| 60 // fprintf(1, '\t%.14f, %.14f, %.14f,\n', win); | 67 // fprintf(1, '\t%.14f, %.14f, %.14f,\n', win); | 
| 61 ALIGN16_BEG const float ALIGN16_END WebRtcAec_sqrtHanning[65] = { | 68 ALIGN16_BEG const float ALIGN16_END WebRtcAec_sqrtHanning[65] = { | 
| 62     0.00000000000000f, 0.02454122852291f, 0.04906767432742f, 0.07356456359967f, | 69     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; | 150 WebRtcAecWindowData WebRtcAec_WindowData; | 
| 144 | 151 | 
| 145 __inline static float MulRe(float aRe, float aIm, float bRe, float bIm) { | 152 __inline static float MulRe(float aRe, float aIm, float bRe, float bIm) { | 
| 146   return aRe * bRe - aIm * bIm; | 153   return aRe * bRe - aIm * bIm; | 
| 147 } | 154 } | 
| 148 | 155 | 
| 149 __inline static float MulIm(float aRe, float aIm, float bRe, float bIm) { | 156 __inline static float MulIm(float aRe, float aIm, float bRe, float bIm) { | 
| 150   return aRe * bIm + aIm * bRe; | 157   return aRe * bIm + aIm * bRe; | 
| 151 } | 158 } | 
| 152 | 159 | 
|  | 160 // TODO(minyue): Due to a legacy bug, |framelevel| and |averagelevel| use a | 
|  | 161 // window, of which the length is 1 unit longer than indicated. Remove "+1" when | 
|  | 162 // the code is refactored. | 
| 153 PowerLevel::PowerLevel() | 163 PowerLevel::PowerLevel() | 
| 154 // TODO(minyue): Due to a legacy bug, |framelevel| and |averagelevel| use a | 164     : framelevel(kSubCountLen + 1), | 
| 155 // window, of which the length is 1 unit longer than indicated. Remove "+1" | 165       averagelevel(kCountLen + 1) { | 
| 156 // when the code is refactored. | 166 } | 
| 157 : framelevel(kSubCountLen + 1), | 167 | 
| 158   averagelevel(kCountLen + 1) { | 168 DivergentFilterFraction::DivergentFilterFraction() | 
|  | 169     : count_(0), | 
|  | 170       occurrence_(0), | 
|  | 171       fraction_(-1.0) { | 
|  | 172 } | 
|  | 173 | 
|  | 174 void DivergentFilterFraction::Reset() { | 
|  | 175   Clear(); | 
|  | 176   fraction_ = -1.0; | 
|  | 177 } | 
|  | 178 | 
|  | 179 void DivergentFilterFraction::AddObservation(const PowerLevel& nearlevel, | 
|  | 180                                              const PowerLevel& linoutlevel, | 
|  | 181                                              const PowerLevel& nlpoutlevel) { | 
|  | 182   const float near_level = nearlevel.framelevel.GetLatestMean(); | 
|  | 183   const float level_increase = | 
|  | 184       linoutlevel.framelevel.GetLatestMean() - near_level; | 
|  | 185   const bool output_signal_active = nlpoutlevel.framelevel.GetLatestMean() > | 
|  | 186           40.0 * nlpoutlevel.minlevel; | 
|  | 187   // Level increase should be, in principle, negative, when the filter | 
|  | 188   // does not diverge. Here we allow some margin (0.01 * near end level) and | 
|  | 189   // numerical error (1.0). We count divergence only when the AEC output | 
|  | 190   // signal is active. | 
|  | 191   if (output_signal_active && | 
|  | 192       level_increase > std::max(0.01 * near_level, 1.0)) | 
|  | 193     occurrence_++; | 
|  | 194   ++count_; | 
|  | 195   if (count_ == kDivergentFilterFractionAggregationWindowSize) { | 
|  | 196     fraction_ = static_cast<float>(occurrence_) / | 
|  | 197         kDivergentFilterFractionAggregationWindowSize; | 
|  | 198     Clear(); | 
|  | 199   } | 
|  | 200 } | 
|  | 201 | 
|  | 202 float DivergentFilterFraction::GetLatestFraction() const { | 
|  | 203   return fraction_; | 
|  | 204 } | 
|  | 205 | 
|  | 206 void DivergentFilterFraction::Clear() { | 
|  | 207   count_ = 0; | 
|  | 208   occurrence_ = 0; | 
| 159 } | 209 } | 
| 160 | 210 | 
| 161 // TODO(minyue): Moving some initialization from WebRtcAec_CreateAec() to ctor. | 211 // TODO(minyue): Moving some initialization from WebRtcAec_CreateAec() to ctor. | 
| 162 AecCore::AecCore() = default; | 212 AecCore::AecCore() = default; | 
| 163 | 213 | 
| 164 static int CmpFloat(const void* a, const void* b) { | 214 static int CmpFloat(const void* a, const void* b) { | 
| 165   const float* da = (const float*)a; | 215   const float* da = (const float*)a; | 
| 166   const float* db = (const float*)b; | 216   const float* db = (const float*)b; | 
| 167 | 217 | 
| 168   return (*da > *db) - (*da < *db); | 218   return (*da > *db) - (*da < *db); | 
| (...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 555   self->stateCounter = 0; | 605   self->stateCounter = 0; | 
| 556   InitLevel(&self->farlevel); | 606   InitLevel(&self->farlevel); | 
| 557   InitLevel(&self->nearlevel); | 607   InitLevel(&self->nearlevel); | 
| 558   InitLevel(&self->linoutlevel); | 608   InitLevel(&self->linoutlevel); | 
| 559   InitLevel(&self->nlpoutlevel); | 609   InitLevel(&self->nlpoutlevel); | 
| 560 | 610 | 
| 561   InitStats(&self->erl); | 611   InitStats(&self->erl); | 
| 562   InitStats(&self->erle); | 612   InitStats(&self->erle); | 
| 563   InitStats(&self->aNlp); | 613   InitStats(&self->aNlp); | 
| 564   InitStats(&self->rerl); | 614   InitStats(&self->rerl); | 
|  | 615 | 
|  | 616   self->divergent_filter_fraction.Reset(); | 
| 565 } | 617 } | 
| 566 | 618 | 
| 567 static float CalculatePower(const float* in, size_t num_samples) { | 619 static float CalculatePower(const float* in, size_t num_samples) { | 
| 568   size_t k; | 620   size_t k; | 
| 569   float energy = 0.0f; | 621   float energy = 0.0f; | 
| 570 | 622 | 
| 571   for (k = 0; k < num_samples; ++k) { | 623   for (k = 0; k < num_samples; ++k) { | 
| 572     energy += in[k] * in[k]; | 624     energy += in[k] * in[k]; | 
| 573   } | 625   } | 
| 574   return energy / num_samples; | 626   return energy / num_samples; | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
| 598 | 650 | 
| 599   const float noisyPower = 300000.0f; | 651   const float noisyPower = 300000.0f; | 
| 600 | 652 | 
| 601   float actThreshold; | 653   float actThreshold; | 
| 602   float echo, suppressedEcho; | 654   float echo, suppressedEcho; | 
| 603 | 655 | 
| 604   if (aec->echoState) {  // Check if echo is likely present | 656   if (aec->echoState) {  // Check if echo is likely present | 
| 605     aec->stateCounter++; | 657     aec->stateCounter++; | 
| 606   } | 658   } | 
| 607 | 659 | 
|  | 660   if (aec->linoutlevel.framelevel.EndOfBlock()) { | 
|  | 661     aec->divergent_filter_fraction.AddObservation(aec->nearlevel, | 
|  | 662                                                   aec->linoutlevel, | 
|  | 663                                                   aec->nlpoutlevel); | 
|  | 664   } | 
|  | 665 | 
| 608   if (aec->farlevel.averagelevel.EndOfBlock()) { | 666   if (aec->farlevel.averagelevel.EndOfBlock()) { | 
| 609     if (aec->farlevel.minlevel < noisyPower) { | 667     if (aec->farlevel.minlevel < noisyPower) { | 
| 610       actThreshold = actThresholdClean; | 668       actThreshold = actThresholdClean; | 
| 611     } else { | 669     } else { | 
| 612       actThreshold = actThresholdNoisy; | 670       actThreshold = actThresholdNoisy; | 
| 613     } | 671     } | 
| 614 | 672 | 
| 615     const float far_average_level = aec->farlevel.averagelevel.GetLatestMean(); | 673     const float far_average_level = aec->farlevel.averagelevel.GetLatestMean(); | 
| 616 | 674 | 
| 617     // The last condition is to let estimation be made in active far-end | 675     // 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 | 1950 | 
| 1893 int WebRtcAec_system_delay(AecCore* self) { | 1951 int WebRtcAec_system_delay(AecCore* self) { | 
| 1894   return self->system_delay; | 1952   return self->system_delay; | 
| 1895 } | 1953 } | 
| 1896 | 1954 | 
| 1897 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { | 1955 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { | 
| 1898   assert(delay >= 0); | 1956   assert(delay >= 0); | 
| 1899   self->system_delay = delay; | 1957   self->system_delay = delay; | 
| 1900 } | 1958 } | 
| 1901 }  // namespace webrtc | 1959 }  // namespace webrtc | 
| OLD | NEW | 
|---|