Arun Raghavan c4fb4e38de 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
2015-10-15 16:18:25 +05:30

289 lines
8.3 KiB
C

/*
* 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);
}