summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/codecs/amrnb/dec/src/pstfilt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/codecs/amrnb/dec/src/pstfilt.cpp')
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/pstfilt.cpp578
1 files changed, 578 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/amrnb/dec/src/pstfilt.cpp b/media/libstagefright/codecs/amrnb/dec/src/pstfilt.cpp
new file mode 100644
index 0000000..0336990
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/pstfilt.cpp
@@ -0,0 +1,578 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/pstfilt.c
+ Functions:
+ Post_Filter_reset
+ Post_Filter
+
+ Date: 04/14/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changed template used to PV coding template. First attempt at
+ optimizing C code.
+
+ Description: Updated file per comments gathered from Phase 2/3 review.
+
+ Description: Added setting of Overflow flag in inlined code.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Replaced basic_op.h with the header file of the math functions
+ used in the file.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Updated copyright year.
+ 2. Modified FOR loops to count down.
+ 3. Fixed typecasting issue with TI C compiler.
+ 4. Added "break" statement after overflow condition occurs.
+
+ Description: Removed the functions pstfilt_init and pstfilt_exit.
+ The pst_filt related structure is no longer dynamically allocated.
+
+ Description: Modified code for EPOC changes where pOverflow is passed in
+ rather than allowing overflow to be a global variable.
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with defined types.
+ Added proper casting (Word32) to some left shifting operations
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the function that performs adaptive post-filtering on the
+ synthesized speech. It also contains the functions that initialize, reset,
+ and exit the post-filtering function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <string.h>
+
+#include "pstfilt.h"
+#include "typedef.h"
+#include "mode.h"
+#include "basicop_malloc.h"
+#include "basic_op.h"
+#include "weight_a.h"
+#include "residu.h"
+#include "copy.h"
+#include "syn_filt.h"
+#include "preemph.h"
+#include "cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define L_H 22 /* size of truncated impulse response of A(z/g1)/A(z/g2) */
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/* Spectral expansion factors */
+static const Word16 gamma3_MR122[M] =
+{
+ 22938, 16057, 11240, 7868, 5508,
+ 3856, 2699, 1889, 1322, 925
+};
+
+static const Word16 gamma3[M] =
+{
+ 18022, 9912, 5451, 2998, 1649, 907, 499, 274, 151, 83
+};
+
+static const Word16 gamma4_MR122[M] =
+{
+ 24576, 18432, 13824, 10368, 7776,
+ 5832, 4374, 3281, 2461, 1846
+};
+
+static const Word16 gamma4[M] =
+{
+ 22938, 16057, 11240, 7868, 5508, 3856, 2699, 1889, 1322, 925
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Post_Filter_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to structure of type Post_FilterState
+
+ Outputs:
+ fields of the structure pointed to by state is initialized to zero
+
+ Returns:
+ return_value = 0, if reset was successful; -1, otherwise (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function initializes the state memory used by the Post_Filter function
+ to zero.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pstfilt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Post_Filter_reset (Post_FilterState *state)
+{
+ if (state == (Post_FilterState *) NULL){
+ fprintf(stderr, "Post_Filter_reset: invalid parameter\n");
+ return -1;
+ }
+
+ Set_zero (state->mem_syn_pst, M);
+ Set_zero (state->res2, L_SUBFR);
+ Set_zero (state->synth_buf, L_FRAME + M);
+ agc_reset(state->agc_state);
+ preemphasis_reset(state->preemph_state);
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Post_Filter_reset(Post_FilterState *state)
+{
+ if (state == (Post_FilterState *) NULL)
+ {
+ /*fprintf(stderr, "Post_Filter_reset: invalid parameter\n"); */
+ return(-1);
+ }
+
+ memset(state->mem_syn_pst, 0, sizeof(Word16)*M);
+ memset(state->res2, 0, sizeof(Word16)*L_SUBFR);
+ memset(state->synth_buf, 0, sizeof(Word16)*(L_FRAME + M));
+ agc_reset(&(state->agc_state));
+ preemphasis_reset(&(state->preemph_state));
+
+ return(0);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Post_Filter
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a structure of type Post_FilterState
+ mode = AMR mode
+ syn = pointer to a buffer containing synthesized speech; upon
+ exiting this function, it will contain the post-filtered
+ synthesized speech
+ Az_4 = pointer to the interpolated LPC parameters for all subframes
+ pOverflow = pointer to overflow indicator of type Flag
+
+ Outputs:
+ fields of the structure pointed to by st contains the updated field
+ values
+ syn buffer contains the post-filtered synthesized speech
+ pOverflow = 1 if overflow occurrs in the math functions called else
+ it is zero.
+
+ Returns:
+ return_value = 0 (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs the post-filtering on the synthesized speech. The
+ post-filtering process is described as follows:
+ (1) inverse filtering of syn[] through A(z/0.7) to get res2[]
+ (2) tilt compensation filtering; 1 - MU*k*z^-1
+ (3) synthesis filtering through 1/A(z/0.75)
+ (4) adaptive gain control
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pstfilt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Post_Filter (
+ Post_FilterState *st, // i/o : post filter states
+ enum Mode mode, // i : AMR mode
+ Word16 *syn, // i/o : synthesis speech (postfiltered is output)
+ Word16 *Az_4 // i : interpolated LPC parameters in all subfr.
+)
+{
+ *-------------------------------------------------------------------*
+ * Declaration of parameters *
+ *-------------------------------------------------------------------*
+
+ Word16 Ap3[MP1], Ap4[MP1]; // bandwidth expanded LP parameters
+ Word16 *Az; // pointer to Az_4:
+ // LPC parameters in each subframe
+ Word16 i_subfr; // index for beginning of subframe
+ Word16 h[L_H];
+
+ Word16 i;
+ Word16 temp1, temp2;
+ Word32 L_tmp;
+ Word16 *syn_work = &st->synth_buf[M];
+
+
+ *-----------------------------------------------------*
+ * Post filtering *
+ *-----------------------------------------------------*
+
+ Copy (syn, syn_work , L_FRAME);
+
+ Az = Az_4;
+
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ // Find weighted filter coefficients Ap3[] and ap[4]
+
+ if (sub(mode, MR122) == 0 || sub(mode, MR102) == 0)
+ {
+ Weight_Ai (Az, gamma3_MR122, Ap3);
+ Weight_Ai (Az, gamma4_MR122, Ap4);
+ }
+ else
+ {
+ Weight_Ai (Az, gamma3, Ap3);
+ Weight_Ai (Az, gamma4, Ap4);
+ }
+
+ // filtering of synthesis speech by A(z/0.7) to find res2[]
+
+ Residu (Ap3, &syn_work[i_subfr], st->res2, L_SUBFR);
+
+ // tilt compensation filter
+
+ // impulse response of A(z/0.7)/A(z/0.75)
+
+ Copy (Ap3, h, M + 1);
+ Set_zero (&h[M + 1], L_H - M - 1);
+ Syn_filt (Ap4, h, h, L_H, &h[M + 1], 0);
+
+ // 1st correlation of h[]
+
+ L_tmp = L_mult (h[0], h[0]);
+ for (i = 1; i < L_H; i++)
+ {
+ L_tmp = L_mac (L_tmp, h[i], h[i]);
+ }
+ temp1 = extract_h (L_tmp);
+
+ L_tmp = L_mult (h[0], h[1]);
+ for (i = 1; i < L_H - 1; i++)
+ {
+ L_tmp = L_mac (L_tmp, h[i], h[i + 1]);
+ }
+ temp2 = extract_h (L_tmp);
+
+ if (temp2 <= 0)
+ {
+ temp2 = 0;
+ }
+ else
+ {
+ temp2 = mult (temp2, MU);
+ temp2 = div_s (temp2, temp1);
+ }
+
+ preemphasis (st->preemph_state, st->res2, temp2, L_SUBFR);
+
+ // filtering through 1/A(z/0.75)
+
+ Syn_filt (Ap4, st->res2, &syn[i_subfr], L_SUBFR, st->mem_syn_pst, 1);
+
+ // scale output to input
+
+ agc (st->agc_state, &syn_work[i_subfr], &syn[i_subfr],
+ AGC_FAC, L_SUBFR);
+
+ Az += MP1;
+ }
+
+ // update syn_work[] buffer
+
+ Copy (&syn_work[L_FRAME - M], &syn_work[-M], M);
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Post_Filter(
+ Post_FilterState *st, /* i/o : post filter states */
+ enum Mode mode, /* i : AMR mode */
+ Word16 *syn, /* i/o : synthesis speech (postfiltered is output) */
+ Word16 *Az_4, /* i : interpolated LPC parameters in all subfr. */
+ Flag *pOverflow
+)
+{
+ Word16 Ap3[MP1];
+ Word16 Ap4[MP1]; /* bandwidth expanded LP parameters */
+ Word16 *Az; /* pointer to Az_4: */
+ /* LPC parameters in each subframe */
+ register Word16 i_subfr; /* index for beginning of subframe */
+ Word16 h[L_H];
+
+ register Word16 i;
+ Word16 temp1;
+ Word16 temp2;
+ Word32 L_tmp;
+ Word32 L_tmp2;
+ Word16 *syn_work = &st->synth_buf[M];
+
+
+ /*-----------------------------------------------------*
+ * Post filtering *
+ *-----------------------------------------------------*/
+
+ Copy(syn, syn_work , L_FRAME);
+
+ Az = Az_4;
+
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ /* Find weighted filter coefficients Ap3[] and ap[4] */
+
+ if (mode == MR122 || mode == MR102)
+ {
+ Weight_Ai(Az, gamma3_MR122, Ap3);
+ Weight_Ai(Az, gamma4_MR122, Ap4);
+ }
+ else
+ {
+ Weight_Ai(Az, gamma3, Ap3);
+ Weight_Ai(Az, gamma4, Ap4);
+ }
+
+ /* filtering of synthesis speech by A(z/0.7) to find res2[] */
+
+ Residu(Ap3, &syn_work[i_subfr], st->res2, L_SUBFR);
+
+ /* tilt compensation filter */
+
+ /* impulse response of A(z/0.7)/A(z/0.75) */
+
+ Copy(Ap3, h, M + 1);
+ memset(&h[M + 1], 0, sizeof(Word16)*(L_H - M - 1));
+ Syn_filt(Ap4, h, h, L_H, &h[M + 1], 0);
+
+ /* 1st correlation of h[] */
+
+ L_tmp = 0;
+
+ for (i = L_H - 1; i >= 0; i--)
+ {
+ L_tmp2 = ((Word32) h[i]) * h[i];
+
+ if (L_tmp2 != (Word32) 0x40000000L)
+ {
+ L_tmp2 = L_tmp2 << 1;
+ }
+ else
+ {
+ *pOverflow = 1;
+ L_tmp2 = MAX_32;
+ break;
+ }
+
+ L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
+ }
+ temp1 = (Word16)(L_tmp >> 16);
+
+ L_tmp = 0;
+
+ for (i = L_H - 2; i >= 0; i--)
+ {
+ L_tmp2 = ((Word32) h[i]) * h[i + 1];
+
+ if (L_tmp2 != (Word32) 0x40000000L)
+ {
+ L_tmp2 = L_tmp2 << 1;
+ }
+ else
+ {
+ *pOverflow = 1;
+ L_tmp2 = MAX_32;
+ break;
+ }
+
+ L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
+ }
+ temp2 = (Word16)(L_tmp >> 16);
+
+ if (temp2 <= 0)
+ {
+ temp2 = 0;
+ }
+ else
+ {
+ L_tmp = (((Word32) temp2) * MU) >> 15;
+
+ /* Sign-extend product */
+ if (L_tmp & (Word32) 0x00010000L)
+ {
+ L_tmp = L_tmp | (Word32) 0xffff0000L;
+ }
+ temp2 = (Word16) L_tmp;
+
+ temp2 = div_s(temp2, temp1);
+ }
+
+ preemphasis(&(st->preemph_state), st->res2, temp2, L_SUBFR, pOverflow);
+
+ /* filtering through 1/A(z/0.75) */
+
+ Syn_filt(Ap4, st->res2, &syn[i_subfr], L_SUBFR, st->mem_syn_pst, 1);
+
+ /* scale output to input */
+
+ agc(&(st->agc_state), &syn_work[i_subfr], &syn[i_subfr],
+ AGC_FAC, L_SUBFR, pOverflow);
+
+ Az += MP1;
+ }
+
+ /* update syn_work[] buffer */
+
+ Copy(&syn_work[L_FRAME - M], &syn_work[-M], M);
+
+ return;
+}