/* * 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 "webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h" #include #include #include #include "webrtc/modules/audio_processing/utility/delay_estimator.h" #include "webrtc/modules/audio_processing/utility/delay_estimator_internal.h" #include "webrtc/system_wrappers/include/compile_assert_c.h" // Only bit |kBandFirst| through bit |kBandLast| are processed and // |kBandFirst| - |kBandLast| must be < 32. enum { kBandFirst = 12 }; enum { kBandLast = 43 }; static __inline uint32_t SetBit(uint32_t in, int pos) { uint32_t mask = (1 << pos); uint32_t out = (in | mask); return out; } // Calculates the mean recursively. Same version as WebRtc_MeanEstimatorFix(), // but for float. // // Inputs: // - new_value : New additional value. // - scale : Scale for smoothing (should be less than 1.0). // // Input/Output: // - mean_value : Pointer to the mean value for updating. // static void MeanEstimatorFloat(float new_value, float scale, float* mean_value) { assert(scale < 1.0f); *mean_value += (new_value - *mean_value) * scale; } // Computes the binary spectrum by comparing the input |spectrum| with a // |threshold_spectrum|. Float and fixed point versions. // // Inputs: // - spectrum : Spectrum of which the binary spectrum should be // calculated. // - threshold_spectrum : Threshold spectrum with which the input // spectrum is compared. // Return: // - out : Binary spectrum. // static uint32_t BinarySpectrumFix(const uint16_t* spectrum, SpectrumType* threshold_spectrum, int q_domain, int* threshold_initialized) { int i = kBandFirst; uint32_t out = 0; assert(q_domain < 16); if (!(*threshold_initialized)) { // Set the |threshold_spectrum| to half the input |spectrum| as starting // value. This speeds up the convergence. for (i = kBandFirst; i <= kBandLast; i++) { if (spectrum[i] > 0) { // Convert input spectrum from Q(|q_domain|) to Q15. int32_t spectrum_q15 = ((int32_t) spectrum[i]) << (15 - q_domain); threshold_spectrum[i].int32_ = (spectrum_q15 >> 1); *threshold_initialized = 1; } } } for (i = kBandFirst; i <= kBandLast; i++) { // Convert input spectrum from Q(|q_domain|) to Q15. int32_t spectrum_q15 = ((int32_t) spectrum[i]) << (15 - q_domain); // Update the |threshold_spectrum|. WebRtc_MeanEstimatorFix(spectrum_q15, 6, &(threshold_spectrum[i].int32_)); // Convert |spectrum| at current frequency bin to a binary value. if (spectrum_q15 > threshold_spectrum[i].int32_) { out = SetBit(out, i - kBandFirst); } } return out; } static uint32_t BinarySpectrumFloat(const float* spectrum, SpectrumType* threshold_spectrum, int* threshold_initialized) { int i = kBandFirst; uint32_t out = 0; const float kScale = 1 / 64.0; if (!(*threshold_initialized)) { // Set the |threshold_spectrum| to half the input |spectrum| as starting // value. This speeds up the convergence. for (i = kBandFirst; i <= kBandLast; i++) { if (spectrum[i] > 0.0f) { threshold_spectrum[i].float_ = (spectrum[i] / 2); *threshold_initialized = 1; } } } for (i = kBandFirst; i <= kBandLast; i++) { // Update the |threshold_spectrum|. MeanEstimatorFloat(spectrum[i], kScale, &(threshold_spectrum[i].float_)); // Convert |spectrum| at current frequency bin to a binary value. if (spectrum[i] > threshold_spectrum[i].float_) { out = SetBit(out, i - kBandFirst); } } return out; } void WebRtc_FreeDelayEstimatorFarend(void* handle) { DelayEstimatorFarend* self = (DelayEstimatorFarend*) handle; if (handle == NULL) { return; } free(self->mean_far_spectrum); self->mean_far_spectrum = NULL; WebRtc_FreeBinaryDelayEstimatorFarend(self->binary_farend); self->binary_farend = NULL; free(self); } void* WebRtc_CreateDelayEstimatorFarend(int spectrum_size, int history_size) { DelayEstimatorFarend* self = NULL; // Check if the sub band used in the delay estimation is small enough to fit // the binary spectra in a uint32_t. COMPILE_ASSERT(kBandLast - kBandFirst < 32); if (spectrum_size >= kBandLast) { self = malloc(sizeof(DelayEstimatorFarend)); } if (self != NULL) { int memory_fail = 0; // Allocate memory for the binary far-end spectrum handling. self->binary_farend = WebRtc_CreateBinaryDelayEstimatorFarend(history_size); memory_fail |= (self->binary_farend == NULL); // Allocate memory for spectrum buffers. self->mean_far_spectrum = malloc(spectrum_size * sizeof(SpectrumType)); memory_fail |= (self->mean_far_spectrum == NULL); self->spectrum_size = spectrum_size; if (memory_fail) { WebRtc_FreeDelayEstimatorFarend(self); self = NULL; } } return self; } int WebRtc_InitDelayEstimatorFarend(void* handle) { DelayEstimatorFarend* self = (DelayEstimatorFarend*) handle; if (self == NULL) { return -1; } // Initialize far-end part of binary delay estimator. WebRtc_InitBinaryDelayEstimatorFarend(self->binary_farend); // Set averaged far and near end spectra to zero. memset(self->mean_far_spectrum, 0, sizeof(SpectrumType) * self->spectrum_size); // Reset initialization indicators. self->far_spectrum_initialized = 0; return 0; } void WebRtc_SoftResetDelayEstimatorFarend(void* handle, int delay_shift) { DelayEstimatorFarend* self = (DelayEstimatorFarend*) handle; assert(self != NULL); WebRtc_SoftResetBinaryDelayEstimatorFarend(self->binary_farend, delay_shift); } int WebRtc_AddFarSpectrumFix(void* handle, const uint16_t* far_spectrum, int spectrum_size, int far_q) { DelayEstimatorFarend* self = (DelayEstimatorFarend*) handle; uint32_t binary_spectrum = 0; if (self == NULL) { return -1; } if (far_spectrum == NULL) { // Empty far end spectrum. return -1; } if (spectrum_size != self->spectrum_size) { // Data sizes don't match. return -1; } if (far_q > 15) { // If |far_q| is larger than 15 we cannot guarantee no wrap around. return -1; } // Get binary spectrum. binary_spectrum = BinarySpectrumFix(far_spectrum, self->mean_far_spectrum, far_q, &(self->far_spectrum_initialized)); WebRtc_AddBinaryFarSpectrum(self->binary_farend, binary_spectrum); return 0; } int WebRtc_AddFarSpectrumFloat(void* handle, const float* far_spectrum, int spectrum_size) { DelayEstimatorFarend* self = (DelayEstimatorFarend*) handle; uint32_t binary_spectrum = 0; if (self == NULL) { return -1; } if (far_spectrum == NULL) { // Empty far end spectrum. return -1; } if (spectrum_size != self->spectrum_size) { // Data sizes don't match. return -1; } // Get binary spectrum. binary_spectrum = BinarySpectrumFloat(far_spectrum, self->mean_far_spectrum, &(self->far_spectrum_initialized)); WebRtc_AddBinaryFarSpectrum(self->binary_farend, binary_spectrum); return 0; } void WebRtc_FreeDelayEstimator(void* handle) { DelayEstimator* self = (DelayEstimator*) handle; if (handle == NULL) { return; } free(self->mean_near_spectrum); self->mean_near_spectrum = NULL; WebRtc_FreeBinaryDelayEstimator(self->binary_handle); self->binary_handle = NULL; free(self); } void* WebRtc_CreateDelayEstimator(void* farend_handle, int max_lookahead) { DelayEstimator* self = NULL; DelayEstimatorFarend* farend = (DelayEstimatorFarend*) farend_handle; if (farend_handle != NULL) { self = malloc(sizeof(DelayEstimator)); } if (self != NULL) { int memory_fail = 0; // Allocate memory for the farend spectrum handling. self->binary_handle = WebRtc_CreateBinaryDelayEstimator(farend->binary_farend, max_lookahead); memory_fail |= (self->binary_handle == NULL); // Allocate memory for spectrum buffers. self->mean_near_spectrum = malloc(farend->spectrum_size * sizeof(SpectrumType)); memory_fail |= (self->mean_near_spectrum == NULL); self->spectrum_size = farend->spectrum_size; if (memory_fail) { WebRtc_FreeDelayEstimator(self); self = NULL; } } return self; } int WebRtc_InitDelayEstimator(void* handle) { DelayEstimator* self = (DelayEstimator*) handle; if (self == NULL) { return -1; } // Initialize binary delay estimator. WebRtc_InitBinaryDelayEstimator(self->binary_handle); // Set averaged far and near end spectra to zero. memset(self->mean_near_spectrum, 0, sizeof(SpectrumType) * self->spectrum_size); // Reset initialization indicators. self->near_spectrum_initialized = 0; return 0; } int WebRtc_SoftResetDelayEstimator(void* handle, int delay_shift) { DelayEstimator* self = (DelayEstimator*) handle; assert(self != NULL); return WebRtc_SoftResetBinaryDelayEstimator(self->binary_handle, delay_shift); } int WebRtc_set_history_size(void* handle, int history_size) { DelayEstimator* self = handle; if ((self == NULL) || (history_size <= 1)) { return -1; } return WebRtc_AllocateHistoryBufferMemory(self->binary_handle, history_size); } int WebRtc_history_size(const void* handle) { const DelayEstimator* self = handle; if (self == NULL) { return -1; } if (self->binary_handle->farend->history_size != self->binary_handle->history_size) { // Non matching history sizes. return -1; } return self->binary_handle->history_size; } int WebRtc_set_lookahead(void* handle, int lookahead) { DelayEstimator* self = (DelayEstimator*) handle; assert(self != NULL); assert(self->binary_handle != NULL); if ((lookahead > self->binary_handle->near_history_size - 1) || (lookahead < 0)) { return -1; } self->binary_handle->lookahead = lookahead; return self->binary_handle->lookahead; } int WebRtc_lookahead(void* handle) { DelayEstimator* self = (DelayEstimator*) handle; assert(self != NULL); assert(self->binary_handle != NULL); return self->binary_handle->lookahead; } int WebRtc_set_allowed_offset(void* handle, int allowed_offset) { DelayEstimator* self = (DelayEstimator*) handle; if ((self == NULL) || (allowed_offset < 0)) { return -1; } self->binary_handle->allowed_offset = allowed_offset; return 0; } int WebRtc_get_allowed_offset(const void* handle) { const DelayEstimator* self = (const DelayEstimator*) handle; if (self == NULL) { return -1; } return self->binary_handle->allowed_offset; } int WebRtc_enable_robust_validation(void* handle, int enable) { DelayEstimator* self = (DelayEstimator*) handle; if (self == NULL) { return -1; } if ((enable < 0) || (enable > 1)) { return -1; } assert(self->binary_handle != NULL); self->binary_handle->robust_validation_enabled = enable; return 0; } int WebRtc_is_robust_validation_enabled(const void* handle) { const DelayEstimator* self = (const DelayEstimator*) handle; if (self == NULL) { return -1; } return self->binary_handle->robust_validation_enabled; } int WebRtc_DelayEstimatorProcessFix(void* handle, const uint16_t* near_spectrum, int spectrum_size, int near_q) { DelayEstimator* self = (DelayEstimator*) handle; uint32_t binary_spectrum = 0; if (self == NULL) { return -1; } if (near_spectrum == NULL) { // Empty near end spectrum. return -1; } if (spectrum_size != self->spectrum_size) { // Data sizes don't match. return -1; } if (near_q > 15) { // If |near_q| is larger than 15 we cannot guarantee no wrap around. return -1; } // Get binary spectra. binary_spectrum = BinarySpectrumFix(near_spectrum, self->mean_near_spectrum, near_q, &(self->near_spectrum_initialized)); return WebRtc_ProcessBinarySpectrum(self->binary_handle, binary_spectrum); } int WebRtc_DelayEstimatorProcessFloat(void* handle, const float* near_spectrum, int spectrum_size) { DelayEstimator* self = (DelayEstimator*) handle; uint32_t binary_spectrum = 0; if (self == NULL) { return -1; } if (near_spectrum == NULL) { // Empty near end spectrum. return -1; } if (spectrum_size != self->spectrum_size) { // Data sizes don't match. return -1; } // Get binary spectrum. binary_spectrum = BinarySpectrumFloat(near_spectrum, self->mean_near_spectrum, &(self->near_spectrum_initialized)); return WebRtc_ProcessBinarySpectrum(self->binary_handle, binary_spectrum); } int WebRtc_last_delay(void* handle) { DelayEstimator* self = (DelayEstimator*) handle; if (self == NULL) { return -1; } return WebRtc_binary_last_delay(self->binary_handle); } float WebRtc_last_delay_quality(void* handle) { DelayEstimator* self = (DelayEstimator*) handle; assert(self != NULL); return WebRtc_binary_last_delay_quality(self->binary_handle); }