Update common_audio

Corresponds to upstream commit 524e9b043e7e86fd72353b987c9d5f6a1ebf83e1

Update notes:

 * Moved src/ to webrtc/ to easily diff against the third_party/webrtc
   in the chromium tree

 * ARM/NEON/MIPS support is not yet hooked up

 * Tests have not been copied
This commit is contained in:
Arun Raghavan
2015-10-13 12:16:16 +05:30
parent 9413986e79
commit c4fb4e38de
230 changed files with 11201 additions and 8656 deletions

View File

@ -0,0 +1,12 @@
noinst_LTLIBRARIES = libapm_util.la
libapm_util_la_SOURCES = delay_estimator_float.c \
delay_estimator_float.h \
delay_estimator.c \
delay_estimator.h \
fft4g.c \
fft4g.h \
ring_buffer.c \
ring_buffer.h
libapm_util_la_CFLAGS = $(AM_CFLAGS) $(COMMON_CFLAGS) \
-I$(top_srcdir)/src/common_audio/signal_processing_library/main/interface

View File

@ -0,0 +1,550 @@
/*
* 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.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "signal_processing_library.h"
typedef struct {
// Pointers to mean values of spectrum and bit counts
int32_t* mean_far_spectrum;
int32_t* mean_near_spectrum;
int32_t* mean_bit_counts;
// Arrays only used locally in DelayEstimatorProcess() but whose size
// is determined at run-time.
int32_t* bit_counts;
int32_t* far_spectrum_32;
int32_t* near_spectrum_32;
// Binary history variables
uint32_t* binary_far_history;
// Far end history variables
uint16_t* far_history;
int far_history_pos;
int* far_q_domains;
// Delay histogram variables
int* delay_histogram;
int vad_counter;
// Delay memory
int last_delay;
// Used to enable far end alignment. If it is disabled, only delay values are
// produced
int alignment_enabled;
// Buffer size parameters
int history_size;
int spectrum_size;
} 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, int32_t pos) {
uint32_t mask = WEBRTC_SPL_LSHIFT_W32(1, pos);
uint32_t out = (in | mask);
return out;
}
// Compares the |binary_vector| with all rows of the |binary_matrix| and counts
// per row the number of times they have the same value.
//
// Inputs:
// - binary_vector : binary "vector" stored in a long
// - binary_matrix : binary "matrix" stored as a vector of long
// - matrix_size : size of binary "matrix"
//
// Output:
// - bit_counts : "Vector" stored as a long, containing for each
// row the number of times the matrix row and the
// input vector have the same value
//
static void BitCountComparison(uint32_t binary_vector,
const uint32_t* binary_matrix,
int matrix_size,
int32_t* bit_counts) {
int n = 0;
uint32_t a = binary_vector;
register uint32_t tmp;
// compare |binary_vector| with all rows of the |binary_matrix|
for (; n < matrix_size; n++) {
a = (binary_vector ^ binary_matrix[n]);
// Returns bit counts in tmp
tmp = a - ((a >> 1) & 033333333333) - ((a >> 2) & 011111111111);
tmp = ((tmp + (tmp >> 3)) & 030707070707);
tmp = (tmp + (tmp >> 6));
tmp = (tmp + (tmp >> 12) + (tmp >> 24)) & 077;
bit_counts[n] = (int32_t) tmp;
}
}
// Computes the binary spectrum by comparing the input |spectrum| with a
// |threshold_spectrum|.
//
// 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 BinarySpectrum(int32_t* spectrum, int32_t* threshold_spectrum) {
int k = kBandFirst;
uint32_t out = 0;
for (; k <= kBandLast; k++) {
if (spectrum[k] > threshold_spectrum[k]) {
out = SetBit(out, k - kBandFirst);
}
}
return out;
}
// Calculates the mean recursively.
//
// Inputs:
// - new_value : new additional value
// - factor : factor for smoothing
//
// Input/Output:
// - mean_value : pointer to the mean value that should be updated
//
static void MeanEstimator(const int32_t new_value,
int factor,
int32_t* mean_value) {
int32_t mean_new = *mean_value;
int32_t diff = new_value - mean_new;
// mean_new = mean_value + ((new_value - mean_value) >> factor);
if (diff < 0) {
diff = -WEBRTC_SPL_RSHIFT_W32(-diff, factor);
} else {
diff = WEBRTC_SPL_RSHIFT_W32(diff, factor);
}
mean_new += diff;
*mean_value = mean_new;
}
// 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
//
static void UpdateFarHistory(DelayEstimator_t* self,
uint16_t* far_spectrum,
int far_q) {
// Get new buffer position
self->far_history_pos++;
if (self->far_history_pos >= self->history_size) {
self->far_history_pos = 0;
}
// Update Q-domain buffer
self->far_q_domains[self->far_history_pos] = far_q;
// Update far end spectrum buffer
memcpy(&(self->far_history[self->far_history_pos * self->spectrum_size]),
far_spectrum,
sizeof(uint16_t) * self->spectrum_size);
}
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;
}
if (self->mean_bit_counts != NULL) {
free(self->mean_bit_counts);
self->mean_bit_counts = NULL;
}
if (self->bit_counts != NULL) {
free(self->bit_counts);
self->bit_counts = NULL;
}
if (self->far_spectrum_32 != NULL) {
free(self->far_spectrum_32);
self->far_spectrum_32 = NULL;
}
if (self->near_spectrum_32 != NULL) {
free(self->near_spectrum_32);
self->near_spectrum_32 = NULL;
}
if (self->binary_far_history != NULL) {
free(self->binary_far_history);
self->binary_far_history = NULL;
}
if (self->far_history != NULL) {
free(self->far_history);
self->far_history = NULL;
}
if (self->far_q_domains != NULL) {
free(self->far_q_domains);
self->far_q_domains = NULL;
}
if (self->delay_histogram != NULL) {
free(self->delay_histogram);
self->delay_histogram = NULL;
}
free(self);
return 0;
}
int WebRtc_CreateDelayEstimator(void** handle,
int spectrum_size,
int history_size,
int enable_alignment) {
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 (spectrum_size < kBandLast) {
return -1;
}
if (history_size < 0) {
return -1;
}
if ((enable_alignment != 0) && (enable_alignment != 1)) {
return -1;
}
self = malloc(sizeof(DelayEstimator_t));
*handle = self;
if (self == NULL) {
return -1;
}
self->mean_far_spectrum = NULL;
self->mean_near_spectrum = NULL;
self->mean_bit_counts = NULL;
self->bit_counts = NULL;
self->far_spectrum_32 = NULL;
self->near_spectrum_32 = NULL;
self->binary_far_history = NULL;
self->far_history = NULL;
self->far_q_domains = NULL;
self->delay_histogram = NULL;
// Allocate memory for spectrum buffers
self->mean_far_spectrum = malloc(spectrum_size * sizeof(int32_t));
if (self->mean_far_spectrum == NULL) {
WebRtc_FreeDelayEstimator(self);
self = NULL;
return -1;
}
self->mean_near_spectrum = malloc(spectrum_size * sizeof(int32_t));
if (self->mean_near_spectrum == NULL) {
WebRtc_FreeDelayEstimator(self);
self = NULL;
return -1;
}
self->mean_bit_counts = malloc(history_size * sizeof(int32_t));
if (self->mean_bit_counts == NULL) {
WebRtc_FreeDelayEstimator(self);
self = NULL;
return -1;
}
self->bit_counts = malloc(history_size * sizeof(int32_t));
if (self->bit_counts == NULL) {
WebRtc_FreeDelayEstimator(self);
self = NULL;
return -1;
}
self->far_spectrum_32 = malloc(spectrum_size * sizeof(int32_t));
if (self->far_spectrum_32 == NULL) {
WebRtc_FreeDelayEstimator(self);
self = NULL;
return -1;
}
self->near_spectrum_32 = malloc(spectrum_size * sizeof(int32_t));
if (self->near_spectrum_32 == NULL) {
WebRtc_FreeDelayEstimator(self);
self = NULL;
return -1;
}
// Allocate memory for history buffers
self->binary_far_history = malloc(history_size * sizeof(uint32_t));
if (self->binary_far_history == NULL) {
WebRtc_FreeDelayEstimator(self);
self = NULL;
return -1;
}
if (enable_alignment) {
self->far_history = malloc(spectrum_size * history_size * sizeof(uint16_t));
if (self->far_history == NULL) {
WebRtc_FreeDelayEstimator(self);
self = NULL;
return -1;
}
self->far_q_domains = malloc(history_size * sizeof(int));
if (self->far_q_domains == NULL) {
WebRtc_FreeDelayEstimator(self);
self = NULL;
return -1;
}
}
self->delay_histogram = malloc(history_size * sizeof(int));
if (self->delay_histogram == NULL) {
WebRtc_FreeDelayEstimator(self);
self = NULL;
return -1;
}
self->spectrum_size = spectrum_size;
self->history_size = history_size;
self->alignment_enabled = enable_alignment;
return 0;
}
int WebRtc_InitDelayEstimator(void* handle) {
DelayEstimator_t* self = (DelayEstimator_t*) handle;
if (self == NULL) {
return -1;
}
// Set averaged far and near end spectra to zero
memset(self->mean_far_spectrum, 0, sizeof(int32_t) * self->spectrum_size);
memset(self->mean_near_spectrum, 0, sizeof(int32_t) * self->spectrum_size);
// Set averaged bit counts to zero
memset(self->mean_bit_counts, 0, sizeof(int32_t) * self->history_size);
memset(self->bit_counts, 0, sizeof(int32_t) * self->history_size);
memset(self->far_spectrum_32, 0, sizeof(int32_t) * self->spectrum_size);
memset(self->near_spectrum_32, 0, sizeof(int32_t) * self->spectrum_size);
// Set far end histories to zero
memset(self->binary_far_history, 0, sizeof(uint32_t) * self->history_size);
if (self->alignment_enabled) {
memset(self->far_history,
0,
sizeof(uint16_t) * self->spectrum_size * self->history_size);
memset(self->far_q_domains, 0, sizeof(int) * self->history_size);
self->far_history_pos = self->history_size;
}
// Set delay histogram to zero
memset(self->delay_histogram, 0, sizeof(int) * self->history_size);
// Set VAD counter to zero
self->vad_counter = 0;
// Set delay memory to zero
self->last_delay = 0;
return 0;
}
int WebRtc_DelayEstimatorProcess(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;
const int kVadCountThreshold = 25;
const int kMaxHistogram = 600;
int histogram_bin = 0;
int i = 0;
int max_histogram_level = 0;
int min_position = -1;
uint32_t binary_far_spectrum = 0;
uint32_t binary_near_spectrum = 0;
int32_t bit_counts_tmp = 0;
if (self == NULL) {
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;
}
if (self->alignment_enabled) {
// Update far end history
UpdateFarHistory(self, far_spectrum, far_q);
} // Update the far and near end means
for (i = 0; i < self->spectrum_size; i++) {
self->far_spectrum_32[i] = (int32_t) far_spectrum[i];
MeanEstimator(self->far_spectrum_32[i], 6, &(self->mean_far_spectrum[i]));
self->near_spectrum_32[i] = (int32_t) near_spectrum[i];
MeanEstimator(self->near_spectrum_32[i], 6, &(self->mean_near_spectrum[i]));
}
// Shift binary spectrum history
memmove(&(self->binary_far_history[1]), &(self->binary_far_history[0]),
(self->history_size - 1) * sizeof(uint32_t));
// Get binary spectra
binary_far_spectrum = BinarySpectrum(self->far_spectrum_32,
self->mean_far_spectrum);
binary_near_spectrum = BinarySpectrum(self->near_spectrum_32,
self->mean_near_spectrum);
// Insert new binary spectrum
self->binary_far_history[0] = binary_far_spectrum;
// Compare with delayed spectra
BitCountComparison(binary_near_spectrum,
self->binary_far_history,
self->history_size,
self->bit_counts);
// Smooth bit count curve
for (i = 0; i < self->history_size; i++) {
// Update sum
// |bit_counts| is constrained to [0, 32], meaning we can smooth with a
// factor up to 2^26. We use Q9.
bit_counts_tmp = WEBRTC_SPL_LSHIFT_W32(self->bit_counts[i], 9); // Q9
MeanEstimator(bit_counts_tmp, 9, &(self->mean_bit_counts[i]));
}
// Find minimum position of bit count curve
min_position = (int) WebRtcSpl_MinIndexW32(self->mean_bit_counts,
(int16_t) self->history_size);
// If the far end has been active sufficiently long, begin accumulating a
// histogram of the minimum positions. Search for the maximum bin to
// determine the delay.
if (vad_value == 1) {
if (self->vad_counter >= kVadCountThreshold) {
// Increment the histogram at the current minimum position.
if (self->delay_histogram[min_position] < kMaxHistogram) {
self->delay_histogram[min_position] += 3;
}
self->last_delay = 0;
for (i = 0; i < self->history_size; i++) {
histogram_bin = self->delay_histogram[i];
// Decrement the histogram bin.
if (histogram_bin > 0) {
histogram_bin--;
self->delay_histogram[i] = histogram_bin;
// Select the histogram index corresponding to the maximum bin as the
// delay.
if (histogram_bin > max_histogram_level) {
max_histogram_level = histogram_bin;
self->last_delay = i;
}
}
}
} else {
self->vad_counter++;
}
} else {
self->vad_counter = 0;
}
return self->last_delay;
}
const uint16_t* WebRtc_AlignedFarend(void* handle,
int far_spectrum_size,
int* far_q) {
DelayEstimator_t* self = (DelayEstimator_t*) handle;
int buffer_position = 0;
if (self == NULL) {
return NULL;
}
if (far_spectrum_size != self->spectrum_size) {
return NULL;
}
if (self->alignment_enabled == 0) {
return NULL;
}
// Get buffer position
buffer_position = self->far_history_pos - self->last_delay;
if (buffer_position < 0) {
buffer_position += self->history_size;
}
// Get Q-domain
*far_q = self->far_q_domains[buffer_position];
// Return far end spectrum
return (self->far_history + (buffer_position * far_spectrum_size));
}
int WebRtc_last_delay(void* handle) {
DelayEstimator_t* self = (DelayEstimator_t*) handle;
if (self == NULL) {
return -1;
}
return self->last_delay;
}
int WebRtc_history_size(void* handle) {
DelayEstimator_t* self = (DelayEstimator_t*) handle;
if (self == NULL) {
return -1;
}
return self->history_size;
}
int WebRtc_spectrum_size(void* handle) {
DelayEstimator_t* self = (DelayEstimator_t*) handle;
if (self == NULL) {
return -1;
}
return self->spectrum_size;
}
int WebRtc_is_alignment_enabled(void* handle) {
DelayEstimator_t* self = (DelayEstimator_t*) handle;
if (self == NULL) {
return -1;
}
return self->alignment_enabled;
}

View File

@ -0,0 +1,154 @@
/*
* 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.
*/
// Performs delay estimation on a block by block basis
// The return value is 0 - OK and -1 - Error, unless otherwise stated.
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_H_
#include "typedefs.h"
// Releases the memory allocated by WebRtc_CreateDelayEstimator(...)
// Input:
// - handle : Pointer to the delay estimation instance
//
int WebRtc_FreeDelayEstimator(void* handle);
// Allocates the memory needed by the delay estimation. The memory needs to be
// initialized separately using the WebRtc_InitDelayEstimator(...)
// function.
//
// Inputs:
// - handle : Instance that should be created
// - spectrum_size : Size of the spectrum used both in far end and
// near end. Used to allocate memory for spectrum
// specific buffers.
// - history_size : Size of the far end history used to estimate the
// delay from. Used to allocate memory for history
// specific buffers.
// - enable_alignment : With this mode set to 1, a far end history is
// created, so that the user can retrieve aligned
// far end spectra using
// WebRtc_AlignedFarend(...). Otherwise, only delay
// values are calculated.
//
// Output:
// - handle : Created instance
//
int WebRtc_CreateDelayEstimator(void** handle,
int spectrum_size,
int history_size,
int enable_alignment);
// Initializes the delay estimation instance created with
// WebRtc_CreateDelayEstimator(...)
// Input:
// - handle : Pointer to the delay estimation instance
//
// Output:
// - handle : Initialized instance
//
int WebRtc_InitDelayEstimator(void* handle);
// Estimates and returns the delay between the far end and near end blocks.
// Inputs:
// - handle : Pointer to the delay estimation instance
// - far_spectrum : Pointer to the far end spectrum data
// - near_spectrum : Pointer to the near end spectrum data of the current
// block
// - spectrum_size : The size of the data arrays (same for both far and
// near end)
// - far_q : The Q-domain of the far end data
// - vad_value : The VAD decision of the current block
//
// Output:
// - handle : Updated instance
//
// Return value:
// - delay : >= 0 - Calculated delay value
// -1 - Error
//
int WebRtc_DelayEstimatorProcess(void* handle,
uint16_t* far_spectrum,
uint16_t* near_spectrum,
int spectrum_size,
int far_q,
int vad_value);
// Returns a pointer to the far end spectrum aligned to current near end
// spectrum. The function WebRtc_DelayEstimatorProcess(...) should have been
// called before WebRtc_AlignedFarend(...). Otherwise, you get the pointer to
// the previous frame. The memory is only valid until the next call of
// WebRtc_DelayEstimatorProcess(...).
//
// Inputs:
// - handle : Pointer to the delay estimation instance
// - far_spectrum_size : Size of far_spectrum allocated by the caller
//
// 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* WebRtc_AlignedFarend(void* handle,
int far_spectrum_size,
int* far_q);
// Returns the last calculated delay updated by the function
// WebRtc_DelayEstimatorProcess(...)
//
// Input:
// - handle : Pointer to the delay estimation instance
//
// Return value:
// - delay : >= 0 - Last calculated delay value
// -1 - Error
//
int WebRtc_last_delay(void* handle);
// Returns the history size used in the far end buffers to calculate the delay
// over.
//
// Input:
// - handle : Pointer to the delay estimation instance
//
// Return value:
// - history_size : > 0 - Far end history size
// -1 - Error
//
int WebRtc_history_size(void* handle);
// Returns the fixed spectrum size used in the algorithm.
//
// Input:
// - handle : Pointer to the delay estimation instance
//
// Return value:
// - spectrum_size : > 0 - Spectrum size
// -1 - Error
//
int WebRtc_spectrum_size(void* handle);
// Returns 1 if the far end alignment is enabled and 0 otherwise.
//
// Input:
// - handle : Pointer to the delay estimation instance
//
// Return value:
// - alignment_enabled : 1 - Enabled
// 0 - Disabled
// -1 - Error
//
int WebRtc_is_alignment_enabled(void* handle);
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_H_

View File

@ -0,0 +1,288 @@
/*
* 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_float.h"
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "delay_estimator.h"
#include "signal_processing_library.h"
typedef struct {
// Fixed point spectra
uint16_t* far_spectrum_u16;
uint16_t* near_spectrum_u16;
// Far end history variables
float* far_history;
int far_history_pos;
// Fixed point delay estimator
void* fixed_handle;
} DelayEstimatorFloat_t;
// Moves the pointer to the next buffer entry and inserts new far end spectrum.
// Only used when alignment is enabled.
//
// Inputs:
// - self : Pointer to the delay estimation instance
// - far_spectrum : Pointer to the far end spectrum
//
static void UpdateFarHistory(DelayEstimatorFloat_t* self, float* far_spectrum) {
int spectrum_size = WebRtc_spectrum_size(self->fixed_handle);
// Get new buffer position
self->far_history_pos++;
if (self->far_history_pos >= WebRtc_history_size(self->fixed_handle)) {
self->far_history_pos = 0;
}
// Update far end spectrum buffer
memcpy(&(self->far_history[self->far_history_pos * spectrum_size]),
far_spectrum,
sizeof(float) * spectrum_size);
}
int WebRtc_FreeDelayEstimatorFloat(void* handle) {
DelayEstimatorFloat_t* self = (DelayEstimatorFloat_t*) handle;
if (self == NULL) {
return -1;
}
if (self->far_history != NULL) {
free(self->far_history);
self->far_history = NULL;
}
if (self->far_spectrum_u16 != NULL) {
free(self->far_spectrum_u16);
self->far_spectrum_u16 = NULL;
}
if (self->near_spectrum_u16 != NULL) {
free(self->near_spectrum_u16);
self->near_spectrum_u16 = NULL;
}
WebRtc_FreeDelayEstimator(self->fixed_handle);
free(self);
return 0;
}
int WebRtc_CreateDelayEstimatorFloat(void** handle,
int spectrum_size,
int history_size,
int enable_alignment) {
DelayEstimatorFloat_t *self = NULL;
if ((enable_alignment != 0) && (enable_alignment != 1)) {
return -1;
}
self = malloc(sizeof(DelayEstimatorFloat_t));
*handle = self;
if (self == NULL) {
return -1;
}
self->far_history = NULL;
self->far_spectrum_u16 = NULL;
self->near_spectrum_u16 = NULL;
// Create fixed point core delay estimator
if (WebRtc_CreateDelayEstimator(&self->fixed_handle,
spectrum_size,
history_size,
enable_alignment) != 0) {
WebRtc_FreeDelayEstimatorFloat(self);
self = NULL;
return -1;
}
// Allocate memory for far history buffer
if (enable_alignment) {
self->far_history = malloc(spectrum_size * history_size * sizeof(float));
if (self->far_history == NULL) {
WebRtc_FreeDelayEstimatorFloat(self);
self = NULL;
return -1;
}
}
// Allocate memory for fixed point spectra
self->far_spectrum_u16 = malloc(spectrum_size * sizeof(uint16_t));
if (self->far_spectrum_u16 == NULL) {
WebRtc_FreeDelayEstimatorFloat(self);
self = NULL;
return -1;
}
self->near_spectrum_u16 = malloc(spectrum_size * sizeof(uint16_t));
if (self->near_spectrum_u16 == NULL) {
WebRtc_FreeDelayEstimatorFloat(self);
self = NULL;
return -1;
}
return 0;
}
int WebRtc_InitDelayEstimatorFloat(void* handle) {
DelayEstimatorFloat_t* self = (DelayEstimatorFloat_t*) handle;
if (self == NULL) {
return -1;
}
if (WebRtc_InitDelayEstimator(self->fixed_handle) != 0) {
return -1;
}
{
int history_size = WebRtc_history_size(self->fixed_handle);
int spectrum_size = WebRtc_spectrum_size(self->fixed_handle);
if (WebRtc_is_alignment_enabled(self->fixed_handle) == 1) {
// Set far end histories to zero
memset(self->far_history,
0,
sizeof(float) * spectrum_size * history_size);
self->far_history_pos = history_size;
}
// Set fixed point spectra to zero
memset(self->far_spectrum_u16, 0, sizeof(uint16_t) * spectrum_size);
memset(self->near_spectrum_u16, 0, sizeof(uint16_t) * spectrum_size);
}
return 0;
}
int WebRtc_DelayEstimatorProcessFloat(void* handle,
float* far_spectrum,
float* near_spectrum,
int spectrum_size,
int vad_value) {
DelayEstimatorFloat_t* self = (DelayEstimatorFloat_t*) handle;
const float kFftSize = (float) (2 * (spectrum_size - 1));
const float kLogOf2Inverse = 1.4426950f;
float max_value = 0.0f;
float scaling = 0;
int far_q = 0;
int scaling_log = 0;
int i = 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 != WebRtc_spectrum_size(self->fixed_handle)) {
// Data sizes don't match
return -1;
}
// Convert floating point spectrum to fixed point
// 1) Find largest value
// 2) Scale largest value to fit in Word16
for (i = 0; i < spectrum_size; ++i) {
if (near_spectrum[i] > max_value) {
max_value = near_spectrum[i];
}
}
// Find the largest possible scaling that is a multiple of two.
// With largest we mean to fit in a Word16.
// TODO(bjornv): I've taken the size of FFT into account, since there is a
// different scaling in float vs fixed point FFTs. I'm not completely sure
// this is necessary.
scaling_log = 14 - (int) (log(max_value / kFftSize + 1) * kLogOf2Inverse);
scaling = (float) (1 << scaling_log) / kFftSize;
for (i = 0; i < spectrum_size; ++i) {
self->near_spectrum_u16[i] = (uint16_t) (near_spectrum[i] * scaling);
}
// Same for far end
max_value = 0.0f;
for (i = 0; i < spectrum_size; ++i) {
if (far_spectrum[i] > max_value) {
max_value = far_spectrum[i];
}
}
// Find the largest possible scaling that is a multiple of two.
// With largest we mean to fit in a Word16.
scaling_log = 14 - (int) (log(max_value / kFftSize + 1) * kLogOf2Inverse);
scaling = (float) (1 << scaling_log) / kFftSize;
for (i = 0; i < spectrum_size; ++i) {
self->far_spectrum_u16[i] = (uint16_t) (far_spectrum[i] * scaling);
}
far_q = (int) scaling_log;
assert(far_q < 16); // Catch too large scaling, which should never be able to
// occur.
if (WebRtc_is_alignment_enabled(self->fixed_handle) == 1) {
// Update far end history
UpdateFarHistory(self, far_spectrum);
}
return WebRtc_DelayEstimatorProcess(self->fixed_handle,
self->far_spectrum_u16,
self->near_spectrum_u16,
spectrum_size,
far_q,
vad_value);
}
const float* WebRtc_AlignedFarendFloat(void* handle, int far_spectrum_size) {
DelayEstimatorFloat_t* self = (DelayEstimatorFloat_t*) handle;
int buffer_pos = 0;
if (self == NULL) {
return NULL;
}
if (far_spectrum_size != WebRtc_spectrum_size(self->fixed_handle)) {
return NULL;
}
if (WebRtc_is_alignment_enabled(self->fixed_handle) != 1) {
return NULL;
}
// Get buffer position
buffer_pos = self->far_history_pos - WebRtc_last_delay(self->fixed_handle);
if (buffer_pos < 0) {
buffer_pos += WebRtc_history_size(self->fixed_handle);
}
// Return pointer to far end spectrum
return (self->far_history + (buffer_pos * far_spectrum_size));
}
int WebRtc_last_delay_float(void* handle) {
DelayEstimatorFloat_t* self = (DelayEstimatorFloat_t*) handle;
if (self == NULL) {
return -1;
}
return WebRtc_last_delay(self->fixed_handle);
}
int WebRtc_is_alignment_enabled_float(void* handle) {
DelayEstimatorFloat_t* self = (DelayEstimatorFloat_t*) handle;
if (self == NULL) {
return -1;
}
return WebRtc_is_alignment_enabled(self->fixed_handle);
}

View File

@ -0,0 +1,125 @@
/*
* 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.
*/
// Performs delay estimation on a block by block basis
// The return value is 0 - OK and -1 - Error, unless otherwise stated.
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_FLOAT_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_FLOAT_H_
// Releases the memory allocated by WebRtc_CreateDelayEstimatorFloat(...)
// Input:
// - handle : Pointer to the delay estimation instance
//
int WebRtc_FreeDelayEstimatorFloat(void* handle);
// Allocates the memory needed by the delay estimation. The memory needs to be
// initialized separately using the WebRtc_InitDelayEstimatorFloat(...)
// function.
//
// Inputs:
// - handle : Instance that should be created
// - spectrum_size : Size of the spectrum used both in far end and
// near end. Used to allocate memory for spectrum
// specific buffers.
// - history_size : Size of the far end history used to estimate the
// delay from. Used to allocate memory for history
// specific buffers.
// - enable_alignment : With this mode set to 1, a far end history is
// created, so that the user can retrieve aligned
// far end spectra using
// WebRtc_AlignedFarendFloat(...). Otherwise, only
// delay values are calculated.
//
// Output:
// - handle : Created instance
//
int WebRtc_CreateDelayEstimatorFloat(void** handle,
int spectrum_size,
int history_size,
int enable_alignment);
// Initializes the delay estimation instance created with
// WebRtc_CreateDelayEstimatorFloat(...)
// Input:
// - handle : Pointer to the delay estimation instance
//
// Output:
// - handle : Initialized instance
//
int WebRtc_InitDelayEstimatorFloat(void* handle);
// Estimates and returns the delay between the far end and near end blocks.
// Inputs:
// - handle : Pointer to the delay estimation instance
// - far_spectrum : Pointer to the far end spectrum data
// - near_spectrum : Pointer to the near end spectrum data of the current
// block
// - spectrum_size : The size of the data arrays (same for both far and
// near end)
// - far_q : The Q-domain of the far end data
// - vad_value : The VAD decision of the current block
//
// Output:
// - handle : Updated instance
//
// Return value:
// - delay : >= 0 - Calculated delay value
// -1 - Error
//
int WebRtc_DelayEstimatorProcessFloat(void* handle,
float* far_spectrum,
float* near_spectrum,
int spectrum_size,
int vad_value);
// Returns a pointer to the far end spectrum aligned to current near end
// spectrum. The function WebRtc_DelayEstimatorProcessFloat(...) should
// have been called before WebRtc_AlignedFarendFloat(...). Otherwise, you get
// the pointer to the previous frame. The memory is only valid until the
// next call of WebRtc_DelayEstimatorProcessFloat(...).
//
// Inputs:
// - handle : Pointer to the delay estimation instance
// - far_spectrum_size : Size of far_spectrum allocated by the caller
//
// Output:
//
// Return value:
// - far_spectrum : Pointer to the aligned far end spectrum
// NULL - Error
//
const float* WebRtc_AlignedFarendFloat(void* handle, int far_spectrum_size);
// Returns the last calculated delay updated by the function
// WebRtcApm_DelayEstimatorProcessFloat(...)
//
// Inputs:
// - handle : Pointer to the delay estimation instance
//
// Return value:
// - delay : >= 0 - Last calculated delay value
// -1 - Error
//
int WebRtc_last_delay_float(void* handle);
// Returns 1 if the far end alignment is enabled and 0 otherwise.
//
// Input:
// - handle : Pointer to the delay estimation instance
//
// Return value:
// - alignment_enabled : 1 - Enabled
// 0 - Disabled
// -1 - Error
//
int WebRtc_is_alignment_enabled_float(void* handle);
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_FLOAT_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
/*
* 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.
*/
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_FFT4G_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_FFT4G_H_
void rdft(int, int, float *, int *, float *);
void cdft(int, int, float *, int *, float *);
#endif

View File

@ -0,0 +1,239 @@
/*
* 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.
*/
/*
* Provides a generic ring buffer that can be written to and read from with
* arbitrarily sized blocks. The AEC uses this for several different tasks.
*/
#include <stdlib.h>
#include <string.h>
#include "ring_buffer.h"
typedef struct {
int readPos;
int writePos;
int size;
char rwWrap;
bufdata_t *data;
} buf_t;
enum {SAME_WRAP, DIFF_WRAP};
int WebRtcApm_CreateBuffer(void **bufInst, int size)
{
buf_t *buf = NULL;
if (size < 0) {
return -1;
}
buf = malloc(sizeof(buf_t));
*bufInst = buf;
if (buf == NULL) {
return -1;
}
buf->data = malloc(size*sizeof(bufdata_t));
if (buf->data == NULL) {
free(buf);
buf = NULL;
return -1;
}
buf->size = size;
return 0;
}
int WebRtcApm_InitBuffer(void *bufInst)
{
buf_t *buf = (buf_t*)bufInst;
buf->readPos = 0;
buf->writePos = 0;
buf->rwWrap = SAME_WRAP;
// Initialize buffer to zeros
memset(buf->data, 0, sizeof(bufdata_t)*buf->size);
return 0;
}
int WebRtcApm_FreeBuffer(void *bufInst)
{
buf_t *buf = (buf_t*)bufInst;
if (buf == NULL) {
return -1;
}
free(buf->data);
free(buf);
return 0;
}
int WebRtcApm_ReadBuffer(void *bufInst, bufdata_t *data, int size)
{
buf_t *buf = (buf_t*)bufInst;
int n = 0, margin = 0;
if (size <= 0 || size > buf->size) {
return -1;
}
n = size;
if (buf->rwWrap == DIFF_WRAP) {
margin = buf->size - buf->readPos;
if (n > margin) {
buf->rwWrap = SAME_WRAP;
memcpy(data, buf->data + buf->readPos,
sizeof(bufdata_t)*margin);
buf->readPos = 0;
n = size - margin;
}
else {
memcpy(data, buf->data + buf->readPos,
sizeof(bufdata_t)*n);
buf->readPos += n;
return n;
}
}
if (buf->rwWrap == SAME_WRAP) {
margin = buf->writePos - buf->readPos;
if (margin > n)
margin = n;
memcpy(data + size - n, buf->data + buf->readPos,
sizeof(bufdata_t)*margin);
buf->readPos += margin;
n -= margin;
}
return size - n;
}
int WebRtcApm_WriteBuffer(void *bufInst, const bufdata_t *data, int size)
{
buf_t *buf = (buf_t*)bufInst;
int n = 0, margin = 0;
if (size < 0 || size > buf->size) {
return -1;
}
n = size;
if (buf->rwWrap == SAME_WRAP) {
margin = buf->size - buf->writePos;
if (n > margin) {
buf->rwWrap = DIFF_WRAP;
memcpy(buf->data + buf->writePos, data,
sizeof(bufdata_t)*margin);
buf->writePos = 0;
n = size - margin;
}
else {
memcpy(buf->data + buf->writePos, data,
sizeof(bufdata_t)*n);
buf->writePos += n;
return n;
}
}
if (buf->rwWrap == DIFF_WRAP) {
margin = buf->readPos - buf->writePos;
if (margin > n)
margin = n;
memcpy(buf->data + buf->writePos, data + size - n,
sizeof(bufdata_t)*margin);
buf->writePos += margin;
n -= margin;
}
return size - n;
}
int WebRtcApm_FlushBuffer(void *bufInst, int size)
{
buf_t *buf = (buf_t*)bufInst;
int n = 0, margin = 0;
if (size <= 0 || size > buf->size) {
return -1;
}
n = size;
if (buf->rwWrap == DIFF_WRAP) {
margin = buf->size - buf->readPos;
if (n > margin) {
buf->rwWrap = SAME_WRAP;
buf->readPos = 0;
n = size - margin;
}
else {
buf->readPos += n;
return n;
}
}
if (buf->rwWrap == SAME_WRAP) {
margin = buf->writePos - buf->readPos;
if (margin > n)
margin = n;
buf->readPos += margin;
n -= margin;
}
return size - n;
}
int WebRtcApm_StuffBuffer(void *bufInst, int size)
{
buf_t *buf = (buf_t*)bufInst;
int n = 0, margin = 0;
if (size <= 0 || size > buf->size) {
return -1;
}
n = size;
if (buf->rwWrap == SAME_WRAP) {
margin = buf->readPos;
if (n > margin) {
buf->rwWrap = DIFF_WRAP;
buf->readPos = buf->size - 1;
n -= margin + 1;
}
else {
buf->readPos -= n;
return n;
}
}
if (buf->rwWrap == DIFF_WRAP) {
margin = buf->readPos - buf->writePos;
if (margin > n)
margin = n;
buf->readPos -= margin;
n -= margin;
}
return size - n;
}
int WebRtcApm_get_buffer_size(const void *bufInst)
{
const buf_t *buf = (buf_t*)bufInst;
if (buf->rwWrap == SAME_WRAP)
return buf->writePos - buf->readPos;
else
return buf->size - buf->readPos + buf->writePos;
}

View File

@ -0,0 +1,41 @@
/*
* 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.
*/
/*
* Specifies the interface for the AEC generic buffer.
*/
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_RING_BUFFER_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_RING_BUFFER_H_
// Determines buffer datatype
typedef short bufdata_t;
// Unless otherwise specified, functions return 0 on success and -1 on error
int WebRtcApm_CreateBuffer(void **bufInst, int size);
int WebRtcApm_InitBuffer(void *bufInst);
int WebRtcApm_FreeBuffer(void *bufInst);
// Returns number of samples read
int WebRtcApm_ReadBuffer(void *bufInst, bufdata_t *data, int size);
// Returns number of samples written
int WebRtcApm_WriteBuffer(void *bufInst, const bufdata_t *data, int size);
// Returns number of samples flushed
int WebRtcApm_FlushBuffer(void *bufInst, int size);
// Returns number of samples stuffed
int WebRtcApm_StuffBuffer(void *bufInst, int size);
// Returns number of samples in buffer
int WebRtcApm_get_buffer_size(const void *bufInst);
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_RING_BUFFER_H_

View File

@ -0,0 +1,40 @@
# 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.
{
'targets': [
{
'target_name': 'apm_util',
'type': '<(library)',
'dependencies': [
'<(webrtc_root)/common_audio/common_audio.gyp:spl',
],
'direct_dependent_settings': {
'include_dirs': [
'.',
],
},
'sources': [
'delay_estimator_float.c',
'delay_estimator_float.h',
'delay_estimator.c',
'delay_estimator.h',
'fft4g.c',
'fft4g.h',
'ring_buffer.c',
'ring_buffer.h',
],
},
],
}
# Local Variables:
# tab-width:2
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=2 shiftwidth=2: