| /* |
| * Copyright (c) 2011 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 "delay_estimator_wrapper.h" |
| |
| #include <assert.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "delay_estimator.h" |
| #include "signal_processing_library.h" |
| |
| typedef union { |
| float float_; |
| int32_t int32_; |
| } SpectrumType_t; |
| |
| typedef struct { |
| // Pointers to mean values of spectrum |
| SpectrumType_t* mean_far_spectrum; |
| SpectrumType_t* mean_near_spectrum; |
| |
| // Spectrum size |
| int spectrum_size; |
| |
| // Binary spectrum based delay estimator |
| BinaryDelayEstimator_t* binary_handle; |
| } DelayEstimator_t; |
| |
| // Only bit |kBandFirst| through bit |kBandLast| are processed |
| // |kBandFirst| - |kBandLast| must be < 32 |
| static const int kBandFirst = 12; |
| static const int kBandLast = 43; |
| |
| static __inline uint32_t SetBit(uint32_t in, int pos) { |
| uint32_t mask = WEBRTC_SPL_LSHIFT_W32(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_new = mean_value + ((new_value - mean_value) * scale); |
| *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(uint16_t* spectrum, |
| SpectrumType_t* threshold_spectrum) { |
| int k = kBandFirst; |
| uint32_t out = 0; |
| |
| for (; k <= kBandLast; k++) { |
| WebRtc_MeanEstimatorFix((int32_t) spectrum[k], |
| 6, |
| &(threshold_spectrum[k].int32_)); |
| if (spectrum[k] > threshold_spectrum[k].int32_) { |
| out = SetBit(out, k - kBandFirst); |
| } |
| } |
| |
| return out; |
| } |
| |
| static uint32_t BinarySpectrumFloat(float* spectrum, |
| SpectrumType_t* threshold_spectrum) { |
| int k = kBandFirst; |
| uint32_t out = 0; |
| float scale = 1 / 64.0; |
| |
| for (; k <= kBandLast; k++) { |
| MeanEstimatorFloat(spectrum[k], scale, &(threshold_spectrum[k].float_)); |
| if (spectrum[k] > threshold_spectrum[k].float_) { |
| out = SetBit(out, k - kBandFirst); |
| } |
| } |
| |
| return out; |
| } |
| |
| int WebRtc_FreeDelayEstimator(void* handle) { |
| DelayEstimator_t* self = (DelayEstimator_t*) handle; |
| |
| if (self == NULL) { |
| return -1; |
| } |
| |
| if (self->mean_far_spectrum != NULL) { |
| free(self->mean_far_spectrum); |
| self->mean_far_spectrum = NULL; |
| } |
| if (self->mean_near_spectrum != NULL) { |
| free(self->mean_near_spectrum); |
| self->mean_near_spectrum = NULL; |
| } |
| |
| WebRtc_FreeBinaryDelayEstimator(self->binary_handle); |
| |
| free(self); |
| |
| return 0; |
| } |
| |
| int WebRtc_CreateDelayEstimator(void** handle, |
| int spectrum_size, |
| int max_delay, |
| int lookahead) { |
| DelayEstimator_t *self = NULL; |
| |
| // Check if the sub band used in the delay estimation is small enough to |
| // fit the binary spectra in a uint32. |
| assert(kBandLast - kBandFirst < 32); |
| |
| if (handle == NULL) { |
| return -1; |
| } |
| if (spectrum_size < kBandLast) { |
| return -1; |
| } |
| |
| self = malloc(sizeof(DelayEstimator_t)); |
| *handle = self; |
| if (self == NULL) { |
| return -1; |
| } |
| |
| self->mean_far_spectrum = NULL; |
| self->mean_near_spectrum = NULL; |
| |
| // Create binary delay estimator. |
| if (WebRtc_CreateBinaryDelayEstimator(&self->binary_handle, |
| max_delay, |
| lookahead) != 0) { |
| WebRtc_FreeDelayEstimator(self); |
| self = NULL; |
| return -1; |
| } |
| // Allocate memory for spectrum buffers |
| self->mean_far_spectrum = malloc(spectrum_size * sizeof(SpectrumType_t)); |
| if (self->mean_far_spectrum == NULL) { |
| WebRtc_FreeDelayEstimator(self); |
| self = NULL; |
| return -1; |
| } |
| self->mean_near_spectrum = malloc(spectrum_size * sizeof(SpectrumType_t)); |
| if (self->mean_near_spectrum == NULL) { |
| WebRtc_FreeDelayEstimator(self); |
| self = NULL; |
| return -1; |
| } |
| |
| self->spectrum_size = spectrum_size; |
| |
| return 0; |
| } |
| |
| int WebRtc_InitDelayEstimator(void* handle) { |
| DelayEstimator_t* self = (DelayEstimator_t*) handle; |
| |
| if (self == NULL) { |
| return -1; |
| } |
| |
| // Initialize binary delay estimator |
| if (WebRtc_InitBinaryDelayEstimator(self->binary_handle) != 0) { |
| return -1; |
| } |
| // Set averaged far and near end spectra to zero |
| memset(self->mean_far_spectrum, |
| 0, |
| sizeof(SpectrumType_t) * self->spectrum_size); |
| memset(self->mean_near_spectrum, |
| 0, |
| sizeof(SpectrumType_t) * self->spectrum_size); |
| |
| return 0; |
| } |
| |
| int WebRtc_DelayEstimatorProcessFix(void* handle, |
| uint16_t* far_spectrum, |
| uint16_t* near_spectrum, |
| int spectrum_size, |
| int far_q, |
| int vad_value) { |
| DelayEstimator_t* self = (DelayEstimator_t*) handle; |
| uint32_t binary_far_spectrum = 0; |
| uint32_t binary_near_spectrum = 0; |
| |
| if (self == NULL) { |
| return -1; |
| } |
| if (far_spectrum == NULL) { |
| // Empty far end spectrum |
| 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 (far_q > 15) { |
| // If |far_q| is larger than 15 we cannot guarantee no wrap around |
| return -1; |
| } |
| |
| // Get binary spectra |
| binary_far_spectrum = BinarySpectrumFix(far_spectrum, |
| self->mean_far_spectrum); |
| binary_near_spectrum = BinarySpectrumFix(near_spectrum, |
| self->mean_near_spectrum); |
| |
| return WebRtc_ProcessBinarySpectrum(self->binary_handle, |
| binary_far_spectrum, |
| binary_near_spectrum, |
| vad_value); |
| } |
| |
| int WebRtc_DelayEstimatorProcessFloat(void* handle, |
| float* far_spectrum, |
| float* near_spectrum, |
| int spectrum_size, |
| int vad_value) { |
| DelayEstimator_t* self = (DelayEstimator_t*) handle; |
| uint32_t binary_far_spectrum = 0; |
| uint32_t binary_near_spectrum = 0; |
| |
| if (self == NULL) { |
| return -1; |
| } |
| if (far_spectrum == NULL) { |
| // Empty far end spectrum |
| 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 spectra |
| binary_far_spectrum = BinarySpectrumFloat(far_spectrum, |
| self->mean_far_spectrum); |
| binary_near_spectrum = BinarySpectrumFloat(near_spectrum, |
| self->mean_near_spectrum); |
| |
| return WebRtc_ProcessBinarySpectrum(self->binary_handle, |
| binary_far_spectrum, |
| binary_near_spectrum, |
| vad_value); |
| } |
| |
| int WebRtc_last_delay(void* handle) { |
| DelayEstimator_t* self = (DelayEstimator_t*) handle; |
| |
| if (self == NULL) { |
| return -1; |
| } |
| |
| return WebRtc_binary_last_delay(self->binary_handle); |
| } |