Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mumble-voip/speexdsp.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjm <jm@0101bb08-14d6-0310-b084-bc0e0c8e3800>2007-03-15 16:13:25 +0300
committerjm <jm@0101bb08-14d6-0310-b084-bc0e0c8e3800>2007-03-15 16:13:25 +0300
commit4c7f0a5ffd7ea5e52968aad1e89108e124be012b (patch)
tree0c5858c0c5b1f04b9d20173f254ce47a1f098d72 /tmv/preprocess_tm.h
parent57656c5f88e699a8a6b6af442c736b0ef95cbf3d (diff)
Merging Trimedia support contributed by Hong Zhiqian (incomplete for now)
git-svn-id: http://svn.xiph.org/trunk/speex@12764 0101bb08-14d6-0310-b084-bc0e0c8e3800
Diffstat (limited to 'tmv/preprocess_tm.h')
-rw-r--r--tmv/preprocess_tm.h1135
1 files changed, 1135 insertions, 0 deletions
diff --git a/tmv/preprocess_tm.h b/tmv/preprocess_tm.h
new file mode 100644
index 0000000..f903b73
--- /dev/null
+++ b/tmv/preprocess_tm.h
@@ -0,0 +1,1135 @@
+/* Copyright (C) 2007 Hong Zhiqian */
+/**
+ @file preprocess_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"
+
+#ifdef FIXED_POINT
+#define OVERRIDE_PREPROCESS_ANALYSIS
+static void preprocess_analysis(SpeexPreprocessState * restrict st, spx_int16_t * restrict x)
+{
+ register int i, j, framesize = st->frame_size;
+ register int N = st->ps_size;
+ register int N3 = 2*N - framesize;
+ register int N4 = framesize - N3;
+ register int * restrict ps = st->ps;
+ register int * restrict frame;
+ register int * restrict inbuf;
+ register int * restrict ptr;
+ register int max_val;
+
+ frame = (int*)(st->frame);
+ inbuf = (int*)(st->inbuf);
+ ptr = (int*)(st->frame+N3);
+
+ TMDEBUG_ALIGNMEM(x);
+ TMDEBUG_ALIGNMEM(frame);
+ TMDEBUG_ALIGNMEM(inbuf);
+
+ PREPROCESSANAYLSIS_START();
+
+ N3 >>= 1;
+ framesize >>= 1;
+ max_val = 0;
+
+ for ( i=0,j=0 ; i<N3 ; i+=2,j+=8 )
+ { register int r1, r2;
+
+ r1 = ld32x(inbuf,i);
+ r2 = ld32x(inbuf,i+1);
+
+ st32d(j, frame, r1);
+ st32d(j+4, frame, r2);
+ }
+
+ for ( i=0,j=0 ; i<framesize ; i+=2,j+=8 )
+ { register int r1, r2;
+
+ r1 = ld32x(x, i);
+ r2 = ld32x(x, i+1);
+
+ st32d(j, ptr, r1);
+ st32d(j+4,ptr, r2);
+ }
+
+ for ( i=0,j=0,ptr=(int*)(x+N4) ; i<N3 ; i+=2,j+=8 )
+ { register int r1, r2;
+
+ r1 = ld32x(ptr, i);
+ r2 = ld32x(ptr, i+1);
+
+ st32d(j, inbuf, r1);
+ st32d(j+4,inbuf, r2);
+ }
+#if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)
+#pragma TCS_unroll=2
+#pragma TCS_unrollexact=1
+#endif
+ for ( i=0,j=0,ptr=(int*)st->window ; i<N ; ++i,j+=4 )
+ { register int f10, w10, r0, r1;
+
+ f10 = ld32x(frame, i);
+ w10 = ld32x(ptr, i);
+
+ r0 = (sex16(f10) * sex16(w10)) >> 15;
+ r1 = (asri(16,f10) * asri(16,w10)) >> 15;
+
+ max_val = imax(iabs(sex16(r0)), max_val);
+ max_val = imax(iabs(sex16(r1)), max_val);
+
+ r0 = pack16lsb(r1, r0);
+ st32d(j, frame, r0);
+ }
+#if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+
+ max_val = 14 - spx_ilog2(max_val);
+ st->frame_shift = max_val;
+
+ if ( max_val != 0 )
+ {
+#if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for ( i=0,j=0 ; i<N ; ++i,j+=4 )
+ { register int f10;
+
+ f10 = ld32x(frame, i);
+ f10 = dualasl(f10, max_val);
+ st32d(j, frame, f10);
+
+ }
+#if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+ }
+
+ spx_fft(st->fft_lookup, st->frame, st->ft);
+ power_spectrum(st->ft, ps, N << 1);
+
+#if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for ( i=0,ptr=(int*)st->ps,max_val<<=1,j=((1<<((max_val))>>1)) ;i<N ; ++i )
+ {
+ ps[i] = (ps[i] + j) >> max_val;
+ }
+#if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+
+ filterbank_compute_bank32(st->bank, ps, ps+N);
+
+ PREPROCESSANAYLSIS_STOP();
+}
+
+#define _MULT16_32_Q15(a,b,c) ADD32(MULT16_16((a),(b)), SHR(MULT16_16((a),(c)),15))
+
+#define OVERRIDE_UPDATE_NOISE_PROB
+static void update_noise_prob(SpeexPreprocessState * restrict st)
+{
+ register int i;
+ register int min_range, nb_adapt;
+ register int N = st->ps_size;
+ register int * restrict Smin = (int*)st->Smin;
+ register int * restrict Stmp = (int*)st->Stmp;
+ register int * restrict S = (int*)st->S;
+
+ UPDATENOISEPROB_START();
+
+ {
+ register int psi_lsb, psi_msb, ips_lsb, ips_msb, psii_lsb, psii_msb;
+ register int psiii_lsb, psiii_msb;
+ register int q8, q05, q2, q1;
+ register int *ps = (int*)st->ps;
+ register int si_lsb, si_msb, sii_lsb, sii_msb;
+
+ q8 = QCONST16(.8f,15);
+ q05 = QCONST16(.05f,15);
+ q2 = QCONST16(.2f,15);
+ q1 = QCONST16(.1f,15);
+
+ ips_lsb = ps[0];
+ psi_lsb = ps[1];
+ si_lsb = S[0];
+ ips_msb = ips_lsb >> 15;
+ psi_msb = psi_lsb >> 15;
+ si_msb = si_lsb >> 15;
+
+ ips_lsb &= 0x00007fff;
+ psi_lsb &= 0x00007fff;
+ si_lsb &= 0x00007fff;
+
+ S[0] = _MULT16_32_Q15(q8,si_msb,si_lsb) + _MULT16_32_Q15(q2,ips_msb,ips_lsb);
+
+ for ( i=1 ; i<N-1 ; i+=2 )
+ {
+ psii_lsb = ps[i+1];
+ si_lsb = S[i];
+
+ psii_msb = psii_lsb >> 15;
+ si_msb = si_lsb >> 15;
+ si_lsb &= 0x00007fff;
+ psii_lsb &= 0x00007fff;
+
+ S[i]= _MULT16_32_Q15(q8,si_msb,si_lsb) +
+ _MULT16_32_Q15(q05,ips_msb,ips_lsb) +
+ _MULT16_32_Q15(q1,psi_msb,psi_lsb) +
+ _MULT16_32_Q15(q05,psii_msb,psii_lsb);
+
+ psiii_lsb = ps[i+2];
+ sii_lsb = S[i+1];
+
+ sii_msb = sii_lsb >> 15;
+ psiii_msb= psiii_lsb >> 15;
+ sii_lsb &= 0x00007fff;
+ psiii_lsb&= 0x00007fff;
+
+ S[i+1]= _MULT16_32_Q15(q8,sii_msb,sii_lsb) +
+ _MULT16_32_Q15(q05,psi_msb,psi_lsb) +
+ _MULT16_32_Q15(q1,psii_msb,psii_lsb) +
+ _MULT16_32_Q15(q05,psiii_msb,psiii_lsb);
+
+ ips_lsb = psii_lsb;
+ ips_msb = psii_msb;
+ psi_lsb = psiii_lsb;
+ psi_msb = psiii_msb;
+ }
+
+ S[N-1] = MULT16_32_Q15(q8,S[N-1]) + MULT16_32_Q15(q2,ps[N-1]);
+ }
+
+ nb_adapt = st->nb_adapt;
+
+ if ( nb_adapt==1 )
+ { for ( i=0 ; i<N ; ++i )
+ Smin[i] = Stmp[i] = 0;
+
+ }
+
+ min_range = mux(nb_adapt < 100, 15,
+ mux(nb_adapt < 1000, 50,
+ mux(nb_adapt < 10000, 150, 300)));
+
+ if ( st->min_count > min_range )
+ {
+ st->min_count = 0;
+
+#if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)
+#pragma TCS_unroll=2
+#pragma TCS_unrollexact=1
+#endif
+ for ( i=0 ; i<N ; ++i )
+ { register int si, stmpi;
+
+ si = S[i];
+ stmpi = Stmp[i];
+
+ Smin[i] = imin(stmpi,si);
+ Stmp[i] = si;
+ }
+#if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+ } else
+ {
+
+#if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)
+#pragma TCS_unroll=2
+#pragma TCS_unrollexact=1
+#endif
+ for ( i=0 ; i<N ; ++i )
+ { register int si, stmpi, smini;
+
+ si = S[i];
+ stmpi = Stmp[i];
+ smini = Smin[i];
+
+ Smin[i] = imin(smini,si);
+ Stmp[i] = imin(stmpi,si);
+ }
+#if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+ }
+
+
+ {
+ register int q4;
+ register int * restrict update_prob = (int*)st->update_prob;
+
+ q4 = QCONST16(.4f,15);
+
+#if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for ( i=0 ; i<N ; ++i )
+ { register int si;
+ register int smini;
+
+ si = S[i];
+ smini = Smin[i];
+ update_prob[i] = mux(MULT16_32_Q15(q4,si) > ADD32(smini,20), 1, 0);
+ }
+#if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+ }
+
+ UPDATENOISEPROB_STOP();
+}
+
+#else
+
+#define OVERRIDE_PREPROCESS_ANALYSIS
+static void preprocess_analysis(SpeexPreprocessState * restrict st, spx_int16_t * restrict x)
+{
+ register int i;
+ register int framesize = st->frame_size;
+ register int N = st->ps_size;
+ register int N3 = 2*N - framesize;
+ register int N4 = framesize - N3;
+ register float * restrict ps = st->ps;
+ register float * restrict frame = st->frame;
+ register float * restrict inbuf = st->inbuf;
+
+ PREPROCESSANAYLSIS_START();
+
+#if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for ( i=0 ; i<N3 ; ++i )
+ {
+ frame[i] = inbuf[i];
+ }
+#if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+
+#if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for ( i=0 ; i<framesize ; ++i )
+ { frame[N3+i] = x[i];
+ }
+#if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+
+#if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for ( i=0,x+=N4 ; i<N3 ; ++i )
+ { inbuf[i] = x[i];
+ }
+#if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+
+ inbuf = st->window;
+
+#if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for ( i=0 ; i<2*N ; ++i )
+ {
+ frame[i] = frame[i] * inbuf[i];
+ }
+#if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+
+ spx_fft(st->fft_lookup, frame, st->ft);
+ power_spectrum(st->ft, ps, N << 1);
+ filterbank_compute_bank32(st->bank, ps, ps+N);
+
+ PREPROCESSANAYLSIS_STOP();
+}
+
+
+#define OVERRIDE_UPDATE_NOISE_PROB
+static void update_noise_prob(SpeexPreprocessState * restrict st)
+{
+
+ register float * restrict S = st->S;
+ register float * restrict ps = st->ps;
+ register int N = st->ps_size;
+ register int min_range;
+ register int i;
+ register int nb_adapt;
+ register float * restrict Smin = st->Smin;
+ register float * restrict Stmp = st->Stmp;
+
+ UPDATENOISEPROB_START();
+
+ {
+ register float ips, psi;
+
+ ips = ps[0];
+ psi = ps[1];
+
+ S[0] = .8f * S[0] + .2f * ips;
+
+ for ( i=1 ; i<N-1 ; i+=2 )
+ {
+ register float psii, psiii;
+
+ psii = ps[i+1];
+ psiii = ps[i+2];
+ S[i] = .8f * S[i] + .05f * ips + .1f * psi + .05f * psii;
+ S[i+1] = .8f * S[i+1] + .05f * psi + .1f * psii + .05f * psiii;
+ ips = psii;
+ psi = psiii;
+ }
+
+ S[N-1] = .8f * S[N-1] + .2f * ps[N-1];
+ }
+
+ nb_adapt = st->nb_adapt;
+
+ if ( nb_adapt==1 )
+ {
+ for (i=0;i<N;i++)
+ Smin[i] = st->Stmp[i] = 0;
+ }
+
+ min_range = mux(nb_adapt < 100, 15,
+ mux(nb_adapt < 1000, 50,
+ mux(nb_adapt < 10000, 150, 300)));
+
+
+ if ( st->min_count > min_range )
+ {
+ st->min_count = 0;
+#if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for ( i=0 ; i<N ; ++i )
+ {
+ register float stmpi, si;
+
+ stmpi = Stmp[i];
+ si = S[i];
+
+ Smin[i] = fmin(stmpi,si);
+ Stmp[i] = si;
+ }
+#if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+
+ } else
+ {
+ register float * restrict Smin = st->Smin;
+
+#if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for ( i=0 ; i<N ; ++i )
+ {
+ register float stmpi, si, smini;
+
+ stmpi = Stmp[i];
+ si = S[i];
+ smini = Smin[i];
+
+ Smin[i] = fmin(smini,si);
+ Stmp[i] = fmin(stmpi,si);
+ }
+#if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+ }
+
+ {
+ register int * restrict update_prob = (int*)st->update_prob;
+
+#if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for (i=0;i<N;i++)
+ { register float si;
+ register float smini;
+
+ si = S[i];
+ smini = Smin[i];
+ update_prob[i] = mux( (.4 * si) > (smini + 20.f), 1, 0);
+
+ }
+#if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+ }
+
+ UPDATENOISEPROB_STOP();
+}
+
+
+#define OVERRIDE_COMPUTE_GAIN_FLOOR
+static void compute_gain_floor(
+ int noise_suppress,
+ int effective_echo_suppress,
+ float * restrict noise,
+ float * restrict echo,
+ float * gain_floor,
+ int len
+)
+{
+ register int i;
+ register float echo_floor;
+ register float noise_floor;
+
+ COMPUTEGAINFLOOR_START();
+
+ noise_floor = exp(.2302585f*noise_suppress);
+ echo_floor = exp(.2302585f*effective_echo_suppress);
+
+#if (TM_UNROLL && TM_UNROLL_COMPUTEGAINFLOOR)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for (i=0;i<len;i++)
+ { register float noisei, echoi;
+
+ noisei = noise[i];
+ echoi = echo[i];
+
+ gain_floor[i] = FRAC_SCALING * sqrt(noise_floor * noisei + echo_floor * echoi) / sqrt(1+noisei+echoi);
+
+ }
+#if (TM_UNROLL && TM_UNROLL_COMPUTEGAINFLOOR)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+
+ COMPUTEGAINFLOOR_STOP();
+}
+
+#endif
+
+static inline spx_word32_t hypergeom_gain(spx_word32_t xx);
+static inline spx_word16_t qcurve(spx_word16_t x);
+static void compute_gain_floor(int noise_suppress, int effective_echo_suppress, spx_word32_t *noise, spx_word32_t *echo, spx_word16_t *gain_floor, int len);
+void speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *Yout, int len);
+
+#ifndef FIXED_POINT
+static void speex_compute_agc(SpeexPreprocessState *st, spx_word16_t Pframe, spx_word16_t *ft);
+#endif
+
+void preprocess_residue_echo(
+ SpeexPreprocessState * restrict st,
+ int N,
+ int NM
+)
+{
+ if (st->echo_state)
+ {
+ register spx_word32_t * restrict r_echo = st->residual_echo;
+ register spx_word32_t * restrict e_noise = st->echo_noise;
+ register int i;
+
+#ifndef FIXED_POINT
+ register spx_word32_t r;
+#endif
+
+ speex_echo_get_residual(st->echo_state, r_echo, N);
+
+#ifndef FIXED_POINT
+ r = r_echo[0];
+ if (!(r >=0 && r < N*1e9f) )
+ {
+ memset(r_echo, 0, N * sizeof(spx_word32_t));
+ }
+#endif
+
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for (i=0;i<N;i++)
+ { register spx_word32_t eni = e_noise[i];
+ e_noise[i] = MAX32(MULT16_32_Q15(QCONST16(.6f,15),eni), r_echo[i]);
+ }
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+ filterbank_compute_bank32(st->bank, e_noise, e_noise+N);
+
+ } else
+ { memset(st->echo_noise, 0, (NM) * sizeof(spx_word32_t));
+ }
+}
+
+void preprocess_update_noise(
+ SpeexPreprocessState * restrict st,
+ spx_word32_t * restrict ps,
+ int N
+)
+{
+ register spx_word16_t beta, beta_1;
+ register int * restrict up = st->update_prob;
+ register spx_word32_t * restrict noise = st->noise;
+ register int i;
+
+ beta = MAX16(QCONST16(.03,15),DIV32_16(Q15_ONE,st->nb_adapt));
+ beta_1 = Q15_ONE-beta;
+
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for (i=0;i<N;i++)
+ { register spx_word32_t ni = noise[i];
+ register spx_word32_t psi = ps[i];
+
+ if ( !up[i] || psi < PSHR32(ni, NOISE_SHIFT) )
+ { noise[i] = MAX32(EXTEND32(0),MULT16_32_Q15(beta_1,ni) +
+ MULT16_32_Q15(beta,SHL32(psi,NOISE_SHIFT)));
+ }
+ }
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+ filterbank_compute_bank32(st->bank, noise, noise+N);
+}
+
+void preprocess_compute_SNR(
+ SpeexPreprocessState * restrict st,
+ spx_word32_t * restrict ps,
+ int NM
+)
+{
+ register spx_word32_t * restrict noise = st->noise;
+ register spx_word32_t * restrict echo = st->echo_noise;
+ register spx_word32_t * restrict reverb = st->reverb_estimate;
+ register spx_word16_t * restrict post = st->post;
+ register spx_word32_t * restrict old_ps = st->old_ps;
+ register spx_word16_t * restrict prior = st->prior;
+ register int i;
+
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for ( i=0 ; i<NM ; i++)
+ {
+ register spx_word16_t gamma;
+ register spx_word32_t tot_noise;
+ register spx_word16_t posti;
+ register spx_word32_t opsi;
+ register spx_word16_t priori;
+
+ tot_noise = ADD32(ADD32(ADD32(EXTEND32(1), PSHR32(noise[i],NOISE_SHIFT)), echo[i]) , reverb[i]);
+
+ posti = SUB16(DIV32_16_Q8(ps[i],tot_noise), QCONST16(1.f,SNR_SHIFT));
+ posti = MIN16(posti, QCONST16(100.f,SNR_SHIFT));
+ post[i] = posti;
+
+ opsi = old_ps[i];
+
+ gamma = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.89f,15),SQR16_Q15(DIV32_16_Q15(opsi,ADD32(opsi,tot_noise))));
+
+ priori = EXTRACT16(PSHR32(ADD32(MULT16_16(gamma,MAX16(0,posti)), MULT16_16(Q15_ONE-gamma,DIV32_16_Q8(opsi,tot_noise))), 15));
+ prior[i]=MIN16(priori, QCONST16(100.f,SNR_SHIFT));
+ }
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+}
+
+spx_word32_t preprocess_smooth_SNR(
+ SpeexPreprocessState * restrict st,
+ int N,
+ int NM
+)
+{
+ register spx_word16_t * restrict zeta = st->zeta;
+ register spx_word16_t * restrict prior = st->prior;
+ register spx_word32_t Zframe;
+ register spx_word16_t iprior, priori;
+ register int _N = N-1;
+ register int i;
+
+ iprior = prior[0];
+ priori = prior[1];
+ zeta[0] = PSHR32(ADD32(MULT16_16(QCONST16(.7f,15),zeta[0]), MULT16_16(QCONST16(.3f,15),iprior)),15);
+
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unroll=2
+#pragma TCS_unrollexact=1
+#endif
+ for ( i=1 ; i<_N ; i++)
+ { register spx_word16_t zetai = zeta[i];
+ register spx_word16_t priorii = prior[i+1];
+
+ zeta[i] = PSHR32(ADD32(ADD32(ADD32(MULT16_16(QCONST16(.7f,15),zetai), MULT16_16(QCONST16(.15f,15),priori)),
+ MULT16_16(QCONST16(.075f,15),iprior)), MULT16_16(QCONST16(.075f,15),priorii)),15);
+
+ iprior = priori;
+ priori = priorii;
+ }
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+
+ for (i=_N; i<NM ; i++)
+ { register spx_word16_t zetai = zeta[i];
+
+ priori = prior[i];
+ zeta[i] = PSHR32(ADD32(MULT16_16(QCONST16(.7f,15),zetai), MULT16_16(QCONST16(.3f,15),priori)),15);
+ }
+
+ Zframe = 0;
+
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for ( i=N ; i<NM ; i++ )
+ { Zframe = ADD32(Zframe, EXTEND32(zeta[i]));
+ }
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+
+ return Zframe;
+}
+
+void preprocess_compute_emgain(
+ SpeexPreprocessState * restrict st,
+ spx_word32_t * restrict ps,
+ spx_word16_t Pframe,
+ int NM
+)
+{
+ register spx_word16_t * restrict zeta = st->zeta;
+ register spx_word16_t * restrict prior = st->prior;
+ register spx_word16_t * restrict gain = st->gain;
+ register spx_word32_t * restrict old_ps = st->old_ps;
+ register spx_word16_t * restrict post = st->post;
+ register spx_word16_t * restrict gain2 = st->gain2;
+ register int i;
+ register int N=st->ps_size;
+
+ for ( i=N ; i<NM ; ++i )
+ {
+ register spx_word32_t theta;
+ register spx_word32_t MM;
+ register spx_word16_t prior_ratio;
+ register spx_word16_t P1;
+ register spx_word16_t q;
+
+#ifdef FIXED_POINT
+ register spx_word16_t tmp;
+#endif
+ register spx_word16_t priori = prior[i];
+
+ prior_ratio = PDIV32_16(SHL32(EXTEND32(priori), 15), ADD16(priori, SHL32(1,SNR_SHIFT)));
+ theta = MULT16_32_P15(prior_ratio, QCONST32(1.f,EXPIN_SHIFT)+SHL32(EXTEND32(post[i]),EXPIN_SHIFT-SNR_SHIFT));
+
+ MM = hypergeom_gain(theta);
+ gain[i] = EXTRACT16(MIN32(Q15_ONE, MULT16_32_Q15(prior_ratio, MM)));
+ old_ps[i] = MULT16_32_P15(QCONST16(.2f,15),old_ps[i]) + MULT16_32_P15(MULT16_16_P15(QCONST16(.8f,15),SQR16_Q15(gain[i])),ps[i]);
+
+ P1 = QCONST16(.199f,15)+MULT16_16_Q15(QCONST16(.8f,15),qcurve (zeta[i]));
+ q = Q15_ONE-MULT16_16_Q15(Pframe,P1);
+
+#ifdef FIXED_POINT
+ theta = MIN32(theta, EXTEND32(32767));
+ tmp = MULT16_16_Q15((SHL32(1,SNR_SHIFT)+priori),EXTRACT16(MIN32(Q15ONE,SHR32(spx_exp(-EXTRACT16(theta)),1))));
+ tmp = MIN16(QCONST16(3.,SNR_SHIFT), tmp);
+ tmp = EXTRACT16(PSHR32(MULT16_16(PDIV32_16(SHL32(EXTEND32(q),8),(Q15_ONE-q)),tmp),8));
+ gain2[i]=DIV32_16(SHL32(EXTEND32(32767),SNR_SHIFT), ADD16(256,tmp));
+#else
+ gain2[i]=1/(1.f + (q/(1.f-q))*(1+priori)*exp(-theta));
+#endif
+ }
+
+ filterbank_compute_psd16(st->bank,gain2+N, gain2);
+ filterbank_compute_psd16(st->bank,gain+N, gain);
+}
+
+void preprocess_compute_linear_gain(
+ SpeexPreprocessState * restrict st,
+ spx_word32_t * restrict ps,
+ int N
+)
+{
+ register spx_word16_t * restrict gain_floor = st->gain_floor;
+ register spx_word16_t * restrict prior = st->prior;
+ register spx_word16_t * restrict gain = st->gain;
+ register spx_word32_t * restrict old_ps = st->old_ps;
+ register spx_word16_t * restrict post = st->post;
+ register spx_word16_t * restrict gain2 = st->gain2;
+ register int i;
+
+ filterbank_compute_psd16(st->bank,gain_floor+N,gain_floor);
+
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for (i=0;i<N;i++)
+ {
+ register spx_word32_t MM;
+ register spx_word32_t theta;
+ register spx_word16_t prior_ratio;
+ register spx_word16_t tmp;
+ register spx_word16_t p;
+ register spx_word16_t g;
+ register spx_word16_t gfi = gain_floor[i];
+
+ prior_ratio = PDIV32_16(SHL32(EXTEND32(st->prior[i]), 15), ADD16(prior[i], SHL32(1,SNR_SHIFT)));
+ theta = MULT16_32_P15(prior_ratio, QCONST32(1.f,EXPIN_SHIFT)+SHL32(EXTEND32(post[i]),EXPIN_SHIFT-SNR_SHIFT));
+ MM = hypergeom_gain(theta);
+
+ g = EXTRACT16(MIN32(Q15_ONE, MULT16_32_Q15(prior_ratio, MM)));
+ p = gain2[i];
+
+ g = VMUX( MULT16_16_Q15(QCONST16(.333f,15),g) > gain[i], MULT16_16(3,gain[i]), g);
+
+ old_ps[i]= MULT16_32_P15(QCONST16(.2f,15),old_ps[i]) +
+ MULT16_32_P15(MULT16_16_P15(QCONST16(.8f,15),SQR16_Q15(g)),ps[i]);
+
+ g = VMUX( g < gfi, gfi, g );
+ gain[i] = g;
+
+ tmp = MULT16_16_P15(p,spx_sqrt(SHL32(EXTEND32(g),15))) +
+ MULT16_16_P15(SUB16(Q15_ONE,p),spx_sqrt(SHL32(EXTEND32(gfi),15)));
+
+ gain2[i]=SQR16_Q15(tmp);
+
+ /* Use this if you want a log-domain MMSE estimator instead */
+ /* gain2[i] = pow(g, p) * pow(gfi,1.f-p);*/
+ }
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+}
+
+
+#if 0
+void preprocess_compute_bark_gain(
+ SpeexPreprocessState * restrict st,
+ int N,
+ int NM
+)
+{
+ register spx_word16_t * restrict gain_floor = st->gain_floor;
+ register spx_word16_t * restrict gain = st->gain;
+ register spx_word16_t * restrict gain2 = st->gain2;
+ register int i;
+
+ for (i=N;i<NM;i++)
+ {
+ register spx_word16_t tmp;
+ register spx_word16_t p = gain2[i];
+ register spx_word16_t gaini;
+ register spx_word16_t gfi = gain_floor[i];
+
+ gaini = MAX16(gain[i], gfi);
+
+ gain[i] = gaini;
+
+ tmp = MULT16_16_P15(p,spx_sqrt(SHL32(EXTEND32(gaini),15))) +
+ MULT16_16_P15(SUB16(Q15_ONE,p),spx_sqrt(SHL32(EXTEND32(gfi),15)));
+
+ gain2[i]=SQR16_Q15(tmp);
+ }
+
+ filterbank_compute_psd16(st->bank,gain2+N, gain2);
+}
+#endif
+
+void preprocess_apply_gain(
+ SpeexPreprocessState * restrict st,
+ int N
+)
+{
+ register spx_word16_t * restrict ft = st->ft;
+ register spx_word16_t * restrict gain2 = st->gain2;
+ register int j, i;
+
+ ft[0] = MULT16_16_P15(gain2[0],ft[0]);
+
+ for (i=1,j=1; i<N ; i++,j+=2)
+ {
+ register spx_word16_t gain2i = gain2[i];
+ register spx_word16_t ftj = ft[j];
+ register spx_word16_t ftjj = ft[j+1];
+
+ ft[j] = MULT16_16_P15(gain2i,ftj);
+ ft[j+1] = MULT16_16_P15(gain2i,ftjj);
+ }
+
+ ft[(N<<1)-1] = MULT16_16_P15(gain2[N-1],ft[(N<<1)-1]);
+}
+
+#ifdef FIXED_POINT
+void preprocess_scale(
+ SpeexPreprocessState * restrict st,
+ int N
+)
+{
+ register spx_word16_t * restrict frame = st->frame;
+ register int shift = st->frame_shift;
+ register int i;
+ register int N2 = N << 1;
+
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for ( i=0 ; i<N2 ;i++)
+ { register spx_word16_t framei = frame[i];
+
+ frame[i] = PSHR16(framei,shift);
+ }
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+}
+
+#else
+
+void preprocess_apply_agc(
+ SpeexPreprocessState * restrict st,
+ int N
+)
+{
+ register spx_word16_t max_sample=0;
+ register spx_word16_t * restrict frame = st->frame;
+ register int i;
+ register int N2 = N << 1;
+
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for (i=0;i<N2;i++)
+ { register spx_word16_t framei = VABS(frame[i]);
+
+ max_sample = VMUX( framei > max_sample, framei, max_sample);
+ }
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+
+ if ( max_sample > 28000.f )
+ {
+ float damp = 28000.f/max_sample;
+
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for ( i=0 ; i< N2 ; i++ )
+ { frame[i] *= damp;
+ }
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+ }
+}
+#endif
+
+
+void preprocess_update(
+ SpeexPreprocessState * restrict st,
+ spx_int16_t * restrict x,
+ int N
+)
+{
+ register spx_word16_t * restrict frame = st->frame;
+ register spx_word16_t * restrict window = st->window;
+ register spx_word16_t * restrict outbuf = st->outbuf;
+ register int framesize = st->frame_size;
+ register int N2 = N << 1;
+ register int N3 = N2 - framesize;
+ register int N4 = (framesize) - N3;
+ register int i;
+
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for ( i=0 ; i<N2 ; i++)
+ { register spx_word16_t fi = frame[i];
+ register spx_word16_t wi = window[i];
+
+ frame[i] = MULT16_16_Q15(fi, wi);
+ }
+ for (i=0;i<N3;i++)
+ { x[i] = outbuf[i] + frame[i];
+ }
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+
+ for ( i=0;i<N4;i++)
+ { x[N3+i] = frame[N3+i];
+ }
+
+ memcpy(outbuf, frame+framesize, (N3) * sizeof(spx_word16_t));
+}
+
+#define OVERRIDE_SPEEX_PREPROCESS_RUN
+int speex_preprocess_run(SpeexPreprocessState * restrict st, spx_int16_t * restrict x)
+{
+ register int i, N, M, NM;
+ register spx_word32_t * restrict ps=st->ps;
+ register spx_word32_t Zframe;
+ register spx_word16_t Pframe;
+
+ st->nb_adapt++;
+ st->min_count++;
+ N = st->ps_size;
+ M = st->nbands;
+ NM = N + M;
+
+ preprocess_residue_echo(st, N, NM);
+ preprocess_analysis(st, x);
+ update_noise_prob(st);
+ preprocess_update_noise(st, ps, N);
+
+ if ( st->nb_adapt == 1 )
+ { memcpy(st->old_ps, ps, (NM) * sizeof(spx_word32_t));
+ }
+
+ preprocess_compute_SNR(st, ps, NM);
+ Zframe = preprocess_smooth_SNR(st, N, NM);
+
+
+ {
+ register spx_word16_t effective_echo_suppress;
+
+ Pframe = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.899f,15),qcurve(DIV32_16(Zframe,M)));
+ effective_echo_suppress = EXTRACT16(PSHR32(ADD32(MULT16_16(SUB16(Q15_ONE,Pframe), st->echo_suppress),
+ MULT16_16(Pframe, st->echo_suppress_active)),15));
+ compute_gain_floor(st->noise_suppress, effective_echo_suppress, st->noise+N, st->echo_noise+N, st->gain_floor+N, M);
+
+ }
+
+ preprocess_compute_emgain(st, ps, Pframe, NM);
+ preprocess_compute_linear_gain(st, ps, N);
+
+
+ if (!st->denoise_enabled)
+ {
+ register spx_word16_t * restrict gain2 = st->gain2;
+
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unroll=4
+#pragma TCS_unrollexact=1
+#endif
+ for ( i=0 ; i<NM ; i++ )
+ { gain2[i] = Q15_ONE;
+ }
+#if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)
+#pragma TCS_unrollexact=0
+#pragma TCS_unroll=0
+#endif
+ }
+
+ preprocess_apply_gain(st, N);
+
+#ifndef FIXED_POINT
+ if (st->agc_enabled)
+ { speex_compute_agc(st, Pframe, st->ft);
+ }
+#endif
+
+
+ spx_ifft(st->fft_lookup, st->ft, st->frame);
+
+#ifdef FIXED_POINT
+ preprocess_scale(st, N);
+#endif
+
+#ifndef FIXED_POINT
+ if ( st->agc_enabled )
+ { preprocess_apply_agc(st, N);
+ }
+#endif
+
+ preprocess_update(st, x, N);
+
+ if ( st->vad_enabled )
+ {
+ if (Pframe > st->speech_prob_start || (st->was_speech && Pframe > st->speech_prob_continue))
+ { st->was_speech=1;
+ return 1;
+
+ } else
+ { st->was_speech=0;
+ return 0;
+ }
+ } else
+ { return 1;
+ }
+}