/* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "modules/audio_processing/aecm/aecm_core.h" #include <stddef.h> #include <stdlib.h> #include <string.h> extern "C" { #include "common_audio/ring_buffer.h" #include "common_audio/signal_processing/include/real_fft.h" } #include "common_audio/signal_processing/include/signal_processing_library.h" #include "modules/audio_processing/aecm/echo_control_mobile.h" #include "modules/audio_processing/utility/delay_estimator_wrapper.h" #include "rtc_base/checks.h" #include "rtc_base/numerics/safe_conversions.h" namespace webrtc { namespace { #ifdef AEC_DEBUG FILE* dfile; FILE* testfile; #endif // Initialization table for echo channel in 8 kHz static const int16_t kChannelStored8kHz[PART_LEN1] = …; // Initialization table for echo channel in 16 kHz static const int16_t kChannelStored16kHz[PART_LEN1] = …; } // namespace const int16_t WebRtcAecm_kCosTable[] = …; const int16_t WebRtcAecm_kSinTable[] = …; // Moves the pointer to the next entry and inserts `far_spectrum` and // corresponding Q-domain in its buffer. // // Inputs: // - self : Pointer to the delay estimation instance // - far_spectrum : Pointer to the far end spectrum // - far_q : Q-domain of far end spectrum // void WebRtcAecm_UpdateFarHistory(AecmCore* self, uint16_t* far_spectrum, int far_q) { … } // Returns a pointer to the far end spectrum aligned to current near end // spectrum. The function WebRtc_DelayEstimatorProcessFix(...) should have been // called before AlignedFarend(...). Otherwise, you get the pointer to the // previous frame. The memory is only valid until the next call of // WebRtc_DelayEstimatorProcessFix(...). // // Inputs: // - self : Pointer to the AECM instance. // - delay : Current delay estimate. // // Output: // - far_q : The Q-domain of the aligned far end spectrum // // Return value: // - far_spectrum : Pointer to the aligned far end spectrum // NULL - Error // const uint16_t* WebRtcAecm_AlignedFarend(AecmCore* self, int* far_q, int delay) { … } // Declare function pointers. CalcLinearEnergies WebRtcAecm_CalcLinearEnergies; StoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel; ResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel; AecmCore* WebRtcAecm_CreateCore() { … } void WebRtcAecm_InitEchoPathCore(AecmCore* aecm, const int16_t* echo_path) { … } static void CalcLinearEnergiesC(AecmCore* aecm, const uint16_t* far_spectrum, int32_t* echo_est, uint32_t* far_energy, uint32_t* echo_energy_adapt, uint32_t* echo_energy_stored) { … } static void StoreAdaptiveChannelC(AecmCore* aecm, const uint16_t* far_spectrum, int32_t* echo_est) { … } static void ResetAdaptiveChannelC(AecmCore* aecm) { … } // Initialize function pointers for ARM Neon platform. #if defined(WEBRTC_HAS_NEON) static void WebRtcAecm_InitNeon(void) { WebRtcAecm_StoreAdaptiveChannel = WebRtcAecm_StoreAdaptiveChannelNeon; WebRtcAecm_ResetAdaptiveChannel = WebRtcAecm_ResetAdaptiveChannelNeon; WebRtcAecm_CalcLinearEnergies = WebRtcAecm_CalcLinearEnergiesNeon; } #endif // Initialize function pointers for MIPS platform. #if defined(MIPS32_LE) static void WebRtcAecm_InitMips(void) { #if defined(MIPS_DSP_R1_LE) WebRtcAecm_StoreAdaptiveChannel = WebRtcAecm_StoreAdaptiveChannel_mips; WebRtcAecm_ResetAdaptiveChannel = WebRtcAecm_ResetAdaptiveChannel_mips; #endif WebRtcAecm_CalcLinearEnergies = WebRtcAecm_CalcLinearEnergies_mips; } #endif // WebRtcAecm_InitCore(...) // // This function initializes the AECM instant created with // WebRtcAecm_CreateCore(...) Input: // - aecm : Pointer to the Echo Suppression instance // - samplingFreq : Sampling Frequency // // Output: // - aecm : Initialized instance // // Return value : 0 - Ok // -1 - Error // int WebRtcAecm_InitCore(AecmCore* const aecm, int samplingFreq) { … } // TODO(bjornv): This function is currently not used. Add support for these // parameters from a higher level int WebRtcAecm_Control(AecmCore* aecm, int delay, int nlpFlag) { … } void WebRtcAecm_FreeCore(AecmCore* aecm) { … } int WebRtcAecm_ProcessFrame(AecmCore* aecm, const int16_t* farend, const int16_t* nearendNoisy, const int16_t* nearendClean, int16_t* out) { … } // WebRtcAecm_AsymFilt(...) // // Performs asymmetric filtering. // // Inputs: // - filtOld : Previous filtered value. // - inVal : New input value. // - stepSizePos : Step size when we have a positive contribution. // - stepSizeNeg : Step size when we have a negative contribution. // // Output: // // Return: - Filtered value. // int16_t WebRtcAecm_AsymFilt(const int16_t filtOld, const int16_t inVal, const int16_t stepSizePos, const int16_t stepSizeNeg) { … } // ExtractFractionPart(a, zeros) // // returns the fraction part of `a`, with `zeros` number of leading zeros, as an // int16_t scaled to Q8. There is no sanity check of `a` in the sense that the // number of zeros match. static int16_t ExtractFractionPart(uint32_t a, int zeros) { … } // Calculates and returns the log of `energy` in Q8. The input `energy` is // supposed to be in Q(`q_domain`). static int16_t LogOfEnergyInQ8(uint32_t energy, int q_domain) { … } // WebRtcAecm_CalcEnergies(...) // // This function calculates the log of energies for nearend, farend and // estimated echoes. There is also an update of energy decision levels, i.e. // internal VAD. // // // @param aecm [i/o] Handle of the AECM instance. // @param far_spectrum [in] Pointer to farend spectrum. // @param far_q [in] Q-domain of farend spectrum. // @param nearEner [in] Near end energy for current block in // Q(aecm->dfaQDomain). // @param echoEst [out] Estimated echo in Q(xfa_q+RESOLUTION_CHANNEL16). // void WebRtcAecm_CalcEnergies(AecmCore* aecm, const uint16_t* far_spectrum, const int16_t far_q, const uint32_t nearEner, int32_t* echoEst) { … } // WebRtcAecm_CalcStepSize(...) // // This function calculates the step size used in channel estimation // // // @param aecm [in] Handle of the AECM instance. // @param mu [out] (Return value) Stepsize in log2(), i.e. number of // shifts. // // int16_t WebRtcAecm_CalcStepSize(AecmCore* const aecm) { … } // WebRtcAecm_UpdateChannel(...) // // This function performs channel estimation. NLMS and decision on channel // storage. // // // @param aecm [i/o] Handle of the AECM instance. // @param far_spectrum [in] Absolute value of the farend signal in Q(far_q) // @param far_q [in] Q-domain of the farend signal // @param dfa [in] Absolute value of the nearend signal // (Q[aecm->dfaQDomain]) // @param mu [in] NLMS step size. // @param echoEst [i/o] Estimated echo in Q(far_q+RESOLUTION_CHANNEL16). // void WebRtcAecm_UpdateChannel(AecmCore* aecm, const uint16_t* far_spectrum, const int16_t far_q, const uint16_t* const dfa, const int16_t mu, int32_t* echoEst) { … } // CalcSuppressionGain(...) // // This function calculates the suppression gain that is used in the Wiener // filter. // // // @param aecm [i/n] Handle of the AECM instance. // @param supGain [out] (Return value) Suppression gain with which to scale // the noise // level (Q14). // // int16_t WebRtcAecm_CalcSuppressionGain(AecmCore* const aecm) { … } void WebRtcAecm_BufferFarFrame(AecmCore* const aecm, const int16_t* const farend, const int farLen) { … } void WebRtcAecm_FetchFarFrame(AecmCore* const aecm, int16_t* const farend, const int farLen, const int knownDelay) { … } } // namespace webrtc