| /* ------------------------------------------------------------------ |
| * 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/c_g_aver.c |
| Functions: |
| Cb_gain_average_reset |
| Cb_gain_average |
| |
| Date: 03/28/2000 |
| |
| ------------------------------------------------------------------------------ |
| REVISION HISTORY |
| |
| Description: Made some changes to the comments to match the comments from |
| other modules. |
| |
| Description: Made changes based on comments from the review meeting. |
| |
| Description: Synchronized file with UMTS version 3.2.0. Updated coding |
| template. |
| |
| Description: Made the following changes per comments from Phase 2/3 review: |
| 1. Defined one local variable per line. |
| |
| Description: Removed the functions Cb_gain_average_init and |
| Cb_gain_average_exit. The Cb_gain_average related structure is no longer |
| dynamically allocated. |
| |
| Description: Passing in pOverflow to comply with changes needed for EPOC |
| Updated the include files for the module. |
| |
| Description: Changed round function name to pv_round to avoid conflict with |
| round function in C standard library. |
| |
| |
| Description: Replaced OSCL mem type functions and eliminated include |
| files that now are chosen by OSCL definitions |
| |
| Description: |
| ------------------------------------------------------------------------------ |
| MODULE DESCRIPTION |
| |
| This file contains functions that reset and perform |
| codebook gain calculations. |
| |
| ------------------------------------------------------------------------------ |
| */ |
| |
| |
| /*---------------------------------------------------------------------------- |
| ; INCLUDES |
| ----------------------------------------------------------------------------*/ |
| #include <string.h> |
| |
| #include "c_g_aver.h" |
| #include "typedef.h" |
| #include "mode.h" |
| #include "cnst.h" |
| |
| #include "basic_op.h" |
| |
| /*---------------------------------------------------------------------------- |
| ; MACROS |
| ; Define module specific macros here |
| ----------------------------------------------------------------------------*/ |
| |
| |
| /*---------------------------------------------------------------------------- |
| ; DEFINES |
| ; Include all pre-processor statements here. Include conditional |
| ; compile variables also. |
| ----------------------------------------------------------------------------*/ |
| |
| /*---------------------------------------------------------------------------- |
| ; LOCAL FUNCTION DEFINITIONS |
| ; Function Prototype declaration |
| ----------------------------------------------------------------------------*/ |
| |
| /*---------------------------------------------------------------------------- |
| ; LOCAL VARIABLE DEFINITIONS |
| ; Variable declaration - defined here and used outside this module |
| ----------------------------------------------------------------------------*/ |
| |
| /* |
| ------------------------------------------------------------------------------ |
| FUNCTION NAME: Cb_gain_average_reset |
| ------------------------------------------------------------------------------ |
| INPUT AND OUTPUT DEFINITIONS |
| |
| Inputs: |
| state = pointer to a structure of type Cb_gain_averageState |
| |
| Outputs: |
| Structure pointed to by state is initialized to zeros |
| |
| Returns: |
| Returns 0 if memory was successfully initialized, |
| otherwise returns -1. |
| |
| Global Variables Used: |
| None. |
| |
| Local Variables Needed: |
| None. |
| |
| ------------------------------------------------------------------------------ |
| FUNCTION DESCRIPTION |
| |
| Resets state memory |
| |
| ------------------------------------------------------------------------------ |
| REQUIREMENTS |
| |
| None. |
| |
| ------------------------------------------------------------------------------ |
| REFERENCES |
| |
| c_g_aver.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 |
| |
| ------------------------------------------------------------------------------ |
| PSEUDO-CODE |
| |
| Word16 Cb_gain_average_reset (Cb_gain_averageState *state) |
| { |
| if (state == (Cb_gain_averageState *) NULL){ |
| fprintf(stderr, "Cb_gain_average_reset: invalid parameter\n"); |
| return -1; |
| } |
| |
| // Static vectors to zero |
| Set_zero (state->cbGainHistory, L_CBGAINHIST); |
| |
| // Initialize hangover handling |
| state->hangVar = 0; |
| state->hangCount= 0; |
| |
| 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 Cb_gain_average_reset(Cb_gain_averageState *state) |
| { |
| if (state == (Cb_gain_averageState *) NULL) |
| { |
| /* fprint(stderr, "Cb_gain_average_reset: invalid parameter\n"); */ |
| return(-1); |
| } |
| |
| /* Static vectors to zero */ |
| memset(state->cbGainHistory, 0, L_CBGAINHIST*sizeof(Word16)); |
| |
| /* Initialize hangover handling */ |
| state->hangVar = 0; |
| state->hangCount = 0; |
| |
| return(0); |
| } |
| |
| /****************************************************************************/ |
| |
| /* |
| ------------------------------------------------------------------------------ |
| FUNCTION NAME: Cb_gain_average |
| ------------------------------------------------------------------------------ |
| INPUT AND OUTPUT DEFINITIONS |
| |
| Inputs: |
| st = pointer to structure of type Cb_gain_averageState |
| mode = AMR mode (enum Mode) |
| gain_code = CB gain (Word16) |
| lsp = the LSP for the current frame (Word16) |
| lspAver = the average of LSP for 8 frames (Word16) |
| bfi = bad frame indication flag (Word16) |
| prev_bf = previous bad frame indication flag (Word16) |
| pdfi = potential degraded bad frame ind flag (Word16) |
| prev_pdf = prev pot. degraded bad frame ind flag (Word16) |
| inBackgroundNoise = background noise decision (Word16) |
| voicedHangover = # of frames after last voiced frame (Word16) |
| pOverflow = address of overflow (Flag) |
| |
| Returns: |
| cbGainMix = codebook gain (Word16) |
| |
| Outputs: |
| None. |
| |
| Global Variables Used: |
| None. |
| |
| Local Variables Needed: |
| None. |
| |
| ------------------------------------------------------------------------------ |
| FUNCTION DESCRIPTION |
| |
| The mix cb gains for MR475, MR515, MR59, MR67, MR102; gain_code other modes |
| |
| ------------------------------------------------------------------------------ |
| REQUIREMENTS |
| |
| None. |
| |
| ------------------------------------------------------------------------------ |
| REFERENCES |
| |
| c_g_aver.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 |
| |
| ------------------------------------------------------------------------------ |
| PSEUDO-CODE |
| |
| Word16 Cb_gain_average ( |
| Cb_gain_averageState *st, // i/o : State variables for CB gain avergeing |
| enum Mode mode, // i : AMR mode |
| Word16 gain_code, // i : CB gain Q1 |
| Word16 lsp[], // i : The LSP for the current frame Q15 |
| Word16 lspAver[], // i : The average of LSP for 8 frames Q15 |
| Word16 bfi, // i : bad frame indication flag |
| Word16 prev_bf, // i : previous bad frame indication flag |
| Word16 pdfi, // i : potential degraded bad frame ind flag |
| Word16 prev_pdf, // i : prev pot. degraded bad frame ind flag |
| Word16 inBackgroundNoise, // i : background noise decision |
| Word16 voicedHangover // i : # of frames after last voiced frame |
| ) |
| { |
| //---------------------------------------------------------* |
| * Compute mixed cb gain, used to make cb gain more * |
| * smooth in background noise for modes 5.15, 5.9 and 6.7 * |
| * states that needs to be updated by all * |
| *--------------------------------------------------------- |
| Word16 i; |
| Word16 cbGainMix, diff, tmp_diff, bgMix, cbGainMean; |
| Word32 L_sum; |
| Word16 tmp[M], tmp1, tmp2, shift1, shift2, shift; |
| |
| // set correct cbGainMix for MR74, MR795, MR122 |
| cbGainMix = gain_code; |
| |
| *-------------------------------------------------------* |
| * Store list of CB gain needed in the CB gain * |
| * averaging * |
| *-------------------------------------------------------* |
| for (i = 0; i < (L_CBGAINHIST-1); i++) |
| { |
| st->cbGainHistory[i] = st->cbGainHistory[i+1]; |
| } |
| st->cbGainHistory[L_CBGAINHIST-1] = gain_code; |
| |
| // compute lsp difference |
| for (i = 0; i < M; i++) { |
| tmp1 = abs_s(sub(lspAver[i], lsp[i])); // Q15 |
| shift1 = sub(norm_s(tmp1), 1); // Qn |
| tmp1 = shl(tmp1, shift1); // Q15+Qn |
| shift2 = norm_s(lspAver[i]); // Qm |
| tmp2 = shl(lspAver[i], shift2); // Q15+Qm |
| tmp[i] = div_s(tmp1, tmp2); // Q15+(Q15+Qn)-(Q15+Qm) |
| shift = sub(add(2, shift1), shift2); |
| if (shift >= 0) |
| { |
| tmp[i] = shr(tmp[i], shift); // Q15+Qn-Qm-Qx=Q13 |
| } |
| else |
| { |
| tmp[i] = shl(tmp[i], negate(shift)); // Q15+Qn-Qm-Qx=Q13 |
| } |
| } |
| |
| diff = tmp[0]; |
| for (i = 1; i < M; i++) { |
| diff = add(diff, tmp[i]); // Q13 |
| } |
| |
| // Compute hangover |
| if (sub(diff, 5325) > 0) // 0.65 in Q11 |
| { |
| st->hangVar = add(st->hangVar, 1); |
| } |
| else |
| { |
| st->hangVar = 0; |
| } |
| |
| if (sub(st->hangVar, 10) > 0) |
| { |
| st->hangCount = 0; // Speech period, reset hangover variable |
| } |
| |
| // Compute mix constant (bgMix) |
| bgMix = 8192; // 1 in Q13 |
| if ((sub(mode, MR67) <= 0) || (sub(mode, MR102) == 0)) |
| // MR475, MR515, MR59, MR67, MR102 |
| { |
| // if errors and presumed noise make smoothing probability stronger |
| if (((((pdfi != 0) && (prev_pdf != 0)) || (bfi != 0) || (prev_bf != 0)) && |
| (sub(voicedHangover, 1) > 0) && (inBackgroundNoise != 0) && |
| ((sub(mode, MR475) == 0) || |
| (sub(mode, MR515) == 0) || |
| (sub(mode, MR59) == 0)) )) |
| { |
| // bgMix = min(0.25, max(0.0, diff-0.55)) / 0.25; |
| tmp_diff = sub(diff, 4506); // 0.55 in Q13 |
| |
| // max(0.0, diff-0.55) |
| if (tmp_diff > 0) |
| { |
| tmp1 = tmp_diff; |
| } |
| else |
| { |
| tmp1 = 0; |
| } |
| |
| // min(0.25, tmp1) |
| if (sub(2048, tmp1) < 0) |
| { |
| bgMix = 8192; |
| } |
| else |
| { |
| bgMix = shl(tmp1, 2); |
| } |
| } |
| else |
| { |
| // bgMix = min(0.25, max(0.0, diff-0.40)) / 0.25; |
| tmp_diff = sub(diff, 3277); // 0.4 in Q13 |
| |
| // max(0.0, diff-0.40) |
| if (tmp_diff > 0) |
| { |
| tmp1 = tmp_diff; |
| } |
| else |
| { |
| tmp1 = 0; |
| } |
| |
| // min(0.25, tmp1) |
| if (sub(2048, tmp1) < 0) |
| { |
| bgMix = 8192; |
| } |
| else |
| { |
| bgMix = shl(tmp1, 2); |
| } |
| } |
| |
| if ((sub(st->hangCount, 40) < 0) || (sub(diff, 5325) > 0)) // 0.65 in Q13 |
| { |
| bgMix = 8192; // disable mix if too short time since |
| } |
| |
| // Smoothen the cb gain trajectory |
| // smoothing depends on mix constant bgMix |
| L_sum = L_mult(6554, st->cbGainHistory[2]); // 0.2 in Q15; L_sum in Q17 |
| for (i = 3; i < L_CBGAINHIST; i++) |
| { |
| L_sum = L_mac(L_sum, 6554, st->cbGainHistory[i]); |
| } |
| cbGainMean = pv_round(L_sum); // Q1 |
| |
| // more smoothing in error and bg noise (NB no DFI used here) |
| if (((bfi != 0) || (prev_bf != 0)) && (inBackgroundNoise != 0) && |
| ((sub(mode, MR475) == 0) || |
| (sub(mode, MR515) == 0) || |
| (sub(mode, MR59) == 0)) ) |
| { |
| L_sum = L_mult(4681, st->cbGainHistory[0]); // 0.143 in Q15; L_sum in Q17 |
| for (i = 1; i < L_CBGAINHIST; i++) |
| { |
| L_sum = L_mac(L_sum, 4681, st->cbGainHistory[i]); |
| } |
| cbGainMean = pv_round(L_sum); // Q1 |
| } |
| |
| // cbGainMix = bgMix*cbGainMix + (1-bgMix)*cbGainMean; |
| L_sum = L_mult(bgMix, cbGainMix); // L_sum in Q15 |
| L_sum = L_mac(L_sum, 8192, cbGainMean); |
| L_sum = L_msu(L_sum, bgMix, cbGainMean); |
| cbGainMix = pv_round(L_shl(L_sum, 2)); // Q1 |
| } |
| |
| st->hangCount = add(st->hangCount, 1); |
| return cbGainMix; |
| } |
| |
| ------------------------------------------------------------------------------ |
| 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 Cb_gain_average( |
| Cb_gain_averageState *st, /* i/o : State variables for CB gain averaging */ |
| enum Mode mode, /* i : AMR mode */ |
| Word16 gain_code, /* i : CB gain Q1 */ |
| Word16 lsp[], /* i : The LSP for the current frame Q15 */ |
| Word16 lspAver[], /* i : The average of LSP for 8 frames Q15 */ |
| Word16 bfi, /* i : bad frame indication flag */ |
| Word16 prev_bf, /* i : previous bad frame indication flag */ |
| Word16 pdfi, /* i : potential degraded bad frame ind flag */ |
| Word16 prev_pdf, /* i : prev pot. degraded bad frame ind flag */ |
| Word16 inBackgroundNoise, /* i : background noise decision */ |
| Word16 voicedHangover, /* i : # of frames after last voiced frame */ |
| Flag *pOverflow |
| ) |
| { |
| Word16 i; |
| Word16 cbGainMix; |
| Word16 diff; |
| Word16 tmp_diff; |
| Word16 bgMix; |
| Word16 cbGainMean; |
| Word32 L_sum; |
| Word16 tmp[M]; |
| Word16 tmp1; |
| Word16 tmp2; |
| Word16 shift1; |
| Word16 shift2; |
| Word16 shift; |
| |
| /*---------------------------------------------------------* |
| * Compute mixed cb gain, used to make cb gain more * |
| * smooth in background noise for modes 5.15, 5.9 and 6.7 * |
| * states that needs to be updated by all * |
| *---------------------------------------------------------*/ |
| |
| /* set correct cbGainMix for MR74, MR795, MR122 */ |
| cbGainMix = gain_code; |
| |
| /*-------------------------------------------------------* |
| * Store list of CB gain needed in the CB gain * |
| * averaging * |
| *-------------------------------------------------------*/ |
| for (i = 0; i < (L_CBGAINHIST - 1); i++) |
| { |
| st->cbGainHistory[i] = st->cbGainHistory[i+1]; |
| } |
| st->cbGainHistory[L_CBGAINHIST-1] = gain_code; |
| |
| diff = 0; |
| |
| /* compute lsp difference */ |
| for (i = 0; i < M; i++) |
| { |
| tmp1 = abs_s(sub(*(lspAver + i), *(lsp + i), pOverflow)); |
| /* Q15 */ |
| shift1 = sub(norm_s(tmp1), 1, pOverflow); /* Qn */ |
| tmp1 = shl(tmp1, shift1, pOverflow); /* Q15+Qn */ |
| shift2 = norm_s(*(lspAver + i)); /* Qm */ |
| tmp2 = shl(*(lspAver + i), shift2, pOverflow); /* Q15+Qm */ |
| tmp[i] = div_s(tmp1, tmp2); /* Q15+(Q15+Qn)-(Q15+Qm) */ |
| |
| shift = 2 + shift1 - shift2; |
| |
| if (shift >= 0) |
| { |
| *(tmp + i) = shr(*(tmp + i), shift, pOverflow); |
| /* Q15+Qn-Qm-Qx=Q13 */ |
| } |
| else |
| { |
| *(tmp + i) = shl(*(tmp + i), negate(shift), pOverflow); |
| /* Q15+Qn-Qm-Qx=Q13 */ |
| } |
| |
| diff = add(diff, *(tmp + i), pOverflow); /* Q13 */ |
| } |
| |
| /* Compute hangover */ |
| |
| if (diff > 5325) /* 0.65 in Q11 */ |
| { |
| st->hangVar += 1; |
| } |
| else |
| { |
| st->hangVar = 0; |
| } |
| |
| |
| if (st->hangVar > 10) |
| { |
| /* Speech period, reset hangover variable */ |
| st->hangCount = 0; |
| } |
| |
| /* Compute mix constant (bgMix) */ |
| bgMix = 8192; /* 1 in Q13 */ |
| |
| if ((mode <= MR67) || (mode == MR102)) |
| /* MR475, MR515, MR59, MR67, MR102 */ |
| { |
| /* if errors and presumed noise make smoothing probability stronger */ |
| |
| if (((((pdfi != 0) && (prev_pdf != 0)) || (bfi != 0) || |
| (prev_bf != 0)) |
| && (voicedHangover > 1) |
| && (inBackgroundNoise != 0) |
| && ((mode == MR475) || (mode == MR515) || |
| (mode == MR59)))) |
| { |
| /* bgMix = min(0.25, max(0.0, diff-0.55)) / 0.25; */ |
| tmp_diff = sub(diff, 4506, pOverflow); /* 0.55 in Q13 */ |
| } |
| else |
| { |
| /* bgMix = min(0.25, max(0.0, diff-0.40)) / 0.25; */ |
| tmp_diff = sub(diff, 3277, pOverflow); /* 0.4 in Q13 */ |
| } |
| |
| /* max(0.0, diff-0.55) or */ |
| /* max(0.0, diff-0.40) */ |
| if (tmp_diff > 0) |
| { |
| tmp1 = tmp_diff; |
| } |
| else |
| { |
| tmp1 = 0; |
| } |
| |
| /* min(0.25, tmp1) */ |
| if (2048 < tmp1) |
| { |
| bgMix = 8192; |
| } |
| else |
| { |
| bgMix = shl(tmp1, 2, pOverflow); |
| } |
| |
| if ((st->hangCount < 40) || (diff > 5325)) /* 0.65 in Q13 */ |
| { |
| /* disable mix if too short time since */ |
| bgMix = 8192; |
| } |
| |
| /* Smoothen the cb gain trajectory */ |
| /* smoothing depends on mix constant bgMix */ |
| L_sum = L_mult(6554, st->cbGainHistory[2], pOverflow); |
| /* 0.2 in Q15; L_sum in Q17 */ |
| |
| for (i = 3; i < L_CBGAINHIST; i++) |
| { |
| L_sum = L_mac(L_sum, 6554, st->cbGainHistory[i], pOverflow); |
| } |
| cbGainMean = pv_round(L_sum, pOverflow); /* Q1 */ |
| |
| /* more smoothing in error and bg noise (NB no DFI used here) */ |
| |
| if (((bfi != 0) || (prev_bf != 0)) && (inBackgroundNoise != 0) |
| && ((mode == MR475) || (mode == MR515) |
| || (mode == MR59))) |
| { |
| /* 0.143 in Q15; L_sum in Q17 */ |
| L_sum = L_mult(4681, st->cbGainHistory[0], pOverflow); |
| for (i = 1; i < L_CBGAINHIST; i++) |
| { |
| L_sum = |
| L_mac(L_sum, 4681, st->cbGainHistory[i], pOverflow); |
| } |
| cbGainMean = pv_round(L_sum, pOverflow); /* Q1 */ |
| } |
| |
| /* cbGainMix = bgMix*cbGainMix + (1-bgMix)*cbGainMean; */ |
| /* L_sum in Q15 */ |
| L_sum = L_mult(bgMix, cbGainMix, pOverflow); |
| L_sum = L_mac(L_sum, 8192, cbGainMean, pOverflow); |
| L_sum = L_msu(L_sum, bgMix, cbGainMean, pOverflow); |
| cbGainMix = pv_round(L_shl(L_sum, 2, pOverflow), pOverflow); /* Q1 */ |
| } |
| |
| st->hangCount += 1; |
| |
| return (cbGainMix); |
| } |
| |