| 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 * Contains the API functions for the AEC. | 12 * Contains the API functions for the AEC. |
| 13 */ | 13 */ |
| 14 #include "webrtc/modules/audio_processing/aec/echo_cancellation.h" | 14 #include "webrtc/modules/audio_processing/aec/echo_cancellation.h" |
| 15 | 15 |
| 16 #include <math.h> | 16 #include <math.h> |
| 17 #ifdef WEBRTC_AEC_DEBUG_DUMP | 17 #if WEBRTC_AEC_DEBUG_DUMP == 1 |
| 18 #include <stdio.h> | 18 #include <stdio.h> |
| 19 #endif | 19 #endif |
| 20 #include <stdlib.h> | 20 #include <stdlib.h> |
| 21 #include <string.h> | 21 #include <string.h> |
| 22 | 22 |
| 23 extern "C" { | 23 extern "C" { |
| 24 #include "webrtc/common_audio/ring_buffer.h" | 24 #include "webrtc/common_audio/ring_buffer.h" |
| 25 #include "webrtc/common_audio/signal_processing/include/signal_processing_librar
y.h" | 25 #include "webrtc/common_audio/signal_processing/include/signal_processing_librar
y.h" |
| 26 } | 26 } |
| 27 #include "webrtc/modules/audio_processing/aec/aec_core.h" | 27 #include "webrtc/modules/audio_processing/aec/aec_core.h" |
| 28 #include "webrtc/modules/audio_processing/aec/aec_resampler.h" | 28 #include "webrtc/modules/audio_processing/aec/aec_resampler.h" |
| 29 #include "webrtc/modules/audio_processing/aec/echo_cancellation_internal.h" | 29 #include "webrtc/modules/audio_processing/aec/echo_cancellation_internal.h" |
| 30 #include "webrtc/typedefs.h" | 30 #include "webrtc/typedefs.h" |
| 31 | 31 |
| 32 // Check to verify that the define is properly set. |
| 33 #if !defined(WEBRTC_AEC_DEBUG_DUMP) || \ |
| 34 (WEBRTC_AEC_DEBUG_DUMP != 0 && WEBRTC_AEC_DEBUG_DUMP != 1) |
| 35 #error "Set WEBRTC_AEC_DEBUG_DUMP to either 0 or 1" |
| 36 #endif |
| 37 |
| 32 namespace webrtc { | 38 namespace webrtc { |
| 33 | 39 |
| 34 // Measured delays [ms] | 40 // Measured delays [ms] |
| 35 // Device Chrome GTP | 41 // Device Chrome GTP |
| 36 // MacBook Air 10 | 42 // MacBook Air 10 |
| 37 // MacBook Retina 10 100 | 43 // MacBook Retina 10 100 |
| 38 // MacPro 30? | 44 // MacPro 30? |
| 39 // | 45 // |
| 40 // Win7 Desktop 70 80? | 46 // Win7 Desktop 70 80? |
| 41 // Win7 T430s 110 | 47 // Win7 T430s 110 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 // Maximum length of resampled signal. Must be an integer multiple of frames | 98 // Maximum length of resampled signal. Must be an integer multiple of frames |
| 93 // (ceil(1/(1 + MIN_SKEW)*2) + 1)*FRAME_LEN | 99 // (ceil(1/(1 + MIN_SKEW)*2) + 1)*FRAME_LEN |
| 94 // The factor of 2 handles wb, and the + 1 is as a safety margin | 100 // The factor of 2 handles wb, and the + 1 is as a safety margin |
| 95 // TODO(bjornv): Replace with kResamplerBufferSize | 101 // TODO(bjornv): Replace with kResamplerBufferSize |
| 96 #define MAX_RESAMP_LEN (5 * FRAME_LEN) | 102 #define MAX_RESAMP_LEN (5 * FRAME_LEN) |
| 97 | 103 |
| 98 static const int kMaxBufSizeStart = 62; // In partitions | 104 static const int kMaxBufSizeStart = 62; // In partitions |
| 99 static const int sampMsNb = 8; // samples per ms in nb | 105 static const int sampMsNb = 8; // samples per ms in nb |
| 100 static const int initCheck = 42; | 106 static const int initCheck = 42; |
| 101 | 107 |
| 102 #ifdef WEBRTC_AEC_DEBUG_DUMP | 108 int Aec::instance_count = 0; |
| 103 int webrtc_aec_instance_count = 0; | |
| 104 #endif | |
| 105 | 109 |
| 106 // Estimates delay to set the position of the far-end buffer read pointer | 110 // Estimates delay to set the position of the far-end buffer read pointer |
| 107 // (controlled by knownDelay) | 111 // (controlled by knownDelay) |
| 108 static void EstBufDelayNormal(Aec* aecInst); | 112 static void EstBufDelayNormal(Aec* aecInst); |
| 109 static void EstBufDelayExtended(Aec* aecInst); | 113 static void EstBufDelayExtended(Aec* aecInst); |
| 110 static int ProcessNormal(Aec* self, | 114 static int ProcessNormal(Aec* self, |
| 111 const float* const* near, | 115 const float* const* near, |
| 112 size_t num_bands, | 116 size_t num_bands, |
| 113 float* const* out, | 117 float* const* out, |
| 114 size_t num_samples, | 118 size_t num_samples, |
| 115 int16_t reported_delay_ms, | 119 int16_t reported_delay_ms, |
| 116 int32_t skew); | 120 int32_t skew); |
| 117 static void ProcessExtended(Aec* self, | 121 static void ProcessExtended(Aec* self, |
| 118 const float* const* near, | 122 const float* const* near, |
| 119 size_t num_bands, | 123 size_t num_bands, |
| 120 float* const* out, | 124 float* const* out, |
| 121 size_t num_samples, | 125 size_t num_samples, |
| 122 int16_t reported_delay_ms, | 126 int16_t reported_delay_ms, |
| 123 int32_t skew); | 127 int32_t skew); |
| 124 | 128 |
| 125 void* WebRtcAec_Create() { | 129 void* WebRtcAec_Create() { |
| 126 Aec* aecpc = reinterpret_cast<Aec*>(malloc(sizeof(Aec))); | 130 Aec* aecpc = reinterpret_cast<Aec*>(malloc(sizeof(Aec))); |
| 127 | 131 |
| 128 if (!aecpc) { | 132 if (!aecpc) { |
| 129 return NULL; | 133 return NULL; |
| 130 } | 134 } |
| 131 | 135 |
| 132 aecpc->aec = WebRtcAec_CreateAec(); | 136 aecpc->aec = WebRtcAec_CreateAec(aecpc->instance_count); |
| 133 if (!aecpc->aec) { | 137 if (!aecpc->aec) { |
| 134 WebRtcAec_Free(aecpc); | 138 WebRtcAec_Free(aecpc); |
| 135 return NULL; | 139 return NULL; |
| 136 } | 140 } |
| 137 aecpc->resampler = WebRtcAec_CreateResampler(); | 141 aecpc->resampler = WebRtcAec_CreateResampler(); |
| 138 if (!aecpc->resampler) { | 142 if (!aecpc->resampler) { |
| 139 WebRtcAec_Free(aecpc); | 143 WebRtcAec_Free(aecpc); |
| 140 return NULL; | 144 return NULL; |
| 141 } | 145 } |
| 142 // Create far-end pre-buffer. The buffer size has to be large enough for | 146 // Create far-end pre-buffer. The buffer size has to be large enough for |
| 143 // largest possible drift compensation (kResamplerBufferSize) + "almost" an | 147 // largest possible drift compensation (kResamplerBufferSize) + "almost" an |
| 144 // FFT buffer (PART_LEN2 - 1). | 148 // FFT buffer (PART_LEN2 - 1). |
| 145 aecpc->far_pre_buf = | 149 aecpc->far_pre_buf = |
| 146 WebRtc_CreateBuffer(PART_LEN2 + kResamplerBufferSize, sizeof(float)); | 150 WebRtc_CreateBuffer(PART_LEN2 + kResamplerBufferSize, sizeof(float)); |
| 147 if (!aecpc->far_pre_buf) { | 151 if (!aecpc->far_pre_buf) { |
| 148 WebRtcAec_Free(aecpc); | 152 WebRtcAec_Free(aecpc); |
| 149 return NULL; | 153 return NULL; |
| 150 } | 154 } |
| 151 | 155 |
| 152 aecpc->initFlag = 0; | 156 aecpc->initFlag = 0; |
| 153 | 157 |
| 154 #ifdef WEBRTC_AEC_DEBUG_DUMP | 158 #if WEBRTC_AEC_DEBUG_DUMP == 1 |
| 155 { | 159 char filename[64]; |
| 156 char filename[64]; | 160 snprintf(filename, sizeof(filename), "aec_buf%d.dat", aecpc->instance_count); |
| 157 snprintf(filename, sizeof(filename), "aec_buf%d.dat", | 161 aecpc->bufFile = fopen(filename, "wb"); |
| 158 webrtc_aec_instance_count); | 162 snprintf(filename, sizeof(filename), "aec_skew%d.dat", aecpc->instance_count); |
| 159 aecpc->bufFile = fopen(filename, "wb"); | 163 aecpc->skewFile = fopen(filename, "wb"); |
| 160 snprintf(filename, sizeof(filename), "aec_skew%d.dat", | 164 snprintf(filename, sizeof(filename), "aec_delay%d.dat", |
| 161 webrtc_aec_instance_count); | 165 aecpc->instance_count); |
| 162 aecpc->skewFile = fopen(filename, "wb"); | 166 aecpc->delayFile = fopen(filename, "wb"); |
| 163 snprintf(filename, sizeof(filename), "aec_delay%d.dat", | |
| 164 webrtc_aec_instance_count); | |
| 165 aecpc->delayFile = fopen(filename, "wb"); | |
| 166 webrtc_aec_instance_count++; | |
| 167 } | |
| 168 #endif | 167 #endif |
| 168 aecpc->instance_count++; |
| 169 | 169 |
| 170 return aecpc; | 170 return aecpc; |
| 171 } | 171 } |
| 172 | 172 |
| 173 void WebRtcAec_Free(void* aecInst) { | 173 void WebRtcAec_Free(void* aecInst) { |
| 174 Aec* aecpc = reinterpret_cast<Aec*>(aecInst); | 174 Aec* aecpc = reinterpret_cast<Aec*>(aecInst); |
| 175 | 175 |
| 176 if (aecpc == NULL) { | 176 if (aecpc == NULL) { |
| 177 return; | 177 return; |
| 178 } | 178 } |
| 179 | 179 |
| 180 WebRtc_FreeBuffer(aecpc->far_pre_buf); | 180 WebRtc_FreeBuffer(aecpc->far_pre_buf); |
| 181 | 181 |
| 182 #ifdef WEBRTC_AEC_DEBUG_DUMP | 182 #if WEBRTC_AEC_DEBUG_DUMP == 1 |
| 183 fclose(aecpc->bufFile); | 183 fclose(aecpc->bufFile); |
| 184 fclose(aecpc->skewFile); | 184 fclose(aecpc->skewFile); |
| 185 fclose(aecpc->delayFile); | 185 fclose(aecpc->delayFile); |
| 186 #endif | 186 #endif |
| 187 | 187 |
| 188 WebRtcAec_FreeAec(aecpc->aec); | 188 WebRtcAec_FreeAec(aecpc->aec); |
| 189 WebRtcAec_FreeResampler(aecpc->resampler); | 189 WebRtcAec_FreeResampler(aecpc->resampler); |
| 190 free(aecpc); | 190 free(aecpc); |
| 191 } | 191 } |
| 192 | 192 |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 | 369 |
| 370 // This returns the value of aec->extended_filter_enabled. | 370 // This returns the value of aec->extended_filter_enabled. |
| 371 if (WebRtcAec_extended_filter_enabled(aecpc->aec)) { | 371 if (WebRtcAec_extended_filter_enabled(aecpc->aec)) { |
| 372 ProcessExtended(aecpc, nearend, num_bands, out, nrOfSamples, msInSndCardBuf, | 372 ProcessExtended(aecpc, nearend, num_bands, out, nrOfSamples, msInSndCardBuf, |
| 373 skew); | 373 skew); |
| 374 } else { | 374 } else { |
| 375 retVal = ProcessNormal(aecpc, nearend, num_bands, out, nrOfSamples, | 375 retVal = ProcessNormal(aecpc, nearend, num_bands, out, nrOfSamples, |
| 376 msInSndCardBuf, skew); | 376 msInSndCardBuf, skew); |
| 377 } | 377 } |
| 378 | 378 |
| 379 #ifdef WEBRTC_AEC_DEBUG_DUMP | 379 #if WEBRTC_AEC_DEBUG_DUMP == 1 |
| 380 { | 380 { |
| 381 int16_t far_buf_size_ms = (int16_t)(WebRtcAec_system_delay(aecpc->aec) / | 381 int16_t far_buf_size_ms = (int16_t)(WebRtcAec_system_delay(aecpc->aec) / |
| 382 (sampMsNb * aecpc->rate_factor)); | 382 (sampMsNb * aecpc->rate_factor)); |
| 383 (void)fwrite(&far_buf_size_ms, 2, 1, aecpc->bufFile); | 383 (void)fwrite(&far_buf_size_ms, 2, 1, aecpc->bufFile); |
| 384 (void)fwrite(&aecpc->knownDelay, sizeof(aecpc->knownDelay), 1, | 384 (void)fwrite(&aecpc->knownDelay, sizeof(aecpc->knownDelay), 1, |
| 385 aecpc->delayFile); | 385 aecpc->delayFile); |
| 386 } | 386 } |
| 387 #endif | 387 #endif |
| 388 | 388 |
| 389 return retVal; | 389 return retVal; |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 596 } else { | 596 } else { |
| 597 aecpc->resample = kAecTrue; | 597 aecpc->resample = kAecTrue; |
| 598 } | 598 } |
| 599 | 599 |
| 600 if (aecpc->skew < minSkewEst) { | 600 if (aecpc->skew < minSkewEst) { |
| 601 aecpc->skew = minSkewEst; | 601 aecpc->skew = minSkewEst; |
| 602 } else if (aecpc->skew > maxSkewEst) { | 602 } else if (aecpc->skew > maxSkewEst) { |
| 603 aecpc->skew = maxSkewEst; | 603 aecpc->skew = maxSkewEst; |
| 604 } | 604 } |
| 605 | 605 |
| 606 #ifdef WEBRTC_AEC_DEBUG_DUMP | 606 #if WEBRTC_AEC_DEBUG_DUMP == 1 |
| 607 (void)fwrite(&aecpc->skew, sizeof(aecpc->skew), 1, aecpc->skewFile); | 607 (void)fwrite(&aecpc->skew, sizeof(aecpc->skew), 1, aecpc->skewFile); |
| 608 #endif | 608 #endif |
| 609 } | 609 } |
| 610 } | 610 } |
| 611 | 611 |
| 612 nBlocks10ms = nrOfSamples / (FRAME_LEN * aecpc->rate_factor); | 612 nBlocks10ms = nrOfSamples / (FRAME_LEN * aecpc->rate_factor); |
| 613 | 613 |
| 614 if (aecpc->startup_phase) { | 614 if (aecpc->startup_phase) { |
| 615 for (i = 0; i < num_bands; ++i) { | 615 for (i = 0; i < num_bands; ++i) { |
| 616 // Only needed if they don't already point to the same place. | 616 // Only needed if they don't already point to the same place. |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 878 } else { | 878 } else { |
| 879 self->timeForDelayChange = 0; | 879 self->timeForDelayChange = 0; |
| 880 } | 880 } |
| 881 self->lastDelayDiff = delay_difference; | 881 self->lastDelayDiff = delay_difference; |
| 882 | 882 |
| 883 if (self->timeForDelayChange > 25) { | 883 if (self->timeForDelayChange > 25) { |
| 884 self->knownDelay = WEBRTC_SPL_MAX((int)self->filtDelay - 256, 0); | 884 self->knownDelay = WEBRTC_SPL_MAX((int)self->filtDelay - 256, 0); |
| 885 } | 885 } |
| 886 } | 886 } |
| 887 } // namespace webrtc | 887 } // namespace webrtc |
| OLD | NEW |