Git init
[external/opencore-amr.git] / opencore / codecs_v2 / audio / gsm_amr / amr_nb / dec / src / pstfilt.cpp
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 /****************************************************************************************
19 Portions of this file are derived from the following 3GPP standard:
20
21     3GPP TS 26.073
22     ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
23     Available from http://www.3gpp.org
24
25 (C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
26 Permission to distribute, modify and use this file under the standard license
27 terms listed above has been obtained from the copyright holder.
28 ****************************************************************************************/
29 /*
30 ------------------------------------------------------------------------------
31
32
33
34  Filename: pstfilt.cpp
35  Functions:
36             Post_Filter_reset
37             Post_Filter
38
39 ------------------------------------------------------------------------------
40  MODULE DESCRIPTION
41
42  This file contains the function that performs adaptive post-filtering on the
43  synthesized speech. It also contains the functions that initialize, reset,
44  and exit the post-filtering function.
45
46 ------------------------------------------------------------------------------
47 */
48
49 /*----------------------------------------------------------------------------
50 ; INCLUDES
51 ----------------------------------------------------------------------------*/
52 #include "pstfilt.h"
53 #include "typedef.h"
54 #include "mode.h"
55 #include "basicop_malloc.h"
56 #include "basic_op.h"
57 #include "weight_a.h"
58 #include "residu.h"
59 #include "syn_filt.h"
60 #include "preemph.h"
61 #include "cnst.h"
62 #include "oscl_mem.h"
63
64 /*----------------------------------------------------------------------------
65 ; MACROS
66 ; Define module specific macros here
67 ----------------------------------------------------------------------------*/
68
69 /*----------------------------------------------------------------------------
70 ; DEFINES
71 ; Include all pre-processor statements here. Include conditional
72 ; compile variables also.
73 ----------------------------------------------------------------------------*/
74 #define L_H 22  /* size of truncated impulse response of A(z/g1)/A(z/g2) */
75
76 /*----------------------------------------------------------------------------
77 ; LOCAL FUNCTION DEFINITIONS
78 ; Function Prototype declaration
79 ----------------------------------------------------------------------------*/
80
81 /*----------------------------------------------------------------------------
82 ; LOCAL VARIABLE DEFINITIONS
83 ; Variable declaration - defined here and used outside this module
84 ----------------------------------------------------------------------------*/
85
86 /* Spectral expansion factors */
87 static const Word16 gamma3_MR122[M] =
88 {
89     22938, 16057, 11240, 7868, 5508,
90     3856, 2699, 1889, 1322, 925
91 };
92
93 static const Word16 gamma3[M] =
94 {
95     18022, 9912, 5451, 2998, 1649, 907, 499, 274, 151, 83
96 };
97
98 static const Word16 gamma4_MR122[M] =
99 {
100     24576, 18432, 13824, 10368, 7776,
101     5832, 4374, 3281, 2461, 1846
102 };
103
104 static const Word16 gamma4[M] =
105 {
106     22938, 16057, 11240, 7868, 5508, 3856, 2699, 1889, 1322, 925
107 };
108
109 /*----------------------------------------------------------------------------
110 ; EXTERNAL FUNCTION REFERENCES
111 ; Declare functions defined elsewhere and referenced in this module
112 ----------------------------------------------------------------------------*/
113
114 /*----------------------------------------------------------------------------
115 ; EXTERNAL VARIABLES REFERENCES
116 ; Declare variables used in this module but defined elsewhere
117 ----------------------------------------------------------------------------*/
118
119 /*
120 ------------------------------------------------------------------------------
121  FUNCTION NAME: Post_Filter_reset
122 ------------------------------------------------------------------------------
123  INPUT AND OUTPUT DEFINITIONS
124
125  Inputs:
126     state = pointer to structure of type Post_FilterState
127
128  Outputs:
129     fields of the structure pointed to by state is initialized to zero
130
131  Returns:
132     return_value = 0, if reset was successful; -1, otherwise (int)
133
134  Global Variables Used:
135     None
136
137  Local Variables Needed:
138     None
139
140 ------------------------------------------------------------------------------
141  FUNCTION DESCRIPTION
142
143  This function initializes the state memory used by the Post_Filter function
144  to zero.
145
146 ------------------------------------------------------------------------------
147  REQUIREMENTS
148
149  None
150
151 ------------------------------------------------------------------------------
152  REFERENCES
153
154  pstfilt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
155
156 ------------------------------------------------------------------------------
157  PSEUDO-CODE
158
159 int Post_Filter_reset (Post_FilterState *state)
160 {
161   if (state == (Post_FilterState *) NULL){
162       fprintf(stderr, "Post_Filter_reset: invalid parameter\n");
163       return -1;
164   }
165
166   Set_zero (state->mem_syn_pst, M);
167   Set_zero (state->res2, L_SUBFR);
168   Set_zero (state->synth_buf, L_FRAME + M);
169   agc_reset(state->agc_state);
170   preemphasis_reset(state->preemph_state);
171
172   return 0;
173 }
174
175 ------------------------------------------------------------------------------
176  CAUTION [optional]
177  [State any special notes, constraints or cautions for users of this function]
178
179 ------------------------------------------------------------------------------
180 */
181
182 Word16 Post_Filter_reset(Post_FilterState *state)
183 {
184     if (state == (Post_FilterState *) NULL)
185     {
186         /*fprintf(stderr, "Post_Filter_reset: invalid parameter\n");  */
187         return(-1);
188     }
189
190     oscl_memset(state->mem_syn_pst, 0, sizeof(Word16)*M);
191     oscl_memset(state->res2, 0, sizeof(Word16)*L_SUBFR);
192     oscl_memset(state->synth_buf, 0, sizeof(Word16)*(L_FRAME + M));
193     agc_reset(&(state->agc_state));
194     preemphasis_reset(&(state->preemph_state));
195
196     return(0);
197 }
198
199 /****************************************************************************/
200
201 /*
202 ------------------------------------------------------------------------------
203  FUNCTION NAME: Post_Filter
204 ------------------------------------------------------------------------------
205  INPUT AND OUTPUT DEFINITIONS
206
207  Inputs:
208     st = pointer to a structure of type Post_FilterState
209     mode = AMR mode
210     syn = pointer to a buffer containing synthesized speech; upon
211           exiting this function, it will contain the post-filtered
212           synthesized speech
213     Az_4 = pointer to the interpolated LPC parameters for all subframes
214     pOverflow = pointer to overflow indicator of type Flag
215
216  Outputs:
217     fields of the structure pointed to by st contains the updated field
218       values
219     syn buffer contains the post-filtered synthesized speech
220     pOverflow = 1 if overflow occurrs in the math functions called else
221                 it is zero.
222
223  Returns:
224     return_value = 0 (int)
225
226  Global Variables Used:
227     None
228
229  Local Variables Needed:
230     None
231
232 ------------------------------------------------------------------------------
233  FUNCTION DESCRIPTION
234
235  This function performs the post-filtering on the synthesized speech. The
236  post-filtering process is described as follows:
237  (1) inverse filtering of syn[] through A(z/0.7) to get res2[]
238  (2) tilt compensation filtering; 1 - MU*k*z^-1
239  (3) synthesis filtering through 1/A(z/0.75)
240  (4) adaptive gain control
241
242 ------------------------------------------------------------------------------
243  REQUIREMENTS
244
245  None
246
247 ------------------------------------------------------------------------------
248  REFERENCES
249
250  pstfilt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
251
252 ------------------------------------------------------------------------------
253  PSEUDO-CODE
254
255 int Post_Filter (
256     Post_FilterState *st, // i/o : post filter states
257     enum Mode mode,       // i   : AMR mode
258     Word16 *syn,          // i/o : synthesis speech (postfiltered is output)
259     Word16 *Az_4          // i   : interpolated LPC parameters in all subfr.
260 )
261 {
262      *-------------------------------------------------------------------*
263      *           Declaration of parameters                               *
264      *-------------------------------------------------------------------*
265
266     Word16 Ap3[MP1], Ap4[MP1];  // bandwidth expanded LP parameters
267     Word16 *Az;                 // pointer to Az_4:
268                                 //  LPC parameters in each subframe
269     Word16 i_subfr;             // index for beginning of subframe
270     Word16 h[L_H];
271
272     Word16 i;
273     Word16 temp1, temp2;
274     Word32 L_tmp;
275     Word16 *syn_work = &st->synth_buf[M];
276
277
278      *-----------------------------------------------------*
279      * Post filtering                                      *
280      *-----------------------------------------------------*
281
282     Copy (syn, syn_work , L_FRAME);
283
284     Az = Az_4;
285
286     for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
287     {
288        // Find weighted filter coefficients Ap3[] and ap[4]
289
290        if (sub(mode, MR122) == 0 || sub(mode, MR102) == 0)
291        {
292           Weight_Ai (Az, gamma3_MR122, Ap3);
293           Weight_Ai (Az, gamma4_MR122, Ap4);
294        }
295        else
296        {
297           Weight_Ai (Az, gamma3, Ap3);
298           Weight_Ai (Az, gamma4, Ap4);
299        }
300
301        // filtering of synthesis speech by A(z/0.7) to find res2[]
302
303        Residu (Ap3, &syn_work[i_subfr], st->res2, L_SUBFR);
304
305        // tilt compensation filter
306
307        // impulse response of A(z/0.7)/A(z/0.75)
308
309        Copy (Ap3, h, M + 1);
310        Set_zero (&h[M + 1], L_H - M - 1);
311        Syn_filt (Ap4, h, h, L_H, &h[M + 1], 0);
312
313        // 1st correlation of h[]
314
315        L_tmp = L_mult (h[0], h[0]);
316        for (i = 1; i < L_H; i++)
317        {
318           L_tmp = L_mac (L_tmp, h[i], h[i]);
319        }
320        temp1 = extract_h (L_tmp);
321
322        L_tmp = L_mult (h[0], h[1]);
323        for (i = 1; i < L_H - 1; i++)
324        {
325           L_tmp = L_mac (L_tmp, h[i], h[i + 1]);
326        }
327        temp2 = extract_h (L_tmp);
328
329        if (temp2 <= 0)
330        {
331           temp2 = 0;
332        }
333        else
334        {
335           temp2 = mult (temp2, MU);
336           temp2 = div_s (temp2, temp1);
337        }
338
339        preemphasis (st->preemph_state, st->res2, temp2, L_SUBFR);
340
341        // filtering through  1/A(z/0.75)
342
343        Syn_filt (Ap4, st->res2, &syn[i_subfr], L_SUBFR, st->mem_syn_pst, 1);
344
345        // scale output to input
346
347        agc (st->agc_state, &syn_work[i_subfr], &syn[i_subfr],
348             AGC_FAC, L_SUBFR);
349
350        Az += MP1;
351     }
352
353     // update syn_work[] buffer
354
355     Copy (&syn_work[L_FRAME - M], &syn_work[-M], M);
356
357     return 0;
358 }
359
360 ------------------------------------------------------------------------------
361  CAUTION [optional]
362  [State any special notes, constraints or cautions for users of this function]
363
364 ------------------------------------------------------------------------------
365 */
366
367 void Post_Filter(
368     Post_FilterState *st, /* i/o : post filter states                        */
369     enum Mode mode,       /* i   : AMR mode                                  */
370     Word16 *syn,          /* i/o : synthesis speech (postfiltered is output) */
371     Word16 *Az_4,         /* i   : interpolated LPC parameters in all subfr. */
372     Flag   *pOverflow
373 )
374 {
375     Word16 Ap3[MP1];
376     Word16 Ap4[MP1];            /* bandwidth expanded LP parameters */
377     Word16 *Az;                 /* pointer to Az_4:                 */
378     /*  LPC parameters in each subframe */
379     register Word16 i_subfr;    /* index for beginning of subframe  */
380     Word16 h[L_H];
381
382     register Word16 i;
383     Word16 temp1;
384     Word16 temp2;
385     Word32 L_tmp;
386     Word32 L_tmp2;
387     Word16 *syn_work = &st->synth_buf[M];
388
389
390     /*-----------------------------------------------------*
391      * Post filtering                                      *
392      *-----------------------------------------------------*/
393
394     oscl_memmove((void *)syn_work , syn, L_FRAME*sizeof(*syn));
395
396     Az = Az_4;
397
398     for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
399     {
400         /* Find weighted filter coefficients Ap3[] and ap[4] */
401
402         if (mode == MR122 || mode == MR102)
403         {
404             Weight_Ai(Az, gamma3_MR122, Ap3);
405             Weight_Ai(Az, gamma4_MR122, Ap4);
406         }
407         else
408         {
409             Weight_Ai(Az, gamma3, Ap3);
410             Weight_Ai(Az, gamma4, Ap4);
411         }
412
413         /* filtering of synthesis speech by A(z/0.7) to find res2[] */
414
415         Residu(Ap3, &syn_work[i_subfr], st->res2, L_SUBFR);
416
417         /* tilt compensation filter */
418
419         /* impulse response of A(z/0.7)/A(z/0.75) */
420
421         oscl_memmove((void *)h, Ap3, (M + 1)*sizeof(*Ap3));
422         oscl_memset(&h[M + 1], 0, sizeof(Word16)*(L_H - M - 1));
423         Syn_filt(Ap4, h, h, L_H, &h[M + 1], 0);
424
425         /* 1st correlation of h[] */
426
427         L_tmp = 0;
428
429         for (i = L_H - 1; i >= 0; i--)
430         {
431             L_tmp2 = ((Word32) h[i]) * h[i];
432
433             if (L_tmp2 != (Word32) 0x40000000L)
434             {
435                 L_tmp2 = L_tmp2 << 1;
436             }
437             else
438             {
439                 *pOverflow = 1;
440                 L_tmp2 = MAX_32;
441                 break;
442             }
443
444             L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
445         }
446         temp1 = (Word16)(L_tmp >> 16);
447
448         L_tmp = 0;
449
450         for (i = L_H - 2; i >= 0; i--)
451         {
452             L_tmp2 = ((Word32) h[i]) * h[i + 1];
453
454             if (L_tmp2 != (Word32) 0x40000000L)
455             {
456                 L_tmp2 = L_tmp2 << 1;
457             }
458             else
459             {
460                 *pOverflow = 1;
461                 L_tmp2 = MAX_32;
462                 break;
463             }
464
465             L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
466         }
467         temp2 = (Word16)(L_tmp >> 16);
468
469         if (temp2 <= 0)
470         {
471             temp2 = 0;
472         }
473         else
474         {
475             L_tmp = (((Word32) temp2) * MU) >> 15;
476
477             /* Sign-extend product */
478             if (L_tmp & (Word32) 0x00010000L)
479             {
480                 L_tmp = L_tmp | (Word32) 0xffff0000L;
481             }
482             temp2 = (Word16) L_tmp;
483
484             temp2 = div_s(temp2, temp1);
485         }
486
487         preemphasis(&(st->preemph_state), st->res2, temp2, L_SUBFR, pOverflow);
488
489         /* filtering through  1/A(z/0.75) */
490
491         Syn_filt(Ap4, st->res2, &syn[i_subfr], L_SUBFR, st->mem_syn_pst, 1);
492
493         /* scale output to input */
494
495         agc(&(st->agc_state), &syn_work[i_subfr], &syn[i_subfr],
496             AGC_FAC, L_SUBFR, pOverflow);
497
498         Az += MP1;
499     }
500
501     /* update syn_work[] buffer */
502
503     oscl_memmove((void *)&syn_work[-M], &syn_work[L_FRAME - M], M*sizeof(*syn_work));
504
505     return;
506 }