Загрузка данных
/** Compute weighted cross-power spectrum of a half-complex (packed) vector with conjugate */
static inline void weighted_spectral_mul_conj(const spx_float_t *w, const spx_float_t p, const spx_word16_t *X, const spx_word16_t *Y, spx_word32_t *prod, int N)
{
int i, j;
spx_float_t W;
W = FLOAT_AMULT(p, w[0]);
prod[0] = FLOAT_MUL32(W,MULT16_16(X[0],Y[0]));
for (i=1,j=1;i<N-1;i+=2,j++)
{
W = FLOAT_AMULT(p, w[j]);
prod[i] = FLOAT_MUL32(W,MAC16_16(MULT16_16(X[i],Y[i]), X[i+1],Y[i+1]));
prod[i+1] = FLOAT_MUL32(W,MAC16_16(MULT16_16(-X[i+1],Y[i]), X[i],Y[i+1]));
}
W = FLOAT_AMULT(p, w[j]);
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, int P, spx_word16_t *prop)
{
int i, j, p;
spx_word16_t max_sum = 1;
spx_word32_t prop_sum = 1;
for (i=0;i<M;i++)
{
spx_word32_t tmp = 1;
for (p=0;p<P;p++)
for (j=0;j<N;j++)
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
/* Just a security in case an overflow were to occur */
tmp = MIN32(ABS32(tmp), 536870912);
#endif
prop[i] = spx_sqrt(tmp);
if (prop[i] > max_sum)
max_sum = prop[i];
}
for (i=0;i<M;i++)
{
prop[i] += MULT16_16_Q15(QCONST16(.1f,15),max_sum);
prop_sum += EXTEND32(prop[i]);
}
for (i=0;i<M;i++)
{
prop[i] = DIV32(MULT16_16(QCONST16(.99f,15), prop[i]),prop_sum);
/*printf ("%f ", prop[i]);*/
}
/*printf ("\n");*/
}
#ifdef DUMP_ECHO_CANCEL_DATA
#include <stdio.h>
static FILE *rFile=NULL, *pFile=NULL, *oFile=NULL;
static void dump_audio(const spx_int16_t *rec, const spx_int16_t *play, const spx_int16_t *out, int len)
{
if (!(rFile && pFile && oFile))
{
speex_fatal("Dump files not open");
}
fwrite(rec, sizeof(spx_int16_t), len, rFile);
fwrite(play, sizeof(spx_int16_t), len, pFile);
fwrite(out, sizeof(spx_int16_t), len, oFile);
}
#endif
/** Creates a new echo canceller state */
EXPORT SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length)
{
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));
st->K = nb_speakers;
st->C = nb_mic;
C=st->C;
K=st->K;
#ifdef DUMP_ECHO_CANCEL_DATA
if (rFile || pFile || oFile)
speex_fatal("Opening dump files twice");
rFile = fopen("aec_rec.sw", "wb");
pFile = fopen("aec_play.sw", "wb");
oFile = fopen("aec_out.sw", "wb");
#endif
st->frame_size = frame_size;
st->window_size = 2*frame_size;
N = st->window_size;
M = st->M = (filter_length+st->frame_size-1)/frame_size;
st->cancel_count=0;
st->sum_adapt = 0;
st->saturated = 0;
st->screwed_up = 0;
/* This is the default sampling rate */
st->sampling_rate = 8000;
st->spec_average = DIV32_16(SHL32(EXTEND32(st->frame_size), 15), st->sampling_rate);
#ifdef FIXED_POINT
st->beta0 = DIV32_16(SHL32(EXTEND32(st->frame_size), 16), st->sampling_rate);
st->beta_max = DIV32_16(SHL32(EXTEND32(st->frame_size), 14), st->sampling_rate);
#else
st->beta0 = (2.0f*st->frame_size)/st->sampling_rate;
st->beta_max = (.5f*st->frame_size)/st->sampling_rate;
#endif
st->leak_estimate = 0;
st->fft_table = spx_fft_init(N);
st->e = (spx_word16_t*)speex_alloc(C*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(C*st->frame_size*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(C*N*sizeof(spx_word16_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->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->Eh = (spx_word32_t*)speex_alloc((st->frame_size+1)*sizeof(spx_word32_t));
st->X = (spx_word16_t*)speex_alloc(K*(M+1)*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(C*N*sizeof(spx_word16_t));
st->W = (spx_word32_t*)speex_alloc(C*K*M*N*sizeof(spx_word32_t));
#ifdef TWO_PATH
st->foreground = (spx_word16_t*)speex_alloc(M*N*C*K*sizeof(spx_word16_t));
#endif
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_1 = (spx_float_t*)speex_alloc((frame_size+1)*sizeof(spx_float_t));
st->window = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t));
st->prop = (spx_word16_t*)speex_alloc(M*sizeof(spx_word16_t));
st->wtmp = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t));
#ifdef FIXED_POINT
st->wtmp2 = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t));
for (i=0;i<N>>1;i++)
{
st->window[i] = (16383-SHL16(spx_cos(DIV32_16(MULT16_16(25736,i<<1),N)),1));
st->window[N-i-1] = st->window[i];
}
#else
for (i=0;i<N;i++)
st->window[i] = .5-.5*cos(2*M_PI*i/N);
#endif
for (i=0;i<=st->frame_size;i++)
st->power_1[i] = FLOAT_ONE;
for (i=0;i<N*M*K*C;i++)
st->W[i] = 0;
{
spx_word32_t sum = 0;
/* Ratio of ~10 between adaptation rate of first and last block */
spx_word16_t decay = SHR32(spx_exp(NEG16(DIV32_16(QCONST16(2.4,11),M))),1);
st->prop[0] = QCONST16(.7, 15);
sum = EXTEND32(st->prop[0]);
for (i=1;i<M;i++)
{
st->prop[i] = MULT16_16_Q15(st->prop[i-1], decay);
sum = ADD32(sum, EXTEND32(st->prop[i]));
}
for (i=M-1;i>=0;i--)
{
st->prop[i] = DIV32(MULT16_16(QCONST16(.8f,15), st->prop[i]),sum);
}
}
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);
if (st->sampling_rate<12000)
st->notch_radius = QCONST16(.9, 15);
else if (st->sampling_rate<24000)
st->notch_radius = QCONST16(.982, 15);
else
st->notch_radius = QCONST16(.992, 15);
st->notch_mem = (spx_mem_t*)speex_alloc(2*C*sizeof(spx_mem_t));
st->adapted = 0;
st->Pey = st->Pyy = FLOAT_ONE;
#ifdef TWO_PATH
st->Davg1 = st->Davg2 = 0;
st->Dvar1 = st->Dvar2 = FLOAT_ZERO;
#endif
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_started = 0;
return st;
}
/** Resets echo canceller state */
EXPORT void speex_echo_state_reset(SpeexEchoState *st)
{
int i, M, N, C, K;
st->cancel_count=0;
st->screwed_up = 0;
N = st->window_size;
M = st->M;
C=st->C;
K=st->K;
for (i=0;i<N*M;i++)
st->W[i] = 0;
#ifdef TWO_PATH
for (i=0;i<N*M;i++)
st->foreground[i] = 0;
#endif
for (i=0;i<N*(M+1);i++)
st->X[i] = 0;
for (i=0;i<=st->frame_size;i++)
{
st->power[i] = 0;
st->power_1[i] = FLOAT_ONE;
st->Eh[i] = 0;
st->Yh[i] = 0;
}
for (i=0;i<st->frame_size;i++)
{
st->last_y[i] = 0;
}
for (i=0;i<N*C;i++)
{
st->E[i] = 0;
}
for (i=0;i<N*K;i++)
{
st->x[i] = 0;
}
for (i=0;i<2*C;i++)
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->adapted = 0;
st->sum_adapt = 0;
st->Pey = st->Pyy = FLOAT_ONE;
#ifdef TWO_PATH
st->Davg1 = st->Davg2 = 0;
st->Dvar1 = st->Dvar2 = FLOAT_ZERO;
#endif
for (i=0;i<3*st->frame_size;i++)
st->play_buf[i] = 0;
st->play_buf_pos = PLAYBACK_DELAY*st->frame_size;
st->play_buf_started = 0;
}