1193 lines
29 KiB
C
1193 lines
29 KiB
C
/* Copyright (C) 2007 Hong Zhiqian */
|
|
/**
|
|
@file mdf_tm.h
|
|
@author Hong Zhiqian
|
|
@brief Various compatibility routines for Speex (TriMedia 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 <ops/custom_defs.h>
|
|
#include "profile_tm.h"
|
|
|
|
// shifted power spectrum to fftwrap.c so that optimisation can be shared between mdf.c and preprocess.c
|
|
#define OVERRIDE_POWER_SPECTRUM
|
|
|
|
#ifdef FIXED_POINT
|
|
|
|
#else
|
|
|
|
#define OVERRIDE_FILTER_DC_NOTCH16
|
|
void filter_dc_notch16(
|
|
const spx_int16_t * restrict in,
|
|
float radius,
|
|
float * restrict out,
|
|
int len,
|
|
float * restrict mem
|
|
)
|
|
{
|
|
register int i;
|
|
register float den2, r1;
|
|
register float mem0, mem1;
|
|
|
|
FILTERDCNOTCH16_START();
|
|
|
|
r1 = 1 - radius;
|
|
den2 = (radius * radius) + (0.7 * r1 * r1);
|
|
mem0 = mem[0];
|
|
mem1 = mem[1];
|
|
|
|
#if (TM_UNROLL && TM_UNROLL_FILTERDCNOTCH16)
|
|
#pragma TCS_unroll=4
|
|
#pragma TCS_unrollexact=1
|
|
#endif
|
|
for ( i=0 ; i<len ; ++i )
|
|
{
|
|
register float vin = in[i];
|
|
register float vout = mem0 + vin;
|
|
register float rvout = radius * vout;
|
|
|
|
mem0 = mem1 + 2 * (-vin + rvout);
|
|
mem1 = vin - (den2 * vout);
|
|
|
|
out[i] = rvout;
|
|
}
|
|
#if (TM_UNROLL && TM_UNROLL_FILTERDCNOTCH16)
|
|
#pragma TCS_unrollexact=0
|
|
#pragma TCS_unroll=0
|
|
#endif
|
|
|
|
mem[0] = mem0;
|
|
mem[1] = mem1;
|
|
|
|
FILTERDCNOTCH16_STOP();
|
|
}
|
|
|
|
#define OVERRIDE_MDF_INNER_PROD
|
|
float mdf_inner_prod(
|
|
const float * restrict x,
|
|
const float * restrict y,
|
|
int len
|
|
)
|
|
{
|
|
register float sum = 0;
|
|
|
|
MDFINNERPROD_START();
|
|
|
|
len >>= 1;
|
|
|
|
#if (TM_UNROLL && TM_UNROLL_MDFINNERPRODUCT)
|
|
#pragma TCS_unroll=4
|
|
#pragma TCS_unrollexact=1
|
|
#endif
|
|
while(len--)
|
|
{
|
|
register float acc0, acc1;
|
|
|
|
acc0 = (*x++) * (*y++);
|
|
acc1 = (*x++) * (*y++);
|
|
|
|
sum += acc0 + acc1;
|
|
}
|
|
#if (TM_UNROLL && TM_UNROLL_MDFINNERPRODUCT)
|
|
#pragma TCS_unrollexact=0
|
|
#pragma TCS_unroll=0
|
|
#endif
|
|
|
|
MDFINNERPROD_STOP();
|
|
|
|
return sum;
|
|
}
|
|
|
|
#define OVERRIDE_SPECTRAL_MUL_ACCUM
|
|
void spectral_mul_accum(
|
|
const float * restrict X,
|
|
const float * restrict Y,
|
|
float * restrict acc,
|
|
int N, int M
|
|
)
|
|
{
|
|
register int i, j;
|
|
register float Xi, Yi, Xii, Yii;
|
|
register int _N;
|
|
|
|
SPECTRALMULACCUM_START();
|
|
|
|
acc[0] = X[0] * Y[0];
|
|
_N = N-1;
|
|
|
|
for ( i=1 ; i<_N ; i+=2 )
|
|
{
|
|
Xi = X[i];
|
|
Yi = Y[i];
|
|
Xii = X[i+1];
|
|
Yii = Y[i+1];
|
|
|
|
acc[i] = (Xi * Yi - Xii * Yii);
|
|
acc[i+1]= (Xii * Yi + Xi * Yii);
|
|
}
|
|
|
|
acc[_N] = X[_N] * Y[_N];
|
|
|
|
for ( j=1,X+=N,Y+=N ; j<M ; j++ )
|
|
{
|
|
acc[0] += X[0] * Y[0];
|
|
|
|
for ( i=1 ; i<N-1 ; i+=2 )
|
|
{
|
|
Xi = X[i];
|
|
Yi = Y[i];
|
|
Xii = X[i+1];
|
|
Yii = Y[i+1];
|
|
|
|
acc[i] += (Xi * Yi - Xii * Yii);
|
|
acc[i+1]+= (Xii * Yi + Xi * Yii);
|
|
}
|
|
|
|
acc[_N] += X[_N] * Y[_N];
|
|
X += N;
|
|
Y += N;
|
|
}
|
|
|
|
SPECTRALMULACCUM_STOP();
|
|
}
|
|
|
|
#define OVERRIDE_WEIGHTED_SPECTRAL_MUL_CONJ
|
|
void weighted_spectral_mul_conj(
|
|
const float * restrict w,
|
|
const float p,
|
|
const float * restrict X,
|
|
const float * restrict Y,
|
|
float * restrict prod,
|
|
int N
|
|
)
|
|
{
|
|
register int i, j;
|
|
register int _N;
|
|
|
|
WEIGHTEDSPECTRALMULCONJ_START();
|
|
|
|
prod[0] = p * w[0] * X[0] * Y[0];
|
|
_N = N-1;
|
|
|
|
for (i=1,j=1;i<_N;i+=2,j++)
|
|
{
|
|
register float W;
|
|
register float Xi, Yi, Xii, Yii;
|
|
|
|
Xi = X[i];
|
|
Yi = Y[i];
|
|
Xii = X[i+1];
|
|
Yii = Y[i+1];
|
|
W = p * w[j];
|
|
|
|
|
|
prod[i] = W * (Xi * Yi + Xii * Yii);
|
|
prod[i+1]= W * (Xi * Yii - Xii * Yi);
|
|
}
|
|
|
|
prod[_N] = p * w[j] * X[_N] * Y[_N];
|
|
|
|
WEIGHTEDSPECTRALMULCONJ_STOP();
|
|
}
|
|
|
|
#define OVERRIDE_MDF_ADJUST_PROP
|
|
void mdf_adjust_prop(
|
|
const float * restrict W,
|
|
int N,
|
|
int M,
|
|
float * restrict prop
|
|
)
|
|
{
|
|
register int i, j;
|
|
register float max_sum = 1;
|
|
register float prop_sum = 1;
|
|
|
|
MDFADJUSTPROP_START();
|
|
|
|
for ( i=0 ; i<M ; ++i )
|
|
{
|
|
register float tmp = 1;
|
|
register int k = i * N;
|
|
register int l = k + N;
|
|
register float propi;
|
|
|
|
#if (TM_UNROLL && TM_UNROLL_MDFADJUSTPROP)
|
|
#pragma TCS_unroll=4
|
|
#pragma TCS_unrollexact=1
|
|
#endif
|
|
for ( j=k ; j<l ; ++j )
|
|
{
|
|
register float wi = W[j];
|
|
|
|
tmp += wi * wi;
|
|
}
|
|
#if (TM_UNROLL && TM_UNROLL_MDFADJUSTPROP)
|
|
#pragma TCS_unrollexact=0
|
|
#pragma TCS_unroll=0
|
|
#endif
|
|
|
|
propi = spx_sqrt(tmp);
|
|
prop[i]= propi;
|
|
max_sum= fmux(propi > max_sum, propi, max_sum);
|
|
}
|
|
|
|
for ( i=0 ; i<M ; ++i )
|
|
{
|
|
register float propi = prop[i];
|
|
|
|
propi += .1f * max_sum;
|
|
prop_sum += propi;
|
|
prop[i] = propi;
|
|
}
|
|
|
|
prop_sum = 0.99f / prop_sum;
|
|
for ( i=0 ; i<M ; ++i )
|
|
{ prop[i] = prop_sum * prop[i];
|
|
}
|
|
|
|
MDFADJUSTPROP_STOP();
|
|
}
|
|
|
|
|
|
#define OVERRIDE_SPEEX_ECHO_GET_RESIDUAL
|
|
void speex_echo_get_residual(
|
|
SpeexEchoState * restrict st,
|
|
float * restrict residual_echo,
|
|
int len
|
|
)
|
|
{
|
|
register int i;
|
|
register float leak2, leake;
|
|
register int N;
|
|
register float * restrict window;
|
|
register float * restrict last_y;
|
|
register float * restrict y;
|
|
|
|
SPEEXECHOGETRESIDUAL_START();
|
|
|
|
window = st->window;
|
|
last_y = st->last_y;
|
|
y = st->y;
|
|
N = st->window_size;
|
|
|
|
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOGETRESIDUAL)
|
|
#pragma TCS_unroll=4
|
|
#pragma TCS_unrollexact=1
|
|
#endif
|
|
for (i=0;i<N;i++)
|
|
{ y[i] = window[i] * last_y[i];
|
|
}
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOGETRESIDUAL)
|
|
#pragma TCS_unrollexact=0
|
|
#pragma TCS_unroll=0
|
|
#endif
|
|
|
|
spx_fft(st->fft_table, st->y, st->Y);
|
|
power_spectrum(st->Y, residual_echo, N);
|
|
|
|
leake = st->leak_estimate;
|
|
leak2 = fmux(leake > .5, 1, 2 * leake);
|
|
N = st->frame_size;
|
|
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOGETRESIDUAL)
|
|
#pragma TCS_unroll=4
|
|
#pragma TCS_unrollexact=1
|
|
#endif
|
|
for ( i=0 ; i<N ; ++i )
|
|
{ residual_echo[i] *= leak2;
|
|
}
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOGETRESIDUAL)
|
|
#pragma TCS_unrollexact=0
|
|
#pragma TCS_unroll=0
|
|
#endif
|
|
|
|
residual_echo[N] *= leak2;
|
|
|
|
#ifndef NO_REMARK
|
|
(void)len;
|
|
#endif
|
|
|
|
SPEEXECHOGETRESIDUAL_STOP();
|
|
}
|
|
#endif
|
|
|
|
|
|
void mdf_preemph(
|
|
SpeexEchoState * restrict st,
|
|
spx_word16_t * restrict x,
|
|
const spx_int16_t * restrict far_end,
|
|
int framesize
|
|
)
|
|
{
|
|
register spx_word16_t preemph = st->preemph;
|
|
register spx_word16_t memX = st->memX;
|
|
register spx_word16_t memD = st->memD;
|
|
register spx_word16_t * restrict input = st->input;
|
|
register int i;
|
|
#ifdef FIXED_POINT
|
|
register int saturated = st->saturated;
|
|
#endif
|
|
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unroll=4
|
|
#pragma TCS_unrollexact=1
|
|
#endif
|
|
for ( i=0 ; i<framesize ; ++i )
|
|
{
|
|
register spx_int16_t far_endi = far_end[i];
|
|
register spx_word32_t tmp32;
|
|
register spx_word16_t inputi = input[i];
|
|
|
|
tmp32 = SUB32(EXTEND32(far_endi), EXTEND32(MULT16_16_P15(preemph,memX)));
|
|
|
|
#ifdef FIXED_POINT
|
|
saturated = mux(iabs(tmp32) > 32767, M+1, saturated);
|
|
tmp32 = iclipi(tmp32,32767);
|
|
#endif
|
|
|
|
x[i] = EXTRACT16(tmp32);
|
|
memX = far_endi;
|
|
tmp32 = SUB32(EXTEND32(inputi), EXTEND32(MULT16_16_P15(preemph, memD)));
|
|
|
|
#ifdef FIXED_POINT
|
|
saturated = mux( ((tmp32 > 32767) && (saturated == 0)), 1,
|
|
mux( ((tmp32 <-32767) && (saturated == 0)), 1, saturated ));
|
|
tmp32 = iclipi(tmp32,32767);
|
|
#endif
|
|
memD = inputi;
|
|
input[i] = tmp32;
|
|
}
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unrollexact=0
|
|
#pragma TCS_unroll=0
|
|
#endif
|
|
|
|
st->memD = memD;
|
|
st->memX = memX;
|
|
|
|
#ifdef FIXED_POINT
|
|
st->saturated = saturated;
|
|
#endif
|
|
}
|
|
|
|
void mdf_sub(
|
|
spx_word16_t * restrict dest,
|
|
const spx_word16_t * restrict src1,
|
|
const spx_word16_t * restrict src2,
|
|
int framesize
|
|
)
|
|
{
|
|
register int i;
|
|
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unroll=4
|
|
#pragma TCS_unrollexact=1
|
|
#endif
|
|
|
|
#ifdef FIXED_POINT
|
|
for ( i=0,framesize<<=1 ; i<framesize ; i+=4 )
|
|
{ register int src1i, src2i, desti;
|
|
|
|
src1i = ld32d(src1,i);
|
|
src2i = ld32d(src2,i);
|
|
desti = dspidualsub(src1i,src2i);
|
|
st32d(i, dest, desti);
|
|
}
|
|
#else
|
|
for ( i=0 ; i<framesize ; ++i )
|
|
{ dest[i] = src1[i] - src2[i];
|
|
}
|
|
#endif
|
|
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unrollexact=0
|
|
#pragma TCS_unroll=0
|
|
#endif
|
|
}
|
|
|
|
void mdf_sub_int(
|
|
spx_word16_t * restrict dest,
|
|
const spx_int16_t * restrict src1,
|
|
const spx_int16_t * restrict src2,
|
|
int framesize
|
|
)
|
|
{
|
|
register int i, j;
|
|
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unroll=4
|
|
#pragma TCS_unrollexact=1
|
|
#endif
|
|
|
|
#ifdef FIXED_POINT
|
|
for ( i=0,framesize<<=1 ; i<framesize ; i+=4 )
|
|
{ register int src1i, src2i, desti;
|
|
|
|
src1i = ld32d(src1,i);
|
|
src2i = ld32d(src2,i);
|
|
desti = dspidualsub(src1i,src2i);
|
|
st32d(i, dest, desti);
|
|
}
|
|
#else
|
|
for ( i=0,j=0 ; i<framesize ; i+=2,++j )
|
|
{ register int src1i, src2i, desti;
|
|
|
|
|
|
src1i = ld32d(src1,j);
|
|
src2i = ld32d(src2,j);
|
|
desti = dspidualsub(src1i,src2i);
|
|
|
|
dest[i] = sex16(desti);
|
|
dest[i+1] = asri(16,desti);
|
|
}
|
|
#endif
|
|
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unrollexact=0
|
|
#pragma TCS_unroll=0
|
|
#endif
|
|
}
|
|
|
|
void mdf_compute_weight_gradient(
|
|
SpeexEchoState * restrict st,
|
|
spx_word16_t * restrict X,
|
|
int N,
|
|
int M
|
|
)
|
|
{
|
|
register int i, j;
|
|
register spx_word32_t * restrict PHI = st->PHI;
|
|
|
|
for (j=M-1;j>=0;j--)
|
|
{
|
|
register spx_word32_t * restrict W = &(st->W[j*N]);
|
|
|
|
weighted_spectral_mul_conj(
|
|
st->power_1,
|
|
FLOAT_SHL(PSEUDOFLOAT(st->prop[j]),-15),
|
|
&X[(j+1)*N],
|
|
st->E,
|
|
st->PHI,
|
|
N);
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unroll=4
|
|
#pragma TCS_unrollexact=1
|
|
#endif
|
|
for (i=0;i<N;i++)
|
|
{ W[i] = ADD32(W[i],PHI[i]);
|
|
}
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unrollexact=0
|
|
#pragma TCS_unroll=0
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void mdf_update_weight(
|
|
SpeexEchoState * restrict st,
|
|
int N,
|
|
int M,
|
|
int framesize
|
|
)
|
|
{
|
|
register int j;
|
|
register int cancel_count = st->cancel_count;
|
|
register spx_word16_t * restrict wtmp = st->wtmp;
|
|
#ifdef FIXED_POINT
|
|
register spx_word16_t * restrict wtmp2 = st->wtmp2;
|
|
register int i;
|
|
#endif
|
|
|
|
for ( j=0 ; j<M ; j++ )
|
|
{
|
|
register spx_word32_t * restrict W = &(st->W[j*N]);
|
|
|
|
if (j==0 || cancel_count%(M-1) == j-1)
|
|
{
|
|
#ifdef FIXED_POINT
|
|
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unroll=4
|
|
#pragma TCS_unrollexact=1
|
|
#endif
|
|
for ( i=0 ; i<N ; i++ )
|
|
wtmp2[i] = EXTRACT16(PSHR32(W[i],NORMALIZE_SCALEDOWN+16));
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unrollexact=0
|
|
#pragma TCS_unroll=0
|
|
#endif
|
|
spx_ifft(st->fft_table, wtmp2, wtmp);
|
|
memset(wtmp, 0, framesize * sizeof(spx_word16_t));
|
|
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unroll=4
|
|
#pragma TCS_unrollexact=1
|
|
#endif
|
|
for (j=framesize; j<N ; ++j)
|
|
{ wtmp[j]=SHL16(wtmp[j],NORMALIZE_SCALEUP);
|
|
}
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unrollexact=0
|
|
#pragma TCS_unroll=0
|
|
#endif
|
|
|
|
spx_fft(st->fft_table, wtmp, wtmp2);
|
|
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unroll=4
|
|
#pragma TCS_unrollexact=1
|
|
#endif
|
|
for (i=0;i<N;i++)
|
|
{ W[i] -= SHL32(EXTEND32(wtmp2[i]),16+NORMALIZE_SCALEDOWN-NORMALIZE_SCALEUP-1);
|
|
}
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unrollexact=0
|
|
#pragma TCS_unroll=0
|
|
#endif
|
|
|
|
#else
|
|
spx_ifft(st->fft_table, W, wtmp);
|
|
memset(&wtmp[framesize], 0, (N-framesize) * sizeof(spx_word16_t));
|
|
spx_fft(st->fft_table, wtmp, W);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef TWO_PATH
|
|
// first four parameters is passed by registers
|
|
// generate faster performance with 4 parameters functions
|
|
spx_word32_t mdf_update_foreground(
|
|
SpeexEchoState * restrict st,
|
|
spx_word32_t Dbf,
|
|
spx_word32_t Sff,
|
|
spx_word32_t See
|
|
)
|
|
{
|
|
register spx_word32_t Davg1 = st->Davg1;
|
|
register spx_word32_t Davg2 = st->Davg2;
|
|
register spx_word32_t Dvar1 = st->Dvar1;
|
|
register spx_word32_t Dvar2 = st->Dvar2;
|
|
register spx_word16_t * restrict input = st->input;
|
|
register int framesize = st->frame_size;
|
|
register spx_word16_t * restrict xx = st->x + framesize;
|
|
register spx_word16_t * restrict y = st->y + framesize;
|
|
register spx_word16_t * restrict ee = st->e + framesize;
|
|
register int update_foreground;
|
|
register int i;
|
|
register int N = st->window_size;
|
|
register int M = st->M;
|
|
|
|
#ifdef FIXED_POINT
|
|
register spx_word32_t sc0 = SUB32(Sff,See);
|
|
register spx_float_t sc1 = FLOAT_MUL32U(Sff,Dbf);
|
|
|
|
Davg1 = ADD32(MULT16_32_Q15(QCONST16(.6f,15),Davg1), MULT16_32_Q15(QCONST16(.4f,15),sc0));
|
|
Davg2 = ADD32(MULT16_32_Q15(QCONST16(.85f,15),Davg2), MULT16_32_Q15(QCONST16(.15f,15),sc0));
|
|
Dvar1 = FLOAT_ADD(
|
|
FLOAT_MULT(VAR1_SMOOTH,Dvar1),
|
|
FLOAT_MUL32U(MULT16_32_Q15(QCONST16(.4f,15),Sff),
|
|
MULT16_32_Q15(QCONST16(.4f,15),Dbf)));
|
|
Dvar2 = FLOAT_ADD(
|
|
FLOAT_MULT(VAR2_SMOOTH,Dvar2),
|
|
FLOAT_MUL32U(MULT16_32_Q15(QCONST16(.15f,15),Sff),
|
|
MULT16_32_Q15(QCONST16(.15f,15),Dbf)));
|
|
#else
|
|
register spx_word32_t sc0 = Sff - See;
|
|
register spx_word32_t sc1 = Sff * Dbf;
|
|
|
|
Davg1 = .6*Davg1 + .4*sc0;
|
|
Davg2 = .85*Davg2 + .15*sc0;
|
|
Dvar1 = VAR1_SMOOTH*Dvar1 + .16*sc1;
|
|
Dvar2 = VAR2_SMOOTH*Dvar2 + .0225*sc1;
|
|
#endif
|
|
|
|
update_foreground =
|
|
mux( FLOAT_GT(FLOAT_MUL32U(sc0, VABS(sc0)), sc1), 1,
|
|
mux( FLOAT_GT(FLOAT_MUL32U(Davg1, VABS(Davg1)), FLOAT_MULT(VAR1_UPDATE,(Dvar1))), 1,
|
|
mux( FLOAT_GT(FLOAT_MUL32U(Davg2, VABS(Davg2)), FLOAT_MULT(VAR2_UPDATE,(Dvar2))), 1, 0)));
|
|
|
|
if ( update_foreground )
|
|
{
|
|
register spx_word16_t * restrict windowf = st->window + framesize;
|
|
register spx_word16_t * restrict window = st->window;
|
|
|
|
st->Davg1 = st->Davg2 = 0;
|
|
st->Dvar1 = st->Dvar2 = FLOAT_ZERO;
|
|
|
|
memcpy(st->foreground, st->W, N*M*sizeof(spx_word32_t));
|
|
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unroll=4
|
|
#pragma TCS_unrollexact=1
|
|
#endif
|
|
for ( i=0 ; i<framesize ; ++i)
|
|
{ register spx_word16_t wi = window[i];
|
|
register spx_word16_t wfi = windowf[i];
|
|
register spx_word16_t ei = ee[i];
|
|
register spx_word16_t yi = y[i];
|
|
|
|
ee[i] = MULT16_16_Q15(wfi,ei) + MULT16_16_Q15(wi,yi);
|
|
}
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unrollexact=0
|
|
#pragma TCS_unroll=0
|
|
#endif
|
|
|
|
} else
|
|
{
|
|
register int reset_background;
|
|
|
|
reset_background =
|
|
mux( FLOAT_GT(FLOAT_MUL32U(-(sc0),VABS(sc0)), FLOAT_MULT(VAR_BACKTRACK,sc1)), 1,
|
|
mux( FLOAT_GT(FLOAT_MUL32U(-(Davg1), VABS(Davg1)), FLOAT_MULT(VAR_BACKTRACK,Dvar1)), 1,
|
|
mux( FLOAT_GT(FLOAT_MUL32U(-(Davg2), VABS(Davg2)), FLOAT_MULT(VAR_BACKTRACK,Dvar2)), 1, 0)));
|
|
|
|
if ( reset_background )
|
|
{
|
|
memcpy(st->W, st->foreground, N*M*sizeof(spx_word32_t));
|
|
memcpy(y, ee, framesize * sizeof(spx_word16_t));
|
|
mdf_sub(xx,input,y,framesize);
|
|
See = Sff;
|
|
st->Davg1 = st->Davg2 = 0;
|
|
st->Dvar1 = st->Dvar2 = FLOAT_ZERO;
|
|
} else
|
|
{
|
|
st->Davg1 = Davg1;
|
|
st->Davg2 = Davg2;
|
|
st->Dvar1 = Dvar1;
|
|
st->Dvar2 = Dvar2;
|
|
}
|
|
}
|
|
|
|
return See;
|
|
}
|
|
#endif
|
|
|
|
void mdf_compute_error_signal(
|
|
SpeexEchoState * restrict st,
|
|
const spx_int16_t * restrict in,
|
|
spx_int16_t * restrict out,
|
|
int framesize
|
|
)
|
|
{
|
|
register spx_word16_t preemph = st->preemph;
|
|
register spx_word16_t memE = st->memE;
|
|
register int saturated = st->saturated;
|
|
register spx_word16_t * restrict e = st->e;
|
|
register spx_word16_t * restrict ee = st->e + framesize;
|
|
register spx_word16_t * restrict input = st->input;
|
|
register spx_word16_t * restrict xx = st->x + framesize;
|
|
register int i;
|
|
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unroll=4
|
|
#pragma TCS_unrollexact=1
|
|
#endif
|
|
for ( i=0 ; i<framesize ; ++i )
|
|
{
|
|
register spx_word32_t tmp_out;
|
|
register spx_int16_t ini = in[i];
|
|
register int flg;
|
|
|
|
#ifdef FIXED_POINT
|
|
|
|
#ifdef TWO_PATH
|
|
tmp_out = SUB32(EXTEND32(input[i]), EXTEND32(ee[i]));
|
|
tmp_out = iclipi(tmp_out,32767);
|
|
#else
|
|
tmp_out = SUB32(EXTEND32(input[i]), EXTEND32(y[i]));
|
|
tmp_out = iclipi(tmp_out,32767);
|
|
#endif
|
|
|
|
#else
|
|
#ifdef TWO_PATH
|
|
tmp_out = SUB32(EXTEND32(input[i]), EXTEND32(ee[i]));
|
|
#else
|
|
tmp_out = SUB32(EXTEND32(input[i]), EXTEND32(y[i]));
|
|
#endif
|
|
tmp_out =
|
|
fmux( tmp_out > 32767, 32767,
|
|
fmux( tmp_out < -32768, -32768, tmp_out));
|
|
#endif
|
|
|
|
tmp_out = ADD32(tmp_out, EXTEND32(MULT16_16_P15(preemph,memE)));
|
|
flg = iabs(ini) >= 32000;
|
|
tmp_out = VMUX( flg, 0, tmp_out);
|
|
saturated = mux( flg && (saturated == 0), 1, saturated);
|
|
|
|
out[i] = (spx_int16_t)tmp_out;
|
|
memE = tmp_out;
|
|
}
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unrollexact=0
|
|
#pragma TCS_unroll=0
|
|
#endif
|
|
|
|
st->memE = memE;
|
|
st->saturated = saturated;
|
|
memset(e, 0, framesize * sizeof(spx_word16_t));
|
|
memcpy(ee, xx, framesize * sizeof(spx_word16_t));
|
|
}
|
|
|
|
inline int mdf_check(
|
|
SpeexEchoState * restrict st,
|
|
spx_int16_t * out,
|
|
spx_word32_t Syy,
|
|
spx_word32_t Sxx,
|
|
spx_word32_t See,
|
|
spx_word32_t Sff,
|
|
spx_word32_t Sdd
|
|
)
|
|
{
|
|
register int N = st->window_size;
|
|
register spx_word32_t N1e9 = N * 1e9;
|
|
register int screwed_up = st->screwed_up;
|
|
register int framesize = st->frame_size;
|
|
|
|
if (!(Syy>=0 && Sxx>=0 && See >= 0)
|
|
#ifndef FIXED_POINT
|
|
|| !(Sff < N1e9 && Syy < N1e9 && Sxx < N1e9 )
|
|
#endif
|
|
)
|
|
{
|
|
screwed_up += 50;
|
|
memset(out, 0, framesize * sizeof(spx_int16_t));
|
|
|
|
} else
|
|
{ screwed_up = mux( SHR32(Sff, 2) > ADD32(Sdd, SHR32(MULT16_16(N, 10000),6)), screwed_up+1, 0);
|
|
}
|
|
|
|
st->screwed_up = screwed_up;
|
|
|
|
return screwed_up;
|
|
}
|
|
|
|
void mdf_smooth(
|
|
spx_word32_t * restrict power,
|
|
spx_word32_t * restrict Xf,
|
|
int framesize,
|
|
int M
|
|
)
|
|
{
|
|
register spx_word16_t ss, ss_1, pf, xff;
|
|
register int j;
|
|
|
|
#ifdef FIXED_POINT
|
|
ss=DIV32_16(11469,M);
|
|
ss_1 = SUB16(32767,ss);
|
|
#else
|
|
ss=.35/M;
|
|
ss_1 = 1-ss;
|
|
#endif
|
|
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unroll=4
|
|
#pragma TCS_unrollexact=1
|
|
#endif
|
|
for ( j=0 ; j<framesize ; ++j )
|
|
{ register spx_word32_t pi = power[j];
|
|
register spx_word32_t xfi = Xf[j];
|
|
|
|
power[j] = MULT16_32_Q15(ss_1,pi) + 1 + MULT16_32_Q15(ss,xfi);
|
|
}
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unrollexact=0
|
|
#pragma TCS_unroll=0
|
|
#endif
|
|
|
|
pf = power[framesize];
|
|
xff = Xf[framesize];
|
|
power[framesize] = MULT16_32_Q15(ss_1,pf) + 1 + MULT16_32_Q15(ss,xff);
|
|
}
|
|
|
|
void mdf_compute_filtered_spectra_crosscorrelations(
|
|
SpeexEchoState * restrict st,
|
|
spx_word32_t Syy,
|
|
spx_word32_t See,
|
|
int framesize
|
|
)
|
|
{
|
|
register spx_float_t Pey = FLOAT_ONE;
|
|
register spx_float_t Pyy = FLOAT_ONE;
|
|
register spx_word16_t spec_average = st->spec_average;
|
|
register spx_word32_t * restrict pRf = st->Rf;
|
|
register spx_word32_t * restrict pYf = st->Yf;
|
|
register spx_word32_t * restrict pEh = st->Eh;
|
|
register spx_word32_t * restrict pYh = st->Yh;
|
|
register spx_word16_t beta0 = st->beta0;
|
|
register spx_word16_t beta_max = st->beta_max;
|
|
register spx_float_t alpha, alpha_1;
|
|
register spx_word32_t tmp32, tmpx;
|
|
register spx_float_t sPey = st->Pey;
|
|
register spx_float_t sPyy = st->Pyy;
|
|
register spx_float_t tmp;
|
|
register spx_word16_t leak_estimate;
|
|
register int j;
|
|
register spx_float_t Eh, Yh;
|
|
register spx_word32_t _Ehj, _Rfj, _Yfj, _Yhj;
|
|
|
|
#ifdef FIXED_POINT
|
|
register spx_word16_t spec_average1 = SUB16(32767,spec_average);
|
|
#else
|
|
register spx_word16_t spec_average1 = 1 - spec_average;
|
|
#endif
|
|
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unroll=4
|
|
#pragma TCS_unrollexact=1
|
|
#endif
|
|
for (j=framesize; j>0 ; --j)
|
|
{
|
|
_Ehj = pEh[j];
|
|
_Rfj = pRf[j];
|
|
_Yfj = pYf[j];
|
|
_Yhj = pYh[j];
|
|
|
|
Eh = PSEUDOFLOAT(_Rfj - _Ehj);
|
|
Yh = PSEUDOFLOAT(_Yfj - _Yhj);
|
|
|
|
Pey = FLOAT_ADD(Pey,FLOAT_MULT(Eh,Yh));
|
|
Pyy = FLOAT_ADD(Pyy,FLOAT_MULT(Yh,Yh));
|
|
|
|
pEh[j] = MAC16_32_Q15(MULT16_32_Q15(spec_average1, _Ehj), spec_average, _Rfj);
|
|
pYh[j] = MAC16_32_Q15(MULT16_32_Q15(spec_average1, _Yhj), spec_average, _Yfj);
|
|
}
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unrollexact=0
|
|
#pragma TCS_unroll=0
|
|
#endif
|
|
_Ehj = pEh[0];
|
|
_Rfj = pRf[0];
|
|
_Yfj = pYf[0];
|
|
_Yhj = pYh[0];
|
|
|
|
Eh = PSEUDOFLOAT(_Rfj - _Ehj);
|
|
Yh = PSEUDOFLOAT(_Yfj - _Yhj);
|
|
|
|
Pey = FLOAT_ADD(Pey,FLOAT_MULT(Eh,Yh));
|
|
Pyy = FLOAT_ADD(Pyy,FLOAT_MULT(Yh,Yh));
|
|
|
|
pEh[0] = MAC16_32_Q15(MULT16_32_Q15(spec_average1, _Ehj), spec_average, _Rfj);
|
|
pYh[0] = MAC16_32_Q15(MULT16_32_Q15(spec_average1, _Yhj), spec_average, _Yfj);
|
|
|
|
Pyy = FLOAT_SQRT(Pyy);
|
|
Pey = FLOAT_DIVU(Pey,Pyy);
|
|
|
|
tmp32 = MULT16_32_Q15(beta0,Syy);
|
|
tmpx = MULT16_32_Q15(beta_max,See);
|
|
tmp32 = VMUX(tmp32 > tmpx, tmpx, tmp32);
|
|
alpha = FLOAT_DIV32(tmp32, See);
|
|
alpha_1 = FLOAT_SUB(FLOAT_ONE, alpha);
|
|
|
|
sPey = FLOAT_ADD(FLOAT_MULT(alpha_1,sPey) , FLOAT_MULT(alpha,Pey));
|
|
sPyy = FLOAT_ADD(FLOAT_MULT(alpha_1,sPyy) , FLOAT_MULT(alpha,Pyy));
|
|
tmp = FLOAT_MULT(MIN_LEAK,sPyy);
|
|
|
|
#ifndef FIXED_POINT
|
|
sPyy = VMUX(FLOAT_LT(sPyy, FLOAT_ONE), FLOAT_ONE, sPyy);
|
|
sPey = VMUX(FLOAT_LT(sPey, tmp), tmp, sPey);
|
|
sPey = VMUX(FLOAT_LT(sPey, sPyy), sPey, sPyy);
|
|
#else
|
|
sPyy = FLOAT_LT(sPyy, FLOAT_ONE) ? FLOAT_ONE : sPyy;
|
|
sPey = FLOAT_LT(sPey, tmp) ? tmp : sPey;
|
|
sPey = FLOAT_LT(sPey, sPyy) ? sPey : sPyy;
|
|
#endif
|
|
|
|
leak_estimate = FLOAT_EXTRACT16(FLOAT_SHL(FLOAT_DIVU(sPey, sPyy),14));
|
|
|
|
leak_estimate = VMUX( leak_estimate > 16383, 32767, SHL16(leak_estimate,1));
|
|
st->Pey = sPey;
|
|
st->Pyy = sPyy;
|
|
st->leak_estimate = leak_estimate;
|
|
}
|
|
|
|
inline spx_word16_t mdf_compute_RER(
|
|
spx_word32_t See,
|
|
spx_word32_t Syy,
|
|
spx_word32_t Sey,
|
|
spx_word32_t Sxx,
|
|
spx_word16_t leake
|
|
)
|
|
{
|
|
register spx_word16_t RER;
|
|
|
|
#ifdef FIXED_POINT
|
|
register spx_word32_t tmp32;
|
|
register spx_word32_t tmp;
|
|
spx_float_t bound = PSEUDOFLOAT(Sey);
|
|
|
|
tmp32 = MULT16_32_Q15(leake,Syy);
|
|
tmp32 = ADD32(SHR32(Sxx,13), ADD32(tmp32, SHL32(tmp32,1)));
|
|
|
|
bound = FLOAT_DIVU(FLOAT_MULT(bound, bound), PSEUDOFLOAT(ADD32(1,Syy)));
|
|
tmp = FLOAT_EXTRACT32(bound);
|
|
tmp32 = imux( FLOAT_GT(bound, PSEUDOFLOAT(See)), See,
|
|
imux( tmp32 < tmp, tmp, tmp32));
|
|
|
|
tmp = SHR32(See,1);
|
|
tmp32 = imux(tmp32 > tmp, tmp, tmp32);
|
|
RER = FLOAT_EXTRACT16(FLOAT_SHL(FLOAT_DIV32(tmp32,See),15));
|
|
#else
|
|
register spx_word32_t r0;
|
|
|
|
r0 = (Sey * Sey)/(1 + See * Syy);
|
|
|
|
RER = (.0001*Sxx + 3.* MULT16_32_Q15(leake,Syy)) / See;
|
|
RER = fmux( RER < r0, r0, RER);
|
|
RER = fmux( RER > .5, .5, RER);
|
|
#endif
|
|
|
|
return RER;
|
|
}
|
|
|
|
void mdf_adapt(
|
|
SpeexEchoState * restrict st,
|
|
spx_word16_t RER,
|
|
spx_word32_t Syy,
|
|
spx_word32_t See,
|
|
spx_word32_t Sxx
|
|
)
|
|
{
|
|
register spx_float_t * restrict power_1 = st->power_1;
|
|
register spx_word32_t * restrict power = st->power;
|
|
register int adapted = st->adapted;
|
|
register spx_word32_t sum_adapt = st->sum_adapt;
|
|
register spx_word16_t leake = st->leak_estimate;
|
|
register int framesize = st->frame_size;
|
|
register int i;
|
|
register int M = st->M;
|
|
|
|
adapted = mux( !adapted && sum_adapt > QCONST32(M,15) &&
|
|
MULT16_32_Q15(leake,Syy) > MULT16_32_Q15(QCONST16(.03f,15),Syy), 1, adapted);
|
|
|
|
if ( adapted )
|
|
{ register spx_word32_t * restrict Yf = st->Yf;
|
|
register spx_word32_t * restrict Rf = st->Rf;
|
|
register spx_word32_t r, e, e2;
|
|
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unroll=4
|
|
#pragma TCS_unrollexact=1
|
|
#endif
|
|
for ( i=0 ; i<framesize ; ++i )
|
|
{
|
|
r = SHL32(Yf[i],3);
|
|
r = MULT16_32_Q15(leake,r);
|
|
e = SHL32(Rf[i],3)+1;
|
|
|
|
#ifdef FIXED_POINT
|
|
e2 = SHR32(e,1);
|
|
r = mux( r > e2, e2, r);
|
|
#else
|
|
e2 = e * .5;
|
|
r = fmux( r > e2, e2, r);
|
|
#endif
|
|
|
|
r = MULT16_32_Q15(QCONST16(.7,15),r) +
|
|
MULT16_32_Q15(QCONST16(.3,15),(spx_word32_t)(MULT16_32_Q15(RER,e)));
|
|
|
|
power_1[i] = FLOAT_SHL(FLOAT_DIV32_FLOAT(r,FLOAT_MUL32U(e,power[i]+10)),WEIGHT_SHIFT+16);
|
|
}
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unrollexact=0
|
|
#pragma TCS_unroll=0
|
|
#endif
|
|
|
|
r = SHL32(Yf[framesize],3);
|
|
r = MULT16_32_Q15(leake,r);
|
|
e = SHL32(Rf[framesize],3)+1;
|
|
|
|
#ifdef FIXED_POINT
|
|
e2 = SHR32(e,1);
|
|
r = mux( r > e2, e2, r);
|
|
#else
|
|
e2 = e * .5;
|
|
r = fmux( r > e2, e2, r);
|
|
#endif
|
|
|
|
r = MULT16_32_Q15(QCONST16(.7,15),r) +
|
|
MULT16_32_Q15(QCONST16(.3,15),(spx_word32_t)(MULT16_32_Q15(RER,e)));
|
|
|
|
power_1[framesize] = FLOAT_SHL(FLOAT_DIV32_FLOAT(r,FLOAT_MUL32U(e,power[framesize]+10)),WEIGHT_SHIFT+16);
|
|
|
|
} else
|
|
{
|
|
register spx_word16_t adapt_rate=0;
|
|
register int N = st->window_size;
|
|
|
|
if ( Sxx > SHR32(MULT16_16(N, 1000),6) )
|
|
{ register spx_word32_t tmp32, tmp32q;
|
|
|
|
tmp32 = MULT16_32_Q15(QCONST16(.25f, 15), Sxx);
|
|
#ifdef FIXED_POINT
|
|
tmp32q = SHR32(See,2);
|
|
tmp32 = mux(tmp32 > tmp32q, tmp32q, tmp32);
|
|
#else
|
|
tmp32q = 0.25 * See;
|
|
tmp32 = fmux(tmp32 > tmp32q, tmp32q, tmp32);
|
|
#endif
|
|
adapt_rate = FLOAT_EXTRACT16(FLOAT_SHL(FLOAT_DIV32(tmp32, See),15));
|
|
}
|
|
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unroll=4
|
|
#pragma TCS_unrollexact=1
|
|
#endif
|
|
for (i=0;i<framesize;i++)
|
|
power_1[i] = FLOAT_SHL(FLOAT_DIV32(EXTEND32(adapt_rate),ADD32(power[i],10)),WEIGHT_SHIFT+1);
|
|
#if (TM_UNROLL && TM_UNROLL_SPEEXECHOCANCELLATION)
|
|
#pragma TCS_unrollexact=0
|
|
#pragma TCS_unroll=0
|
|
#endif
|
|
power_1[framesize] = FLOAT_SHL(FLOAT_DIV32(EXTEND32(adapt_rate),ADD32(power[framesize],10)),WEIGHT_SHIFT+1);
|
|
sum_adapt = ADD32(sum_adapt,adapt_rate);
|
|
}
|
|
|
|
st->sum_adapt = sum_adapt;
|
|
st->adapted = adapted;
|
|
}
|
|
|
|
#define OVERRIDE_ECHO_CANCELLATION
|
|
void speex_echo_cancellation(
|
|
SpeexEchoState * restrict st,
|
|
const spx_int16_t * restrict in,
|
|
const spx_int16_t * restrict far_end,
|
|
spx_int16_t * restrict out
|
|
)
|
|
{
|
|
register int framesize = st->frame_size;
|
|
register spx_word16_t * restrict x = st->x;
|
|
register spx_word16_t * restrict xx = st->x + framesize;
|
|
register spx_word16_t * restrict yy = st->y + framesize;
|
|
register spx_word16_t * restrict ee = st->e + framesize;
|
|
register spx_word32_t Syy, See, Sxx, Sdd, Sff;
|
|
register spx_word16_t RER;
|
|
register spx_word32_t Sey;
|
|
register int j;
|
|
register int N,M;
|
|
#ifdef TWO_PATH
|
|
register spx_word32_t Dbf;
|
|
#endif
|
|
|
|
N = st->window_size;
|
|
M = st->M;
|
|
st->cancel_count++;
|
|
|
|
filter_dc_notch16(in, st->notch_radius, st->input, framesize, st->notch_mem);
|
|
mdf_preemph(st, xx, far_end, framesize);
|
|
|
|
{
|
|
|
|
register spx_word16_t * restrict X = st->X;
|
|
|
|
for ( j=M-1 ; j>=0 ; j-- )
|
|
{ register spx_word16_t * restrict Xdes = &(X[(j+1)*N]);
|
|
register spx_word16_t * restrict Xsrc = &(X[j*N]);
|
|
|
|
memcpy(Xdes, Xsrc, N * sizeof(spx_word16_t));
|
|
}
|
|
|
|
spx_fft(st->fft_table, x, X);
|
|
memcpy(st->last_y, st->x, N * sizeof(spx_word16_t));
|
|
Sxx = mdf_inner_prod(xx, xx, framesize);
|
|
memcpy(x, xx, framesize * sizeof(spx_word16_t));
|
|
|
|
#ifdef TWO_PATH
|
|
spectral_mul_accum(st->X, st->foreground, st->Y, N, M);
|
|
spx_ifft(st->fft_table, st->Y, st->e);
|
|
mdf_sub(xx, st->input, ee, framesize);
|
|
Sff = mdf_inner_prod(xx, xx, framesize);
|
|
#endif
|
|
|
|
mdf_adjust_prop (st->W, N, M, st->prop);
|
|
|
|
if (st->saturated == 0)
|
|
{ mdf_compute_weight_gradient(st, X, N, M);
|
|
} else
|
|
{ st->saturated--;
|
|
}
|
|
}
|
|
|
|
mdf_update_weight(st, N, M, framesize);
|
|
spectral_mul_accum(st->X, st->W, st->Y, N, M);
|
|
spx_ifft(st->fft_table, st->Y, st->y);
|
|
|
|
#ifdef TWO_PATH
|
|
mdf_sub(xx, ee, yy, framesize);
|
|
Dbf = 10+mdf_inner_prod(xx, xx, framesize);
|
|
#endif
|
|
|
|
mdf_sub(xx, st->input, yy, framesize);
|
|
See = mdf_inner_prod(xx, xx, framesize);
|
|
|
|
#ifndef TWO_PATH
|
|
Sff = See;
|
|
#else
|
|
See = mdf_update_foreground(st,Dbf,Sff,See);
|
|
#endif
|
|
|
|
|
|
mdf_compute_error_signal(st, in, out, framesize);
|
|
Sey = mdf_inner_prod(ee, yy, framesize);
|
|
Syy = mdf_inner_prod(yy, yy, framesize);
|
|
Sdd = mdf_inner_prod(st->input, st->input, framesize);
|
|
|
|
if ( mdf_check(st,out,Syy,Sxx,See,Sff,Sdd) >= 50 )
|
|
{ speex_warning("The echo canceller started acting funny and got slapped (reset). It swears it will behave now.");
|
|
speex_echo_state_reset(st);
|
|
return;
|
|
}
|
|
|
|
See = MAX32(See, SHR32(MULT16_16(N, 100),6));
|
|
spx_fft(st->fft_table, st->e, st->E);
|
|
memset(st->y, 0, framesize * sizeof(spx_word16_t));
|
|
spx_fft(st->fft_table, st->y, st->Y);
|
|
power_spectrum(st->E, st->Rf, N);
|
|
power_spectrum(st->Y, st->Yf, N);
|
|
power_spectrum(st->X, st->Xf, N);
|
|
|
|
mdf_smooth(st->power,st->Xf,framesize, M);
|
|
mdf_compute_filtered_spectra_crosscorrelations(st,Syy,See,framesize);
|
|
RER = mdf_compute_RER(See,Syy,Sey,Sxx,st->leak_estimate);
|
|
mdf_adapt(st, RER, Syy, See, Sxx);
|
|
|
|
if ( st->adapted )
|
|
{ register spx_word16_t * restrict last_yy = st->last_y + framesize;
|
|
|
|
memcpy(st->last_y, last_yy, framesize * sizeof(spx_word16_t));
|
|
mdf_sub_int(last_yy, in, out, framesize);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|