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  Pathname: ./audio/gsm-amr/c/src/pstfilt.c
35  Functions:
36             Post_Filter_reset
37             Post_Filter
38 
39      Date: 04/14/2000
40 
41 ------------------------------------------------------------------------------
42  REVISION HISTORY
43 
44  Description: Changed template used to PV coding template. First attempt at
45           optimizing C code.
46 
47  Description: Updated file per comments gathered from Phase 2/3 review.
48 
49  Description: Added setting of Overflow flag in inlined code.
50 
51  Description: Synchronized file with UMTS version 3.2.0. Updated coding
52               template. Removed unnecessary include files.
53 
54  Description: Replaced basic_op.h with the header file of the math functions
55               used in the file.
56 
57  Description: Made the following changes per comments from Phase 2/3 review:
58               1. Updated copyright year.
59               2. Modified FOR loops to count down.
60               3. Fixed typecasting issue with TI C compiler.
61               4. Added "break" statement after overflow condition occurs.
62 
63  Description: Removed the functions pstfilt_init and pstfilt_exit.
64  The pst_filt related structure is no longer dynamically allocated.
65 
66  Description: Modified code for EPOC changes where pOverflow is passed in
67               rather than allowing overflow to be a global variable.
68 
69  Description:  Replaced OSCL mem type functions and eliminated include
70                files that now are chosen by OSCL definitions
71 
72  Description:  Replaced "int" and/or "char" with defined types.
73                Added proper casting (Word32) to some left shifting operations
74 
75  Description:
76 
77 ------------------------------------------------------------------------------
78  MODULE DESCRIPTION
79 
80  This file contains the function that performs adaptive post-filtering on the
81  synthesized speech. It also contains the functions that initialize, reset,
82  and exit the post-filtering function.
83 
84 ------------------------------------------------------------------------------
85 */
86 
87 /*----------------------------------------------------------------------------
88 ; INCLUDES
89 ----------------------------------------------------------------------------*/
90 #include <string.h>
91 
92 #include "pstfilt.h"
93 #include "typedef.h"
94 #include "mode.h"
95 #include "basicop_malloc.h"
96 #include "basic_op.h"
97 #include "weight_a.h"
98 #include "residu.h"
99 #include "copy.h"
100 #include "syn_filt.h"
101 #include "preemph.h"
102 #include "cnst.h"
103 
104 /*----------------------------------------------------------------------------
105 ; MACROS
106 ; Define module specific macros here
107 ----------------------------------------------------------------------------*/
108 
109 /*----------------------------------------------------------------------------
110 ; DEFINES
111 ; Include all pre-processor statements here. Include conditional
112 ; compile variables also.
113 ----------------------------------------------------------------------------*/
114 #define L_H 22  /* size of truncated impulse response of A(z/g1)/A(z/g2) */
115 
116 /*----------------------------------------------------------------------------
117 ; LOCAL FUNCTION DEFINITIONS
118 ; Function Prototype declaration
119 ----------------------------------------------------------------------------*/
120 
121 /*----------------------------------------------------------------------------
122 ; LOCAL VARIABLE DEFINITIONS
123 ; Variable declaration - defined here and used outside this module
124 ----------------------------------------------------------------------------*/
125 
126 /* Spectral expansion factors */
127 static const Word16 gamma3_MR122[M] =
128 {
129     22938, 16057, 11240, 7868, 5508,
130     3856, 2699, 1889, 1322, 925
131 };
132 
133 static const Word16 gamma3[M] =
134 {
135     18022, 9912, 5451, 2998, 1649, 907, 499, 274, 151, 83
136 };
137 
138 static const Word16 gamma4_MR122[M] =
139 {
140     24576, 18432, 13824, 10368, 7776,
141     5832, 4374, 3281, 2461, 1846
142 };
143 
144 static const Word16 gamma4[M] =
145 {
146     22938, 16057, 11240, 7868, 5508, 3856, 2699, 1889, 1322, 925
147 };
148 
149 /*----------------------------------------------------------------------------
150 ; EXTERNAL FUNCTION REFERENCES
151 ; Declare functions defined elsewhere and referenced in this module
152 ----------------------------------------------------------------------------*/
153 
154 /*----------------------------------------------------------------------------
155 ; EXTERNAL VARIABLES REFERENCES
156 ; Declare variables used in this module but defined elsewhere
157 ----------------------------------------------------------------------------*/
158 
159 /*
160 ------------------------------------------------------------------------------
161  FUNCTION NAME: Post_Filter_reset
162 ------------------------------------------------------------------------------
163  INPUT AND OUTPUT DEFINITIONS
164 
165  Inputs:
166     state = pointer to structure of type Post_FilterState
167 
168  Outputs:
169     fields of the structure pointed to by state is initialized to zero
170 
171  Returns:
172     return_value = 0, if reset was successful; -1, otherwise (int)
173 
174  Global Variables Used:
175     None
176 
177  Local Variables Needed:
178     None
179 
180 ------------------------------------------------------------------------------
181  FUNCTION DESCRIPTION
182 
183  This function initializes the state memory used by the Post_Filter function
184  to zero.
185 
186 ------------------------------------------------------------------------------
187  REQUIREMENTS
188 
189  None
190 
191 ------------------------------------------------------------------------------
192  REFERENCES
193 
194  pstfilt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
195 
196 ------------------------------------------------------------------------------
197  PSEUDO-CODE
198 
199 int Post_Filter_reset (Post_FilterState *state)
200 {
201   if (state == (Post_FilterState *) NULL){
202       fprintf(stderr, "Post_Filter_reset: invalid parameter\n");
203       return -1;
204   }
205 
206   Set_zero (state->mem_syn_pst, M);
207   Set_zero (state->res2, L_SUBFR);
208   Set_zero (state->synth_buf, L_FRAME + M);
209   agc_reset(state->agc_state);
210   preemphasis_reset(state->preemph_state);
211 
212   return 0;
213 }
214 
215 ------------------------------------------------------------------------------
216  RESOURCES USED [optional]
217 
218  When the code is written for a specific target processor the
219  the resources used should be documented below.
220 
221  HEAP MEMORY USED: x bytes
222 
223  STACK MEMORY USED: x bytes
224 
225  CLOCK CYCLES: (cycle count equation for this function) + (variable
226                 used to represent cycle count for each subroutine
227                 called)
228      where: (cycle count variable) = cycle count for [subroutine
229                                      name]
230 
231 ------------------------------------------------------------------------------
232  CAUTION [optional]
233  [State any special notes, constraints or cautions for users of this function]
234 
235 ------------------------------------------------------------------------------
236 */
237 
Post_Filter_reset(Post_FilterState * state)238 Word16 Post_Filter_reset(Post_FilterState *state)
239 {
240     if (state == (Post_FilterState *) NULL)
241     {
242         /*fprintf(stderr, "Post_Filter_reset: invalid parameter\n");  */
243         return(-1);
244     }
245 
246     memset(state->mem_syn_pst, 0, sizeof(Word16)*M);
247     memset(state->res2, 0, sizeof(Word16)*L_SUBFR);
248     memset(state->synth_buf, 0, sizeof(Word16)*(L_FRAME + M));
249     agc_reset(&(state->agc_state));
250     preemphasis_reset(&(state->preemph_state));
251 
252     return(0);
253 }
254 
255 /****************************************************************************/
256 
257 /*
258 ------------------------------------------------------------------------------
259  FUNCTION NAME: Post_Filter
260 ------------------------------------------------------------------------------
261  INPUT AND OUTPUT DEFINITIONS
262 
263  Inputs:
264     st = pointer to a structure of type Post_FilterState
265     mode = AMR mode
266     syn = pointer to a buffer containing synthesized speech; upon
267           exiting this function, it will contain the post-filtered
268           synthesized speech
269     Az_4 = pointer to the interpolated LPC parameters for all subframes
270     pOverflow = pointer to overflow indicator of type Flag
271 
272  Outputs:
273     fields of the structure pointed to by st contains the updated field
274       values
275     syn buffer contains the post-filtered synthesized speech
276     pOverflow = 1 if overflow occurrs in the math functions called else
277                 it is zero.
278 
279  Returns:
280     return_value = 0 (int)
281 
282  Global Variables Used:
283     None
284 
285  Local Variables Needed:
286     None
287 
288 ------------------------------------------------------------------------------
289  FUNCTION DESCRIPTION
290 
291  This function performs the post-filtering on the synthesized speech. The
292  post-filtering process is described as follows:
293  (1) inverse filtering of syn[] through A(z/0.7) to get res2[]
294  (2) tilt compensation filtering; 1 - MU*k*z^-1
295  (3) synthesis filtering through 1/A(z/0.75)
296  (4) adaptive gain control
297 
298 ------------------------------------------------------------------------------
299  REQUIREMENTS
300 
301  None
302 
303 ------------------------------------------------------------------------------
304  REFERENCES
305 
306  pstfilt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
307 
308 ------------------------------------------------------------------------------
309  PSEUDO-CODE
310 
311 int Post_Filter (
312     Post_FilterState *st, // i/o : post filter states
313     enum Mode mode,       // i   : AMR mode
314     Word16 *syn,          // i/o : synthesis speech (postfiltered is output)
315     Word16 *Az_4          // i   : interpolated LPC parameters in all subfr.
316 )
317 {
318      *-------------------------------------------------------------------*
319      *           Declaration of parameters                               *
320      *-------------------------------------------------------------------*
321 
322     Word16 Ap3[MP1], Ap4[MP1];  // bandwidth expanded LP parameters
323     Word16 *Az;                 // pointer to Az_4:
324                                 //  LPC parameters in each subframe
325     Word16 i_subfr;             // index for beginning of subframe
326     Word16 h[L_H];
327 
328     Word16 i;
329     Word16 temp1, temp2;
330     Word32 L_tmp;
331     Word16 *syn_work = &st->synth_buf[M];
332 
333 
334      *-----------------------------------------------------*
335      * Post filtering                                      *
336      *-----------------------------------------------------*
337 
338     Copy (syn, syn_work , L_FRAME);
339 
340     Az = Az_4;
341 
342     for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
343     {
344        // Find weighted filter coefficients Ap3[] and ap[4]
345 
346        if (sub(mode, MR122) == 0 || sub(mode, MR102) == 0)
347        {
348           Weight_Ai (Az, gamma3_MR122, Ap3);
349           Weight_Ai (Az, gamma4_MR122, Ap4);
350        }
351        else
352        {
353           Weight_Ai (Az, gamma3, Ap3);
354           Weight_Ai (Az, gamma4, Ap4);
355        }
356 
357        // filtering of synthesis speech by A(z/0.7) to find res2[]
358 
359        Residu (Ap3, &syn_work[i_subfr], st->res2, L_SUBFR);
360 
361        // tilt compensation filter
362 
363        // impulse response of A(z/0.7)/A(z/0.75)
364 
365        Copy (Ap3, h, M + 1);
366        Set_zero (&h[M + 1], L_H - M - 1);
367        Syn_filt (Ap4, h, h, L_H, &h[M + 1], 0);
368 
369        // 1st correlation of h[]
370 
371        L_tmp = L_mult (h[0], h[0]);
372        for (i = 1; i < L_H; i++)
373        {
374           L_tmp = L_mac (L_tmp, h[i], h[i]);
375        }
376        temp1 = extract_h (L_tmp);
377 
378        L_tmp = L_mult (h[0], h[1]);
379        for (i = 1; i < L_H - 1; i++)
380        {
381           L_tmp = L_mac (L_tmp, h[i], h[i + 1]);
382        }
383        temp2 = extract_h (L_tmp);
384 
385        if (temp2 <= 0)
386        {
387           temp2 = 0;
388        }
389        else
390        {
391           temp2 = mult (temp2, MU);
392           temp2 = div_s (temp2, temp1);
393        }
394 
395        preemphasis (st->preemph_state, st->res2, temp2, L_SUBFR);
396 
397        // filtering through  1/A(z/0.75)
398 
399        Syn_filt (Ap4, st->res2, &syn[i_subfr], L_SUBFR, st->mem_syn_pst, 1);
400 
401        // scale output to input
402 
403        agc (st->agc_state, &syn_work[i_subfr], &syn[i_subfr],
404             AGC_FAC, L_SUBFR);
405 
406        Az += MP1;
407     }
408 
409     // update syn_work[] buffer
410 
411     Copy (&syn_work[L_FRAME - M], &syn_work[-M], M);
412 
413     return 0;
414 }
415 
416 ------------------------------------------------------------------------------
417  RESOURCES USED [optional]
418 
419  When the code is written for a specific target processor the
420  the resources used should be documented below.
421 
422  HEAP MEMORY USED: x bytes
423 
424  STACK MEMORY USED: x bytes
425 
426  CLOCK CYCLES: (cycle count equation for this function) + (variable
427                 used to represent cycle count for each subroutine
428                 called)
429      where: (cycle count variable) = cycle count for [subroutine
430                                      name]
431 
432 ------------------------------------------------------------------------------
433  CAUTION [optional]
434  [State any special notes, constraints or cautions for users of this function]
435 
436 ------------------------------------------------------------------------------
437 */
438 
Post_Filter(Post_FilterState * st,enum Mode mode,Word16 * syn,Word16 * Az_4,Flag * pOverflow)439 void Post_Filter(
440     Post_FilterState *st, /* i/o : post filter states                        */
441     enum Mode mode,       /* i   : AMR mode                                  */
442     Word16 *syn,          /* i/o : synthesis speech (postfiltered is output) */
443     Word16 *Az_4,         /* i   : interpolated LPC parameters in all subfr. */
444     Flag   *pOverflow
445 )
446 {
447     Word16 Ap3[MP1];
448     Word16 Ap4[MP1];      /* bandwidth expanded LP parameters */
449     Word16 *Az;           /* pointer to Az_4:                 */
450     /*  LPC parameters in each subframe */
451     Word16 i_subfr;       /* index for beginning of subframe  */
452     Word16 h[L_H];
453 
454     Word16 i;
455     Word16 temp1;
456     Word16 temp2;
457     Word32 L_tmp;
458     Word32 L_tmp2;
459     Word16 *syn_work = &st->synth_buf[M];
460 
461 
462     /*-----------------------------------------------------*
463      * Post filtering                                      *
464      *-----------------------------------------------------*/
465 
466     Copy(syn, syn_work , L_FRAME);
467 
468     Az = Az_4;
469 
470     for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
471     {
472         /* Find weighted filter coefficients Ap3[] and ap[4] */
473 
474         if (mode == MR122 || mode == MR102)
475         {
476             Weight_Ai(Az, gamma3_MR122, Ap3);
477             Weight_Ai(Az, gamma4_MR122, Ap4);
478         }
479         else
480         {
481             Weight_Ai(Az, gamma3, Ap3);
482             Weight_Ai(Az, gamma4, Ap4);
483         }
484 
485         /* filtering of synthesis speech by A(z/0.7) to find res2[] */
486 
487         Residu(Ap3, &syn_work[i_subfr], st->res2, L_SUBFR);
488 
489         /* tilt compensation filter */
490 
491         /* impulse response of A(z/0.7)/A(z/0.75) */
492 
493         Copy(Ap3, h, M + 1);
494         memset(&h[M + 1], 0, sizeof(Word16)*(L_H - M - 1));
495         Syn_filt(Ap4, h, h, L_H, &h[M + 1], 0);
496 
497         /* 1st correlation of h[] */
498 
499         L_tmp = 0;
500 
501         for (i = L_H - 1; i >= 0; i--)
502         {
503             L_tmp2 = ((Word32) h[i]) * h[i];
504 
505             if (L_tmp2 != (Word32) 0x40000000L)
506             {
507                 L_tmp2 = L_tmp2 << 1;
508             }
509             else
510             {
511                 *pOverflow = 1;
512                 L_tmp2 = MAX_32;
513                 break;
514             }
515 
516             L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
517         }
518         temp1 = (Word16)(L_tmp >> 16);
519 
520         L_tmp = 0;
521 
522         for (i = L_H - 2; i >= 0; i--)
523         {
524             L_tmp2 = ((Word32) h[i]) * h[i + 1];
525 
526             if (L_tmp2 != (Word32) 0x40000000L)
527             {
528                 L_tmp2 = L_tmp2 << 1;
529             }
530             else
531             {
532                 *pOverflow = 1;
533                 L_tmp2 = MAX_32;
534                 break;
535             }
536 
537             L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
538         }
539         temp2 = (Word16)(L_tmp >> 16);
540 
541         if (temp2 <= 0)
542         {
543             temp2 = 0;
544         }
545         else
546         {
547             L_tmp = (((Word32) temp2) * MU) >> 15;
548 
549             /* Sign-extend product */
550             if (L_tmp & (Word32) 0x00010000L)
551             {
552                 L_tmp = L_tmp | (Word32) 0xffff0000L;
553             }
554             temp2 = (Word16) L_tmp;
555 
556             temp2 = div_s(temp2, temp1);
557         }
558 
559         preemphasis(&(st->preemph_state), st->res2, temp2, L_SUBFR, pOverflow);
560 
561         /* filtering through  1/A(z/0.75) */
562 
563         Syn_filt(Ap4, st->res2, &syn[i_subfr], L_SUBFR, st->mem_syn_pst, 1);
564 
565         /* scale output to input */
566 
567         agc(&(st->agc_state), &syn_work[i_subfr], &syn[i_subfr],
568             AGC_FAC, L_SUBFR, pOverflow);
569 
570         Az += MP1;
571     }
572 
573     /* update syn_work[] buffer */
574 
575     Copy(&syn_work[L_FRAME - M], &syn_work[-M], M);
576 
577     return;
578 }
579