forked from len0rd/rockbox
codecs: Update libspeex from 1.2beta3 to 1.2rc1
This is a relatively minor bump, but it's the first step towards bringing this current. Change-Id: Iab6c9b0c77f0ba705280434ea74b513364719499
This commit is contained in:
parent
8ef20383b1
commit
547b6a570d
21 changed files with 1406 additions and 1001 deletions
|
@ -1,10 +1,11 @@
|
||||||
Copyright 2002-2006
|
Copyright 2002-2008 Xiph.org Foundation
|
||||||
Xiph.org Foundation
|
Copyright 2002-2008 Jean-Marc Valin
|
||||||
Jean-Marc Valin
|
Copyright 2005-2007 Analog Devices Inc.
|
||||||
David Rowe
|
Copyright 2005-2008 Commonwealth Scientific and Industrial Research
|
||||||
EpicGames
|
Organisation (CSIRO)
|
||||||
Analog Devices
|
Copyright 1993, 2002, 2006 David Rowe
|
||||||
Commonwealth Scientific and Industrial Research Organisation (CSIRO)
|
Copyright 2003 EpicGames
|
||||||
|
Copyright 1992-1994 Jutta Degener, Carsten Bormann
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions
|
modification, are permitted provided that the following conditions
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
Library: libspeex-1.2beta3 (SVN version 14054)
|
Library: libspeex-1.2rc1
|
||||||
Imported: 2007-03-12 by Dan Everton
|
Imported 1.2beta3: 2007-03-12 by Dan Everton
|
||||||
|
Updated 1.2rc1: 2024-05-08 by Solomon Peachy
|
||||||
|
|
||||||
This directory contains a local version of libspeex for decoding Ogg/Speex
|
This directory contains a local version of libspeex for decoding Ogg/Speex
|
||||||
audio streams.
|
audio streams.
|
||||||
|
|
|
@ -235,7 +235,7 @@ typedef float spx_word32_t;
|
||||||
|
|
||||||
|
|
||||||
#ifdef FIXED_DEBUG
|
#ifdef FIXED_DEBUG
|
||||||
long long spx_mips=0;
|
extern long long spx_mips=0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ROCKBOX_VOICE_ENCODER
|
#ifdef ROCKBOX_VOICE_ENCODER
|
||||||
void speex_bits_init(SpeexBits *bits)
|
EXPORT void speex_bits_init(SpeexBits *bits)
|
||||||
{
|
{
|
||||||
bits->chars = (char*)speex_alloc(MAX_CHARS_PER_FRAME);
|
bits->chars = (char*)speex_alloc(MAX_CHARS_PER_FRAME);
|
||||||
if (!bits->chars)
|
if (!bits->chars)
|
||||||
|
@ -62,7 +62,7 @@ void speex_bits_init(SpeexBits *bits)
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* Rockbox: unused */
|
/* Rockbox: unused */
|
||||||
void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size)
|
EXPORT void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size)
|
||||||
{
|
{
|
||||||
bits->chars = (char*)buff;
|
bits->chars = (char*)buff;
|
||||||
bits->buf_size = buf_size;
|
bits->buf_size = buf_size;
|
||||||
|
@ -73,7 +73,7 @@ void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void speex_bits_set_bit_buffer(SpeexBits *bits, void *buff, int buf_size)
|
EXPORT void speex_bits_set_bit_buffer(SpeexBits *bits, void *buff, int buf_size)
|
||||||
{
|
{
|
||||||
bits->chars = (char*)buff;
|
bits->chars = (char*)buff;
|
||||||
bits->buf_size = buf_size;
|
bits->buf_size = buf_size;
|
||||||
|
@ -88,7 +88,7 @@ void speex_bits_set_bit_buffer(SpeexBits *bits, void *buff, int buf_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ROCKBOX_VOICE_CODEC
|
#ifndef ROCKBOX_VOICE_CODEC
|
||||||
void speex_bits_destroy(SpeexBits *bits)
|
EXPORT void speex_bits_destroy(SpeexBits *bits)
|
||||||
{
|
{
|
||||||
if (bits->owner)
|
if (bits->owner)
|
||||||
speex_free(bits->chars);
|
speex_free(bits->chars);
|
||||||
|
@ -97,7 +97,7 @@ void speex_bits_destroy(SpeexBits *bits)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ROCKBOX_VOICE_ENCODER
|
#ifdef ROCKBOX_VOICE_ENCODER
|
||||||
void speex_bits_reset(SpeexBits *bits)
|
EXPORT void speex_bits_reset(SpeexBits *bits)
|
||||||
{
|
{
|
||||||
/* We only need to clear the first byte now */
|
/* We only need to clear the first byte now */
|
||||||
bits->chars[0]=0;
|
bits->chars[0]=0;
|
||||||
|
@ -110,7 +110,7 @@ void speex_bits_reset(SpeexBits *bits)
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* Rockbox: unused */
|
/* Rockbox: unused */
|
||||||
void speex_bits_rewind(SpeexBits *bits)
|
EXPORT void speex_bits_rewind(SpeexBits *bits)
|
||||||
{
|
{
|
||||||
bits->charPtr=0;
|
bits->charPtr=0;
|
||||||
bits->bitPtr=0;
|
bits->bitPtr=0;
|
||||||
|
@ -119,7 +119,7 @@ void speex_bits_rewind(SpeexBits *bits)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(SPEEX_VOICE_ENCODER) && !defined(ROCKBOX_VOICE_CODEC)
|
#if !defined(SPEEX_VOICE_ENCODER) && !defined(ROCKBOX_VOICE_CODEC)
|
||||||
void speex_bits_read_from(SpeexBits *bits, char *chars, int len)
|
EXPORT void speex_bits_read_from(SpeexBits *bits, char *chars, int len)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int nchars = len / BYTES_PER_CHAR;
|
int nchars = len / BYTES_PER_CHAR;
|
||||||
|
@ -166,9 +166,10 @@ static void speex_bits_flush(SpeexBits *bits)
|
||||||
bits->charPtr=0;
|
bits->charPtr=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void speex_bits_read_whole_bytes(SpeexBits *bits, char *chars, int nbytes)
|
EXPORT void speex_bits_read_whole_bytes(SpeexBits *bits, char *chars, int nbytes)
|
||||||
{
|
{
|
||||||
int i,pos;
|
int i,pos;
|
||||||
|
|
||||||
int nchars = nbytes/BYTES_PER_CHAR;
|
int nchars = nbytes/BYTES_PER_CHAR;
|
||||||
|
|
||||||
if (((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR)+nchars > bits->buf_size)
|
if (((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR)+nchars > bits->buf_size)
|
||||||
|
@ -200,7 +201,7 @@ void speex_bits_read_whole_bytes(SpeexBits *bits, char *chars, int nbytes)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SPEEX_DISABLE_ENCODER
|
#ifndef SPEEX_DISABLE_ENCODER
|
||||||
int speex_bits_write(SpeexBits *bits, char *chars, int max_nbytes)
|
EXPORT int speex_bits_write(SpeexBits *bits, char *chars, int max_nbytes)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int max_nchars = max_nbytes/BYTES_PER_CHAR;
|
int max_nchars = max_nbytes/BYTES_PER_CHAR;
|
||||||
|
@ -223,7 +224,7 @@ int speex_bits_write(SpeexBits *bits, char *chars, int max_nbytes)
|
||||||
return max_nchars*BYTES_PER_CHAR;
|
return max_nchars*BYTES_PER_CHAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
int speex_bits_write_whole_bytes(SpeexBits *bits, char *chars, int max_nbytes)
|
EXPORT int speex_bits_write_whole_bytes(SpeexBits *bits, char *chars, int max_nbytes)
|
||||||
{
|
{
|
||||||
int max_nchars = max_nbytes/BYTES_PER_CHAR;
|
int max_nchars = max_nbytes/BYTES_PER_CHAR;
|
||||||
int i;
|
int i;
|
||||||
|
@ -241,7 +242,7 @@ int speex_bits_write_whole_bytes(SpeexBits *bits, char *chars, int max_nbytes)
|
||||||
return max_nchars*BYTES_PER_CHAR;
|
return max_nchars*BYTES_PER_CHAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void speex_bits_pack(SpeexBits *bits, int data, int nbBits)
|
EXPORT void speex_bits_pack(SpeexBits *bits, int data, int nbBits)
|
||||||
{
|
{
|
||||||
unsigned int d=data;
|
unsigned int d=data;
|
||||||
|
|
||||||
|
@ -287,7 +288,7 @@ void speex_bits_pack(SpeexBits *bits, int data, int nbBits)
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* Rockbox: unused */
|
/* Rockbox: unused */
|
||||||
int speex_bits_unpack_signed(SpeexBits *bits, int nbBits)
|
EXPORT int speex_bits_unpack_signed(SpeexBits *bits, int nbBits)
|
||||||
{
|
{
|
||||||
unsigned int d=speex_bits_unpack_unsigned(bits,nbBits);
|
unsigned int d=speex_bits_unpack_unsigned(bits,nbBits);
|
||||||
/* If number is negative */
|
/* If number is negative */
|
||||||
|
@ -299,7 +300,7 @@ int speex_bits_unpack_signed(SpeexBits *bits, int nbBits)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits)
|
EXPORT unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits)
|
||||||
{
|
{
|
||||||
unsigned int d=0;
|
unsigned int d=0;
|
||||||
if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+nbBits>bits->nbBits)
|
if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+nbBits>bits->nbBits)
|
||||||
|
@ -323,7 +324,7 @@ unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits)
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* Rockbox: unused */
|
/* Rockbox: unused */
|
||||||
unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits)
|
EXPORT unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits)
|
||||||
{
|
{
|
||||||
unsigned int d=0;
|
unsigned int d=0;
|
||||||
int bitPtr, charPtr;
|
int bitPtr, charPtr;
|
||||||
|
@ -353,7 +354,7 @@ unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int speex_bits_peek(SpeexBits *bits)
|
EXPORT int speex_bits_peek(SpeexBits *bits)
|
||||||
{
|
{
|
||||||
if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+1>bits->nbBits)
|
if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+1>bits->nbBits)
|
||||||
bits->overflow=1;
|
bits->overflow=1;
|
||||||
|
@ -362,7 +363,7 @@ int speex_bits_peek(SpeexBits *bits)
|
||||||
return (bits->chars[bits->charPtr]>>(BITS_PER_CHAR-1 - bits->bitPtr))&1;
|
return (bits->chars[bits->charPtr]>>(BITS_PER_CHAR-1 - bits->bitPtr))&1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void speex_bits_advance(SpeexBits *bits, int n)
|
EXPORT void speex_bits_advance(SpeexBits *bits, int n)
|
||||||
{
|
{
|
||||||
if (((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+n>bits->nbBits) || bits->overflow){
|
if (((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+n>bits->nbBits) || bits->overflow){
|
||||||
bits->overflow=1;
|
bits->overflow=1;
|
||||||
|
@ -372,7 +373,7 @@ void speex_bits_advance(SpeexBits *bits, int n)
|
||||||
bits->bitPtr = (bits->bitPtr+n) & (BITS_PER_CHAR-1); /* modulo by BITS_PER_CHAR */
|
bits->bitPtr = (bits->bitPtr+n) & (BITS_PER_CHAR-1); /* modulo by BITS_PER_CHAR */
|
||||||
}
|
}
|
||||||
|
|
||||||
int speex_bits_remaining(SpeexBits *bits)
|
EXPORT int speex_bits_remaining(SpeexBits *bits)
|
||||||
{
|
{
|
||||||
if (bits->overflow)
|
if (bits->overflow)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -382,14 +383,14 @@ int speex_bits_remaining(SpeexBits *bits)
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* Rockbox: unused */
|
/* Rockbox: unused */
|
||||||
int speex_bits_nbytes(SpeexBits *bits)
|
EXPORT int speex_bits_nbytes(SpeexBits *bits)
|
||||||
{
|
{
|
||||||
return ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR);
|
return ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SPEEX_DISABLE_ENCODER
|
#ifndef SPEEX_DISABLE_ENCODER
|
||||||
void speex_bits_insert_terminator(SpeexBits *bits)
|
EXPORT void speex_bits_insert_terminator(SpeexBits *bits)
|
||||||
{
|
{
|
||||||
if (bits->bitPtr)
|
if (bits->bitPtr)
|
||||||
speex_bits_pack(bits, 0, 1);
|
speex_bits_pack(bits, 0, 1);
|
||||||
|
|
|
@ -17,7 +17,11 @@
|
||||||
|
|
||||||
/* Make use of ARM4E assembly optimizations */
|
/* Make use of ARM4E assembly optimizations */
|
||||||
#if defined(CPU_ARM)
|
#if defined(CPU_ARM)
|
||||||
|
#if (ARM_ARCH < 5)
|
||||||
#define ARM4_ASM
|
#define ARM4_ASM
|
||||||
|
#else
|
||||||
|
#define ARM5E_ASM
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Make use of Coldfire assembly optimizations */
|
/* Make use of Coldfire assembly optimizations */
|
||||||
|
@ -137,13 +141,13 @@
|
||||||
#define SPEEX_MAJOR_VERSION 1
|
#define SPEEX_MAJOR_VERSION 1
|
||||||
|
|
||||||
/* Version micro */
|
/* Version micro */
|
||||||
#define SPEEX_MICRO_VERSION 15
|
#define SPEEX_MICRO_VERSION 16
|
||||||
|
|
||||||
/* Version minor */
|
/* Version minor */
|
||||||
#define SPEEX_MINOR_VERSION 1
|
#define SPEEX_MINOR_VERSION 1
|
||||||
|
|
||||||
/* Complete version string */
|
/* Complete version string */
|
||||||
#define SPEEX_VERSION "1.2beta3"
|
#define SPEEX_VERSION "1.2rc1"
|
||||||
|
|
||||||
/* Define to 1 if you have the ANSI C header files. */
|
/* Define to 1 if you have the ANSI C header files. */
|
||||||
#define STDC_HEADERS 1
|
#define STDC_HEADERS 1
|
||||||
|
@ -184,3 +188,7 @@
|
||||||
|
|
||||||
#define RELEASE 1
|
#define RELEASE 1
|
||||||
|
|
||||||
|
/* We don't care */
|
||||||
|
#define EXPORT
|
||||||
|
|
||||||
|
#define USE_KISS_FFT
|
||||||
|
|
|
@ -36,10 +36,6 @@
|
||||||
#include "config-speex.h"
|
#include "config-speex.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*#define USE_SMALLFT*/
|
|
||||||
#define USE_KISS_FFT
|
|
||||||
|
|
||||||
|
|
||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
#include "os_support.h"
|
#include "os_support.h"
|
||||||
|
|
||||||
|
@ -130,6 +126,119 @@ void spx_ifft(void *table, float *in, float *out)
|
||||||
spx_drft_backward((struct drft_lookup *)table, out);
|
spx_drft_backward((struct drft_lookup *)table, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(USE_INTEL_MKL)
|
||||||
|
#include <mkl.h>
|
||||||
|
|
||||||
|
struct mkl_config {
|
||||||
|
DFTI_DESCRIPTOR_HANDLE desc;
|
||||||
|
int N;
|
||||||
|
};
|
||||||
|
|
||||||
|
void *spx_fft_init(int size)
|
||||||
|
{
|
||||||
|
struct mkl_config *table = (struct mkl_config *) speex_alloc(sizeof(struct mkl_config));
|
||||||
|
table->N = size;
|
||||||
|
DftiCreateDescriptor(&table->desc, DFTI_SINGLE, DFTI_REAL, 1, size);
|
||||||
|
DftiSetValue(table->desc, DFTI_PACKED_FORMAT, DFTI_PACK_FORMAT);
|
||||||
|
DftiSetValue(table->desc, DFTI_PLACEMENT, DFTI_NOT_INPLACE);
|
||||||
|
DftiSetValue(table->desc, DFTI_FORWARD_SCALE, 1.0f / size);
|
||||||
|
DftiCommitDescriptor(table->desc);
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spx_fft_destroy(void *table)
|
||||||
|
{
|
||||||
|
struct mkl_config *t = (struct mkl_config *) table;
|
||||||
|
DftiFreeDescriptor(t->desc);
|
||||||
|
speex_free(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out)
|
||||||
|
{
|
||||||
|
struct mkl_config *t = (struct mkl_config *) table;
|
||||||
|
DftiComputeForward(t->desc, in, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out)
|
||||||
|
{
|
||||||
|
struct mkl_config *t = (struct mkl_config *) table;
|
||||||
|
DftiComputeBackward(t->desc, in, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(USE_GPL_FFTW3)
|
||||||
|
|
||||||
|
#include <fftw3.h>
|
||||||
|
|
||||||
|
struct fftw_config {
|
||||||
|
float *in;
|
||||||
|
float *out;
|
||||||
|
fftwf_plan fft;
|
||||||
|
fftwf_plan ifft;
|
||||||
|
int N;
|
||||||
|
};
|
||||||
|
|
||||||
|
void *spx_fft_init(int size)
|
||||||
|
{
|
||||||
|
struct fftw_config *table = (struct fftw_config *) speex_alloc(sizeof(struct fftw_config));
|
||||||
|
table->in = fftwf_malloc(sizeof(float) * (size+2));
|
||||||
|
table->out = fftwf_malloc(sizeof(float) * (size+2));
|
||||||
|
|
||||||
|
table->fft = fftwf_plan_dft_r2c_1d(size, table->in, (fftwf_complex *) table->out, FFTW_PATIENT);
|
||||||
|
table->ifft = fftwf_plan_dft_c2r_1d(size, (fftwf_complex *) table->in, table->out, FFTW_PATIENT);
|
||||||
|
|
||||||
|
table->N = size;
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spx_fft_destroy(void *table)
|
||||||
|
{
|
||||||
|
struct fftw_config *t = (struct fftw_config *) table;
|
||||||
|
fftwf_destroy_plan(t->fft);
|
||||||
|
fftwf_destroy_plan(t->ifft);
|
||||||
|
fftwf_free(t->in);
|
||||||
|
fftwf_free(t->out);
|
||||||
|
speex_free(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct fftw_config *t = (struct fftw_config *) table;
|
||||||
|
const int N = t->N;
|
||||||
|
float *iptr = t->in;
|
||||||
|
float *optr = t->out;
|
||||||
|
const float m = 1.0 / N;
|
||||||
|
for(i=0;i<N;++i)
|
||||||
|
iptr[i]=in[i] * m;
|
||||||
|
|
||||||
|
fftwf_execute(t->fft);
|
||||||
|
|
||||||
|
out[0] = optr[0];
|
||||||
|
for(i=1;i<N;++i)
|
||||||
|
out[i] = optr[i+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct fftw_config *t = (struct fftw_config *) table;
|
||||||
|
const int N = t->N;
|
||||||
|
float *iptr = t->in;
|
||||||
|
float *optr = t->out;
|
||||||
|
|
||||||
|
iptr[0] = in[0];
|
||||||
|
iptr[1] = 0.0f;
|
||||||
|
for(i=1;i<N;++i)
|
||||||
|
iptr[i+1] = in[i];
|
||||||
|
iptr[N+1] = 0.0f;
|
||||||
|
|
||||||
|
fftwf_execute(t->ifft);
|
||||||
|
|
||||||
|
for(i=0;i<N;++i)
|
||||||
|
out[i] = optr[i];
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined(USE_KISS_FFT)
|
#elif defined(USE_KISS_FFT)
|
||||||
|
|
||||||
#include "kiss_fftr.h"
|
#include "kiss_fftr.h"
|
||||||
|
|
|
@ -86,7 +86,7 @@ int normalize16(const spx_sig_t *x, spx_word16_t *y, spx_sig_t max_scale, int le
|
||||||
"\tmov %5, %5, asr %3 \n"
|
"\tmov %5, %5, asr %3 \n"
|
||||||
"\tstrh %5, [%1], #2 \n"
|
"\tstrh %5, [%1], #2 \n"
|
||||||
|
|
||||||
"\tbge .normalize16loop%=\n"
|
"\tbgt .normalize16loop%=\n"
|
||||||
: "=r" (dead1), "=r" (dead2), "=r" (dead3), "=r" (dead4),
|
: "=r" (dead1), "=r" (dead2), "=r" (dead3), "=r" (dead4),
|
||||||
"=r" (dead5), "=r" (dead6)
|
"=r" (dead5), "=r" (dead6)
|
||||||
: "0" (x), "1" (y), "2" (len>>2), "3" (sig_shift)
|
: "0" (x), "1" (y), "2" (len>>2), "3" (sig_shift)
|
||||||
|
|
|
@ -161,7 +161,7 @@ static inline int SHL32(long long a, int shift)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PSHR16(a,shift) (SHR16(ADD16((a),((1<<((shift))>>1))),shift))
|
#define PSHR16(a,shift) (SHR16(ADD16((a),((1<<((shift))>>1))),shift))
|
||||||
#define PSHR32(a,shift) (SHR32(ADD32((a),((1<<((shift))>>1))),shift))
|
#define PSHR32(a,shift) (SHR32(ADD32((a),((EXTEND32(1)<<((shift))>>1))),shift))
|
||||||
#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
|
#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
|
||||||
|
|
||||||
#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
|
#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
|
||||||
|
@ -279,7 +279,7 @@ static inline int _MULT16_32_QX(int a, long long b, int Q, char *file, int line)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "MULT16_32_Q%d: inputs are not short+int: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
|
fprintf (stderr, "MULT16_32_Q%d: inputs are not short+int: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
|
||||||
}
|
}
|
||||||
if (ABS32(b)>=(1<<(15+Q)))
|
if (ABS32(b)>=(EXTEND32(1)<<(15+Q)))
|
||||||
fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
|
fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
|
||||||
res = (((long long)a)*(long long)b) >> Q;
|
res = (((long long)a)*(long long)b) >> Q;
|
||||||
if (!VERIFY_INT(res))
|
if (!VERIFY_INT(res))
|
||||||
|
@ -295,9 +295,9 @@ static inline int MULT16_32_PX(int a, long long b, int Q)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b);
|
fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b);
|
||||||
}
|
}
|
||||||
if (ABS32(b)>=(1<<(15+Q)))
|
if (ABS32(b)>=(EXTEND32(1)<<(15+Q)))
|
||||||
fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b);
|
fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b);
|
||||||
res = ((((long long)a)*(long long)b) + ((1<<Q)>>1))>> Q;
|
res = ((((long long)a)*(long long)b) + ((EXTEND32(1)<<Q)>>1))>> Q;
|
||||||
if (!VERIFY_INT(res))
|
if (!VERIFY_INT(res))
|
||||||
fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res);
|
fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res);
|
||||||
spx_mips+=5;
|
spx_mips+=5;
|
||||||
|
|
|
@ -47,14 +47,14 @@
|
||||||
#define SHR32(a,shift) ((a) >> (shift))
|
#define SHR32(a,shift) ((a) >> (shift))
|
||||||
#define SHL32(a,shift) ((a) << (shift))
|
#define SHL32(a,shift) ((a) << (shift))
|
||||||
#define PSHR16(a,shift) (SHR16((a)+((1<<((shift))>>1)),shift))
|
#define PSHR16(a,shift) (SHR16((a)+((1<<((shift))>>1)),shift))
|
||||||
#define PSHR32(a,shift) (SHR32((a)+((1<<((shift))>>1)),shift))
|
#define PSHR32(a,shift) (SHR32((a)+((EXTEND32(1)<<((shift))>>1)),shift))
|
||||||
#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
|
#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
|
||||||
#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
|
#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
|
||||||
#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
|
#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
|
||||||
|
|
||||||
#define SHR(a,shift) ((a) >> (shift))
|
#define SHR(a,shift) ((a) >> (shift))
|
||||||
#define SHL(a,shift) ((spx_word32_t)(a) << (shift))
|
#define SHL(a,shift) ((spx_word32_t)(a) << (shift))
|
||||||
#define PSHR(a,shift) (SHR((a)+((1<<((shift))>>1)),shift))
|
#define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift))
|
||||||
#define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
|
#define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -75,15 +75,15 @@ TODO:
|
||||||
|
|
||||||
#define ROUND_DOWN(x, step) ((x)<0 ? ((x)-(step)+1)/(step)*(step) : (x)/(step)*(step))
|
#define ROUND_DOWN(x, step) ((x)<0 ? ((x)-(step)+1)/(step)*(step) : (x)/(step)*(step))
|
||||||
|
|
||||||
#define MAX_TIMINGS 20
|
#define MAX_TIMINGS 40
|
||||||
#define MAX_BUFFERS 3
|
#define MAX_BUFFERS 3
|
||||||
#define TOP_DELAY 20
|
#define TOP_DELAY 40
|
||||||
|
|
||||||
/** Buffer that keeps the time of arrival of the latest packets */
|
/** Buffer that keeps the time of arrival of the latest packets */
|
||||||
struct TimingBuffer {
|
struct TimingBuffer {
|
||||||
int filled; /**< Number of entries occupied in "timing" and "counts"*/
|
int filled; /**< Number of entries occupied in "timing" and "counts"*/
|
||||||
int curr_count; /**< Number of packet timings we got (including those we discarded) */
|
int curr_count; /**< Number of packet timings we got (including those we discarded) */
|
||||||
spx_int16_t timing[MAX_TIMINGS]; /**< Sorted list of all timings ("latest" packets first) */
|
spx_int32_t timing[MAX_TIMINGS]; /**< Sorted list of all timings ("latest" packets first) */
|
||||||
spx_int16_t counts[MAX_TIMINGS]; /**< Order the packets were put in (will be used for short-term estimate) */
|
spx_int16_t counts[MAX_TIMINGS]; /**< Order the packets were put in (will be used for short-term estimate) */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ static spx_int16_t compute_opt_delay(JitterBuffer *jitter)
|
||||||
if (latest >= 0 && !penalty_taken)
|
if (latest >= 0 && !penalty_taken)
|
||||||
{
|
{
|
||||||
penalty_taken = 1;
|
penalty_taken = 1;
|
||||||
late+=2;
|
late+=4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ static spx_int16_t compute_opt_delay(JitterBuffer *jitter)
|
||||||
|
|
||||||
|
|
||||||
/** Initialise jitter buffer */
|
/** Initialise jitter buffer */
|
||||||
JitterBuffer *jitter_buffer_init(int step_size)
|
EXPORT JitterBuffer *jitter_buffer_init(int step_size)
|
||||||
{
|
{
|
||||||
JitterBuffer *jitter = (JitterBuffer*)speex_alloc(sizeof(JitterBuffer));
|
JitterBuffer *jitter = (JitterBuffer*)speex_alloc(sizeof(JitterBuffer));
|
||||||
if (jitter)
|
if (jitter)
|
||||||
|
@ -294,7 +294,7 @@ JitterBuffer *jitter_buffer_init(int step_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Reset jitter buffer */
|
/** Reset jitter buffer */
|
||||||
void jitter_buffer_reset(JitterBuffer *jitter)
|
EXPORT void jitter_buffer_reset(JitterBuffer *jitter)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
|
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
|
||||||
|
@ -325,7 +325,7 @@ void jitter_buffer_reset(JitterBuffer *jitter)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Destroy jitter buffer */
|
/** Destroy jitter buffer */
|
||||||
void jitter_buffer_destroy(JitterBuffer *jitter)
|
EXPORT void jitter_buffer_destroy(JitterBuffer *jitter)
|
||||||
{
|
{
|
||||||
jitter_buffer_reset(jitter);
|
jitter_buffer_reset(jitter);
|
||||||
speex_free(jitter);
|
speex_free(jitter);
|
||||||
|
@ -365,7 +365,7 @@ static void shift_timings(JitterBuffer *jitter, spx_int16_t amount)
|
||||||
|
|
||||||
|
|
||||||
/** Put one packet into the jitter buffer */
|
/** Put one packet into the jitter buffer */
|
||||||
void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet)
|
EXPORT void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet)
|
||||||
{
|
{
|
||||||
int i,j;
|
int i,j;
|
||||||
int late;
|
int late;
|
||||||
|
@ -399,6 +399,13 @@ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet)
|
||||||
late = 0;
|
late = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For some reason, the consumer has failed the last 20 fetches. Make sure this packet is
|
||||||
|
* used to resync. */
|
||||||
|
if (jitter->lost_count>20)
|
||||||
|
{
|
||||||
|
jitter_buffer_reset(jitter);
|
||||||
|
}
|
||||||
|
|
||||||
/* Only insert the packet if it's not hopelessly late (i.e. totally useless) */
|
/* Only insert the packet if it's not hopelessly late (i.e. totally useless) */
|
||||||
if (jitter->reset_state || GE32(packet->timestamp+packet->span+jitter->delay_step, jitter->pointer_timestamp))
|
if (jitter->reset_state || GE32(packet->timestamp+packet->span+jitter->delay_step, jitter->pointer_timestamp))
|
||||||
{
|
{
|
||||||
|
@ -428,10 +435,6 @@ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet)
|
||||||
else
|
else
|
||||||
speex_free(jitter->packets[i].data);
|
speex_free(jitter->packets[i].data);
|
||||||
jitter->packets[i].data=NULL;
|
jitter->packets[i].data=NULL;
|
||||||
if (jitter->lost_count>20)
|
|
||||||
{
|
|
||||||
jitter_buffer_reset(jitter);
|
|
||||||
}
|
|
||||||
/*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/
|
/*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,7 +462,7 @@ void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get one packet from the jitter buffer */
|
/** Get one packet from the jitter buffer */
|
||||||
int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset)
|
EXPORT int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
|
@ -673,7 +676,7 @@ int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int3
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet)
|
EXPORT int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
|
for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)
|
||||||
|
@ -732,7 +735,7 @@ static int _jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Let the jitter buffer know it's the right time to adjust the buffering delay to the network conditions */
|
/* Let the jitter buffer know it's the right time to adjust the buffering delay to the network conditions */
|
||||||
int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset)
|
EXPORT int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset)
|
||||||
{
|
{
|
||||||
/* If the programmer calls jitter_buffer_update_delay() directly,
|
/* If the programmer calls jitter_buffer_update_delay() directly,
|
||||||
automatically disable auto-adjustment */
|
automatically disable auto-adjustment */
|
||||||
|
@ -742,12 +745,12 @@ int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet,
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get pointer timestamp of jitter buffer */
|
/** Get pointer timestamp of jitter buffer */
|
||||||
int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter)
|
EXPORT int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter)
|
||||||
{
|
{
|
||||||
return jitter->pointer_timestamp;
|
return jitter->pointer_timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void jitter_buffer_tick(JitterBuffer *jitter)
|
EXPORT void jitter_buffer_tick(JitterBuffer *jitter)
|
||||||
{
|
{
|
||||||
/* Automatically-adjust the buffering delay if requested */
|
/* Automatically-adjust the buffering delay if requested */
|
||||||
if (jitter->auto_adjust)
|
if (jitter->auto_adjust)
|
||||||
|
@ -763,7 +766,7 @@ void jitter_buffer_tick(JitterBuffer *jitter)
|
||||||
jitter->buffered = 0;
|
jitter->buffered = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem)
|
EXPORT void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem)
|
||||||
{
|
{
|
||||||
/* Automatically-adjust the buffering delay if requested */
|
/* Automatically-adjust the buffering delay if requested */
|
||||||
if (jitter->auto_adjust)
|
if (jitter->auto_adjust)
|
||||||
|
@ -776,7 +779,7 @@ void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem)
|
||||||
|
|
||||||
|
|
||||||
/* Used like the ioctl function to control the jitter buffer parameters */
|
/* Used like the ioctl function to control the jitter buffer parameters */
|
||||||
int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr)
|
EXPORT int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr)
|
||||||
{
|
{
|
||||||
int count, i;
|
int count, i;
|
||||||
switch(request)
|
switch(request)
|
||||||
|
@ -836,4 +839,3 @@ int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr)
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2003-2006 Jean-Marc Valin
|
/* Copyright (C) 2003-2008 Jean-Marc Valin
|
||||||
|
|
||||||
File: mdf.c
|
File: mdf.c
|
||||||
Echo canceller based on the MDF algorithm (see below)
|
Echo canceller based on the MDF algorithm (see below)
|
||||||
|
@ -88,6 +88,12 @@
|
||||||
#define WEIGHT_SHIFT 0
|
#define WEIGHT_SHIFT 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef FIXED_POINT
|
||||||
|
#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x)))
|
||||||
|
#else
|
||||||
|
#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))
|
||||||
|
#endif
|
||||||
|
|
||||||
/* If enabled, the AEC will use a foreground filter and a background filter to be more robust to double-talk
|
/* If enabled, the AEC will use a foreground filter and a background filter to be more robust to double-talk
|
||||||
and difficult signals in general. The cost is an extra FFT and a matrix-vector multiply */
|
and difficult signals in general. The cost is an extra FFT and a matrix-vector multiply */
|
||||||
#define TWO_PATH
|
#define TWO_PATH
|
||||||
|
@ -131,6 +137,8 @@ struct SpeexEchoState_ {
|
||||||
int adapted;
|
int adapted;
|
||||||
int saturated;
|
int saturated;
|
||||||
int screwed_up;
|
int screwed_up;
|
||||||
|
int C; /** Number of input channels (microphones) */
|
||||||
|
int K; /** Number of output channels (loudspeakers) */
|
||||||
spx_int32_t sampling_rate;
|
spx_int32_t sampling_rate;
|
||||||
spx_word16_t spec_average;
|
spx_word16_t spec_average;
|
||||||
spx_word16_t beta0;
|
spx_word16_t beta0;
|
||||||
|
@ -171,10 +179,10 @@ struct SpeexEchoState_ {
|
||||||
spx_word16_t *window;
|
spx_word16_t *window;
|
||||||
spx_word16_t *prop;
|
spx_word16_t *prop;
|
||||||
void *fft_table;
|
void *fft_table;
|
||||||
spx_word16_t memX, memD, memE;
|
spx_word16_t *memX, *memD, *memE;
|
||||||
spx_word16_t preemph;
|
spx_word16_t preemph;
|
||||||
spx_word16_t notch_radius;
|
spx_word16_t notch_radius;
|
||||||
spx_mem_t notch_mem[2];
|
spx_mem_t *notch_mem;
|
||||||
|
|
||||||
/* NOTE: If you only use speex_echo_cancel() and want to save some memory, remove this */
|
/* NOTE: If you only use speex_echo_cancel() and want to save some memory, remove this */
|
||||||
spx_int16_t *play_buf;
|
spx_int16_t *play_buf;
|
||||||
|
@ -182,7 +190,7 @@ struct SpeexEchoState_ {
|
||||||
int play_buf_started;
|
int play_buf_started;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void filter_dc_notch16(const spx_int16_t *in, spx_word16_t radius, spx_word16_t *out, int len, spx_mem_t *mem)
|
static inline void filter_dc_notch16(const spx_int16_t *in, spx_word16_t radius, spx_word16_t *out, int len, spx_mem_t *mem, int stride)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
spx_word16_t den2;
|
spx_word16_t den2;
|
||||||
|
@ -194,7 +202,7 @@ static inline void filter_dc_notch16(const spx_int16_t *in, spx_word16_t radius,
|
||||||
/*printf ("%d %d %d %d %d %d\n", num[0], num[1], num[2], den[0], den[1], den[2]);*/
|
/*printf ("%d %d %d %d %d %d\n", num[0], num[1], num[2], den[0], den[1], den[2]);*/
|
||||||
for (i=0;i<len;i++)
|
for (i=0;i<len;i++)
|
||||||
{
|
{
|
||||||
spx_word16_t vin = in[i];
|
spx_word16_t vin = in[i*stride];
|
||||||
spx_word32_t vout = mem[0] + SHL32(EXTEND32(vin),15);
|
spx_word32_t vout = mem[0] + SHL32(EXTEND32(vin),15);
|
||||||
#ifdef FIXED_POINT
|
#ifdef FIXED_POINT
|
||||||
mem[0] = mem[1] + SHL32(SHL32(-EXTEND32(vin),15) + MULT16_32_Q15(radius,vout),1);
|
mem[0] = mem[1] + SHL32(SHL32(-EXTEND32(vin),15) + MULT16_32_Q15(radius,vout),1);
|
||||||
|
@ -234,6 +242,18 @@ static inline void power_spectrum(const spx_word16_t *X, spx_word32_t *ps, int N
|
||||||
ps[j]=MULT16_16(X[i],X[i]);
|
ps[j]=MULT16_16(X[i],X[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Compute power spectrum of a half-complex (packed) vector and accumulate */
|
||||||
|
static inline void power_spectrum_accum(const spx_word16_t *X, spx_word32_t *ps, int N)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
ps[0]+=MULT16_16(X[0],X[0]);
|
||||||
|
for (i=1,j=1;i<N-1;i+=2,j++)
|
||||||
|
{
|
||||||
|
ps[j] += MULT16_16(X[i],X[i]) + MULT16_16(X[i+1],X[i+1]);
|
||||||
|
}
|
||||||
|
ps[j]+=MULT16_16(X[i],X[i]);
|
||||||
|
}
|
||||||
|
|
||||||
/** Compute cross-power spectrum of a half-complex (packed) vectors and add to acc */
|
/** Compute cross-power spectrum of a half-complex (packed) vectors and add to acc */
|
||||||
#ifdef FIXED_POINT
|
#ifdef FIXED_POINT
|
||||||
static inline void spectral_mul_accum(const spx_word16_t *X, const spx_word32_t *Y, spx_word16_t *acc, int N, int M)
|
static inline void spectral_mul_accum(const spx_word16_t *X, const spx_word32_t *Y, spx_word16_t *acc, int N, int M)
|
||||||
|
@ -330,16 +350,17 @@ static inline void weighted_spectral_mul_conj(const spx_float_t *w, const spx_fl
|
||||||
prod[i] = FLOAT_MUL32(W,MULT16_16(X[i],Y[i]));
|
prod[i] = FLOAT_MUL32(W,MULT16_16(X[i],Y[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void mdf_adjust_prop(const spx_word32_t *W, int N, int M, spx_word16_t *prop)
|
static inline void mdf_adjust_prop(const spx_word32_t *W, int N, int M, int P, spx_word16_t *prop)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j, p;
|
||||||
spx_word16_t max_sum = 1;
|
spx_word16_t max_sum = 1;
|
||||||
spx_word32_t prop_sum = 1;
|
spx_word32_t prop_sum = 1;
|
||||||
for (i=0;i<M;i++)
|
for (i=0;i<M;i++)
|
||||||
{
|
{
|
||||||
spx_word32_t tmp = 1;
|
spx_word32_t tmp = 1;
|
||||||
|
for (p=0;p<P;p++)
|
||||||
for (j=0;j<N;j++)
|
for (j=0;j<N;j++)
|
||||||
tmp += MULT16_16(EXTRACT16(SHR32(W[i*N+j],18)), EXTRACT16(SHR32(W[i*N+j],18)));
|
tmp += MULT16_16(EXTRACT16(SHR32(W[p*N*M + i*N+j],18)), EXTRACT16(SHR32(W[p*N*M + i*N+j],18)));
|
||||||
#ifdef FIXED_POINT
|
#ifdef FIXED_POINT
|
||||||
/* Just a security in case an overflow were to occur */
|
/* Just a security in case an overflow were to occur */
|
||||||
tmp = MIN32(ABS32(tmp), 536870912);
|
tmp = MIN32(ABS32(tmp), 536870912);
|
||||||
|
@ -378,11 +399,20 @@ static void dump_audio(const spx_int16_t *rec, const spx_int16_t *play, const sp
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** Creates a new echo canceller state */
|
/** Creates a new echo canceller state */
|
||||||
SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length)
|
EXPORT SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length)
|
||||||
{
|
{
|
||||||
int i,N,M;
|
return speex_echo_state_init_mc(frame_size, filter_length, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT SpeexEchoState *speex_echo_state_init_mc(int frame_size, int filter_length, int nb_mic, int nb_speakers)
|
||||||
|
{
|
||||||
|
int i,N,M, C, K;
|
||||||
SpeexEchoState *st = (SpeexEchoState *)speex_alloc(sizeof(SpeexEchoState));
|
SpeexEchoState *st = (SpeexEchoState *)speex_alloc(sizeof(SpeexEchoState));
|
||||||
|
|
||||||
|
st->K = nb_speakers;
|
||||||
|
st->C = nb_mic;
|
||||||
|
C=st->C;
|
||||||
|
K=st->K;
|
||||||
#ifdef DUMP_ECHO_CANCEL_DATA
|
#ifdef DUMP_ECHO_CANCEL_DATA
|
||||||
if (rFile || pFile || oFile)
|
if (rFile || pFile || oFile)
|
||||||
speex_fatal("Opening dump files twice");
|
speex_fatal("Opening dump files twice");
|
||||||
|
@ -413,23 +443,23 @@ SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length)
|
||||||
|
|
||||||
st->fft_table = spx_fft_init(N);
|
st->fft_table = spx_fft_init(N);
|
||||||
|
|
||||||
st->e = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t));
|
st->e = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t));
|
||||||
st->x = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t));
|
st->x = (spx_word16_t*)speex_alloc(K*N*sizeof(spx_word16_t));
|
||||||
st->input = (spx_word16_t*)speex_alloc(st->frame_size*sizeof(spx_word16_t));
|
st->input = (spx_word16_t*)speex_alloc(C*st->frame_size*sizeof(spx_word16_t));
|
||||||
st->y = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t));
|
st->y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t));
|
||||||
st->last_y = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t));
|
st->last_y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t));
|
||||||
st->Yf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t));
|
st->Yf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t));
|
||||||
st->Rf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t));
|
st->Rf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t));
|
||||||
st->Xf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t));
|
st->Xf = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t));
|
||||||
st->Yh = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t));
|
st->Yh = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t));
|
||||||
st->Eh = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t));
|
st->Eh = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t));
|
||||||
|
|
||||||
st->X = (spx_word16_t*)speex_alloc((M+1)*N*sizeof(spx_word16_t));
|
st->X = (spx_word16_t*)speex_alloc(K*(M+1)*N*sizeof(spx_word16_t));
|
||||||
st->Y = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t));
|
st->Y = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t));
|
||||||
st->E = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t));
|
st->E = (spx_word16_t*)speex_alloc(C*N*sizeof(spx_word16_t));
|
||||||
st->W = (spx_word32_t*)speex_alloc(M*N*sizeof(spx_word32_t));
|
st->W = (spx_word32_t*)speex_alloc(C*K*M*N*sizeof(spx_word32_t));
|
||||||
#ifdef TWO_PATH
|
#ifdef TWO_PATH
|
||||||
st->foreground = (spx_word16_t*)speex_alloc(M*N*sizeof(spx_word16_t));
|
st->foreground = (spx_word16_t*)speex_alloc(M*N*C*K*sizeof(spx_word16_t));
|
||||||
#endif
|
#endif
|
||||||
st->PHI = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t));
|
st->PHI = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t));
|
||||||
st->power = (spx_word32_t*)speex_alloc((frame_size+1)*sizeof(spx_word32_t));
|
st->power = (spx_word32_t*)speex_alloc((frame_size+1)*sizeof(spx_word32_t));
|
||||||
|
@ -450,7 +480,7 @@ SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length)
|
||||||
#endif
|
#endif
|
||||||
for (i=0;i<=st->frame_size;i++)
|
for (i=0;i<=st->frame_size;i++)
|
||||||
st->power_1[i] = FLOAT_ONE;
|
st->power_1[i] = FLOAT_ONE;
|
||||||
for (i=0;i<N*M;i++)
|
for (i=0;i<N*M*K*C;i++)
|
||||||
st->W[i] = 0;
|
st->W[i] = 0;
|
||||||
{
|
{
|
||||||
spx_word32_t sum = 0;
|
spx_word32_t sum = 0;
|
||||||
|
@ -465,11 +495,13 @@ SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length)
|
||||||
}
|
}
|
||||||
for (i=M-1;i>=0;i--)
|
for (i=M-1;i>=0;i--)
|
||||||
{
|
{
|
||||||
st->prop[i] = DIV32(MULT16_16(QCONST16(.8,15), st->prop[i]),sum);
|
st->prop[i] = DIV32(MULT16_16(QCONST16(.8f,15), st->prop[i]),sum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
st->memX=st->memD=st->memE=0;
|
st->memX = (spx_word16_t*)speex_alloc(K*sizeof(spx_word16_t));
|
||||||
|
st->memD = (spx_word16_t*)speex_alloc(C*sizeof(spx_word16_t));
|
||||||
|
st->memE = (spx_word16_t*)speex_alloc(C*sizeof(spx_word16_t));
|
||||||
st->preemph = QCONST16(.9,15);
|
st->preemph = QCONST16(.9,15);
|
||||||
if (st->sampling_rate<12000)
|
if (st->sampling_rate<12000)
|
||||||
st->notch_radius = QCONST16(.9, 15);
|
st->notch_radius = QCONST16(.9, 15);
|
||||||
|
@ -478,7 +510,7 @@ SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length)
|
||||||
else
|
else
|
||||||
st->notch_radius = QCONST16(.992, 15);
|
st->notch_radius = QCONST16(.992, 15);
|
||||||
|
|
||||||
st->notch_mem[0] = st->notch_mem[1] = 0;
|
st->notch_mem = (spx_mem_t*)speex_alloc(2*C*sizeof(spx_mem_t));
|
||||||
st->adapted = 0;
|
st->adapted = 0;
|
||||||
st->Pey = st->Pyy = FLOAT_ONE;
|
st->Pey = st->Pyy = FLOAT_ONE;
|
||||||
|
|
||||||
|
@ -487,7 +519,7 @@ SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length)
|
||||||
st->Dvar1 = st->Dvar2 = FLOAT_ZERO;
|
st->Dvar1 = st->Dvar2 = FLOAT_ZERO;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
st->play_buf = (spx_int16_t*)speex_alloc((PLAYBACK_DELAY+1)*st->frame_size*sizeof(spx_int16_t));
|
st->play_buf = (spx_int16_t*)speex_alloc(K*(PLAYBACK_DELAY+1)*st->frame_size*sizeof(spx_int16_t));
|
||||||
st->play_buf_pos = PLAYBACK_DELAY*st->frame_size;
|
st->play_buf_pos = PLAYBACK_DELAY*st->frame_size;
|
||||||
st->play_buf_started = 0;
|
st->play_buf_started = 0;
|
||||||
|
|
||||||
|
@ -495,13 +527,15 @@ SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Resets echo canceller state */
|
/** Resets echo canceller state */
|
||||||
void speex_echo_state_reset(SpeexEchoState *st)
|
EXPORT void speex_echo_state_reset(SpeexEchoState *st)
|
||||||
{
|
{
|
||||||
int i, M, N;
|
int i, M, N, C, K;
|
||||||
st->cancel_count=0;
|
st->cancel_count=0;
|
||||||
st->screwed_up = 0;
|
st->screwed_up = 0;
|
||||||
N = st->window_size;
|
N = st->window_size;
|
||||||
M = st->M;
|
M = st->M;
|
||||||
|
C=st->C;
|
||||||
|
K=st->K;
|
||||||
for (i=0;i<N*M;i++)
|
for (i=0;i<N*M;i++)
|
||||||
st->W[i] = 0;
|
st->W[i] = 0;
|
||||||
#ifdef TWO_PATH
|
#ifdef TWO_PATH
|
||||||
|
@ -521,13 +555,20 @@ void speex_echo_state_reset(SpeexEchoState *st)
|
||||||
{
|
{
|
||||||
st->last_y[i] = 0;
|
st->last_y[i] = 0;
|
||||||
}
|
}
|
||||||
for (i=0;i<N;i++)
|
for (i=0;i<N*C;i++)
|
||||||
{
|
{
|
||||||
st->E[i] = 0;
|
st->E[i] = 0;
|
||||||
|
}
|
||||||
|
for (i=0;i<N*K;i++)
|
||||||
|
{
|
||||||
st->x[i] = 0;
|
st->x[i] = 0;
|
||||||
}
|
}
|
||||||
st->notch_mem[0] = st->notch_mem[1] = 0;
|
for (i=0;i<2*C;i++)
|
||||||
st->memX=st->memD=st->memE=0;
|
st->notch_mem[i] = 0;
|
||||||
|
for (i=0;i<C;i++)
|
||||||
|
st->memD[i]=st->memE[i]=0;
|
||||||
|
for (i=0;i<K;i++)
|
||||||
|
st->memX[i]=0;
|
||||||
|
|
||||||
st->saturated = 0;
|
st->saturated = 0;
|
||||||
st->adapted = 0;
|
st->adapted = 0;
|
||||||
|
@ -545,7 +586,7 @@ void speex_echo_state_reset(SpeexEchoState *st)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Destroys an echo canceller state */
|
/** Destroys an echo canceller state */
|
||||||
void speex_echo_state_destroy(SpeexEchoState *st)
|
EXPORT void speex_echo_state_destroy(SpeexEchoState *st)
|
||||||
{
|
{
|
||||||
spx_fft_destroy(st->fft_table);
|
spx_fft_destroy(st->fft_table);
|
||||||
|
|
||||||
|
@ -576,6 +617,11 @@ void speex_echo_state_destroy(SpeexEchoState *st)
|
||||||
#ifdef FIXED_POINT
|
#ifdef FIXED_POINT
|
||||||
speex_free(st->wtmp2);
|
speex_free(st->wtmp2);
|
||||||
#endif
|
#endif
|
||||||
|
speex_free(st->memX);
|
||||||
|
speex_free(st->memD);
|
||||||
|
speex_free(st->memE);
|
||||||
|
speex_free(st->notch_mem);
|
||||||
|
|
||||||
speex_free(st->play_buf);
|
speex_free(st->play_buf);
|
||||||
speex_free(st);
|
speex_free(st);
|
||||||
|
|
||||||
|
@ -587,7 +633,7 @@ void speex_echo_state_destroy(SpeexEchoState *st)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out)
|
EXPORT void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
/*speex_warning_int("capture with fill level ", st->play_buf_pos/st->frame_size);*/
|
/*speex_warning_int("capture with fill level ", st->play_buf_pos/st->frame_size);*/
|
||||||
|
@ -610,7 +656,7 @@ void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play)
|
EXPORT void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play)
|
||||||
{
|
{
|
||||||
/*speex_warning_int("playback with fill level ", st->play_buf_pos/st->frame_size);*/
|
/*speex_warning_int("playback with fill level ", st->play_buf_pos/st->frame_size);*/
|
||||||
if (!st->play_buf_started)
|
if (!st->play_buf_started)
|
||||||
|
@ -637,16 +683,16 @@ void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Performs echo cancellation on a frame (deprecated, last arg now ignored) */
|
/** Performs echo cancellation on a frame (deprecated, last arg now ignored) */
|
||||||
void speex_echo_cancel(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out, spx_int32_t *Yout)
|
EXPORT void speex_echo_cancel(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out, spx_int32_t *Yout)
|
||||||
{
|
{
|
||||||
speex_echo_cancellation(st, in, far_end, out);
|
speex_echo_cancellation(st, in, far_end, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Performs echo cancellation on a frame */
|
/** Performs echo cancellation on a frame */
|
||||||
void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out)
|
EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out)
|
||||||
{
|
{
|
||||||
int i,j;
|
int i,j, chan, speak;
|
||||||
int N,M;
|
int N,M, C, K;
|
||||||
spx_word32_t Syy,See,Sxx,Sdd, Sff;
|
spx_word32_t Syy,See,Sxx,Sdd, Sff;
|
||||||
#ifdef TWO_PATH
|
#ifdef TWO_PATH
|
||||||
spx_word32_t Dbf;
|
spx_word32_t Dbf;
|
||||||
|
@ -661,6 +707,9 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
|
||||||
|
|
||||||
N = st->window_size;
|
N = st->window_size;
|
||||||
M = st->M;
|
M = st->M;
|
||||||
|
C = st->C;
|
||||||
|
K = st->K;
|
||||||
|
|
||||||
st->cancel_count++;
|
st->cancel_count++;
|
||||||
#ifdef FIXED_POINT
|
#ifdef FIXED_POINT
|
||||||
ss=DIV32_16(11469,M);
|
ss=DIV32_16(11469,M);
|
||||||
|
@ -670,30 +719,17 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
|
||||||
ss_1 = 1-ss;
|
ss_1 = 1-ss;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
for (chan = 0; chan < C; chan++)
|
||||||
|
{
|
||||||
/* Apply a notch filter to make sure DC doesn't end up causing problems */
|
/* Apply a notch filter to make sure DC doesn't end up causing problems */
|
||||||
filter_dc_notch16(in, st->notch_radius, st->input, st->frame_size, st->notch_mem);
|
filter_dc_notch16(in+chan, st->notch_radius, st->input+chan*st->frame_size, st->frame_size, st->notch_mem+2*chan, C);
|
||||||
/* Copy input data to buffer and apply pre-emphasis */
|
/* Copy input data to buffer and apply pre-emphasis */
|
||||||
|
/* Copy input data to buffer */
|
||||||
for (i=0;i<st->frame_size;i++)
|
for (i=0;i<st->frame_size;i++)
|
||||||
{
|
{
|
||||||
spx_word32_t tmp32;
|
spx_word32_t tmp32;
|
||||||
tmp32 = SUB32(EXTEND32(far_end[i]), EXTEND32(MULT16_16_P15(st->preemph, st->memX)));
|
/* FIXME: This core has changed a bit, need to merge properly */
|
||||||
#ifdef FIXED_POINT
|
tmp32 = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(MULT16_16_P15(st->preemph, st->memD[chan])));
|
||||||
/* If saturation occurs here, we need to freeze adaptation for M+1 frames (not just one) */
|
|
||||||
if (tmp32 > 32767)
|
|
||||||
{
|
|
||||||
tmp32 = 32767;
|
|
||||||
st->saturated = M+1;
|
|
||||||
}
|
|
||||||
if (tmp32 < -32767)
|
|
||||||
{
|
|
||||||
tmp32 = -32767;
|
|
||||||
st->saturated = M+1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
st->x[i+st->frame_size] = EXTRACT16(tmp32);
|
|
||||||
st->memX = far_end[i];
|
|
||||||
|
|
||||||
tmp32 = SUB32(EXTEND32(st->input[i]), EXTEND32(MULT16_16_P15(st->preemph, st->memD)));
|
|
||||||
#ifdef FIXED_POINT
|
#ifdef FIXED_POINT
|
||||||
if (tmp32 > 32767)
|
if (tmp32 > 32767)
|
||||||
{
|
{
|
||||||
|
@ -708,52 +744,97 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
|
||||||
st->saturated = 1;
|
st->saturated = 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
st->memD = st->input[i];
|
st->memD[chan] = st->input[chan*st->frame_size+i];
|
||||||
st->input[i] = tmp32;
|
st->input[chan*st->frame_size+i] = EXTRACT16(tmp32);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (speak = 0; speak < K; speak++)
|
||||||
|
{
|
||||||
|
for (i=0;i<st->frame_size;i++)
|
||||||
|
{
|
||||||
|
spx_word32_t tmp32;
|
||||||
|
st->x[speak*N+i] = st->x[speak*N+i+st->frame_size];
|
||||||
|
tmp32 = SUB32(EXTEND32(far_end[i*K+speak]), EXTEND32(MULT16_16_P15(st->preemph, st->memX[speak])));
|
||||||
|
#ifdef FIXED_POINT
|
||||||
|
/*FIXME: If saturation occurs here, we need to freeze adaptation for M frames (not just one) */
|
||||||
|
if (tmp32 > 32767)
|
||||||
|
{
|
||||||
|
tmp32 = 32767;
|
||||||
|
st->saturated = M+1;
|
||||||
|
}
|
||||||
|
if (tmp32 < -32767)
|
||||||
|
{
|
||||||
|
tmp32 = -32767;
|
||||||
|
st->saturated = M+1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
st->x[speak*N+i+st->frame_size] = EXTRACT16(tmp32);
|
||||||
|
st->memX[speak] = far_end[i*K+speak];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (speak = 0; speak < K; speak++)
|
||||||
|
{
|
||||||
/* Shift memory: this could be optimized eventually*/
|
/* Shift memory: this could be optimized eventually*/
|
||||||
for (j=M-1;j>=0;j--)
|
for (j=M-1;j>=0;j--)
|
||||||
{
|
{
|
||||||
for (i=0;i<N;i++)
|
for (i=0;i<N;i++)
|
||||||
st->X[(j+1)*N+i] = st->X[j*N+i];
|
st->X[(j+1)*N*K+speak*N+i] = st->X[j*N*K+speak*N+i];
|
||||||
|
}
|
||||||
|
/* Convert x (echo input) to frequency domain */
|
||||||
|
spx_fft(st->fft_table, st->x+speak*N, &st->X[speak*N]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert x (far end) to frequency domain */
|
Sxx = 0;
|
||||||
spx_fft(st->fft_table, st->x, &st->X[0]);
|
for (speak = 0; speak < K; speak++)
|
||||||
for (i=0;i<N;i++)
|
{
|
||||||
st->last_y[i] = st->x[i];
|
Sxx += mdf_inner_prod(st->x+speak*N+st->frame_size, st->x+speak*N+st->frame_size, st->frame_size);
|
||||||
Sxx = mdf_inner_prod(st->x+st->frame_size, st->x+st->frame_size, st->frame_size);
|
power_spectrum_accum(st->X+speak*N, st->Xf, N);
|
||||||
for (i=0;i<st->frame_size;i++)
|
}
|
||||||
st->x[i] = st->x[i+st->frame_size];
|
|
||||||
/* From here on, the top part of x is used as scratch space */
|
|
||||||
|
|
||||||
|
Sff = 0;
|
||||||
|
for (chan = 0; chan < C; chan++)
|
||||||
|
{
|
||||||
#ifdef TWO_PATH
|
#ifdef TWO_PATH
|
||||||
/* Compute foreground filter */
|
/* Compute foreground filter */
|
||||||
spectral_mul_accum16(st->X, st->foreground, st->Y, N, M);
|
spectral_mul_accum16(st->X, st->foreground+chan*N*K*M, st->Y+chan*N, N, M*K);
|
||||||
spx_ifft(st->fft_table, st->Y, st->e);
|
spx_ifft(st->fft_table, st->Y+chan*N, st->e+chan*N);
|
||||||
for (i=0;i<st->frame_size;i++)
|
for (i=0;i<st->frame_size;i++)
|
||||||
st->e[i] = SUB16(st->input[i], st->e[i+st->frame_size]);
|
st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->e[chan*N+i+st->frame_size]);
|
||||||
Sff = mdf_inner_prod(st->e, st->e, st->frame_size);
|
Sff += mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* Adjust proportional adaption rate */
|
/* Adjust proportional adaption rate */
|
||||||
mdf_adjust_prop (st->W, N, M, st->prop);
|
/* FIXME: Adjust that for C, K*/
|
||||||
|
if (st->adapted)
|
||||||
|
mdf_adjust_prop (st->W, N, M, C*K, st->prop);
|
||||||
/* Compute weight gradient */
|
/* Compute weight gradient */
|
||||||
if (st->saturated == 0)
|
if (st->saturated == 0)
|
||||||
|
{
|
||||||
|
for (chan = 0; chan < C; chan++)
|
||||||
|
{
|
||||||
|
for (speak = 0; speak < K; speak++)
|
||||||
{
|
{
|
||||||
for (j=M-1;j>=0;j--)
|
for (j=M-1;j>=0;j--)
|
||||||
{
|
{
|
||||||
weighted_spectral_mul_conj(st->power_1, FLOAT_SHL(PSEUDOFLOAT(st->prop[j]),-15), &st->X[(j+1)*N], st->E, st->PHI, N);
|
weighted_spectral_mul_conj(st->power_1, FLOAT_SHL(PSEUDOFLOAT(st->prop[j]),-15), &st->X[(j+1)*N*K+speak*N], st->E+chan*N, st->PHI, N);
|
||||||
for (i=0;i<N;i++)
|
for (i=0;i<N;i++)
|
||||||
st->W[j*N+i] = ADD32(st->W[j*N+i], st->PHI[i]);
|
st->W[chan*N*K*M + j*N*K + speak*N + i] += st->PHI[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
st->saturated--;
|
st->saturated--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: MC conversion required */
|
||||||
/* Update weight to prevent circular convolution (MDF / AUMDF) */
|
/* Update weight to prevent circular convolution (MDF / AUMDF) */
|
||||||
|
for (chan = 0; chan < C; chan++)
|
||||||
|
{
|
||||||
|
for (speak = 0; speak < K; speak++)
|
||||||
|
{
|
||||||
for (j=0;j<M;j++)
|
for (j=0;j<M;j++)
|
||||||
{
|
{
|
||||||
/* This is a variant of the Alternatively Updated MDF (AUMDF) */
|
/* This is a variant of the Alternatively Updated MDF (AUMDF) */
|
||||||
|
@ -762,7 +843,7 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
|
||||||
{
|
{
|
||||||
#ifdef FIXED_POINT
|
#ifdef FIXED_POINT
|
||||||
for (i=0;i<N;i++)
|
for (i=0;i<N;i++)
|
||||||
st->wtmp2[i] = EXTRACT16(PSHR32(st->W[j*N+i],NORMALIZE_SCALEDOWN+16));
|
st->wtmp2[i] = EXTRACT16(PSHR32(st->W[chan*N*K*M + j*N*K + speak*N + i],NORMALIZE_SCALEDOWN+16));
|
||||||
spx_ifft(st->fft_table, st->wtmp2, st->wtmp);
|
spx_ifft(st->fft_table, st->wtmp2, st->wtmp);
|
||||||
for (i=0;i<st->frame_size;i++)
|
for (i=0;i<st->frame_size;i++)
|
||||||
{
|
{
|
||||||
|
@ -775,32 +856,41 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
|
||||||
spx_fft(st->fft_table, st->wtmp, st->wtmp2);
|
spx_fft(st->fft_table, st->wtmp, st->wtmp2);
|
||||||
/* The "-1" in the shift is a sort of kludge that trades less efficient update speed for decrease noise */
|
/* The "-1" in the shift is a sort of kludge that trades less efficient update speed for decrease noise */
|
||||||
for (i=0;i<N;i++)
|
for (i=0;i<N;i++)
|
||||||
st->W[j*N+i] -= SHL32(EXTEND32(st->wtmp2[i]),16+NORMALIZE_SCALEDOWN-NORMALIZE_SCALEUP-1);
|
st->W[chan*N*K*M + j*N*K + speak*N + i] -= SHL32(EXTEND32(st->wtmp2[i]),16+NORMALIZE_SCALEDOWN-NORMALIZE_SCALEUP-1);
|
||||||
#else
|
#else
|
||||||
spx_ifft(st->fft_table, &st->W[j*N], st->wtmp);
|
spx_ifft(st->fft_table, &st->W[chan*N*K*M + j*N*K + speak*N], st->wtmp);
|
||||||
for (i=st->frame_size;i<N;i++)
|
for (i=st->frame_size;i<N;i++)
|
||||||
{
|
{
|
||||||
st->wtmp[i]=0;
|
st->wtmp[i]=0;
|
||||||
}
|
}
|
||||||
spx_fft(st->fft_table, st->wtmp, &st->W[j*N]);
|
spx_fft(st->fft_table, st->wtmp, &st->W[chan*N*K*M + j*N*K + speak*N]);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Compute filter response Y */
|
/* So we can use power_spectrum_accum */
|
||||||
spectral_mul_accum(st->X, st->W, st->Y, N, M);
|
for (i=0;i<=st->frame_size;i++)
|
||||||
spx_ifft(st->fft_table, st->Y, st->y);
|
st->Rf[i] = st->Yf[i] = st->Xf[i] = 0;
|
||||||
|
|
||||||
|
Dbf = 0;
|
||||||
|
See = 0;
|
||||||
#ifdef TWO_PATH
|
#ifdef TWO_PATH
|
||||||
/* Difference in response, this is used to estimate the variance of our residual power estimate */
|
/* Difference in response, this is used to estimate the variance of our residual power estimate */
|
||||||
|
for (chan = 0; chan < C; chan++)
|
||||||
|
{
|
||||||
|
spectral_mul_accum(st->X, st->W+chan*N*K*M, st->Y+chan*N, N, M*K);
|
||||||
|
spx_ifft(st->fft_table, st->Y+chan*N, st->y+chan*N);
|
||||||
for (i=0;i<st->frame_size;i++)
|
for (i=0;i<st->frame_size;i++)
|
||||||
st->e[i] = SUB16(st->e[i+st->frame_size], st->y[i+st->frame_size]);
|
st->e[chan*N+i] = SUB16(st->e[chan*N+i+st->frame_size], st->y[chan*N+i+st->frame_size]);
|
||||||
Dbf = 10+mdf_inner_prod(st->e, st->e, st->frame_size);
|
Dbf += 10+mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size);
|
||||||
|
for (i=0;i<st->frame_size;i++)
|
||||||
|
st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->y[chan*N+i+st->frame_size]);
|
||||||
|
See += mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (i=0;i<st->frame_size;i++)
|
|
||||||
st->e[i] = SUB16(st->input[i], st->y[i+st->frame_size]);
|
|
||||||
See = mdf_inner_prod(st->e, st->e, st->frame_size);
|
|
||||||
#ifndef TWO_PATH
|
#ifndef TWO_PATH
|
||||||
Sff = See;
|
Sff = See;
|
||||||
#endif
|
#endif
|
||||||
|
@ -837,11 +927,12 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
|
||||||
st->Davg1 = st->Davg2 = 0;
|
st->Davg1 = st->Davg2 = 0;
|
||||||
st->Dvar1 = st->Dvar2 = FLOAT_ZERO;
|
st->Dvar1 = st->Dvar2 = FLOAT_ZERO;
|
||||||
/* Copy background filter to foreground filter */
|
/* Copy background filter to foreground filter */
|
||||||
for (i=0;i<N*M;i++)
|
for (i=0;i<N*M*C*K;i++)
|
||||||
st->foreground[i] = EXTRACT16(PSHR32(st->W[i],16));
|
st->foreground[i] = EXTRACT16(PSHR32(st->W[i],16));
|
||||||
/* Apply a smooth transition so as to not introduce blocking artifacts */
|
/* Apply a smooth transition so as to not introduce blocking artifacts */
|
||||||
|
for (chan = 0; chan < C; chan++)
|
||||||
for (i=0;i<st->frame_size;i++)
|
for (i=0;i<st->frame_size;i++)
|
||||||
st->e[i+st->frame_size] = MULT16_16_Q15(st->window[i+st->frame_size],st->e[i+st->frame_size]) + MULT16_16_Q15(st->window[i],st->y[i+st->frame_size]);
|
st->e[chan*N+i+st->frame_size] = MULT16_16_Q15(st->window[i+st->frame_size],st->e[chan*N+i+st->frame_size]) + MULT16_16_Q15(st->window[i],st->y[chan*N+i+st->frame_size]);
|
||||||
} else {
|
} else {
|
||||||
int reset_background=0;
|
int reset_background=0;
|
||||||
/* Otherwise, check if the background filter is significantly worse */
|
/* Otherwise, check if the background filter is significantly worse */
|
||||||
|
@ -854,13 +945,16 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
|
||||||
if (reset_background)
|
if (reset_background)
|
||||||
{
|
{
|
||||||
/* Copy foreground filter to background filter */
|
/* Copy foreground filter to background filter */
|
||||||
for (i=0;i<N*M;i++)
|
for (i=0;i<N*M*C*K;i++)
|
||||||
st->W[i] = SHL32(EXTEND32(st->foreground[i]),16);
|
st->W[i] = SHL32(EXTEND32(st->foreground[i]),16);
|
||||||
/* We also need to copy the output so as to get correct adaptation */
|
/* We also need to copy the output so as to get correct adaptation */
|
||||||
|
for (chan = 0; chan < C; chan++)
|
||||||
|
{
|
||||||
for (i=0;i<st->frame_size;i++)
|
for (i=0;i<st->frame_size;i++)
|
||||||
st->y[i+st->frame_size] = st->e[i+st->frame_size];
|
st->y[chan*N+i+st->frame_size] = st->e[chan*N+i+st->frame_size];
|
||||||
for (i=0;i<st->frame_size;i++)
|
for (i=0;i<st->frame_size;i++)
|
||||||
st->e[i] = SUB16(st->input[i], st->y[i+st->frame_size]);
|
st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->y[chan*N+i+st->frame_size]);
|
||||||
|
}
|
||||||
See = Sff;
|
See = Sff;
|
||||||
st->Davg1 = st->Davg2 = 0;
|
st->Davg1 = st->Davg2 = 0;
|
||||||
st->Dvar1 = st->Dvar2 = FLOAT_ZERO;
|
st->Dvar1 = st->Dvar2 = FLOAT_ZERO;
|
||||||
|
@ -868,30 +962,27 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Sey = Syy = Sdd = 0;
|
||||||
|
for (chan = 0; chan < C; chan++)
|
||||||
|
{
|
||||||
/* Compute error signal (for the output with de-emphasis) */
|
/* Compute error signal (for the output with de-emphasis) */
|
||||||
for (i=0;i<st->frame_size;i++)
|
for (i=0;i<st->frame_size;i++)
|
||||||
{
|
{
|
||||||
spx_word32_t tmp_out;
|
spx_word32_t tmp_out;
|
||||||
#ifdef TWO_PATH
|
#ifdef TWO_PATH
|
||||||
tmp_out = SUB32(EXTEND32(st->input[i]), EXTEND32(st->e[i+st->frame_size]));
|
tmp_out = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(st->e[chan*N+i+st->frame_size]));
|
||||||
#else
|
#else
|
||||||
tmp_out = SUB32(EXTEND32(st->input[i]), EXTEND32(st->y[i+st->frame_size]));
|
tmp_out = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(st->y[chan*N+i+st->frame_size]));
|
||||||
#endif
|
#endif
|
||||||
/* Saturation */
|
tmp_out = ADD32(tmp_out, EXTEND32(MULT16_16_P15(st->preemph, st->memE[chan])));
|
||||||
if (tmp_out>32767)
|
|
||||||
tmp_out = 32767;
|
|
||||||
else if (tmp_out<-32768)
|
|
||||||
tmp_out = -32768;
|
|
||||||
tmp_out = ADD32(tmp_out, EXTEND32(MULT16_16_P15(st->preemph, st->memE)));
|
|
||||||
/* This is an arbitrary test for saturation in the microphone signal */
|
/* This is an arbitrary test for saturation in the microphone signal */
|
||||||
if (in[i] <= -32000 || in[i] >= 32000)
|
if (in[i*C+chan] <= -32000 || in[i*C+chan] >= 32000)
|
||||||
{
|
{
|
||||||
tmp_out = 0;
|
|
||||||
if (st->saturated == 0)
|
if (st->saturated == 0)
|
||||||
st->saturated = 1;
|
st->saturated = 1;
|
||||||
}
|
}
|
||||||
out[i] = (spx_int16_t)tmp_out;
|
out[i*C+chan] = WORD2INT(tmp_out);
|
||||||
st->memE = tmp_out;
|
st->memE[chan] = tmp_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DUMP_ECHO_CANCEL_DATA
|
#ifdef DUMP_ECHO_CANCEL_DATA
|
||||||
|
@ -901,14 +992,27 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
|
||||||
/* Compute error signal (filter update version) */
|
/* Compute error signal (filter update version) */
|
||||||
for (i=0;i<st->frame_size;i++)
|
for (i=0;i<st->frame_size;i++)
|
||||||
{
|
{
|
||||||
st->e[i+st->frame_size] = st->e[i];
|
st->e[chan*N+i+st->frame_size] = st->e[chan*N+i];
|
||||||
st->e[i] = 0;
|
st->e[chan*N+i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute a bunch of correlations */
|
/* Compute a bunch of correlations */
|
||||||
Sey = mdf_inner_prod(st->e+st->frame_size, st->y+st->frame_size, st->frame_size);
|
/* FIXME: bad merge */
|
||||||
Syy = mdf_inner_prod(st->y+st->frame_size, st->y+st->frame_size, st->frame_size);
|
Sey += mdf_inner_prod(st->e+chan*N+st->frame_size, st->y+chan*N+st->frame_size, st->frame_size);
|
||||||
Sdd = mdf_inner_prod(st->input, st->input, st->frame_size);
|
Syy += mdf_inner_prod(st->y+chan*N+st->frame_size, st->y+chan*N+st->frame_size, st->frame_size);
|
||||||
|
Sdd += mdf_inner_prod(st->input+chan*st->frame_size, st->input+chan*st->frame_size, st->frame_size);
|
||||||
|
|
||||||
|
/* Convert error to frequency domain */
|
||||||
|
spx_fft(st->fft_table, st->e+chan*N, st->E+chan*N);
|
||||||
|
for (i=0;i<st->frame_size;i++)
|
||||||
|
st->y[i+chan*N] = 0;
|
||||||
|
spx_fft(st->fft_table, st->y+chan*N, st->Y+chan*N);
|
||||||
|
|
||||||
|
/* Compute power spectrum of echo (X), error (E) and filter response (Y) */
|
||||||
|
power_spectrum_accum(st->E+chan*N, st->Rf, N);
|
||||||
|
power_spectrum_accum(st->Y+chan*N, st->Yf, N);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/*printf ("%f %f %f %f\n", Sff, See, Syy, Sdd, st->update_cond);*/
|
/*printf ("%f %f %f %f\n", Sff, See, Syy, Sdd, st->update_cond);*/
|
||||||
|
|
||||||
|
@ -921,7 +1025,7 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
|
||||||
{
|
{
|
||||||
/* Things have gone really bad */
|
/* Things have gone really bad */
|
||||||
st->screwed_up += 50;
|
st->screwed_up += 50;
|
||||||
for (i=0;i<st->frame_size;i++)
|
for (i=0;i<st->frame_size*C;i++)
|
||||||
out[i] = 0;
|
out[i] = 0;
|
||||||
} else if (SHR32(Sff, 2) > ADD32(Sdd, SHR32(MULT16_16(N, 10000),6)))
|
} else if (SHR32(Sff, 2) > ADD32(Sdd, SHR32(MULT16_16(N, 10000),6)))
|
||||||
{
|
{
|
||||||
|
@ -941,36 +1045,17 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
|
||||||
/* Add a small noise floor to make sure not to have problems when dividing */
|
/* Add a small noise floor to make sure not to have problems when dividing */
|
||||||
See = MAX32(See, SHR32(MULT16_16(N, 100),6));
|
See = MAX32(See, SHR32(MULT16_16(N, 100),6));
|
||||||
|
|
||||||
/* Convert error to frequency domain */
|
for (speak = 0; speak < K; speak++)
|
||||||
spx_fft(st->fft_table, st->e, st->E);
|
{
|
||||||
for (i=0;i<st->frame_size;i++)
|
Sxx += mdf_inner_prod(st->x+speak*N+st->frame_size, st->x+speak*N+st->frame_size, st->frame_size);
|
||||||
st->y[i] = 0;
|
power_spectrum_accum(st->X+speak*N, st->Xf, N);
|
||||||
spx_fft(st->fft_table, st->y, st->Y);
|
}
|
||||||
|
|
||||||
/* Compute power spectrum of far end (X), error (E) and filter response (Y) */
|
|
||||||
power_spectrum(st->E, st->Rf, N);
|
|
||||||
power_spectrum(st->Y, st->Yf, N);
|
|
||||||
power_spectrum(st->X, st->Xf, N);
|
|
||||||
|
|
||||||
/* Smooth far end energy estimate over time */
|
/* Smooth far end energy estimate over time */
|
||||||
for (j=0;j<=st->frame_size;j++)
|
for (j=0;j<=st->frame_size;j++)
|
||||||
st->power[j] = MULT16_32_Q15(ss_1,st->power[j]) + 1 + MULT16_32_Q15(ss,st->Xf[j]);
|
st->power[j] = MULT16_32_Q15(ss_1,st->power[j]) + 1 + MULT16_32_Q15(ss,st->Xf[j]);
|
||||||
|
|
||||||
/* Enable this to compute the power based only on the tail (would need to compute more
|
|
||||||
efficiently to make this really useful */
|
|
||||||
if (0)
|
|
||||||
{
|
|
||||||
float scale2 = .5f/M;
|
|
||||||
for (j=0;j<=st->frame_size;j++)
|
|
||||||
st->power[j] = 100;
|
|
||||||
for (i=0;i<M;i++)
|
|
||||||
{
|
|
||||||
power_spectrum(&st->X[i*N], st->Xf, N);
|
|
||||||
for (j=0;j<=st->frame_size;j++)
|
|
||||||
st->power[j] += scale2*st->Xf[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compute filtered spectra and (cross-)correlations */
|
/* Compute filtered spectra and (cross-)correlations */
|
||||||
for (j=st->frame_size;j>=0;j--)
|
for (j=st->frame_size;j>=0;j--)
|
||||||
{
|
{
|
||||||
|
@ -1091,12 +1176,12 @@ void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const sp
|
||||||
st->sum_adapt = ADD32(st->sum_adapt,adapt_rate);
|
st->sum_adapt = ADD32(st->sum_adapt,adapt_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save residual echo so it can be used by the nonlinear processor */
|
/* FIXME: MC conversion required */
|
||||||
|
for (i=0;i<st->frame_size;i++)
|
||||||
|
st->last_y[i] = st->last_y[st->frame_size+i];
|
||||||
if (st->adapted)
|
if (st->adapted)
|
||||||
{
|
{
|
||||||
/* If the filter is adapted, take the filtered echo */
|
/* If the filter is adapted, take the filtered echo */
|
||||||
for (i=0;i<st->frame_size;i++)
|
|
||||||
st->last_y[i] = st->last_y[st->frame_size+i];
|
|
||||||
for (i=0;i<st->frame_size;i++)
|
for (i=0;i<st->frame_size;i++)
|
||||||
st->last_y[st->frame_size+i] = in[i]-out[i];
|
st->last_y[st->frame_size+i] = in[i]-out[i];
|
||||||
} else {
|
} else {
|
||||||
|
@ -1141,7 +1226,7 @@ void speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *residual_echo, in
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr)
|
EXPORT int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr)
|
||||||
{
|
{
|
||||||
switch(request)
|
switch(request)
|
||||||
{
|
{
|
||||||
|
@ -1169,6 +1254,29 @@ int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr)
|
||||||
case SPEEX_ECHO_GET_SAMPLING_RATE:
|
case SPEEX_ECHO_GET_SAMPLING_RATE:
|
||||||
(*(int*)ptr) = st->sampling_rate;
|
(*(int*)ptr) = st->sampling_rate;
|
||||||
break;
|
break;
|
||||||
|
case SPEEX_ECHO_GET_IMPULSE_RESPONSE_SIZE:
|
||||||
|
/*FIXME: Implement this for multiple channels */
|
||||||
|
*((spx_int32_t *)ptr) = st->M * st->frame_size;
|
||||||
|
break;
|
||||||
|
case SPEEX_ECHO_GET_IMPULSE_RESPONSE:
|
||||||
|
{
|
||||||
|
int M = st->M, N = st->window_size, n = st->frame_size, i, j;
|
||||||
|
spx_int32_t *filt = (spx_int32_t *) ptr;
|
||||||
|
for(j=0;j<M;j++)
|
||||||
|
{
|
||||||
|
/*FIXME: Implement this for multiple channels */
|
||||||
|
#ifdef FIXED_POINT
|
||||||
|
for (i=0;i<N;i++)
|
||||||
|
st->wtmp2[i] = EXTRACT16(PSHR32(st->W[j*N+i],16+NORMALIZE_SCALEDOWN));
|
||||||
|
spx_ifft(st->fft_table, st->wtmp2, st->wtmp);
|
||||||
|
#else
|
||||||
|
spx_ifft(st->fft_table, &st->W[j*N], st->wtmp);
|
||||||
|
#endif
|
||||||
|
for(i=0;i<n;i++)
|
||||||
|
filt[j*n+i] = PSHR32(MULT16_16(32767,st->wtmp[i]), WEIGHT_SHIFT-NORMALIZE_SCALEDOWN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
speex_warning_int("Unknown speex_echo_ctl request: ", request);
|
speex_warning_int("Unknown speex_echo_ctl request: ", request);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -450,7 +450,7 @@ static const SpeexNBMode nb_mode = {
|
||||||
|
|
||||||
|
|
||||||
/* Default mode for narrowband */
|
/* Default mode for narrowband */
|
||||||
const SpeexMode speex_nb_mode = {
|
EXPORT const SpeexMode speex_nb_mode = {
|
||||||
&nb_mode,
|
&nb_mode,
|
||||||
nb_mode_query,
|
nb_mode_query,
|
||||||
"narrowband",
|
"narrowband",
|
||||||
|
@ -479,8 +479,12 @@ const SpeexMode speex_nb_mode = {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int speex_mode_query(const SpeexMode *mode, int request, void *ptr)
|
EXPORT int speex_mode_query(const SpeexMode *mode, int request, void *ptr)
|
||||||
{
|
{
|
||||||
return mode->query(mode->mode, request, ptr);
|
return mode->query(mode->mode, request, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FIXED_DEBUG
|
||||||
|
long long spx_mips=0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -55,9 +55,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ROCKBOX_VOICE_CODEC
|
#ifndef ROCKBOX_VOICE_CODEC
|
||||||
const SpeexMode * const speex_mode_list[SPEEX_NB_MODES] = {&speex_nb_mode, &speex_wb_mode, &speex_uwb_mode};
|
EXPORT const SpeexMode * const speex_mode_list[SPEEX_NB_MODES] = {&speex_nb_mode, &speex_wb_mode, &speex_uwb_mode};
|
||||||
#else
|
#else
|
||||||
const SpeexMode * const speex_mode_list[SPEEX_NB_MODES] = {&speex_nb_mode, &speex_wb_mode, NULL};
|
EXPORT const SpeexMode * const speex_mode_list[SPEEX_NB_MODES] = {&speex_nb_mode, &speex_wb_mode, NULL};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const signed char hexc_table[];
|
extern const signed char hexc_table[];
|
||||||
|
@ -250,7 +250,7 @@ static const SpeexSBMode sb_wb_mode = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const SpeexMode speex_wb_mode = {
|
EXPORT const SpeexMode speex_wb_mode = {
|
||||||
&sb_wb_mode,
|
&sb_wb_mode,
|
||||||
wb_mode_query,
|
wb_mode_query,
|
||||||
"wideband (sub-band CELP)",
|
"wideband (sub-band CELP)",
|
||||||
|
@ -285,7 +285,7 @@ const SpeexMode speex_wb_mode = {
|
||||||
|
|
||||||
#ifndef ROCKBOX_VOICE_CODEC
|
#ifndef ROCKBOX_VOICE_CODEC
|
||||||
/* Split-band "ultra-wideband" (32 kbps) CELP mode*/
|
/* Split-band "ultra-wideband" (32 kbps) CELP mode*/
|
||||||
static const SpeexSBMode sb_uwb_mode = {
|
EXPORT static const SpeexSBMode sb_uwb_mode = {
|
||||||
&speex_wb_mode,
|
&speex_wb_mode,
|
||||||
320, /*frameSize*/
|
320, /*frameSize*/
|
||||||
80, /*subframeSize*/
|
80, /*subframeSize*/
|
||||||
|
@ -365,7 +365,7 @@ const SpeexMode speex_uwb_mode = {
|
||||||
/* We have defined speex_lib_get_mode() as a macro in speex.h */
|
/* We have defined speex_lib_get_mode() as a macro in speex.h */
|
||||||
#undef speex_lib_get_mode
|
#undef speex_lib_get_mode
|
||||||
|
|
||||||
const SpeexMode * speex_lib_get_mode (int mode)
|
EXPORT const SpeexMode * speex_lib_get_mode (int mode)
|
||||||
{
|
{
|
||||||
if (mode < 0 || mode >= SPEEX_NB_MODES) return NULL;
|
if (mode < 0 || mode >= SPEEX_NB_MODES) return NULL;
|
||||||
|
|
||||||
|
|
|
@ -199,6 +199,8 @@ struct SpeexPreprocessState_ {
|
||||||
int echo_suppress_active;
|
int echo_suppress_active;
|
||||||
SpeexEchoState *echo_state;
|
SpeexEchoState *echo_state;
|
||||||
|
|
||||||
|
spx_word16_t speech_prob; /**< Probability last frame was speech */
|
||||||
|
|
||||||
/* DSP-related arrays */
|
/* DSP-related arrays */
|
||||||
spx_word16_t *frame; /**< Processing frame (2*ps_size) */
|
spx_word16_t *frame; /**< Processing frame (2*ps_size) */
|
||||||
spx_word16_t *ft; /**< Processing frame in freq domain (2*ps_size) */
|
spx_word16_t *ft; /**< Processing frame in freq domain (2*ps_size) */
|
||||||
|
@ -234,7 +236,6 @@ struct SpeexPreprocessState_ {
|
||||||
float *loudness_weight; /**< Perceptual loudness curve */
|
float *loudness_weight; /**< Perceptual loudness curve */
|
||||||
float loudness; /**< Loudness estimate */
|
float loudness; /**< Loudness estimate */
|
||||||
float agc_gain; /**< Current AGC gain */
|
float agc_gain; /**< Current AGC gain */
|
||||||
int nb_loudness_adapt; /**< Number of frames used for loudness adaptation so far */
|
|
||||||
float max_gain; /**< Maximum gain allowed */
|
float max_gain; /**< Maximum gain allowed */
|
||||||
float max_increase_step; /**< Maximum increase in gain from one frame to another */
|
float max_increase_step; /**< Maximum increase in gain from one frame to another */
|
||||||
float max_decrease_step; /**< Maximum decrease in gain from one frame to another */
|
float max_decrease_step; /**< Maximum decrease in gain from one frame to another */
|
||||||
|
@ -391,7 +392,7 @@ static void compute_gain_floor(int noise_suppress, int effective_echo_suppress,
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_rate)
|
EXPORT SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_rate)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int N, N3, N4, M;
|
int N, N3, N4, M;
|
||||||
|
@ -514,7 +515,6 @@ SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_r
|
||||||
/*st->loudness = pow(AMP_SCALE*st->agc_level,LOUDNESS_EXP);*/
|
/*st->loudness = pow(AMP_SCALE*st->agc_level,LOUDNESS_EXP);*/
|
||||||
st->loudness = 1e-15;
|
st->loudness = 1e-15;
|
||||||
st->agc_gain = 1;
|
st->agc_gain = 1;
|
||||||
st->nb_loudness_adapt = 0;
|
|
||||||
st->max_gain = 30;
|
st->max_gain = 30;
|
||||||
st->max_increase_step = exp(0.11513f * 12.*st->frame_size / st->sampling_rate);
|
st->max_increase_step = exp(0.11513f * 12.*st->frame_size / st->sampling_rate);
|
||||||
st->max_decrease_step = exp(-0.11513f * 40.*st->frame_size / st->sampling_rate);
|
st->max_decrease_step = exp(-0.11513f * 40.*st->frame_size / st->sampling_rate);
|
||||||
|
@ -530,7 +530,7 @@ SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_r
|
||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
void speex_preprocess_state_destroy(SpeexPreprocessState *st)
|
EXPORT void speex_preprocess_state_destroy(SpeexPreprocessState *st)
|
||||||
{
|
{
|
||||||
speex_free(st->frame);
|
speex_free(st->frame);
|
||||||
speex_free(st->ft);
|
speex_free(st->ft);
|
||||||
|
@ -583,7 +583,6 @@ static void speex_compute_agc(SpeexPreprocessState *st, spx_word16_t Pframe, spx
|
||||||
loudness*2 > pow(st->loudness, 1.0/LOUDNESS_EXP))*/
|
loudness*2 > pow(st->loudness, 1.0/LOUDNESS_EXP))*/
|
||||||
if (Pframe>.3f)
|
if (Pframe>.3f)
|
||||||
{
|
{
|
||||||
st->nb_loudness_adapt++;
|
|
||||||
/*rate=2.0f*Pframe*Pframe/(1+st->nb_loudness_adapt);*/
|
/*rate=2.0f*Pframe*Pframe/(1+st->nb_loudness_adapt);*/
|
||||||
rate = .03*Pframe*Pframe;
|
rate = .03*Pframe*Pframe;
|
||||||
st->loudness = (1-rate)*st->loudness + (rate)*pow(AMP_SCALE*loudness, LOUDNESS_EXP);
|
st->loudness = (1-rate)*st->loudness + (rate)*pow(AMP_SCALE*loudness, LOUDNESS_EXP);
|
||||||
|
@ -705,7 +704,7 @@ static void update_noise_prob(SpeexPreprocessState *st)
|
||||||
}
|
}
|
||||||
for (i=0;i<N;i++)
|
for (i=0;i<N;i++)
|
||||||
{
|
{
|
||||||
if (MULT16_32_Q15(QCONST16(.4f,15),st->S[i]) > ADD32(st->Smin[i],EXTEND32(20)))
|
if (MULT16_32_Q15(QCONST16(.4f,15),st->S[i]) > st->Smin[i])
|
||||||
st->update_prob[i] = 1;
|
st->update_prob[i] = 1;
|
||||||
else
|
else
|
||||||
st->update_prob[i] = 0;
|
st->update_prob[i] = 0;
|
||||||
|
@ -719,12 +718,12 @@ static void update_noise_prob(SpeexPreprocessState *st)
|
||||||
|
|
||||||
void speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *Yout, int len);
|
void speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *Yout, int len);
|
||||||
|
|
||||||
int speex_preprocess(SpeexPreprocessState *st, spx_int16_t *x, spx_int32_t *echo)
|
EXPORT int speex_preprocess(SpeexPreprocessState *st, spx_int16_t *x, spx_int32_t *echo)
|
||||||
{
|
{
|
||||||
return speex_preprocess_run(st, x);
|
return speex_preprocess_run(st, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
|
EXPORT int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int M;
|
int M;
|
||||||
|
@ -994,9 +993,10 @@ int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
|
||||||
st->outbuf[i] = st->frame[st->frame_size+i];
|
st->outbuf[i] = st->frame[st->frame_size+i];
|
||||||
|
|
||||||
/* FIXME: This VAD is a kludge */
|
/* FIXME: This VAD is a kludge */
|
||||||
|
st->speech_prob = Pframe;
|
||||||
if (st->vad_enabled)
|
if (st->vad_enabled)
|
||||||
{
|
{
|
||||||
if (Pframe > st->speech_prob_start || (st->was_speech && Pframe > st->speech_prob_continue))
|
if (st->speech_prob > st->speech_prob_start || (st->was_speech && st->speech_prob > st->speech_prob_continue))
|
||||||
{
|
{
|
||||||
st->was_speech=1;
|
st->was_speech=1;
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1010,7 +1010,7 @@ int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16_t *x)
|
EXPORT void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16_t *x)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int N = st->ps_size;
|
int N = st->ps_size;
|
||||||
|
@ -1045,7 +1045,7 @@ void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16_t *x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *ptr)
|
EXPORT int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *ptr)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
SpeexPreprocessState *st;
|
SpeexPreprocessState *st;
|
||||||
|
@ -1169,17 +1169,51 @@ int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *ptr)
|
||||||
st->echo_state = (SpeexEchoState*)ptr;
|
st->echo_state = (SpeexEchoState*)ptr;
|
||||||
break;
|
break;
|
||||||
case SPEEX_PREPROCESS_GET_ECHO_STATE:
|
case SPEEX_PREPROCESS_GET_ECHO_STATE:
|
||||||
ptr = (void*)st->echo_state;
|
(*(SpeexEchoState**)ptr) = (SpeexEchoState*)st->echo_state;
|
||||||
break;
|
break;
|
||||||
#ifndef FIXED_POINT
|
#ifndef FIXED_POINT
|
||||||
case SPEEX_PREPROCESS_GET_AGC_LOUDNESS:
|
case SPEEX_PREPROCESS_GET_AGC_LOUDNESS:
|
||||||
(*(spx_int32_t*)ptr) = pow(st->loudness, 1.0/LOUDNESS_EXP);
|
(*(spx_int32_t*)ptr) = pow(st->loudness, 1.0/LOUDNESS_EXP);
|
||||||
break;
|
break;
|
||||||
|
case SPEEX_PREPROCESS_GET_AGC_GAIN:
|
||||||
|
(*(spx_int32_t*)ptr) = floor(.5+8.6858*log(st->agc_gain));
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case SPEEX_PREPROCESS_GET_PSD_SIZE:
|
||||||
|
case SPEEX_PREPROCESS_GET_NOISE_PSD_SIZE:
|
||||||
|
(*(spx_int32_t*)ptr) = st->ps_size;
|
||||||
|
break;
|
||||||
|
case SPEEX_PREPROCESS_GET_PSD:
|
||||||
|
for(i=0;i<st->ps_size;i++)
|
||||||
|
((spx_int32_t *)ptr)[i] = (spx_int32_t) st->ps[i];
|
||||||
|
break;
|
||||||
|
case SPEEX_PREPROCESS_GET_NOISE_PSD:
|
||||||
|
for(i=0;i<st->ps_size;i++)
|
||||||
|
((spx_int32_t *)ptr)[i] = (spx_int32_t) PSHR32(st->noise[i], NOISE_SHIFT);
|
||||||
|
break;
|
||||||
|
case SPEEX_PREPROCESS_GET_PROB:
|
||||||
|
(*(spx_int32_t*)ptr) = MULT16_16_Q15(st->speech_prob, 100);
|
||||||
|
break;
|
||||||
|
#ifndef FIXED_POINT
|
||||||
|
case SPEEX_PREPROCESS_SET_AGC_TARGET:
|
||||||
|
st->agc_level = (*(spx_int32_t*)ptr);
|
||||||
|
if (st->agc_level<1)
|
||||||
|
st->agc_level=1;
|
||||||
|
if (st->agc_level>32768)
|
||||||
|
st->agc_level=32768;
|
||||||
|
break;
|
||||||
|
case SPEEX_PREPROCESS_GET_AGC_TARGET:
|
||||||
|
(*(spx_int32_t*)ptr) = st->agc_level;
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
speex_warning_int("Unknown speex_preprocess_ctl request: ", request);
|
speex_warning_int("Unknown speex_preprocess_ctl request: ", request);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FIXED_DEBUG
|
||||||
|
long long spx_mips=0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -68,19 +68,19 @@ static int lsp_quant(
|
||||||
" B0 = %2;\n\t"
|
" B0 = %2;\n\t"
|
||||||
|
|
||||||
" R2.L = W [I0++];\n\t"
|
" R2.L = W [I0++];\n\t"
|
||||||
" LSETUP (lq1, lq2) LC0 = %4;\n\t"
|
" LSETUP (1f, 2f) LC0 = %4;\n\t"
|
||||||
"lq1: R3 = 0;\n\t" /* R3: dist */
|
"1: R3 = 0;\n\t" /* R3: dist */
|
||||||
" LSETUP (lq3, lq4) LC1 = %5;\n\t"
|
" LSETUP (3f, 4f) LC1 = %5;\n\t"
|
||||||
"lq3: R1 = B [P2++] (X);\n\t"
|
"3: R1 = B [P2++] (X);\n\t"
|
||||||
" R1 <<= 5;\n\t"
|
" R1 <<= 5;\n\t"
|
||||||
" R0.L = R2.L - R1.L || R2.L = W [I0++];\n\t"
|
" R0.L = R2.L - R1.L || R2.L = W [I0++];\n\t"
|
||||||
" R0 = R0.L*R0.L;\n\t"
|
" R0 = R0.L*R0.L;\n\t"
|
||||||
"lq4: R3 = R3 + R0;\n\t"
|
"4: R3 = R3 + R0;\n\t"
|
||||||
|
|
||||||
" cc =R3<%0;\n\t"
|
" cc =R3<%0;\n\t"
|
||||||
" if cc %0=R3;\n\t"
|
" if cc %0=R3;\n\t"
|
||||||
" if cc %1=R5;\n\t"
|
" if cc %1=R5;\n\t"
|
||||||
"lq2: R5 += 1;\n\t"
|
"2: R5 += 1;\n\t"
|
||||||
" L0 = 0;\n\t"
|
" L0 = 0;\n\t"
|
||||||
: "=&d" (best_dist), "=&d" (best_id)
|
: "=&d" (best_dist), "=&d" (best_id)
|
||||||
: "a" (x), "b" (cdbk), "a" (nbVec), "a" (nbDim)
|
: "a" (x), "b" (cdbk), "a" (nbVec), "a" (nbDim)
|
||||||
|
@ -132,10 +132,10 @@ static int lsp_weight_quant(
|
||||||
" B0 = %2;\n\t"
|
" B0 = %2;\n\t"
|
||||||
" B1 = %3;\n\t"
|
" B1 = %3;\n\t"
|
||||||
|
|
||||||
" LSETUP (lwq1, lwq2) LC0 = %5;\n\t"
|
" LSETUP (1f, 2f) LC0 = %5;\n\t"
|
||||||
"lwq1: R3 = 0 (X);\n\t" /* R3: dist */
|
"1: R3 = 0 (X);\n\t" /* R3: dist */
|
||||||
" LSETUP (lwq3, lwq4) LC1 = %6;\n\t"
|
" LSETUP (3f, 4f) LC1 = %6;\n\t"
|
||||||
"lwq3: R0.L = W [I0++] || R2.L = W [I1++];\n\t"
|
"3: R0.L = W [I0++] || R2.L = W [I1++];\n\t"
|
||||||
" R1 = B [P2++] (X);\n\t"
|
" R1 = B [P2++] (X);\n\t"
|
||||||
" R1 <<= 5;\n\t"
|
" R1 <<= 5;\n\t"
|
||||||
" R0.L = R0.L - R1.L;\n\t"
|
" R0.L = R0.L - R1.L;\n\t"
|
||||||
|
@ -143,12 +143,12 @@ static int lsp_weight_quant(
|
||||||
" A1 = R2.L*R0.L (M,IS);\n\t"
|
" A1 = R2.L*R0.L (M,IS);\n\t"
|
||||||
" A1 = A1 >>> 16;\n\t"
|
" A1 = A1 >>> 16;\n\t"
|
||||||
" R1 = (A1 += R2.L*R0.H) (IS);\n\t"
|
" R1 = (A1 += R2.L*R0.H) (IS);\n\t"
|
||||||
"lwq4: R3 = R3 + R1;\n\t"
|
"4: R3 = R3 + R1;\n\t"
|
||||||
|
|
||||||
" cc =R3<%0;\n\t"
|
" cc =R3<%0;\n\t"
|
||||||
" if cc %0=R3;\n\t"
|
" if cc %0=R3;\n\t"
|
||||||
" if cc %1=R5;\n\t"
|
" if cc %1=R5;\n\t"
|
||||||
"lwq2: R5 += 1;\n\t"
|
"2: R5 += 1;\n\t"
|
||||||
" L0 = 0;\n\t"
|
" L0 = 0;\n\t"
|
||||||
" L1 = 0;\n\t"
|
" L1 = 0;\n\t"
|
||||||
: "=&d" (best_dist), "=&d" (best_id)
|
: "=&d" (best_dist), "=&d" (best_id)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* Copyright (C) 2007 Jean-Marc Valin
|
/* Copyright (C) 2007-2008 Jean-Marc Valin
|
||||||
|
Copyright (C) 2008 Thorvald Natvig
|
||||||
|
|
||||||
File: resample.c
|
File: resample.c
|
||||||
Arbitrary resampling code
|
Arbitrary resampling code
|
||||||
|
@ -57,7 +58,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config-speex.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef OUTSIDE_SPEEX
|
#ifdef OUTSIDE_SPEEX
|
||||||
|
@ -74,6 +75,7 @@ static void speex_free (void *ptr) {free(ptr);}
|
||||||
#include "os_support.h"
|
#include "os_support.h"
|
||||||
#endif /* OUTSIDE_SPEEX */
|
#endif /* OUTSIDE_SPEEX */
|
||||||
|
|
||||||
|
#include "stack_alloc.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#ifndef M_PI
|
#ifndef M_PI
|
||||||
|
@ -86,10 +88,6 @@ static void speex_free (void *ptr) {free(ptr);}
|
||||||
#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))
|
#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x))))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*#define float double*/
|
|
||||||
#define FILTER_SIZE 64
|
|
||||||
#define OVERSAMPLE 8
|
|
||||||
|
|
||||||
#define IMAX(a,b) ((a) > (b) ? (a) : (b))
|
#define IMAX(a,b) ((a) > (b) ? (a) : (b))
|
||||||
#define IMIN(a,b) ((a) < (b) ? (a) : (b))
|
#define IMIN(a,b) ((a) < (b) ? (a) : (b))
|
||||||
|
|
||||||
|
@ -97,6 +95,17 @@ static void speex_free (void *ptr) {free(ptr);}
|
||||||
#define NULL 0
|
#define NULL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _USE_SSE
|
||||||
|
#include "resample_sse.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Numer of elements to allocate on the stack */
|
||||||
|
#ifdef VAR_ARRAYS
|
||||||
|
#define FIXED_STACK_ALLOC 8192
|
||||||
|
#else
|
||||||
|
#define FIXED_STACK_ALLOC 1024
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *);
|
typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *);
|
||||||
|
|
||||||
struct SpeexResamplerState_ {
|
struct SpeexResamplerState_ {
|
||||||
|
@ -109,6 +118,7 @@ struct SpeexResamplerState_ {
|
||||||
spx_uint32_t nb_channels;
|
spx_uint32_t nb_channels;
|
||||||
spx_uint32_t filt_len;
|
spx_uint32_t filt_len;
|
||||||
spx_uint32_t mem_alloc_size;
|
spx_uint32_t mem_alloc_size;
|
||||||
|
spx_uint32_t buffer_size;
|
||||||
int int_advance;
|
int int_advance;
|
||||||
int frac_advance;
|
int frac_advance;
|
||||||
float cutoff;
|
float cutoff;
|
||||||
|
@ -317,47 +327,47 @@ static void cubic_coef(spx_word16_t frac, spx_word16_t interp[4])
|
||||||
|
|
||||||
static int resampler_basic_direct_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
|
static int resampler_basic_direct_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
|
||||||
{
|
{
|
||||||
int N = st->filt_len;
|
const int N = st->filt_len;
|
||||||
int out_sample = 0;
|
int out_sample = 0;
|
||||||
spx_word16_t *mem;
|
|
||||||
int last_sample = st->last_sample[channel_index];
|
int last_sample = st->last_sample[channel_index];
|
||||||
spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
|
spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
|
||||||
mem = st->mem + channel_index * st->mem_alloc_size;
|
const spx_word16_t *sinc_table = st->sinc_table;
|
||||||
|
const int out_stride = st->out_stride;
|
||||||
|
const int int_advance = st->int_advance;
|
||||||
|
const int frac_advance = st->frac_advance;
|
||||||
|
const spx_uint32_t den_rate = st->den_rate;
|
||||||
|
spx_word32_t sum;
|
||||||
|
int j;
|
||||||
|
|
||||||
while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
|
while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
|
||||||
{
|
{
|
||||||
int j;
|
const spx_word16_t *sinc = & sinc_table[samp_frac_num*N];
|
||||||
spx_word32_t sum=0;
|
const spx_word16_t *iptr = & in[last_sample];
|
||||||
|
|
||||||
/* We already have all the filter coefficients pre-computed in the table */
|
#ifndef OVERRIDE_INNER_PRODUCT_SINGLE
|
||||||
const spx_word16_t *ptr;
|
float accum[4] = {0,0,0,0};
|
||||||
/* Do the memory part */
|
|
||||||
for (j=0;last_sample-N+1+j < 0;j++)
|
|
||||||
{
|
|
||||||
sum += MULT16_16(mem[last_sample+j],st->sinc_table[samp_frac_num*st->filt_len+j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do the new part */
|
for(j=0;j<N;j+=4) {
|
||||||
if (in != NULL)
|
accum[0] += sinc[j]*iptr[j];
|
||||||
{
|
accum[1] += sinc[j+1]*iptr[j+1];
|
||||||
ptr = in+st->in_stride*(last_sample-N+1+j);
|
accum[2] += sinc[j+2]*iptr[j+2];
|
||||||
for (;j<N;j++)
|
accum[3] += sinc[j+3]*iptr[j+3];
|
||||||
{
|
|
||||||
sum += MULT16_16(*ptr,st->sinc_table[samp_frac_num*st->filt_len+j]);
|
|
||||||
ptr += st->in_stride;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
sum = accum[0] + accum[1] + accum[2] + accum[3];
|
||||||
|
#else
|
||||||
|
sum = inner_product_single(sinc, iptr, N);
|
||||||
|
#endif
|
||||||
|
|
||||||
*out = PSHR32(sum,15);
|
out[out_stride * out_sample++] = PSHR32(sum, 15);
|
||||||
out += st->out_stride;
|
last_sample += int_advance;
|
||||||
out_sample++;
|
samp_frac_num += frac_advance;
|
||||||
last_sample += st->int_advance;
|
if (samp_frac_num >= den_rate)
|
||||||
samp_frac_num += st->frac_advance;
|
|
||||||
if (samp_frac_num >= st->den_rate)
|
|
||||||
{
|
{
|
||||||
samp_frac_num -= st->den_rate;
|
samp_frac_num -= den_rate;
|
||||||
last_sample++;
|
last_sample++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
st->last_sample[channel_index] = last_sample;
|
st->last_sample[channel_index] = last_sample;
|
||||||
st->samp_frac_num[channel_index] = samp_frac_num;
|
st->samp_frac_num[channel_index] = samp_frac_num;
|
||||||
return out_sample;
|
return out_sample;
|
||||||
|
@ -368,47 +378,47 @@ static int resampler_basic_direct_single(SpeexResamplerState *st, spx_uint32_t c
|
||||||
/* This is the same as the previous function, except with a double-precision accumulator */
|
/* This is the same as the previous function, except with a double-precision accumulator */
|
||||||
static int resampler_basic_direct_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
|
static int resampler_basic_direct_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
|
||||||
{
|
{
|
||||||
int N = st->filt_len;
|
const int N = st->filt_len;
|
||||||
int out_sample = 0;
|
int out_sample = 0;
|
||||||
spx_word16_t *mem;
|
|
||||||
int last_sample = st->last_sample[channel_index];
|
int last_sample = st->last_sample[channel_index];
|
||||||
spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
|
spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
|
||||||
mem = st->mem + channel_index * st->mem_alloc_size;
|
const spx_word16_t *sinc_table = st->sinc_table;
|
||||||
|
const int out_stride = st->out_stride;
|
||||||
|
const int int_advance = st->int_advance;
|
||||||
|
const int frac_advance = st->frac_advance;
|
||||||
|
const spx_uint32_t den_rate = st->den_rate;
|
||||||
|
double sum;
|
||||||
|
int j;
|
||||||
|
|
||||||
while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
|
while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
|
||||||
{
|
{
|
||||||
int j;
|
const spx_word16_t *sinc = & sinc_table[samp_frac_num*N];
|
||||||
double sum=0;
|
const spx_word16_t *iptr = & in[last_sample];
|
||||||
|
|
||||||
/* We already have all the filter coefficients pre-computed in the table */
|
#ifndef OVERRIDE_INNER_PRODUCT_DOUBLE
|
||||||
const spx_word16_t *ptr;
|
double accum[4] = {0,0,0,0};
|
||||||
/* Do the memory part */
|
|
||||||
for (j=0;last_sample-N+1+j < 0;j++)
|
|
||||||
{
|
|
||||||
sum += MULT16_16(mem[last_sample+j],(double)st->sinc_table[samp_frac_num*st->filt_len+j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do the new part */
|
for(j=0;j<N;j+=4) {
|
||||||
if (in != NULL)
|
accum[0] += sinc[j]*iptr[j];
|
||||||
{
|
accum[1] += sinc[j+1]*iptr[j+1];
|
||||||
ptr = in+st->in_stride*(last_sample-N+1+j);
|
accum[2] += sinc[j+2]*iptr[j+2];
|
||||||
for (;j<N;j++)
|
accum[3] += sinc[j+3]*iptr[j+3];
|
||||||
{
|
|
||||||
sum += MULT16_16(*ptr,(double)st->sinc_table[samp_frac_num*st->filt_len+j]);
|
|
||||||
ptr += st->in_stride;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
sum = accum[0] + accum[1] + accum[2] + accum[3];
|
||||||
|
#else
|
||||||
|
sum = inner_product_double(sinc, iptr, N);
|
||||||
|
#endif
|
||||||
|
|
||||||
*out = sum;
|
out[out_stride * out_sample++] = PSHR32(sum, 15);
|
||||||
out += st->out_stride;
|
last_sample += int_advance;
|
||||||
out_sample++;
|
samp_frac_num += frac_advance;
|
||||||
last_sample += st->int_advance;
|
if (samp_frac_num >= den_rate)
|
||||||
samp_frac_num += st->frac_advance;
|
|
||||||
if (samp_frac_num >= st->den_rate)
|
|
||||||
{
|
{
|
||||||
samp_frac_num -= st->den_rate;
|
samp_frac_num -= den_rate;
|
||||||
last_sample++;
|
last_sample++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
st->last_sample[channel_index] = last_sample;
|
st->last_sample[channel_index] = last_sample;
|
||||||
st->samp_frac_num[channel_index] = samp_frac_num;
|
st->samp_frac_num[channel_index] = samp_frac_num;
|
||||||
return out_sample;
|
return out_sample;
|
||||||
|
@ -417,69 +427,58 @@ static int resampler_basic_direct_double(SpeexResamplerState *st, spx_uint32_t c
|
||||||
|
|
||||||
static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
|
static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
|
||||||
{
|
{
|
||||||
int N = st->filt_len;
|
const int N = st->filt_len;
|
||||||
int out_sample = 0;
|
int out_sample = 0;
|
||||||
spx_word16_t *mem;
|
|
||||||
int last_sample = st->last_sample[channel_index];
|
int last_sample = st->last_sample[channel_index];
|
||||||
spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
|
spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
|
||||||
mem = st->mem + channel_index * st->mem_alloc_size;
|
const int out_stride = st->out_stride;
|
||||||
|
const int int_advance = st->int_advance;
|
||||||
|
const int frac_advance = st->frac_advance;
|
||||||
|
const spx_uint32_t den_rate = st->den_rate;
|
||||||
|
int j;
|
||||||
|
spx_word32_t sum;
|
||||||
|
|
||||||
while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
|
while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
|
||||||
{
|
{
|
||||||
int j;
|
const spx_word16_t *iptr = & in[last_sample];
|
||||||
spx_word32_t sum=0;
|
|
||||||
|
|
||||||
/* We need to interpolate the sinc filter */
|
const int offset = samp_frac_num*st->oversample/st->den_rate;
|
||||||
spx_word32_t accum[4] = {0.f,0.f, 0.f, 0.f};
|
|
||||||
spx_word16_t interp[4];
|
|
||||||
const spx_word16_t *ptr;
|
|
||||||
int offset;
|
|
||||||
spx_word16_t frac;
|
|
||||||
offset = samp_frac_num*st->oversample/st->den_rate;
|
|
||||||
#ifdef FIXED_POINT
|
#ifdef FIXED_POINT
|
||||||
frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
|
const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
|
||||||
#else
|
#else
|
||||||
frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
|
const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
|
||||||
#endif
|
#endif
|
||||||
/* This code is written like this to make it easy to optimise with SIMD.
|
spx_word16_t interp[4];
|
||||||
For most DSPs, it would be best to split the loops in two because most DSPs
|
|
||||||
have only two accumulators */
|
|
||||||
for (j=0;last_sample-N+1+j < 0;j++)
|
|
||||||
{
|
|
||||||
spx_word16_t curr_mem = mem[last_sample+j];
|
|
||||||
accum[0] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
|
|
||||||
accum[1] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
|
|
||||||
accum[2] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset]);
|
|
||||||
accum[3] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in != NULL)
|
|
||||||
{
|
#ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
|
||||||
ptr = in+st->in_stride*(last_sample-N+1+j);
|
spx_word32_t accum[4] = {0,0,0,0};
|
||||||
/* Do the new part */
|
|
||||||
for (;j<N;j++)
|
for(j=0;j<N;j++) {
|
||||||
{
|
const spx_word16_t curr_in=iptr[j];
|
||||||
spx_word16_t curr_in = *ptr;
|
|
||||||
ptr += st->in_stride;
|
|
||||||
accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
|
accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
|
||||||
accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
|
accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
|
||||||
accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
|
accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
|
||||||
accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
|
accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
cubic_coef(frac, interp);
|
cubic_coef(frac, interp);
|
||||||
sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]);
|
sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]);
|
||||||
|
#else
|
||||||
|
cubic_coef(frac, interp);
|
||||||
|
sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);
|
||||||
|
#endif
|
||||||
|
|
||||||
*out = PSHR32(sum,15);
|
out[out_stride * out_sample++] = PSHR32(sum,15);
|
||||||
out += st->out_stride;
|
last_sample += int_advance;
|
||||||
out_sample++;
|
samp_frac_num += frac_advance;
|
||||||
last_sample += st->int_advance;
|
if (samp_frac_num >= den_rate)
|
||||||
samp_frac_num += st->frac_advance;
|
|
||||||
if (samp_frac_num >= st->den_rate)
|
|
||||||
{
|
{
|
||||||
samp_frac_num -= st->den_rate;
|
samp_frac_num -= den_rate;
|
||||||
last_sample++;
|
last_sample++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
st->last_sample[channel_index] = last_sample;
|
st->last_sample[channel_index] = last_sample;
|
||||||
st->samp_frac_num[channel_index] = samp_frac_num;
|
st->samp_frac_num[channel_index] = samp_frac_num;
|
||||||
return out_sample;
|
return out_sample;
|
||||||
|
@ -490,63 +489,58 @@ static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint3
|
||||||
/* This is the same as the previous function, except with a double-precision accumulator */
|
/* This is the same as the previous function, except with a double-precision accumulator */
|
||||||
static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
|
static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
|
||||||
{
|
{
|
||||||
int N = st->filt_len;
|
const int N = st->filt_len;
|
||||||
int out_sample = 0;
|
int out_sample = 0;
|
||||||
spx_word16_t *mem;
|
|
||||||
int last_sample = st->last_sample[channel_index];
|
int last_sample = st->last_sample[channel_index];
|
||||||
spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
|
spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
|
||||||
mem = st->mem + channel_index * st->mem_alloc_size;
|
const int out_stride = st->out_stride;
|
||||||
|
const int int_advance = st->int_advance;
|
||||||
|
const int frac_advance = st->frac_advance;
|
||||||
|
const spx_uint32_t den_rate = st->den_rate;
|
||||||
|
int j;
|
||||||
|
spx_word32_t sum;
|
||||||
|
|
||||||
while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
|
while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
|
||||||
{
|
{
|
||||||
int j;
|
const spx_word16_t *iptr = & in[last_sample];
|
||||||
spx_word32_t sum=0;
|
|
||||||
|
|
||||||
/* We need to interpolate the sinc filter */
|
const int offset = samp_frac_num*st->oversample/st->den_rate;
|
||||||
double accum[4] = {0.f,0.f, 0.f, 0.f};
|
#ifdef FIXED_POINT
|
||||||
float interp[4];
|
const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate);
|
||||||
const spx_word16_t *ptr;
|
#else
|
||||||
float alpha = ((float)samp_frac_num)/st->den_rate;
|
const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate;
|
||||||
int offset = samp_frac_num*st->oversample/st->den_rate;
|
#endif
|
||||||
float frac = alpha*st->oversample - offset;
|
spx_word16_t interp[4];
|
||||||
/* This code is written like this to make it easy to optimise with SIMD.
|
|
||||||
For most DSPs, it would be best to split the loops in two because most DSPs
|
|
||||||
have only two accumulators */
|
#ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
|
||||||
for (j=0;last_sample-N+1+j < 0;j++)
|
double accum[4] = {0,0,0,0};
|
||||||
{
|
|
||||||
double curr_mem = mem[last_sample+j];
|
for(j=0;j<N;j++) {
|
||||||
accum[0] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
|
const double curr_in=iptr[j];
|
||||||
accum[1] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
|
|
||||||
accum[2] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset]);
|
|
||||||
accum[3] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
|
|
||||||
}
|
|
||||||
if (in != NULL)
|
|
||||||
{
|
|
||||||
ptr = in+st->in_stride*(last_sample-N+1+j);
|
|
||||||
/* Do the new part */
|
|
||||||
for (;j<N;j++)
|
|
||||||
{
|
|
||||||
double curr_in = *ptr;
|
|
||||||
ptr += st->in_stride;
|
|
||||||
accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
|
accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]);
|
||||||
accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
|
accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]);
|
||||||
accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
|
accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]);
|
||||||
accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
|
accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
cubic_coef(frac, interp);
|
|
||||||
sum = interp[0]*accum[0] + interp[1]*accum[1] + interp[2]*accum[2] + interp[3]*accum[3];
|
|
||||||
|
|
||||||
*out = PSHR32(sum,15);
|
cubic_coef(frac, interp);
|
||||||
out += st->out_stride;
|
sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]);
|
||||||
out_sample++;
|
#else
|
||||||
last_sample += st->int_advance;
|
cubic_coef(frac, interp);
|
||||||
samp_frac_num += st->frac_advance;
|
sum = interpolate_product_double(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);
|
||||||
if (samp_frac_num >= st->den_rate)
|
#endif
|
||||||
|
|
||||||
|
out[out_stride * out_sample++] = PSHR32(sum,15);
|
||||||
|
last_sample += int_advance;
|
||||||
|
samp_frac_num += frac_advance;
|
||||||
|
if (samp_frac_num >= den_rate)
|
||||||
{
|
{
|
||||||
samp_frac_num -= st->den_rate;
|
samp_frac_num -= den_rate;
|
||||||
last_sample++;
|
last_sample++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
st->last_sample[channel_index] = last_sample;
|
st->last_sample[channel_index] = last_sample;
|
||||||
st->samp_frac_num[channel_index] = samp_frac_num;
|
st->samp_frac_num[channel_index] = samp_frac_num;
|
||||||
return out_sample;
|
return out_sample;
|
||||||
|
@ -643,18 +637,18 @@ static void update_filter(SpeexResamplerState *st)
|
||||||
if (!st->mem)
|
if (!st->mem)
|
||||||
{
|
{
|
||||||
spx_uint32_t i;
|
spx_uint32_t i;
|
||||||
st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
|
st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
|
||||||
for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
|
st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
|
||||||
|
for (i=0;i<st->nb_channels*st->mem_alloc_size;i++)
|
||||||
st->mem[i] = 0;
|
st->mem[i] = 0;
|
||||||
st->mem_alloc_size = st->filt_len-1;
|
|
||||||
/*speex_warning("init filter");*/
|
/*speex_warning("init filter");*/
|
||||||
} else if (!st->started)
|
} else if (!st->started)
|
||||||
{
|
{
|
||||||
spx_uint32_t i;
|
spx_uint32_t i;
|
||||||
st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
|
st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
|
||||||
for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
|
st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
|
||||||
|
for (i=0;i<st->nb_channels*st->mem_alloc_size;i++)
|
||||||
st->mem[i] = 0;
|
st->mem[i] = 0;
|
||||||
st->mem_alloc_size = st->filt_len-1;
|
|
||||||
/*speex_warning("reinit filter");*/
|
/*speex_warning("reinit filter");*/
|
||||||
} else if (st->filt_len > old_length)
|
} else if (st->filt_len > old_length)
|
||||||
{
|
{
|
||||||
|
@ -662,10 +656,10 @@ static void update_filter(SpeexResamplerState *st)
|
||||||
/* Increase the filter length */
|
/* Increase the filter length */
|
||||||
/*speex_warning("increase filter size");*/
|
/*speex_warning("increase filter size");*/
|
||||||
int old_alloc_size = st->mem_alloc_size;
|
int old_alloc_size = st->mem_alloc_size;
|
||||||
if (st->filt_len-1 > st->mem_alloc_size)
|
if ((st->filt_len-1 + st->buffer_size) > st->mem_alloc_size)
|
||||||
{
|
{
|
||||||
st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t));
|
st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
|
||||||
st->mem_alloc_size = st->filt_len-1;
|
st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
|
||||||
}
|
}
|
||||||
for (i=st->nb_channels-1;i>=0;i--)
|
for (i=st->nb_channels-1;i>=0;i--)
|
||||||
{
|
{
|
||||||
|
@ -721,12 +715,12 @@ static void update_filter(SpeexResamplerState *st)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
|
EXPORT SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
|
||||||
{
|
{
|
||||||
return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err);
|
return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
|
EXPORT SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
|
||||||
{
|
{
|
||||||
spx_uint32_t i;
|
spx_uint32_t i;
|
||||||
SpeexResamplerState *st;
|
SpeexResamplerState *st;
|
||||||
|
@ -755,6 +749,12 @@ SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uin
|
||||||
st->in_stride = 1;
|
st->in_stride = 1;
|
||||||
st->out_stride = 1;
|
st->out_stride = 1;
|
||||||
|
|
||||||
|
#ifdef FIXED_POINT
|
||||||
|
st->buffer_size = 160;
|
||||||
|
#else
|
||||||
|
st->buffer_size = 160;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Per channel data */
|
/* Per channel data */
|
||||||
st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int));
|
st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int));
|
||||||
st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
|
st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
|
||||||
|
@ -779,7 +779,7 @@ SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uin
|
||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
void speex_resampler_destroy(SpeexResamplerState *st)
|
EXPORT void speex_resampler_destroy(SpeexResamplerState *st)
|
||||||
{
|
{
|
||||||
speex_free(st->mem);
|
speex_free(st->mem);
|
||||||
speex_free(st->sinc_table);
|
speex_free(st->sinc_table);
|
||||||
|
@ -789,186 +789,168 @@ void speex_resampler_destroy(SpeexResamplerState *st)
|
||||||
speex_free(st);
|
speex_free(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t channel_index, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
|
||||||
|
|
||||||
static int speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
|
|
||||||
{
|
{
|
||||||
int j=0;
|
int j=0;
|
||||||
int N = st->filt_len;
|
const int N = st->filt_len;
|
||||||
int out_sample = 0;
|
int out_sample = 0;
|
||||||
spx_word16_t *mem;
|
spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
|
||||||
spx_uint32_t tmp_out_len = 0;
|
spx_uint32_t ilen;
|
||||||
mem = st->mem + channel_index * st->mem_alloc_size;
|
|
||||||
st->started = 1;
|
st->started = 1;
|
||||||
|
|
||||||
/* Handle the case where we have samples left from a reduction in filter length */
|
|
||||||
if (st->magic_samples[channel_index])
|
|
||||||
{
|
|
||||||
int istride_save;
|
|
||||||
spx_uint32_t tmp_in_len;
|
|
||||||
spx_uint32_t tmp_magic;
|
|
||||||
|
|
||||||
istride_save = st->in_stride;
|
|
||||||
tmp_in_len = st->magic_samples[channel_index];
|
|
||||||
tmp_out_len = *out_len;
|
|
||||||
/* magic_samples needs to be set to zero to avoid infinite recursion */
|
|
||||||
tmp_magic = st->magic_samples[channel_index];
|
|
||||||
st->magic_samples[channel_index] = 0;
|
|
||||||
st->in_stride = 1;
|
|
||||||
speex_resampler_process_native(st, channel_index, mem+N-1, &tmp_in_len, out, &tmp_out_len);
|
|
||||||
st->in_stride = istride_save;
|
|
||||||
/*speex_warning_int("extra samples:", tmp_out_len);*/
|
|
||||||
/* If we couldn't process all "magic" input samples, save the rest for next time */
|
|
||||||
if (tmp_in_len < tmp_magic)
|
|
||||||
{
|
|
||||||
spx_uint32_t i;
|
|
||||||
st->magic_samples[channel_index] = tmp_magic-tmp_in_len;
|
|
||||||
for (i=0;i<st->magic_samples[channel_index];i++)
|
|
||||||
mem[N-1+i]=mem[N-1+i+tmp_in_len];
|
|
||||||
}
|
|
||||||
out += tmp_out_len*st->out_stride;
|
|
||||||
*out_len -= tmp_out_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call the right resampler through the function ptr */
|
/* Call the right resampler through the function ptr */
|
||||||
out_sample = st->resampler_ptr(st, channel_index, in, in_len, out, out_len);
|
out_sample = st->resampler_ptr(st, channel_index, mem, in_len, out, out_len);
|
||||||
|
|
||||||
if (st->last_sample[channel_index] < (spx_int32_t)*in_len)
|
if (st->last_sample[channel_index] < (spx_int32_t)*in_len)
|
||||||
*in_len = st->last_sample[channel_index];
|
*in_len = st->last_sample[channel_index];
|
||||||
*out_len = out_sample+tmp_out_len;
|
*out_len = out_sample;
|
||||||
st->last_sample[channel_index] -= *in_len;
|
st->last_sample[channel_index] -= *in_len;
|
||||||
|
|
||||||
for (j=0;j<N-1-(spx_int32_t)*in_len;j++)
|
ilen = *in_len;
|
||||||
mem[j] = mem[j+*in_len];
|
|
||||||
for (;j<N-1;j++)
|
for(j=0;j<N-1;++j)
|
||||||
mem[j] = in[st->in_stride*(j+*in_len-N+1)];
|
mem[j] = mem[j+ilen];
|
||||||
|
|
||||||
return RESAMPLER_ERR_SUCCESS;
|
return RESAMPLER_ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FIXED_STACK_ALLOC 1024
|
static int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_index, spx_word16_t **out, spx_uint32_t out_len) {
|
||||||
|
spx_uint32_t tmp_in_len = st->magic_samples[channel_index];
|
||||||
|
spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size;
|
||||||
|
const int N = st->filt_len;
|
||||||
|
|
||||||
|
speex_resampler_process_native(st, channel_index, &tmp_in_len, *out, &out_len);
|
||||||
|
|
||||||
|
st->magic_samples[channel_index] -= tmp_in_len;
|
||||||
|
|
||||||
|
/* If we couldn't process all "magic" input samples, save the rest for next time */
|
||||||
|
if (st->magic_samples[channel_index])
|
||||||
|
{
|
||||||
|
spx_uint32_t i;
|
||||||
|
for (i=0;i<st->magic_samples[channel_index];i++)
|
||||||
|
mem[N-1+i]=mem[N-1+i+tmp_in_len];
|
||||||
|
}
|
||||||
|
*out += out_len*st->out_stride;
|
||||||
|
return out_len;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef FIXED_POINT
|
#ifdef FIXED_POINT
|
||||||
int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
|
EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
|
||||||
{
|
|
||||||
spx_uint32_t i;
|
|
||||||
int istride_save, ostride_save;
|
|
||||||
#ifdef VAR_ARRAYS
|
|
||||||
spx_word16_t x[*in_len];
|
|
||||||
spx_word16_t y[*out_len];
|
|
||||||
/*VARDECL(spx_word16_t *x);
|
|
||||||
VARDECL(spx_word16_t *y);
|
|
||||||
ALLOC(x, *in_len, spx_word16_t);
|
|
||||||
ALLOC(y, *out_len, spx_word16_t);*/
|
|
||||||
istride_save = st->in_stride;
|
|
||||||
ostride_save = st->out_stride;
|
|
||||||
for (i=0;i<*in_len;i++)
|
|
||||||
x[i] = WORD2INT(in[i*st->in_stride]);
|
|
||||||
st->in_stride = st->out_stride = 1;
|
|
||||||
speex_resampler_process_native(st, channel_index, x, in_len, y, out_len);
|
|
||||||
st->in_stride = istride_save;
|
|
||||||
st->out_stride = ostride_save;
|
|
||||||
for (i=0;i<*out_len;i++)
|
|
||||||
out[i*st->out_stride] = y[i];
|
|
||||||
#else
|
#else
|
||||||
spx_word16_t x[FIXED_STACK_ALLOC];
|
EXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
|
||||||
spx_word16_t y[FIXED_STACK_ALLOC];
|
#endif
|
||||||
spx_uint32_t ilen=*in_len, olen=*out_len;
|
|
||||||
istride_save = st->in_stride;
|
|
||||||
ostride_save = st->out_stride;
|
|
||||||
while (ilen && olen)
|
|
||||||
{
|
{
|
||||||
spx_uint32_t ichunk, ochunk;
|
int j;
|
||||||
ichunk = ilen;
|
spx_uint32_t ilen = *in_len;
|
||||||
ochunk = olen;
|
spx_uint32_t olen = *out_len;
|
||||||
if (ichunk>FIXED_STACK_ALLOC)
|
spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
|
||||||
ichunk=FIXED_STACK_ALLOC;
|
const int filt_offs = st->filt_len - 1;
|
||||||
if (ochunk>FIXED_STACK_ALLOC)
|
const spx_uint32_t xlen = st->mem_alloc_size - filt_offs;
|
||||||
ochunk=FIXED_STACK_ALLOC;
|
const int istride = st->in_stride;
|
||||||
for (i=0;i<ichunk;i++)
|
|
||||||
x[i] = WORD2INT(in[i*st->in_stride]);
|
if (st->magic_samples[channel_index])
|
||||||
st->in_stride = st->out_stride = 1;
|
olen -= speex_resampler_magic(st, channel_index, &out, olen);
|
||||||
speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk);
|
if (! st->magic_samples[channel_index]) {
|
||||||
st->in_stride = istride_save;
|
while (ilen && olen) {
|
||||||
st->out_stride = ostride_save;
|
spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
|
||||||
for (i=0;i<ochunk;i++)
|
spx_uint32_t ochunk = olen;
|
||||||
out[i*st->out_stride] = y[i];
|
|
||||||
out += ochunk;
|
if (in) {
|
||||||
in += ichunk;
|
for(j=0;j<ichunk;++j)
|
||||||
|
x[j+filt_offs]=in[j*istride];
|
||||||
|
} else {
|
||||||
|
for(j=0;j<ichunk;++j)
|
||||||
|
x[j+filt_offs]=0;
|
||||||
|
}
|
||||||
|
speex_resampler_process_native(st, channel_index, &ichunk, out, &ochunk);
|
||||||
ilen -= ichunk;
|
ilen -= ichunk;
|
||||||
olen -= ochunk;
|
olen -= ochunk;
|
||||||
|
out += ochunk * st->out_stride;
|
||||||
|
if (in)
|
||||||
|
in += ichunk * istride;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*in_len -= ilen;
|
*in_len -= ilen;
|
||||||
*out_len -= olen;
|
*out_len -= olen;
|
||||||
#endif
|
|
||||||
return RESAMPLER_ERR_SUCCESS;
|
return RESAMPLER_ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
|
|
||||||
{
|
#ifdef FIXED_POINT
|
||||||
return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len);
|
EXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
|
EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len);
|
int j;
|
||||||
}
|
const int istride_save = st->in_stride;
|
||||||
int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
|
const int ostride_save = st->out_stride;
|
||||||
{
|
spx_uint32_t ilen = *in_len;
|
||||||
spx_uint32_t i;
|
spx_uint32_t olen = *out_len;
|
||||||
int istride_save, ostride_save;
|
spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size;
|
||||||
|
const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1);
|
||||||
#ifdef VAR_ARRAYS
|
#ifdef VAR_ARRAYS
|
||||||
spx_word16_t x[*in_len];
|
const unsigned int ylen = (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC;
|
||||||
spx_word16_t y[*out_len];
|
VARDECL(spx_word16_t *ystack);
|
||||||
/*VARDECL(spx_word16_t *x);
|
ALLOC(ystack, ylen, spx_word16_t);
|
||||||
VARDECL(spx_word16_t *y);
|
|
||||||
ALLOC(x, *in_len, spx_word16_t);
|
|
||||||
ALLOC(y, *out_len, spx_word16_t);*/
|
|
||||||
istride_save = st->in_stride;
|
|
||||||
ostride_save = st->out_stride;
|
|
||||||
for (i=0;i<*in_len;i++)
|
|
||||||
x[i] = in[i*st->in_stride];
|
|
||||||
st->in_stride = st->out_stride = 1;
|
|
||||||
speex_resampler_process_native(st, channel_index, x, in_len, y, out_len);
|
|
||||||
st->in_stride = istride_save;
|
|
||||||
st->out_stride = ostride_save;
|
|
||||||
for (i=0;i<*out_len;i++)
|
|
||||||
out[i*st->out_stride] = WORD2INT(y[i]);
|
|
||||||
#else
|
#else
|
||||||
spx_word16_t x[FIXED_STACK_ALLOC];
|
const unsigned int ylen = FIXED_STACK_ALLOC;
|
||||||
spx_word16_t y[FIXED_STACK_ALLOC];
|
spx_word16_t ystack[FIXED_STACK_ALLOC];
|
||||||
spx_uint32_t ilen=*in_len, olen=*out_len;
|
|
||||||
istride_save = st->in_stride;
|
|
||||||
ostride_save = st->out_stride;
|
|
||||||
while (ilen && olen)
|
|
||||||
{
|
|
||||||
spx_uint32_t ichunk, ochunk;
|
|
||||||
ichunk = ilen;
|
|
||||||
ochunk = olen;
|
|
||||||
if (ichunk>FIXED_STACK_ALLOC)
|
|
||||||
ichunk=FIXED_STACK_ALLOC;
|
|
||||||
if (ochunk>FIXED_STACK_ALLOC)
|
|
||||||
ochunk=FIXED_STACK_ALLOC;
|
|
||||||
for (i=0;i<ichunk;i++)
|
|
||||||
x[i] = in[i*st->in_stride];
|
|
||||||
st->in_stride = st->out_stride = 1;
|
|
||||||
speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk);
|
|
||||||
st->in_stride = istride_save;
|
|
||||||
st->out_stride = ostride_save;
|
|
||||||
for (i=0;i<ochunk;i++)
|
|
||||||
out[i*st->out_stride] = WORD2INT(y[i]);
|
|
||||||
out += ochunk;
|
|
||||||
in += ichunk;
|
|
||||||
ilen -= ichunk;
|
|
||||||
olen -= ochunk;
|
|
||||||
}
|
|
||||||
*in_len -= ilen;
|
|
||||||
*out_len -= olen;
|
|
||||||
#endif
|
|
||||||
return RESAMPLER_ERR_SUCCESS;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
|
st->out_stride = 1;
|
||||||
|
|
||||||
|
while (ilen && olen) {
|
||||||
|
spx_word16_t *y = ystack;
|
||||||
|
spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen;
|
||||||
|
spx_uint32_t ochunk = (olen > ylen) ? ylen : olen;
|
||||||
|
spx_uint32_t omagic = 0;
|
||||||
|
|
||||||
|
if (st->magic_samples[channel_index]) {
|
||||||
|
omagic = speex_resampler_magic(st, channel_index, &y, ochunk);
|
||||||
|
ochunk -= omagic;
|
||||||
|
olen -= omagic;
|
||||||
|
}
|
||||||
|
if (! st->magic_samples[channel_index]) {
|
||||||
|
if (in) {
|
||||||
|
for(j=0;j<ichunk;++j)
|
||||||
|
#ifdef FIXED_POINT
|
||||||
|
x[j+st->filt_len-1]=WORD2INT(in[j*istride_save]);
|
||||||
|
#else
|
||||||
|
x[j+st->filt_len-1]=in[j*istride_save];
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
for(j=0;j<ichunk;++j)
|
||||||
|
x[j+st->filt_len-1]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
speex_resampler_process_native(st, channel_index, &ichunk, y, &ochunk);
|
||||||
|
} else {
|
||||||
|
ichunk = 0;
|
||||||
|
ochunk = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j=0;j<ochunk+omagic;++j)
|
||||||
|
#ifdef FIXED_POINT
|
||||||
|
out[j*ostride_save] = ystack[j];
|
||||||
|
#else
|
||||||
|
out[j*ostride_save] = WORD2INT(ystack[j]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ilen -= ichunk;
|
||||||
|
olen -= ochunk;
|
||||||
|
out += (ochunk+omagic) * ostride_save;
|
||||||
|
if (in)
|
||||||
|
in += ichunk * istride_save;
|
||||||
|
}
|
||||||
|
st->out_stride = ostride_save;
|
||||||
|
*in_len -= ilen;
|
||||||
|
*out_len -= olen;
|
||||||
|
|
||||||
|
return RESAMPLER_ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
|
||||||
{
|
{
|
||||||
spx_uint32_t i;
|
spx_uint32_t i;
|
||||||
int istride_save, ostride_save;
|
int istride_save, ostride_save;
|
||||||
|
@ -989,8 +971,7 @@ int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const flo
|
||||||
return RESAMPLER_ERR_SUCCESS;
|
return RESAMPLER_ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPORT int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
|
||||||
int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
|
|
||||||
{
|
{
|
||||||
spx_uint32_t i;
|
spx_uint32_t i;
|
||||||
int istride_save, ostride_save;
|
int istride_save, ostride_save;
|
||||||
|
@ -1011,18 +992,18 @@ int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_i
|
||||||
return RESAMPLER_ERR_SUCCESS;
|
return RESAMPLER_ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate)
|
EXPORT int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate)
|
||||||
{
|
{
|
||||||
return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate);
|
return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate)
|
EXPORT void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate)
|
||||||
{
|
{
|
||||||
*in_rate = st->in_rate;
|
*in_rate = st->in_rate;
|
||||||
*out_rate = st->out_rate;
|
*out_rate = st->out_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate)
|
EXPORT int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate)
|
||||||
{
|
{
|
||||||
spx_uint32_t fact;
|
spx_uint32_t fact;
|
||||||
spx_uint32_t old_den;
|
spx_uint32_t old_den;
|
||||||
|
@ -1061,13 +1042,13 @@ int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_nu
|
||||||
return RESAMPLER_ERR_SUCCESS;
|
return RESAMPLER_ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den)
|
EXPORT void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den)
|
||||||
{
|
{
|
||||||
*ratio_num = st->num_rate;
|
*ratio_num = st->num_rate;
|
||||||
*ratio_den = st->den_rate;
|
*ratio_den = st->den_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
int speex_resampler_set_quality(SpeexResamplerState *st, int quality)
|
EXPORT int speex_resampler_set_quality(SpeexResamplerState *st, int quality)
|
||||||
{
|
{
|
||||||
if (quality > 10 || quality < 0)
|
if (quality > 10 || quality < 0)
|
||||||
return RESAMPLER_ERR_INVALID_ARG;
|
return RESAMPLER_ERR_INVALID_ARG;
|
||||||
|
@ -1079,32 +1060,42 @@ int speex_resampler_set_quality(SpeexResamplerState *st, int quality)
|
||||||
return RESAMPLER_ERR_SUCCESS;
|
return RESAMPLER_ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void speex_resampler_get_quality(SpeexResamplerState *st, int *quality)
|
EXPORT void speex_resampler_get_quality(SpeexResamplerState *st, int *quality)
|
||||||
{
|
{
|
||||||
*quality = st->quality;
|
*quality = st->quality;
|
||||||
}
|
}
|
||||||
|
|
||||||
void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride)
|
EXPORT void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride)
|
||||||
{
|
{
|
||||||
st->in_stride = stride;
|
st->in_stride = stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride)
|
EXPORT void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride)
|
||||||
{
|
{
|
||||||
*stride = st->in_stride;
|
*stride = st->in_stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride)
|
EXPORT void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride)
|
||||||
{
|
{
|
||||||
st->out_stride = stride;
|
st->out_stride = stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride)
|
EXPORT void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride)
|
||||||
{
|
{
|
||||||
*stride = st->out_stride;
|
*stride = st->out_stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
int speex_resampler_skip_zeros(SpeexResamplerState *st)
|
EXPORT int speex_resampler_get_input_latency(SpeexResamplerState *st)
|
||||||
|
{
|
||||||
|
return st->filt_len / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT int speex_resampler_get_output_latency(SpeexResamplerState *st)
|
||||||
|
{
|
||||||
|
return ((st->filt_len / 2) * st->den_rate + (st->num_rate >> 1)) / st->num_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT int speex_resampler_skip_zeros(SpeexResamplerState *st)
|
||||||
{
|
{
|
||||||
spx_uint32_t i;
|
spx_uint32_t i;
|
||||||
for (i=0;i<st->nb_channels;i++)
|
for (i=0;i<st->nb_channels;i++)
|
||||||
|
@ -1112,7 +1103,7 @@ int speex_resampler_skip_zeros(SpeexResamplerState *st)
|
||||||
return RESAMPLER_ERR_SUCCESS;
|
return RESAMPLER_ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int speex_resampler_reset_mem(SpeexResamplerState *st)
|
EXPORT int speex_resampler_reset_mem(SpeexResamplerState *st)
|
||||||
{
|
{
|
||||||
spx_uint32_t i;
|
spx_uint32_t i;
|
||||||
for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
|
for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
|
||||||
|
@ -1120,7 +1111,7 @@ int speex_resampler_reset_mem(SpeexResamplerState *st)
|
||||||
return RESAMPLER_ERR_SUCCESS;
|
return RESAMPLER_ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *speex_resampler_strerror(int err)
|
EXPORT const char *speex_resampler_strerror(int err)
|
||||||
{
|
{
|
||||||
switch (err)
|
switch (err)
|
||||||
{
|
{
|
||||||
|
|
128
lib/rbcodec/codecs/libspeex/resample_sse.h
Normal file
128
lib/rbcodec/codecs/libspeex/resample_sse.h
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
/* Copyright (C) 2007-2008 Jean-Marc Valin
|
||||||
|
* Copyright (C) 2008 Thorvald Natvig
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
@file resample_sse.h
|
||||||
|
@brief Resampler functions (SSE version)
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
- Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
- Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
- Neither the name of the Xiph.org Foundation nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||||
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <xmmintrin.h>
|
||||||
|
|
||||||
|
#define OVERRIDE_INNER_PRODUCT_SINGLE
|
||||||
|
static inline float inner_product_single(const float *a, const float *b, unsigned int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
float ret;
|
||||||
|
__m128 sum = _mm_setzero_ps();
|
||||||
|
for (i=0;i<len;i+=8)
|
||||||
|
{
|
||||||
|
sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+i), _mm_loadu_ps(b+i)));
|
||||||
|
sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+i+4), _mm_loadu_ps(b+i+4)));
|
||||||
|
}
|
||||||
|
sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum));
|
||||||
|
sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55));
|
||||||
|
_mm_store_ss(&ret, sum);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
|
||||||
|
static inline float interpolate_product_single(const float *a, const float *b, unsigned int len, const spx_uint32_t oversample, float *frac) {
|
||||||
|
int i;
|
||||||
|
float ret;
|
||||||
|
__m128 sum = _mm_setzero_ps();
|
||||||
|
__m128 f = _mm_loadu_ps(frac);
|
||||||
|
for(i=0;i<len;i+=2)
|
||||||
|
{
|
||||||
|
sum = _mm_add_ps(sum, _mm_mul_ps(_mm_load1_ps(a+i), _mm_loadu_ps(b+i*oversample)));
|
||||||
|
sum = _mm_add_ps(sum, _mm_mul_ps(_mm_load1_ps(a+i+1), _mm_loadu_ps(b+(i+1)*oversample)));
|
||||||
|
}
|
||||||
|
sum = _mm_mul_ps(f, sum);
|
||||||
|
sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum));
|
||||||
|
sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55));
|
||||||
|
_mm_store_ss(&ret, sum);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _USE_SSE2
|
||||||
|
#include <emmintrin.h>
|
||||||
|
#define OVERRIDE_INNER_PRODUCT_DOUBLE
|
||||||
|
|
||||||
|
static inline double inner_product_double(const float *a, const float *b, unsigned int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
double ret;
|
||||||
|
__m128d sum = _mm_setzero_pd();
|
||||||
|
__m128 t;
|
||||||
|
for (i=0;i<len;i+=8)
|
||||||
|
{
|
||||||
|
t = _mm_mul_ps(_mm_loadu_ps(a+i), _mm_loadu_ps(b+i));
|
||||||
|
sum = _mm_add_pd(sum, _mm_cvtps_pd(t));
|
||||||
|
sum = _mm_add_pd(sum, _mm_cvtps_pd(_mm_movehl_ps(t, t)));
|
||||||
|
|
||||||
|
t = _mm_mul_ps(_mm_loadu_ps(a+i+4), _mm_loadu_ps(b+i+4));
|
||||||
|
sum = _mm_add_pd(sum, _mm_cvtps_pd(t));
|
||||||
|
sum = _mm_add_pd(sum, _mm_cvtps_pd(_mm_movehl_ps(t, t)));
|
||||||
|
}
|
||||||
|
sum = _mm_add_sd(sum, (__m128d) _mm_movehl_ps((__m128) sum, (__m128) sum));
|
||||||
|
_mm_store_sd(&ret, sum);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
|
||||||
|
static inline double interpolate_product_double(const float *a, const float *b, unsigned int len, const spx_uint32_t oversample, float *frac) {
|
||||||
|
int i;
|
||||||
|
double ret;
|
||||||
|
__m128d sum;
|
||||||
|
__m128d sum1 = _mm_setzero_pd();
|
||||||
|
__m128d sum2 = _mm_setzero_pd();
|
||||||
|
__m128 f = _mm_loadu_ps(frac);
|
||||||
|
__m128d f1 = _mm_cvtps_pd(f);
|
||||||
|
__m128d f2 = _mm_cvtps_pd(_mm_movehl_ps(f,f));
|
||||||
|
__m128 t;
|
||||||
|
for(i=0;i<len;i+=2)
|
||||||
|
{
|
||||||
|
t = _mm_mul_ps(_mm_load1_ps(a+i), _mm_loadu_ps(b+i*oversample));
|
||||||
|
sum1 = _mm_add_pd(sum1, _mm_cvtps_pd(t));
|
||||||
|
sum2 = _mm_add_pd(sum2, _mm_cvtps_pd(_mm_movehl_ps(t, t)));
|
||||||
|
|
||||||
|
t = _mm_mul_ps(_mm_load1_ps(a+i+1), _mm_loadu_ps(b+(i+1)*oversample));
|
||||||
|
sum1 = _mm_add_pd(sum1, _mm_cvtps_pd(t));
|
||||||
|
sum2 = _mm_add_pd(sum2, _mm_cvtps_pd(_mm_movehl_ps(t, t)));
|
||||||
|
}
|
||||||
|
sum1 = _mm_mul_pd(f1, sum1);
|
||||||
|
sum2 = _mm_mul_pd(f2, sum2);
|
||||||
|
sum = _mm_add_pd(sum1, sum2);
|
||||||
|
sum = _mm_add_sd(sum, (__m128d) _mm_movehl_ps((__m128) sum, (__m128) sum));
|
||||||
|
_mm_store_sd(&ret, sum);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -49,25 +49,25 @@
|
||||||
#define MAX_IN_SAMPLES 640
|
#define MAX_IN_SAMPLES 640
|
||||||
|
|
||||||
#ifndef SPEEX_DISABLE_ENCODER
|
#ifndef SPEEX_DISABLE_ENCODER
|
||||||
void *speex_encoder_init(const SpeexMode *mode)
|
EXPORT void *speex_encoder_init(const SpeexMode *mode)
|
||||||
{
|
{
|
||||||
return mode->enc_init(mode);
|
return mode->enc_init(mode);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void *speex_decoder_init(const SpeexMode *mode)
|
EXPORT void *speex_decoder_init(const SpeexMode *mode)
|
||||||
{
|
{
|
||||||
return mode->dec_init(mode);
|
return mode->dec_init(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SPEEX_DISABLE_ENCODER
|
#ifndef SPEEX_DISABLE_ENCODER
|
||||||
void speex_encoder_destroy(void *state)
|
EXPORT void speex_encoder_destroy(void *state)
|
||||||
{
|
{
|
||||||
(*((SpeexMode**)state))->enc_destroy(state);
|
(*((SpeexMode**)state))->enc_destroy(state);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void speex_decoder_destroy(void *state)
|
EXPORT void speex_decoder_destroy(void *state)
|
||||||
{
|
{
|
||||||
(*((SpeexMode**)state))->dec_destroy(state);
|
(*((SpeexMode**)state))->dec_destroy(state);
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ int speex_decode_native(void *state, SpeexBits *bits, spx_word16_t *out)
|
||||||
|
|
||||||
#ifndef SPEEX_DISABLE_ENCODER
|
#ifndef SPEEX_DISABLE_ENCODER
|
||||||
#ifndef DISABLE_FLOAT_API
|
#ifndef DISABLE_FLOAT_API
|
||||||
int speex_encode(void *state, float *in, SpeexBits *bits)
|
EXPORT int speex_encode(void *state, float *in, SpeexBits *bits)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
spx_int32_t N;
|
spx_int32_t N;
|
||||||
|
@ -109,7 +109,7 @@ int speex_encode(void *state, float *in, SpeexBits *bits)
|
||||||
}
|
}
|
||||||
#endif /* #ifndef DISABLE_FLOAT_API */
|
#endif /* #ifndef DISABLE_FLOAT_API */
|
||||||
|
|
||||||
int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits)
|
EXPORT int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits)
|
||||||
{
|
{
|
||||||
SpeexMode *mode;
|
SpeexMode *mode;
|
||||||
mode = *(SpeexMode**)state;
|
mode = *(SpeexMode**)state;
|
||||||
|
@ -118,7 +118,7 @@ int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits)
|
||||||
#endif /* SPEEX_DISABLE_ENCODER */
|
#endif /* SPEEX_DISABLE_ENCODER */
|
||||||
|
|
||||||
#ifndef DISABLE_FLOAT_API
|
#ifndef DISABLE_FLOAT_API
|
||||||
int speex_decode(void *state, SpeexBits *bits, float *out)
|
EXPORT int speex_decode(void *state, SpeexBits *bits, float *out)
|
||||||
{
|
{
|
||||||
int i, ret;
|
int i, ret;
|
||||||
spx_int32_t N;
|
spx_int32_t N;
|
||||||
|
@ -131,7 +131,7 @@ int speex_decode(void *state, SpeexBits *bits, float *out)
|
||||||
}
|
}
|
||||||
#endif /* #ifndef DISABLE_FLOAT_API */
|
#endif /* #ifndef DISABLE_FLOAT_API */
|
||||||
|
|
||||||
int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out)
|
EXPORT int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out)
|
||||||
{
|
{
|
||||||
SpeexMode *mode = *(SpeexMode**)state;
|
SpeexMode *mode = *(SpeexMode**)state;
|
||||||
return (mode)->dec(state, bits, out);
|
return (mode)->dec(state, bits, out);
|
||||||
|
@ -139,12 +139,12 @@ int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
int speex_encode(void *state, float *in, SpeexBits *bits)
|
EXPORT int speex_encode(void *state, float *in, SpeexBits *bits)
|
||||||
{
|
{
|
||||||
return (*((SpeexMode**)state))->enc(state, in, bits);
|
return (*((SpeexMode**)state))->enc(state, in, bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits)
|
EXPORT int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
spx_int32_t N;
|
spx_int32_t N;
|
||||||
|
@ -155,12 +155,12 @@ int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits)
|
||||||
return (*((SpeexMode**)state))->enc(state, float_in, bits);
|
return (*((SpeexMode**)state))->enc(state, float_in, bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
int speex_decode(void *state, SpeexBits *bits, float *out)
|
EXPORT int speex_decode(void *state, SpeexBits *bits, float *out)
|
||||||
{
|
{
|
||||||
return (*((SpeexMode**)state))->dec(state, bits, out);
|
return (*((SpeexMode**)state))->dec(state, bits, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out)
|
EXPORT int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
spx_int32_t N;
|
spx_int32_t N;
|
||||||
|
@ -182,13 +182,13 @@ int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SPEEX_DISABLE_ENCODER
|
#ifndef SPEEX_DISABLE_ENCODER
|
||||||
int speex_encoder_ctl(void *state, int request, void *ptr)
|
EXPORT int speex_encoder_ctl(void *state, int request, void *ptr)
|
||||||
{
|
{
|
||||||
return (*((SpeexMode**)state))->enc_ctl(state, request, ptr);
|
return (*((SpeexMode**)state))->enc_ctl(state, request, ptr);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int speex_decoder_ctl(void *state, int request, void *ptr)
|
EXPORT int speex_decoder_ctl(void *state, int request, void *ptr)
|
||||||
{
|
{
|
||||||
return (*((SpeexMode**)state))->dec_ctl(state, request, ptr);
|
return (*((SpeexMode**)state))->dec_ctl(state, request, ptr);
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,7 @@ int nb_mode_query(const void *mode, int request, void *ptr)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int speex_lib_ctl(int request, void *ptr)
|
EXPORT int speex_lib_ctl(int request, void *ptr)
|
||||||
{
|
{
|
||||||
switch (request)
|
switch (request)
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
#include "os_support.h"
|
#include "os_support.h"
|
||||||
|
|
||||||
int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *state)
|
EXPORT int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *state)
|
||||||
{
|
{
|
||||||
int id;
|
int id;
|
||||||
SpeexCallback *callback;
|
SpeexCallback *callback;
|
||||||
|
@ -74,7 +74,7 @@ int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *st
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* Rockbox: unused */
|
/* Rockbox: unused */
|
||||||
int speex_std_mode_request_handler(SpeexBits *bits, void *state, void *data)
|
EXPORT int speex_std_mode_request_handler(SpeexBits *bits, void *state, void *data)
|
||||||
{
|
{
|
||||||
(void)state;
|
(void)state;
|
||||||
spx_int32_t m;
|
spx_int32_t m;
|
||||||
|
@ -83,7 +83,7 @@ int speex_std_mode_request_handler(SpeexBits *bits, void *state, void *data)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int speex_std_low_mode_request_handler(SpeexBits *bits, void *state, void *data)
|
EXPORT int speex_std_low_mode_request_handler(SpeexBits *bits, void *state, void *data)
|
||||||
{
|
{
|
||||||
(void)state;
|
(void)state;
|
||||||
spx_int32_t m;
|
spx_int32_t m;
|
||||||
|
@ -92,7 +92,7 @@ int speex_std_low_mode_request_handler(SpeexBits *bits, void *state, void *data)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int speex_std_high_mode_request_handler(SpeexBits *bits, void *state, void *data)
|
EXPORT int speex_std_high_mode_request_handler(SpeexBits *bits, void *state, void *data)
|
||||||
{
|
{
|
||||||
(void)state;
|
(void)state;
|
||||||
spx_int32_t m;
|
spx_int32_t m;
|
||||||
|
@ -103,7 +103,7 @@ int speex_std_high_mode_request_handler(SpeexBits *bits, void *state, void *data
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DISABLE_VBR
|
#ifndef DISABLE_VBR
|
||||||
int speex_std_vbr_request_handler(SpeexBits *bits, void *state, void *data)
|
EXPORT int speex_std_vbr_request_handler(SpeexBits *bits, void *state, void *data)
|
||||||
{
|
{
|
||||||
(void)state;
|
(void)state;
|
||||||
spx_int32_t vbr;
|
spx_int32_t vbr;
|
||||||
|
@ -115,7 +115,7 @@ int speex_std_vbr_request_handler(SpeexBits *bits, void *state, void *data)
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* Rockbox: unused */
|
/* Rockbox: unused */
|
||||||
int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data)
|
EXPORT int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data)
|
||||||
{
|
{
|
||||||
(void)state;
|
(void)state;
|
||||||
spx_int32_t enh;
|
spx_int32_t enh;
|
||||||
|
@ -126,7 +126,7 @@ int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DISABLE_VBR
|
#ifndef DISABLE_VBR
|
||||||
int speex_std_vbr_quality_request_handler(SpeexBits *bits, void *state, void *data)
|
EXPORT int speex_std_vbr_quality_request_handler(SpeexBits *bits, void *state, void *data)
|
||||||
{
|
{
|
||||||
(void)state;
|
(void)state;
|
||||||
float qual;
|
float qual;
|
||||||
|
@ -138,7 +138,7 @@ int speex_std_vbr_quality_request_handler(SpeexBits *bits, void *state, void *da
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* Rockbox: unused */
|
/* Rockbox: unused */
|
||||||
int speex_std_char_handler(SpeexBits *bits, void *state, void *data)
|
EXPORT int speex_std_char_handler(SpeexBits *bits, void *state, void *data)
|
||||||
{
|
{
|
||||||
(void)state;
|
(void)state;
|
||||||
unsigned char ch;
|
unsigned char ch;
|
||||||
|
@ -150,7 +150,7 @@ int speex_std_char_handler(SpeexBits *bits, void *state, void *data)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Default handler for user callbacks: skip it */
|
/* Default handler for user callbacks: skip it */
|
||||||
int speex_default_user_handler(SpeexBits *bits, void *state, void *data)
|
EXPORT int speex_default_user_handler(SpeexBits *bits, void *state, void *data)
|
||||||
{
|
{
|
||||||
(void)state;
|
(void)state;
|
||||||
(void)data;
|
(void)data;
|
||||||
|
|
|
@ -86,7 +86,7 @@ typedef struct SpeexHeader {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SPEEX_DISABLE_ENCODER
|
#ifndef SPEEX_DISABLE_ENCODER
|
||||||
void speex_init_header(SpeexHeader *header, int rate, int nb_channels, const SpeexMode *m)
|
EXPORT void speex_init_header(SpeexHeader *header, int rate, int nb_channels, const SpeexMode *m)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
const char *h="Speex ";
|
const char *h="Speex ";
|
||||||
|
@ -121,7 +121,7 @@ void speex_init_header(SpeexHeader *header, int rate, int nb_channels, const Spe
|
||||||
header->reserved2 = 0;
|
header->reserved2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *speex_header_to_packet(SpeexHeader *header, int *size)
|
EXPORT char *speex_header_to_packet(SpeexHeader *header, int *size)
|
||||||
{
|
{
|
||||||
SpeexHeader *le_header;
|
SpeexHeader *le_header;
|
||||||
le_header = (SpeexHeader*)speex_alloc(sizeof(SpeexHeader));
|
le_header = (SpeexHeader*)speex_alloc(sizeof(SpeexHeader));
|
||||||
|
@ -147,7 +147,7 @@ char *speex_header_to_packet(SpeexHeader *header, int *size)
|
||||||
#endif /* SPEEX_DISABLE_ENCODER */
|
#endif /* SPEEX_DISABLE_ENCODER */
|
||||||
|
|
||||||
static SpeexHeader global_le_header; /* Avoid malloc */
|
static SpeexHeader global_le_header; /* Avoid malloc */
|
||||||
SpeexHeader *speex_packet_to_header(char *packet, int size)
|
EXPORT SpeexHeader *speex_packet_to_header(char *packet, int size)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
SpeexHeader *le_header = &global_le_header;
|
SpeexHeader *le_header = &global_le_header;
|
||||||
|
@ -183,6 +183,25 @@ SpeexHeader *speex_packet_to_header(char *packet, int size)
|
||||||
ENDIAN_SWITCH(le_header->frames_per_packet);
|
ENDIAN_SWITCH(le_header->frames_per_packet);
|
||||||
ENDIAN_SWITCH(le_header->extra_headers);
|
ENDIAN_SWITCH(le_header->extra_headers);
|
||||||
|
|
||||||
|
if (le_header->mode >= SPEEX_NB_MODES || le_header->mode < 0)
|
||||||
|
{
|
||||||
|
speex_notify("Invalid mode specified in Speex header");
|
||||||
|
speex_free (le_header);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (le_header->nb_channels>2)
|
||||||
|
le_header->nb_channels = 2;
|
||||||
|
if (le_header->nb_channels<1)
|
||||||
|
le_header->nb_channels = 1;
|
||||||
|
|
||||||
return le_header;
|
return le_header;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0 /* Unused by rockbox */
|
||||||
|
EXPORT void speex_header_free(void *ptr)
|
||||||
|
{
|
||||||
|
speex_free(ptr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -75,7 +75,7 @@ static const spx_word16_t balance_bounds[31] = {18, 23, 30, 38, 49, 63, 81, 104
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static SpeexStereoState global_stereo_state;
|
static SpeexStereoState global_stereo_state;
|
||||||
SpeexStereoState *speex_stereo_state_init()
|
EXPORT SpeexStereoState *speex_stereo_state_init()
|
||||||
{
|
{
|
||||||
/* SpeexStereoState *stereo = speex_alloc(sizeof(SpeexStereoState)); */
|
/* SpeexStereoState *stereo = speex_alloc(sizeof(SpeexStereoState)); */
|
||||||
SpeexStereoState *stereo = &global_stereo_state;
|
SpeexStereoState *stereo = &global_stereo_state;
|
||||||
|
@ -83,7 +83,7 @@ SpeexStereoState *speex_stereo_state_init()
|
||||||
return stereo;
|
return stereo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void speex_stereo_state_reset(SpeexStereoState *_stereo)
|
EXPORT void speex_stereo_state_reset(SpeexStereoState *_stereo)
|
||||||
{
|
{
|
||||||
RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo;
|
RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo;
|
||||||
#ifdef FIXED_POINT
|
#ifdef FIXED_POINT
|
||||||
|
@ -103,7 +103,7 @@ void speex_stereo_state_reset(SpeexStereoState *_stereo)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void speex_stereo_state_destroy(SpeexStereoState *stereo)
|
EXPORT void speex_stereo_state_destroy(SpeexStereoState *stereo)
|
||||||
{
|
{
|
||||||
(void)stereo;
|
(void)stereo;
|
||||||
/* speex_free(stereo); */
|
/* speex_free(stereo); */
|
||||||
|
@ -111,7 +111,7 @@ void speex_stereo_state_destroy(SpeexStereoState *stereo)
|
||||||
|
|
||||||
#ifndef SPEEX_DISABLE_ENCODER
|
#ifndef SPEEX_DISABLE_ENCODER
|
||||||
#ifndef DISABLE_FLOAT_API
|
#ifndef DISABLE_FLOAT_API
|
||||||
void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits)
|
EXPORT void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits)
|
||||||
{
|
{
|
||||||
int i, tmp;
|
int i, tmp;
|
||||||
float e_left=0, e_right=0, e_tot=0;
|
float e_left=0, e_right=0, e_tot=0;
|
||||||
|
@ -149,7 +149,7 @@ void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits)
|
||||||
}
|
}
|
||||||
#endif /* #ifndef DISABLE_FLOAT_API */
|
#endif /* #ifndef DISABLE_FLOAT_API */
|
||||||
|
|
||||||
void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits)
|
EXPORT void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits)
|
||||||
{
|
{
|
||||||
int i, tmp;
|
int i, tmp;
|
||||||
spx_word32_t e_left=0, e_right=0, e_tot=0;
|
spx_word32_t e_left=0, e_right=0, e_tot=0;
|
||||||
|
@ -225,7 +225,7 @@ void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits)
|
||||||
#endif /* SPEEX_DISABLE_ENCODER */
|
#endif /* SPEEX_DISABLE_ENCODER */
|
||||||
|
|
||||||
#ifndef DISABLE_FLOAT_API
|
#ifndef DISABLE_FLOAT_API
|
||||||
void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *_stereo)
|
EXPORT void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *_stereo)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
spx_word32_t balance;
|
spx_word32_t balance;
|
||||||
|
@ -252,7 +252,7 @@ void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *_stereo)
|
||||||
}
|
}
|
||||||
#endif /* #ifndef DISABLE_FLOAT_API */
|
#endif /* #ifndef DISABLE_FLOAT_API */
|
||||||
|
|
||||||
void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState *_stereo)
|
EXPORT void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState *_stereo)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
spx_word32_t balance;
|
spx_word32_t balance;
|
||||||
|
@ -278,7 +278,7 @@ void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data)
|
EXPORT int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data)
|
||||||
{
|
{
|
||||||
(void)state;
|
(void)state;
|
||||||
RealSpeexStereoState *stereo;
|
RealSpeexStereoState *stereo;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue