Patch by Alexander Chemeris removing medfilter from the VS2005 build
[speexdsp.git] / tmv / preprocess_tm.h
1 /* Copyright (C) 2007 Hong Zhiqian */\r
2 /**\r
3    @file preprocess_tm.h\r
4    @author Hong Zhiqian\r
5    @brief Various compatibility routines for Speex (TriMedia version)\r
6 */\r
7 /*\r
8    Redistribution and use in source and binary forms, with or without\r
9    modification, are permitted provided that the following conditions\r
10    are met:\r
11    \r
12    - Redistributions of source code must retain the above copyright\r
13    notice, this list of conditions and the following disclaimer.\r
14    \r
15    - Redistributions in binary form must reproduce the above copyright\r
16    notice, this list of conditions and the following disclaimer in the\r
17    documentation and/or other materials provided with the distribution.\r
18    \r
19    - Neither the name of the Xiph.org Foundation nor the names of its\r
20    contributors may be used to endorse or promote products derived from\r
21    this software without specific prior written permission.\r
22    \r
23    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
24    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
25    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
26    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR\r
27    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
28    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
29    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r
30    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
31    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
32    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
33    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
34 */\r
35 #include <ops/custom_defs.h>\r
36 #include "profile_tm.h"\r
37 \r
38 #ifdef FIXED_POINT\r
39 #define OVERRIDE_PREPROCESS_ANALYSIS\r
40 static void preprocess_analysis(SpeexPreprocessState * restrict st, spx_int16_t * restrict x)\r
41 {\r
42         register int i, j, framesize = st->frame_size;\r
43         register int N = st->ps_size;\r
44         register int N3 = 2*N - framesize;\r
45         register int N4 = framesize - N3;\r
46         register int * restrict ps = st->ps;\r
47         register int * restrict frame;\r
48         register int * restrict inbuf;\r
49         register int * restrict ptr;\r
50         register int max_val;\r
51 \r
52         frame = (int*)(st->frame);\r
53         inbuf = (int*)(st->inbuf);\r
54         ptr = (int*)(st->frame+N3);\r
55 \r
56         TMDEBUG_ALIGNMEM(x);\r
57         TMDEBUG_ALIGNMEM(frame);\r
58         TMDEBUG_ALIGNMEM(inbuf);\r
59 \r
60         PREPROCESSANAYLSIS_START();\r
61 \r
62         N3 >>= 1;\r
63         framesize >>= 1;\r
64         max_val = 0;\r
65         \r
66         for ( i=0,j=0 ; i<N3 ; i+=2,j+=8 )\r
67         {       register int r1, r2;\r
68 \r
69                 r1 = ld32x(inbuf,i);\r
70                 r2 = ld32x(inbuf,i+1);\r
71 \r
72                 st32d(j,   frame, r1);\r
73                 st32d(j+4, frame, r2);\r
74         }\r
75 \r
76         for ( i=0,j=0 ; i<framesize ; i+=2,j+=8 )\r
77         {       register int r1, r2;\r
78 \r
79                 r1 = ld32x(x, i);\r
80                 r2 = ld32x(x, i+1);\r
81 \r
82                 st32d(j,  ptr, r1);\r
83                 st32d(j+4,ptr, r2);\r
84         }\r
85    \r
86         for ( i=0,j=0,ptr=(int*)(x+N4) ; i<N3 ; i+=2,j+=8 )\r
87         {       register int r1, r2;\r
88 \r
89                 r1 = ld32x(ptr, i);\r
90                 r2 = ld32x(ptr, i+1);\r
91 \r
92                 st32d(j,  inbuf, r1);\r
93                 st32d(j+4,inbuf, r2);\r
94         }\r
95 #if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)\r
96 #pragma TCS_unroll=2\r
97 #pragma TCS_unrollexact=1\r
98 #endif\r
99    for ( i=0,j=0,ptr=(int*)st->window ; i<N ; ++i,j+=4 )\r
100    {    register int f10, w10, r0, r1;\r
101 \r
102                 f10 = ld32x(frame, i);\r
103                 w10 = ld32x(ptr,   i);\r
104 \r
105                 r0  = (sex16(f10) * sex16(w10)) >> 15;\r
106                 r1      = (asri(16,f10) * asri(16,w10)) >> 15;\r
107 \r
108                 max_val = imax(iabs(sex16(r0)), max_val);\r
109                 max_val = imax(iabs(sex16(r1)), max_val);\r
110 \r
111                 r0      = pack16lsb(r1, r0);\r
112                 st32d(j, frame, r0);\r
113         }\r
114 #if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)\r
115 #pragma TCS_unrollexact=0\r
116 #pragma TCS_unroll=0\r
117 #endif\r
118    \r
119         max_val = 14 - spx_ilog2(max_val);\r
120         st->frame_shift = max_val;\r
121 \r
122         if ( max_val != 0 )\r
123         {\r
124 #if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)\r
125 #pragma TCS_unroll=4\r
126 #pragma TCS_unrollexact=1\r
127 #endif\r
128                 for ( i=0,j=0 ; i<N ; ++i,j+=4 )\r
129                 {       register int f10;\r
130 \r
131                         f10 = ld32x(frame, i);\r
132                         f10 = dualasl(f10, max_val);\r
133                         st32d(j, frame, f10);\r
134 \r
135                 }\r
136 #if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)\r
137 #pragma TCS_unrollexact=0\r
138 #pragma TCS_unroll=0\r
139 #endif\r
140         }\r
141 \r
142         spx_fft(st->fft_lookup, st->frame, st->ft);     \r
143         power_spectrum(st->ft, ps, N << 1);\r
144    \r
145 #if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)\r
146 #pragma TCS_unroll=4\r
147 #pragma TCS_unrollexact=1\r
148 #endif\r
149         for ( i=0,ptr=(int*)st->ps,max_val<<=1,j=((1<<((max_val))>>1)) ;i<N ; ++i )\r
150         {       \r
151                 ps[i] = (ps[i] + j) >> max_val;\r
152         }\r
153 #if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)\r
154 #pragma TCS_unrollexact=0\r
155 #pragma TCS_unroll=0\r
156 #endif\r
157 \r
158         filterbank_compute_bank32(st->bank, ps, ps+N);\r
159 \r
160         PREPROCESSANAYLSIS_STOP();\r
161 }\r
162 \r
163 #define _MULT16_32_Q15(a,b,c) ADD32(MULT16_16((a),(b)), SHR(MULT16_16((a),(c)),15))\r
164 \r
165 #define OVERRIDE_UPDATE_NOISE_PROB\r
166 static void update_noise_prob(SpeexPreprocessState * restrict st)\r
167 {\r
168         register int i;\r
169         register int min_range, nb_adapt;\r
170         register int N = st->ps_size;\r
171         register int * restrict Smin = (int*)st->Smin;\r
172         register int * restrict Stmp = (int*)st->Stmp;\r
173         register int * restrict S = (int*)st->S;\r
174         \r
175         UPDATENOISEPROB_START();\r
176 \r
177         {\r
178                 register int psi_lsb, psi_msb, ips_lsb, ips_msb, psii_lsb, psii_msb;\r
179                 register int psiii_lsb, psiii_msb;\r
180                 register int q8, q05, q2, q1;\r
181                 register int *ps = (int*)st->ps;\r
182                 register int si_lsb, si_msb, sii_lsb, sii_msb;\r
183         \r
184                 q8      = QCONST16(.8f,15);\r
185                 q05 = QCONST16(.05f,15);\r
186                 q2      = QCONST16(.2f,15);\r
187                 q1      = QCONST16(.1f,15);\r
188 \r
189                 ips_lsb  = ps[0];\r
190                 psi_lsb  = ps[1];\r
191                 si_lsb   = S[0];\r
192                 ips_msb  = ips_lsb >> 15;\r
193                 psi_msb  = psi_lsb >> 15;\r
194                 si_msb   = si_lsb >> 15;\r
195 \r
196                 ips_lsb  &= 0x00007fff;\r
197                 psi_lsb  &= 0x00007fff;\r
198                 si_lsb   &= 0x00007fff;\r
199                 \r
200                 S[0] = _MULT16_32_Q15(q8,si_msb,si_lsb) +  _MULT16_32_Q15(q2,ips_msb,ips_lsb);\r
201 \r
202                 for ( i=1 ; i<N-1 ; i+=2 )\r
203                 {\r
204                         psii_lsb = ps[i+1];\r
205                         si_lsb   = S[i];\r
206 \r
207                         psii_msb = psii_lsb >> 15;\r
208                         si_msb   = si_lsb >> 15;\r
209                         si_lsb   &= 0x00007fff;\r
210                         psii_lsb &= 0x00007fff;\r
211 \r
212                         S[i]= _MULT16_32_Q15(q8,si_msb,si_lsb) + \r
213                                   _MULT16_32_Q15(q05,ips_msb,ips_lsb) + \r
214                                   _MULT16_32_Q15(q1,psi_msb,psi_lsb) + \r
215                                   _MULT16_32_Q15(q05,psii_msb,psii_lsb);\r
216                         \r
217                         psiii_lsb = ps[i+2];\r
218                         sii_lsb  = S[i+1];\r
219 \r
220                         sii_msb  =  sii_lsb >> 15;\r
221                         psiii_msb=  psiii_lsb >> 15;\r
222                         sii_lsb  &= 0x00007fff;\r
223                         psiii_lsb&= 0x00007fff;\r
224 \r
225                         S[i+1]= _MULT16_32_Q15(q8,sii_msb,sii_lsb) + \r
226                                         _MULT16_32_Q15(q05,psi_msb,psi_lsb) + \r
227                                         _MULT16_32_Q15(q1,psii_msb,psii_lsb) + \r
228                                         _MULT16_32_Q15(q05,psiii_msb,psiii_lsb);\r
229 \r
230                         ips_lsb = psii_lsb;\r
231                         ips_msb = psii_msb;\r
232                         psi_lsb = psiii_lsb;\r
233                         psi_msb = psiii_msb;\r
234                 }\r
235    \r
236                 S[N-1] = MULT16_32_Q15(q8,S[N-1]) + MULT16_32_Q15(q2,ps[N-1]);\r
237         }\r
238 \r
239         nb_adapt = st->nb_adapt;\r
240    \r
241         if ( nb_adapt==1 )\r
242         {       for ( i=0 ; i<N ; ++i )\r
243                         Smin[i] = Stmp[i] = 0;\r
244 \r
245         }\r
246 \r
247         min_range = mux(nb_adapt < 100,         15,\r
248                                 mux(nb_adapt < 1000,    50,\r
249                                 mux(nb_adapt < 10000,   150, 300)));\r
250 \r
251         if ( st->min_count > min_range )\r
252         {\r
253                 st->min_count = 0;\r
254 \r
255 #if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)\r
256 #pragma TCS_unroll=2\r
257 #pragma TCS_unrollexact=1\r
258 #endif\r
259                 for ( i=0 ; i<N ; ++i )\r
260                 {       register int si, stmpi;\r
261 \r
262                         si              = S[i];\r
263                         stmpi   = Stmp[i];\r
264                                 \r
265                         Smin[i] = imin(stmpi,si);\r
266                         Stmp[i] = si;\r
267                 }\r
268 #if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)\r
269 #pragma TCS_unrollexact=0\r
270 #pragma TCS_unroll=0\r
271 #endif\r
272         } else \r
273         {\r
274 \r
275 #if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)\r
276 #pragma TCS_unroll=2\r
277 #pragma TCS_unrollexact=1\r
278 #endif\r
279                 for ( i=0 ; i<N ; ++i )\r
280                 {       register int si, stmpi, smini;\r
281 \r
282                         si              = S[i];\r
283                         stmpi   = Stmp[i];\r
284                         smini   = Smin[i];\r
285 \r
286                         Smin[i] = imin(smini,si);\r
287                         Stmp[i] = imin(stmpi,si);      \r
288                 }\r
289 #if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)\r
290 #pragma TCS_unrollexact=0\r
291 #pragma TCS_unroll=0\r
292 #endif\r
293         }\r
294 \r
295 \r
296         {\r
297                 register int q4;\r
298                 register int * restrict update_prob = (int*)st->update_prob;\r
299 \r
300                 q4 = QCONST16(.4f,15);\r
301 \r
302 #if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)\r
303 #pragma TCS_unroll=4\r
304 #pragma TCS_unrollexact=1\r
305 #endif\r
306                 for ( i=0 ; i<N ; ++i )\r
307                 {       register int si;\r
308                         register int smini;\r
309 \r
310                         si = S[i];\r
311                         smini = Smin[i];\r
312                         update_prob[i] = mux(MULT16_32_Q15(q4,si) > ADD32(smini,20), 1, 0);\r
313                 }\r
314 #if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)\r
315 #pragma TCS_unrollexact=0\r
316 #pragma TCS_unroll=0\r
317 #endif\r
318         }\r
319 \r
320         UPDATENOISEPROB_STOP();\r
321 }\r
322 \r
323 #else\r
324 \r
325 #define OVERRIDE_PREPROCESS_ANALYSIS\r
326 static void preprocess_analysis(SpeexPreprocessState * restrict st, spx_int16_t * restrict x)\r
327 {\r
328         register int i;\r
329         register int framesize = st->frame_size;\r
330         register int N = st->ps_size;\r
331         register int N3 = 2*N - framesize;\r
332         register int N4 = framesize - N3;\r
333         register float * restrict ps = st->ps;\r
334         register float * restrict frame = st->frame;\r
335         register float * restrict inbuf = st->inbuf;\r
336 \r
337         PREPROCESSANAYLSIS_START();\r
338 \r
339 #if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)\r
340 #pragma TCS_unroll=4\r
341 #pragma TCS_unrollexact=1\r
342 #endif\r
343         for ( i=0 ; i<N3 ; ++i )\r
344         {\r
345                 frame[i] = inbuf[i];\r
346         }\r
347 #if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)\r
348 #pragma TCS_unrollexact=0\r
349 #pragma TCS_unroll=0\r
350 #endif\r
351 \r
352 #if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)\r
353 #pragma TCS_unroll=4\r
354 #pragma TCS_unrollexact=1\r
355 #endif\r
356         for ( i=0 ; i<framesize ; ++i )\r
357         {       frame[N3+i] = x[i];\r
358         }\r
359 #if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)\r
360 #pragma TCS_unrollexact=0\r
361 #pragma TCS_unroll=0\r
362 #endif\r
363 \r
364 #if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)\r
365 #pragma TCS_unroll=4\r
366 #pragma TCS_unrollexact=1\r
367 #endif\r
368         for ( i=0,x+=N4 ; i<N3 ; ++i )\r
369         {       inbuf[i]  = x[i];\r
370         }\r
371 #if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)\r
372 #pragma TCS_unrollexact=0\r
373 #pragma TCS_unroll=0\r
374 #endif\r
375 \r
376         inbuf = st->window;\r
377 \r
378 #if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)\r
379 #pragma TCS_unroll=4\r
380 #pragma TCS_unrollexact=1\r
381 #endif\r
382         for ( i=0 ; i<2*N ; ++i )\r
383         {\r
384                 frame[i] = frame[i] * inbuf[i];\r
385         }\r
386 #if (TM_UNROLL && TM_UNROLL_PREPROCESSANALYSIS)\r
387 #pragma TCS_unrollexact=0\r
388 #pragma TCS_unroll=0\r
389 #endif\r
390 \r
391         spx_fft(st->fft_lookup, frame, st->ft);         \r
392         power_spectrum(st->ft, ps, N << 1);\r
393         filterbank_compute_bank32(st->bank, ps, ps+N);\r
394 \r
395         PREPROCESSANAYLSIS_STOP();\r
396 }\r
397 \r
398 \r
399 #define OVERRIDE_UPDATE_NOISE_PROB\r
400 static void update_noise_prob(SpeexPreprocessState * restrict st)\r
401 {\r
402    \r
403         register float * restrict S = st->S;\r
404         register float * restrict ps = st->ps;\r
405         register int N = st->ps_size;\r
406     register int min_range;\r
407         register int i;\r
408         register int nb_adapt;\r
409         register float * restrict Smin = st->Smin;\r
410         register float * restrict Stmp = st->Stmp;\r
411 \r
412         UPDATENOISEPROB_START();\r
413 \r
414         {\r
415                 register float ips, psi;\r
416 \r
417                 ips  = ps[0];\r
418                 psi  = ps[1];\r
419 \r
420                 S[0] = .8f * S[0] + .2f * ips;\r
421 \r
422                 for ( i=1 ; i<N-1 ; i+=2 )\r
423                 {\r
424                         register float psii, psiii;\r
425 \r
426                         psii    = ps[i+1];\r
427                         psiii   = ps[i+2];\r
428                         S[i]    = .8f * S[i]    + .05f * ips + .1f * psi  + .05f * psii;\r
429                         S[i+1]  = .8f * S[i+1]  + .05f * psi + .1f * psii + .05f * psiii; \r
430                         ips             = psii;\r
431                         psi             = psiii;\r
432                 }\r
433 \r
434                 S[N-1] = .8f * S[N-1] + .2f * ps[N-1];\r
435         }\r
436 \r
437         nb_adapt = st->nb_adapt;\r
438    \r
439         if ( nb_adapt==1 )\r
440         {       \r
441                 for (i=0;i<N;i++)\r
442                         Smin[i] = st->Stmp[i] = 0;\r
443         }\r
444 \r
445         min_range = mux(nb_adapt < 100,         15,\r
446                                 mux(nb_adapt < 1000,    50,\r
447                                 mux(nb_adapt < 10000,   150, 300)));\r
448 \r
449    \r
450         if ( st->min_count > min_range )\r
451         {\r
452                 st->min_count = 0;\r
453 #if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)\r
454 #pragma TCS_unroll=4\r
455 #pragma TCS_unrollexact=1\r
456 #endif\r
457                 for ( i=0 ; i<N ; ++i )\r
458                 {\r
459                         register float stmpi, si;\r
460 \r
461                         stmpi   = Stmp[i];\r
462                         si              = S[i];\r
463 \r
464                         Smin[i] = fmin(stmpi,si);\r
465                         Stmp[i] = si;\r
466                 }\r
467 #if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)\r
468 #pragma TCS_unrollexact=0\r
469 #pragma TCS_unroll=0\r
470 #endif\r
471 \r
472         } else \r
473         {\r
474                 register float * restrict Smin = st->Smin;\r
475 \r
476 #if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)\r
477 #pragma TCS_unroll=4\r
478 #pragma TCS_unrollexact=1\r
479 #endif\r
480                 for ( i=0 ; i<N ; ++i )\r
481                 {\r
482                         register float stmpi, si, smini;\r
483 \r
484                         stmpi   = Stmp[i];\r
485                         si              = S[i];\r
486                         smini   = Smin[i];\r
487                         \r
488                         Smin[i] = fmin(smini,si);\r
489                         Stmp[i] = fmin(stmpi,si);      \r
490                 }\r
491 #if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)\r
492 #pragma TCS_unrollexact=0\r
493 #pragma TCS_unroll=0\r
494 #endif\r
495         }\r
496 \r
497         {\r
498                 register int * restrict update_prob = (int*)st->update_prob;\r
499 \r
500 #if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)\r
501 #pragma TCS_unroll=4\r
502 #pragma TCS_unrollexact=1\r
503 #endif\r
504                 for (i=0;i<N;i++)\r
505                 {       register float si;\r
506                         register float smini;\r
507 \r
508                         si              = S[i];\r
509                         smini   = Smin[i];\r
510                         update_prob[i] = mux( (.4 * si) > (smini + 20.f), 1, 0);\r
511                         \r
512                 }\r
513 #if (TM_UNROLL && TM_UNROLL_UPDATENOISEPROB)\r
514 #pragma TCS_unrollexact=0\r
515 #pragma TCS_unroll=0\r
516 #endif\r
517         }\r
518 \r
519         UPDATENOISEPROB_STOP();\r
520 }\r
521 \r
522 \r
523 #define OVERRIDE_COMPUTE_GAIN_FLOOR\r
524 static void compute_gain_floor(\r
525         int noise_suppress, \r
526         int effective_echo_suppress, \r
527         float * restrict noise, \r
528         float * restrict echo, \r
529         float * gain_floor, \r
530         int len\r
531 )\r
532 {\r
533         register int i;\r
534         register float echo_floor;\r
535         register float noise_floor;\r
536 \r
537         COMPUTEGAINFLOOR_START();\r
538 \r
539         noise_floor = exp(.2302585f*noise_suppress);\r
540         echo_floor = exp(.2302585f*effective_echo_suppress);\r
541 \r
542 #if (TM_UNROLL && TM_UNROLL_COMPUTEGAINFLOOR)\r
543 #pragma TCS_unroll=4\r
544 #pragma TCS_unrollexact=1\r
545 #endif\r
546         for (i=0;i<len;i++)\r
547         {       register float noisei, echoi;\r
548 \r
549                 noisei = noise[i];\r
550                 echoi  = echo[i];\r
551 \r
552                 gain_floor[i] = FRAC_SCALING * sqrt(noise_floor * noisei +      echo_floor * echoi) / sqrt(1+noisei+echoi);\r
553 \r
554         }\r
555 #if (TM_UNROLL && TM_UNROLL_COMPUTEGAINFLOOR)\r
556 #pragma TCS_unrollexact=0\r
557 #pragma TCS_unroll=0\r
558 #endif\r
559 \r
560         COMPUTEGAINFLOOR_STOP();\r
561 }\r
562 \r
563 #endif\r
564 \r
565 static inline spx_word32_t hypergeom_gain(spx_word32_t xx);\r
566 static inline spx_word16_t qcurve(spx_word16_t x);\r
567 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);\r
568 void speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *Yout, int len);\r
569 \r
570 #ifndef FIXED_POINT\r
571 static void speex_compute_agc(SpeexPreprocessState *st, spx_word16_t Pframe, spx_word16_t *ft);\r
572 #endif\r
573 \r
574 void preprocess_residue_echo(\r
575         SpeexPreprocessState * restrict st,\r
576         int N,\r
577         int NM\r
578 )\r
579 {\r
580         if (st->echo_state)\r
581         {\r
582                 register spx_word32_t * restrict r_echo = st->residual_echo;\r
583                 register spx_word32_t * restrict e_noise = st->echo_noise;\r
584                 register int i;\r
585 \r
586 #ifndef FIXED_POINT\r
587                 register spx_word32_t r;\r
588 #endif\r
589 \r
590                 speex_echo_get_residual(st->echo_state, r_echo, N);\r
591 \r
592 #ifndef FIXED_POINT\r
593                 r = r_echo[0];\r
594                 if (!(r >=0 && r < N*1e9f) )\r
595                 {       \r
596                         memset(r_echo, 0, N * sizeof(spx_word32_t));\r
597                 }\r
598 #endif\r
599 \r
600 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
601 #pragma TCS_unroll=4\r
602 #pragma TCS_unrollexact=1\r
603 #endif\r
604                 for (i=0;i<N;i++)\r
605                 {       register spx_word32_t eni = e_noise[i];\r
606                         e_noise[i] = MAX32(MULT16_32_Q15(QCONST16(.6f,15),eni), r_echo[i]);\r
607                 }\r
608 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
609 #pragma TCS_unrollexact=0\r
610 #pragma TCS_unroll=0\r
611 #endif\r
612                 filterbank_compute_bank32(st->bank, e_noise, e_noise+N);\r
613    \r
614         } else \r
615         {       memset(st->echo_noise, 0, (NM) * sizeof(spx_word32_t));\r
616         }\r
617 }\r
618 \r
619 void preprocess_update_noise(\r
620         SpeexPreprocessState * restrict st,\r
621         spx_word32_t * restrict ps,\r
622         int N\r
623 )\r
624 {\r
625         register spx_word16_t beta, beta_1;\r
626         register int * restrict up = st->update_prob;\r
627         register spx_word32_t * restrict noise = st->noise;\r
628         register int i;\r
629 \r
630         beta = MAX16(QCONST16(.03,15),DIV32_16(Q15_ONE,st->nb_adapt));\r
631         beta_1 = Q15_ONE-beta;\r
632 \r
633 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
634 #pragma TCS_unroll=4\r
635 #pragma TCS_unrollexact=1\r
636 #endif\r
637         for (i=0;i<N;i++)\r
638         {       register spx_word32_t ni = noise[i];\r
639                 register spx_word32_t psi = ps[i];\r
640 \r
641                 if ( !up[i] || psi < PSHR32(ni, NOISE_SHIFT) )\r
642                 {       noise[i] =      MAX32(EXTEND32(0),MULT16_32_Q15(beta_1,ni) + \r
643                                                 MULT16_32_Q15(beta,SHL32(psi,NOISE_SHIFT)));\r
644                 }\r
645         }\r
646 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
647 #pragma TCS_unrollexact=0\r
648 #pragma TCS_unroll=0\r
649 #endif\r
650         filterbank_compute_bank32(st->bank, noise, noise+N);\r
651 }\r
652 \r
653 void preprocess_compute_SNR(\r
654         SpeexPreprocessState * restrict st,\r
655         spx_word32_t * restrict ps,\r
656         int NM\r
657 )\r
658 {\r
659         register spx_word32_t * restrict noise = st->noise;\r
660         register spx_word32_t * restrict echo = st->echo_noise;\r
661         register spx_word32_t * restrict reverb = st->reverb_estimate;\r
662         register spx_word16_t * restrict post = st->post;\r
663         register spx_word32_t * restrict old_ps = st->old_ps;\r
664         register spx_word16_t * restrict prior = st->prior;\r
665         register int i;\r
666 \r
667 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
668 #pragma TCS_unroll=4\r
669 #pragma TCS_unrollexact=1\r
670 #endif\r
671         for ( i=0 ; i<NM ; i++)\r
672         {\r
673                 register spx_word16_t gamma;\r
674                 register spx_word32_t tot_noise;\r
675                 register spx_word16_t posti;\r
676                 register spx_word32_t opsi;\r
677                 register spx_word16_t priori;\r
678 \r
679                 tot_noise = ADD32(ADD32(ADD32(EXTEND32(1), PSHR32(noise[i],NOISE_SHIFT)), echo[i]) , reverb[i]);\r
680       \r
681                 posti = SUB16(DIV32_16_Q8(ps[i],tot_noise), QCONST16(1.f,SNR_SHIFT));\r
682                 posti = MIN16(posti, QCONST16(100.f,SNR_SHIFT));\r
683                 post[i] = posti;\r
684 \r
685                 opsi = old_ps[i];\r
686 \r
687                 gamma = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.89f,15),SQR16_Q15(DIV32_16_Q15(opsi,ADD32(opsi,tot_noise))));\r
688       \r
689                 priori = EXTRACT16(PSHR32(ADD32(MULT16_16(gamma,MAX16(0,posti)), MULT16_16(Q15_ONE-gamma,DIV32_16_Q8(opsi,tot_noise))), 15));\r
690                 prior[i]=MIN16(priori, QCONST16(100.f,SNR_SHIFT));\r
691         }\r
692 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
693 #pragma TCS_unrollexact=0\r
694 #pragma TCS_unroll=0\r
695 #endif\r
696 }\r
697 \r
698 spx_word32_t preprocess_smooth_SNR(\r
699         SpeexPreprocessState * restrict st,\r
700         int N,\r
701         int NM\r
702 )\r
703 {\r
704         register spx_word16_t * restrict zeta = st->zeta;\r
705         register spx_word16_t * restrict prior = st->prior;\r
706         register spx_word32_t Zframe;\r
707         register spx_word16_t iprior, priori;\r
708         register int _N = N-1;\r
709         register int i;\r
710 \r
711         iprior = prior[0];\r
712         priori = prior[1];\r
713         zeta[0] = PSHR32(ADD32(MULT16_16(QCONST16(.7f,15),zeta[0]), MULT16_16(QCONST16(.3f,15),iprior)),15);\r
714    \r
715 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
716 #pragma TCS_unroll=2\r
717 #pragma TCS_unrollexact=1\r
718 #endif\r
719         for ( i=1 ; i<_N ; i++)\r
720         {       register spx_word16_t zetai = zeta[i];\r
721                 register spx_word16_t priorii = prior[i+1];\r
722 \r
723                 zeta[i] = PSHR32(ADD32(ADD32(ADD32(MULT16_16(QCONST16(.7f,15),zetai), MULT16_16(QCONST16(.15f,15),priori)),\r
724                   MULT16_16(QCONST16(.075f,15),iprior)), MULT16_16(QCONST16(.075f,15),priorii)),15);\r
725 \r
726                 iprior = priori;\r
727                 priori = priorii;\r
728         }\r
729 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
730 #pragma TCS_unrollexact=0\r
731 #pragma TCS_unroll=0\r
732 #endif\r
733 \r
734         for (i=_N; i<NM ; i++)\r
735         {       register spx_word16_t zetai = zeta[i];\r
736                 \r
737                 priori = prior[i];\r
738                 zeta[i] = PSHR32(ADD32(MULT16_16(QCONST16(.7f,15),zetai), MULT16_16(QCONST16(.3f,15),priori)),15);\r
739         }\r
740 \r
741         Zframe = 0;\r
742    \r
743 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
744 #pragma TCS_unroll=4\r
745 #pragma TCS_unrollexact=1\r
746 #endif\r
747         for ( i=N ; i<NM ; i++ )\r
748         {       Zframe = ADD32(Zframe, EXTEND32(zeta[i]));\r
749         }\r
750 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
751 #pragma TCS_unrollexact=0\r
752 #pragma TCS_unroll=0\r
753 #endif\r
754 \r
755         return Zframe;\r
756 }\r
757 \r
758 void preprocess_compute_emgain(\r
759         SpeexPreprocessState * restrict st,\r
760         spx_word32_t * restrict ps,\r
761         spx_word16_t Pframe,\r
762         int NM\r
763 )\r
764 {\r
765         register spx_word16_t * restrict zeta = st->zeta;\r
766         register spx_word16_t * restrict prior = st->prior;\r
767         register spx_word16_t * restrict gain = st->gain;\r
768         register spx_word32_t * restrict old_ps = st->old_ps;\r
769         register spx_word16_t * restrict post = st->post;\r
770         register spx_word16_t * restrict gain2 = st->gain2;\r
771         register int i;\r
772         register int N=st->ps_size;\r
773         \r
774         for ( i=N ; i<NM ; ++i )\r
775         {\r
776                 register spx_word32_t theta;\r
777                 register spx_word32_t MM;\r
778                 register spx_word16_t prior_ratio;\r
779                 register spx_word16_t P1;\r
780                 register spx_word16_t q;\r
781 \r
782 #ifdef FIXED_POINT\r
783                 register spx_word16_t tmp;\r
784 #endif\r
785                 register spx_word16_t priori = prior[i];\r
786                 \r
787                 prior_ratio = PDIV32_16(SHL32(EXTEND32(priori), 15), ADD16(priori, SHL32(1,SNR_SHIFT)));\r
788                 theta = MULT16_32_P15(prior_ratio, QCONST32(1.f,EXPIN_SHIFT)+SHL32(EXTEND32(post[i]),EXPIN_SHIFT-SNR_SHIFT));\r
789 \r
790                 MM = hypergeom_gain(theta);\r
791                 gain[i] = EXTRACT16(MIN32(Q15_ONE, MULT16_32_Q15(prior_ratio, MM)));\r
792                 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]);\r
793 \r
794                 P1 = QCONST16(.199f,15)+MULT16_16_Q15(QCONST16(.8f,15),qcurve (zeta[i]));\r
795                 q = Q15_ONE-MULT16_16_Q15(Pframe,P1);\r
796 \r
797 #ifdef FIXED_POINT\r
798                 theta = MIN32(theta, EXTEND32(32767));\r
799                 tmp = MULT16_16_Q15((SHL32(1,SNR_SHIFT)+priori),EXTRACT16(MIN32(Q15ONE,SHR32(spx_exp(-EXTRACT16(theta)),1))));\r
800                 tmp = MIN16(QCONST16(3.,SNR_SHIFT), tmp);\r
801                 tmp = EXTRACT16(PSHR32(MULT16_16(PDIV32_16(SHL32(EXTEND32(q),8),(Q15_ONE-q)),tmp),8));\r
802                 gain2[i]=DIV32_16(SHL32(EXTEND32(32767),SNR_SHIFT), ADD16(256,tmp));\r
803 #else\r
804                 gain2[i]=1/(1.f + (q/(1.f-q))*(1+priori)*exp(-theta));\r
805 #endif\r
806         }\r
807 \r
808         filterbank_compute_psd16(st->bank,gain2+N, gain2);\r
809         filterbank_compute_psd16(st->bank,gain+N, gain);\r
810 }\r
811 \r
812 void preprocess_compute_linear_gain(\r
813         SpeexPreprocessState * restrict st,\r
814         spx_word32_t * restrict ps,     \r
815         int N\r
816 )\r
817 {\r
818         register spx_word16_t * restrict gain_floor = st->gain_floor;\r
819         register spx_word16_t * restrict prior = st->prior;\r
820         register spx_word16_t * restrict gain = st->gain;\r
821         register spx_word32_t * restrict old_ps = st->old_ps;\r
822         register spx_word16_t * restrict post = st->post;\r
823         register spx_word16_t * restrict gain2 = st->gain2;\r
824         register int i;\r
825 \r
826         filterbank_compute_psd16(st->bank,gain_floor+N,gain_floor);\r
827 \r
828 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
829 #pragma TCS_unroll=4\r
830 #pragma TCS_unrollexact=1\r
831 #endif   \r
832         for (i=0;i<N;i++)\r
833     {\r
834          register spx_word32_t MM;\r
835          register spx_word32_t theta;\r
836          register spx_word16_t prior_ratio;\r
837          register spx_word16_t tmp;\r
838          register spx_word16_t p;\r
839          register spx_word16_t g;\r
840                  register spx_word16_t gfi = gain_floor[i];\r
841 \r
842                  prior_ratio = PDIV32_16(SHL32(EXTEND32(st->prior[i]), 15), ADD16(prior[i], SHL32(1,SNR_SHIFT)));\r
843          theta = MULT16_32_P15(prior_ratio, QCONST32(1.f,EXPIN_SHIFT)+SHL32(EXTEND32(post[i]),EXPIN_SHIFT-SNR_SHIFT));\r
844                  MM = hypergeom_gain(theta);\r
845 \r
846                  g = EXTRACT16(MIN32(Q15_ONE, MULT16_32_Q15(prior_ratio, MM)));\r
847                  p = gain2[i];\r
848          \r
849                  g = VMUX( MULT16_16_Q15(QCONST16(.333f,15),g) > gain[i], MULT16_16(3,gain[i]), g);\r
850 \r
851          old_ps[i]= MULT16_32_P15(QCONST16(.2f,15),old_ps[i]) + \r
852                                         MULT16_32_P15(MULT16_16_P15(QCONST16(.8f,15),SQR16_Q15(g)),ps[i]);\r
853          \r
854                  g = VMUX( g < gfi, gfi, g );\r
855          gain[i] = g;\r
856 \r
857          tmp =  MULT16_16_P15(p,spx_sqrt(SHL32(EXTEND32(g),15))) + \r
858                                 MULT16_16_P15(SUB16(Q15_ONE,p),spx_sqrt(SHL32(EXTEND32(gfi),15)));\r
859 \r
860          gain2[i]=SQR16_Q15(tmp);\r
861 \r
862          /* Use this if you want a log-domain MMSE estimator instead */\r
863          /* gain2[i] = pow(g, p) * pow(gfi,1.f-p);*/\r
864     }\r
865 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
866 #pragma TCS_unrollexact=0\r
867 #pragma TCS_unroll=0\r
868 #endif\r
869 }\r
870 \r
871 \r
872 #if 0\r
873 void preprocess_compute_bark_gain(\r
874         SpeexPreprocessState * restrict st,\r
875         int N,\r
876         int NM\r
877 )\r
878 {\r
879         register spx_word16_t * restrict gain_floor = st->gain_floor;\r
880         register spx_word16_t * restrict gain = st->gain;\r
881         register spx_word16_t * restrict gain2 = st->gain2;\r
882         register int i;\r
883 \r
884     for (i=N;i<NM;i++)\r
885     {\r
886                 register spx_word16_t tmp;\r
887                 register spx_word16_t p = gain2[i];\r
888                 register spx_word16_t gaini;\r
889                 register spx_word16_t gfi = gain_floor[i];\r
890 \r
891                 gaini = MAX16(gain[i], gfi); \r
892 \r
893                 gain[i] = gaini;\r
894 \r
895                 tmp =   MULT16_16_P15(p,spx_sqrt(SHL32(EXTEND32(gaini),15))) + \r
896                         MULT16_16_P15(SUB16(Q15_ONE,p),spx_sqrt(SHL32(EXTEND32(gfi),15)));\r
897 \r
898                 gain2[i]=SQR16_Q15(tmp);\r
899     }\r
900 \r
901     filterbank_compute_psd16(st->bank,gain2+N, gain2);\r
902 }\r
903 #endif\r
904 \r
905 void preprocess_apply_gain(\r
906         SpeexPreprocessState * restrict st,\r
907         int N\r
908 )\r
909 {\r
910         register spx_word16_t * restrict ft = st->ft;\r
911         register spx_word16_t * restrict gain2 = st->gain2;\r
912         register int j, i;\r
913 \r
914         ft[0] = MULT16_16_P15(gain2[0],ft[0]);\r
915 \r
916         for (i=1,j=1; i<N ; i++,j+=2)\r
917         {\r
918                 register spx_word16_t gain2i = gain2[i];\r
919                 register spx_word16_t ftj = ft[j];\r
920                 register spx_word16_t ftjj = ft[j+1];\r
921 \r
922                 ft[j] = MULT16_16_P15(gain2i,ftj);\r
923                 ft[j+1] = MULT16_16_P15(gain2i,ftjj);\r
924         }\r
925 \r
926         ft[(N<<1)-1] = MULT16_16_P15(gain2[N-1],ft[(N<<1)-1]);\r
927 }\r
928 \r
929 #ifdef FIXED_POINT\r
930 void preprocess_scale(\r
931         SpeexPreprocessState * restrict st,\r
932         int N\r
933 )\r
934 {\r
935         register spx_word16_t * restrict frame = st->frame;\r
936         register int shift = st->frame_shift;\r
937         register int i;\r
938         register int N2 = N << 1;\r
939 \r
940 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
941 #pragma TCS_unroll=4\r
942 #pragma TCS_unrollexact=1\r
943 #endif    \r
944         for ( i=0 ; i<N2 ;i++)\r
945         {       register spx_word16_t framei = frame[i];\r
946                 \r
947                 frame[i] = PSHR16(framei,shift);\r
948         }\r
949 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
950 #pragma TCS_unrollexact=0\r
951 #pragma TCS_unroll=0\r
952 #endif\r
953 }\r
954 \r
955 #else\r
956 \r
957 void preprocess_apply_agc(\r
958         SpeexPreprocessState * restrict st,\r
959         int N                             \r
960 )\r
961 {                                 \r
962         register spx_word16_t max_sample=0;\r
963         register spx_word16_t * restrict frame = st->frame;\r
964         register int i;\r
965         register int N2 = N << 1;\r
966 \r
967 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
968 #pragma TCS_unroll=4\r
969 #pragma TCS_unrollexact=1\r
970 #endif    \r
971         for (i=0;i<N2;i++)\r
972         {       register spx_word16_t framei = VABS(frame[i]);\r
973 \r
974                 max_sample = VMUX( framei > max_sample, framei, max_sample);\r
975         }\r
976 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
977 #pragma TCS_unrollexact=0\r
978 #pragma TCS_unroll=0\r
979 #endif    \r
980 \r
981         if ( max_sample > 28000.f )\r
982         {\r
983                 float damp = 28000.f/max_sample;\r
984 \r
985 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
986 #pragma TCS_unroll=4\r
987 #pragma TCS_unrollexact=1\r
988 #endif  \r
989                 for ( i=0 ; i< N2 ; i++ )\r
990                 {       frame[i] *= damp;\r
991                 }\r
992 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
993 #pragma TCS_unrollexact=0\r
994 #pragma TCS_unroll=0\r
995 #endif  \r
996         }\r
997 }\r
998 #endif\r
999 \r
1000 \r
1001 void preprocess_update(\r
1002         SpeexPreprocessState * restrict st,\r
1003         spx_int16_t * restrict x,\r
1004         int N   \r
1005 )\r
1006 {\r
1007         register spx_word16_t * restrict frame = st->frame;\r
1008         register spx_word16_t * restrict window = st->window;\r
1009         register spx_word16_t * restrict outbuf = st->outbuf;\r
1010         register int framesize = st->frame_size;\r
1011         register int N2 = N << 1;\r
1012         register int N3 = N2 - framesize;\r
1013         register int N4 = (framesize) - N3;\r
1014         register int i;\r
1015 \r
1016 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
1017 #pragma TCS_unroll=4\r
1018 #pragma TCS_unrollexact=1\r
1019 #endif  \r
1020         for ( i=0 ; i<N2 ; i++)\r
1021         {       register spx_word16_t fi = frame[i];\r
1022                 register spx_word16_t wi = window[i];\r
1023 \r
1024                 frame[i] = MULT16_16_Q15(fi, wi);\r
1025         }\r
1026         for (i=0;i<N3;i++)\r
1027         {       x[i] = outbuf[i] + frame[i];\r
1028         }\r
1029 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
1030 #pragma TCS_unrollexact=0\r
1031 #pragma TCS_unroll=0\r
1032 #endif \r
1033 \r
1034         for ( i=0;i<N4;i++)\r
1035         {       x[N3+i] = frame[N3+i];\r
1036         }\r
1037         \r
1038         memcpy(outbuf, frame+framesize, (N3) * sizeof(spx_word16_t));\r
1039 }\r
1040 \r
1041 #define OVERRIDE_SPEEX_PREPROCESS_RUN\r
1042 int speex_preprocess_run(SpeexPreprocessState * restrict st, spx_int16_t * restrict x)\r
1043 {\r
1044         register int i, N, M, NM;\r
1045         register spx_word32_t * restrict ps=st->ps;\r
1046         register spx_word32_t Zframe;\r
1047         register spx_word16_t Pframe;\r
1048 \r
1049         st->nb_adapt++;\r
1050         st->min_count++;\r
1051         N = st->ps_size;\r
1052         M = st->nbands;\r
1053         NM = N + M;\r
1054 \r
1055         preprocess_residue_echo(st, N, NM);\r
1056         preprocess_analysis(st, x);\r
1057         update_noise_prob(st);\r
1058         preprocess_update_noise(st, ps, N);\r
1059 \r
1060         if ( st->nb_adapt == 1 )\r
1061         {       memcpy(st->old_ps, ps, (NM) * sizeof(spx_word32_t));\r
1062         }\r
1063 \r
1064         preprocess_compute_SNR(st, ps, NM);\r
1065         Zframe = preprocess_smooth_SNR(st, N, NM);\r
1066         \r
1067 \r
1068         {\r
1069         register spx_word16_t effective_echo_suppress;\r
1070         \r
1071         Pframe = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.899f,15),qcurve(DIV32_16(Zframe,M)));\r
1072         effective_echo_suppress =       EXTRACT16(PSHR32(ADD32(MULT16_16(SUB16(Q15_ONE,Pframe), st->echo_suppress), \r
1073                                                                 MULT16_16(Pframe, st->echo_suppress_active)),15));\r
1074         compute_gain_floor(st->noise_suppress, effective_echo_suppress, st->noise+N, st->echo_noise+N, st->gain_floor+N, M);\r
1075     \r
1076         }\r
1077 \r
1078         preprocess_compute_emgain(st, ps, Pframe, NM);\r
1079         preprocess_compute_linear_gain(st, ps, N);\r
1080 \r
1081    \r
1082         if (!st->denoise_enabled)\r
1083         {\r
1084            register spx_word16_t * restrict gain2 = st->gain2;\r
1085 \r
1086 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
1087 #pragma TCS_unroll=4\r
1088 #pragma TCS_unrollexact=1\r
1089 #endif  \r
1090                 for ( i=0 ; i<NM ; i++ )\r
1091                 {   gain2[i] = Q15_ONE;\r
1092                 }\r
1093 #if (TM_UNROLL && TM_UNROLL_SPEEXPREPROCESSRUN)\r
1094 #pragma TCS_unrollexact=0\r
1095 #pragma TCS_unroll=0\r
1096 #endif\r
1097         }\r
1098      \r
1099         preprocess_apply_gain(st, N);\r
1100 \r
1101 #ifndef FIXED_POINT\r
1102         if (st->agc_enabled)\r
1103         {       speex_compute_agc(st, Pframe, st->ft);\r
1104         }\r
1105 #endif\r
1106 \r
1107 \r
1108    spx_ifft(st->fft_lookup, st->ft, st->frame);\r
1109 \r
1110 #ifdef FIXED_POINT\r
1111         preprocess_scale(st, N);\r
1112 #endif\r
1113 \r
1114 #ifndef FIXED_POINT\r
1115         if ( st->agc_enabled )\r
1116         {       preprocess_apply_agc(st, N);\r
1117         }\r
1118 #endif\r
1119 \r
1120         preprocess_update(st, x, N);\r
1121 \r
1122         if ( st->vad_enabled )\r
1123         {\r
1124                 if (Pframe > st->speech_prob_start || (st->was_speech && Pframe > st->speech_prob_continue))\r
1125                 {       st->was_speech=1;\r
1126                         return 1;\r
1127           \r
1128                 } else\r
1129                 {       st->was_speech=0;\r
1130                         return 0;\r
1131                 }\r
1132         } else \r
1133         {       return 1;\r
1134         }\r
1135 }\r