/* ------------------------------------------------------------------ * 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/dtx_enc.c Funtions: dtx_enc_init dtx_enc_reset dtx_enc_exit dtx_enc dtx_buffer tx_dtx_handler Date: 06/08/2000 ------------------------------------------------------------------------------ REVISION HISTORY Description: Updated template used to PV coding template. First attempt at optimizing C code. Description: Updated file per comments gathered from Phase 2/3 review. Synched up with new template (Inputs/Outputs section). Deleted lines leftover from original code prior to the code section of dtx_enc_exit function. Deleted confusing comment in the log_en calculation in dtx_enc function. Restructured IF statement in the calculation of the sum of squares of speech signals in dtx_buffer. Description: Added setting of Overflow flag in inlined code. Description: Synchronized file with UTMS version 3.2.0. Updated coding template. Removed unnecessary include files. Description: Made the following changes per comments from Phase 2/3 review: 1. Modified FOR loops to count down. 2. Fixed typecasting issue with TI C compiler. 3. Fixed comment in dtx_enc pseudo-code. 4. Added dtx_enc code comment pertaining to possible assembly implementation. Description: Added calls to add() in tx_dtx_handler. Updated copyright year. Description: Pass in pointer to overflow flag to all functions requiring this flag. This is to make the library EPOC compatible. Description: For dtx_enc_reset() only 1. Replaced copy() with memcpy. 2. Eliminated include file copy.h 3. Eliminated printf statement For dtx_buffer() 1. Replaced copy() with memcpy. 2. Eliminated math operations that unnecessary checked for saturation, in some cases this by shifting before adding and in other cases by evaluating the operands 3. Unrolled loop to speed up execution Description: For dtx_buffer() 1. Modified scaling and added check for saturation. Previous scaling was correct but altered precision, this cause bit exactness test failure. Description: For dtx_buffer() 1. Modified scaling and saturation checks. Previous scaling was correct but altered precision, this cause bit exactness test failure for dtx vad2. Description: Replaced OSCL mem type functions and eliminated include files that now are chosen by OSCL definitions Description: Replaced "int" and/or "char" with OSCL defined types. Description: ------------------------------------------------------------------------------ MODULE DESCRIPTION This file contains the various functions that perform the computation of the Silence Indicator (SID) parameters when in Discontinuous Transmission (DTX) mode. ------------------------------------------------------------------------------ */ /*---------------------------------------------------------------------------- ; INCLUDES ----------------------------------------------------------------------------*/ #include #include #include "dtx_enc.h" #include "q_plsf.h" #include "typedef.h" #include "mode.h" #include "basic_op.h" #include "log2.h" #include "lsp_lsf.h" #include "reorder.h" /*---------------------------------------------------------------------------- ; MACROS ; Define module specific macros here ----------------------------------------------------------------------------*/ extern Word32 L_add(register Word32 L_var1, register Word32 L_var2, Flag *pOverflow); /*---------------------------------------------------------------------------- ; 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: dtx_enc_init ------------------------------------------------------------------------------ INPUT AND OUTPUT DEFINITIONS Inputs: st = pointer to an array of pointers to structures of type dtx_encState Outputs: pointer pointed to by st is set to the address of the allocated memory Returns: return_value = 0, if initialization was successful; -1, otherwise (int) Global Variables Used: None Local Variables Needed: None ------------------------------------------------------------------------------ FUNCTION DESCRIPTION This function allocates the state memory used by the dtx_enc function. ------------------------------------------------------------------------------ REQUIREMENTS None ------------------------------------------------------------------------------ REFERENCES dtx_enc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 ------------------------------------------------------------------------------ PSEUDO-CODE int dtx_enc_init (dtx_encState **st) { dtx_encState* s; if (st == (dtx_encState **) NULL){ fprintf(stderr, "dtx_enc_init: invalid parameter\n"); return -1; } *st = NULL; // allocate memory if ((s= (dtx_encState *) malloc(sizeof(dtx_encState))) == NULL){ fprintf(stderr, "dtx_enc_init: can not malloc state structure\n"); return -1; } dtx_enc_reset(s); *st = s; 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 dtx_enc_init(dtx_encState **st) { dtx_encState* s; if (st == (dtx_encState **) NULL) { return(-1); } *st = NULL; /* allocate memory */ if ((s = (dtx_encState *) malloc(sizeof(dtx_encState))) == NULL) { return(-1); } dtx_enc_reset(s); *st = s; return(0); } /****************************************************************************/ /* ------------------------------------------------------------------------------ FUNCTION NAME: dtx_enc_reset ------------------------------------------------------------------------------ INPUT AND OUTPUT DEFINITIONS Inputs: st = pointer to structures of type dtx_encState Outputs: structure pointed to by st is initialized to its reset value Returns: return_value = 1, if reset was successful; -1, otherwise (int) Global Variables Used: None Local Variables Needed: lsp_init_data = table containing LSP initialization values; table elements are constants of type Word16; table length is M ------------------------------------------------------------------------------ FUNCTION DESCRIPTION This function initializes the fields of the state memory used by dtx_enc to their reset values. ------------------------------------------------------------------------------ REQUIREMENTS None ------------------------------------------------------------------------------ REFERENCES dtx_enc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 ------------------------------------------------------------------------------ PSEUDO-CODE int dtx_enc_reset (dtx_encState *st) { Word16 i; if (st == (dtx_encState *) NULL){ fprintf(stderr, "dtx_enc_reset: invalid parameter\n"); return -1; } st->hist_ptr = 0; st->log_en_index = 0; st->init_lsf_vq_index = 0; st->lsp_index[0] = 0; st->lsp_index[1] = 0; st->lsp_index[2] = 0; // Init lsp_hist[] for(i = 0; i < DTX_HIST_SIZE; i++) { Copy(lsp_init_data, &st->lsp_hist[i * M], M); } // Reset energy history Set_zero(st->log_en_hist, M); st->dtxHangoverCount = DTX_HANG_CONST; st->decAnaElapsedCount = 32767; return 1; } ------------------------------------------------------------------------------ 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 dtx_enc_reset(dtx_encState *st) { Word16 i; if (st == (dtx_encState *) NULL) { return(-1); } st->hist_ptr = 0; st->log_en_index = 0; st->init_lsf_vq_index = 0; st->lsp_index[0] = 0; st->lsp_index[1] = 0; st->lsp_index[2] = 0; /* Init lsp_hist[] */ for (i = 0; i < DTX_HIST_SIZE; i++) { memcpy(&st->lsp_hist[i * M], lsp_init_data, M*sizeof(Word16)); } /* Reset energy history */ memset(st->log_en_hist, 0, sizeof(Word16)*M); st->dtxHangoverCount = DTX_HANG_CONST; st->decAnaElapsedCount = 32767; return(1); } /****************************************************************************/ /* ------------------------------------------------------------------------------ FUNCTION NAME: dtx_enc_exit ------------------------------------------------------------------------------ INPUT AND OUTPUT DEFINITIONS Inputs: st = pointer to an array of pointers to structures of type dtx_encState Outputs: st points to the NULL address Returns: None Global Variables Used: None Local Variables Needed: None ------------------------------------------------------------------------------ FUNCTION DESCRIPTION This function deallocates the state memory used by dtx_enc function. ------------------------------------------------------------------------------ REQUIREMENTS None ------------------------------------------------------------------------------ REFERENCES dtx_enc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 ------------------------------------------------------------------------------ PSEUDO-CODE void dtx_enc_exit (dtx_encState **st) { if (st == NULL || *st == NULL) return; // deallocate memory free(*st); *st = NULL; return; } ------------------------------------------------------------------------------ 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 dtx_enc_exit(dtx_encState **st) { if (st == NULL || *st == NULL) { return; } /* deallocate memory */ free(*st); *st = NULL; return; } /****************************************************************************/ /* ------------------------------------------------------------------------------ FUNCTION NAME: dtx_enc ------------------------------------------------------------------------------ INPUT AND OUTPUT DEFINITIONS Inputs: st = pointer to structures of type dtx_encState computeSidFlag = compute SID flag of type Word16 qSt = pointer to structures of type Q_plsfState predState = pointer to structures of type gc_predState anap = pointer to an array of pointers to analysis parameters of type Word16 Outputs: structure pointed to by st contains the newly calculated SID parameters structure pointed to by predState contains the new logarithmic frame energy pointer pointed to by anap points to the location of the new logarithmic frame energy and new LSPs Returns: return_value = 0 (int) Global Variables Used: None Local Variables Needed: None ------------------------------------------------------------------------------ FUNCTION DESCRIPTION This function calculates the SID parameters when in the DTX mode. ------------------------------------------------------------------------------ REQUIREMENTS None ------------------------------------------------------------------------------ REFERENCES dtx_enc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 ------------------------------------------------------------------------------ PSEUDO-CODE int dtx_enc(dtx_encState *st, // i/o : State struct Word16 computeSidFlag, // i : compute SID Q_plsfState *qSt, // i/o : Qunatizer state struct gc_predState* predState, // i/o : State struct Word16 **anap // o : analysis parameters ) { Word16 i,j; Word16 log_en; Word16 lsf[M]; Word16 lsp[M]; Word16 lsp_q[M]; Word32 L_lsp[M]; // VOX mode computation of SID parameters if ((computeSidFlag != 0) || (st->log_en_index == 0)) { // compute new SID frame if safe i.e don't // compute immediately after a talk spurt log_en = 0; for (i = 0; i < M; i++) { L_lsp[i] = 0; } // average energy and lsp for (i = 0; i < DTX_HIST_SIZE; i++) { log_en = add(log_en, shr(st->log_en_hist[i],2)); for (j = 0; j < M; j++) { L_lsp[j] = L_add(L_lsp[j], L_deposit_l(st->lsp_hist[i * M + j])); } } log_en = shr(log_en, 1); for (j = 0; j < M; j++) { lsp[j] = extract_l(L_shr(L_lsp[j], 3)); // divide by 8 } // quantize logarithmic energy to 6 bits st->log_en_index = add(log_en, 2560); // +2.5 in Q10 st->log_en_index = add(st->log_en_index, 128); // add 0.5/4 in Q10 st->log_en_index = shr(st->log_en_index, 8); if (sub(st->log_en_index, 63) > 0) { st->log_en_index = 63; } if (st->log_en_index < 0) { st->log_en_index = 0; } // update gain predictor memory log_en = shl(st->log_en_index, -2+10); // Q11 and divide by 4 log_en = sub(log_en, 2560); // add 2.5 in Q11 log_en = sub(log_en, 9000); if (log_en > 0) { log_en = 0; } if (sub(log_en, -14436) < 0) { log_en = -14436; } // past_qua_en for other modes than MR122 predState->past_qua_en[0] = log_en; predState->past_qua_en[1] = log_en; predState->past_qua_en[2] = log_en; predState->past_qua_en[3] = log_en; // scale down by factor 20*log10(2) in Q15 log_en = mult(5443, log_en); // past_qua_en for mode MR122 predState->past_qua_en_MR122[0] = log_en; predState->past_qua_en_MR122[1] = log_en; predState->past_qua_en_MR122[2] = log_en; predState->past_qua_en_MR122[3] = log_en; // make sure that LSP's are ordered Lsp_lsf(lsp, lsf, M); Reorder_lsf(lsf, LSF_GAP, M); Lsf_lsp(lsf, lsp, M); // Quantize lsp and put on parameter list Q_plsf_3(qSt, MRDTX, lsp, lsp_q, st->lsp_index, &st->init_lsf_vq_index); } *(*anap)++ = st->init_lsf_vq_index; // 3 bits *(*anap)++ = st->lsp_index[0]; // 8 bits *(*anap)++ = st->lsp_index[1]; // 9 bits *(*anap)++ = st->lsp_index[2]; // 9 bits *(*anap)++ = st->log_en_index; // 6 bits // = 35 bits 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 dtx_enc(dtx_encState *st, /* i/o : State struct */ Word16 computeSidFlag, /* i : compute SID */ Q_plsfState *qSt, /* i/o : Qunatizer state struct */ gc_predState* predState, /* i/o : State struct */ Word16 **anap, /* o : analysis parameters */ Flag *pOverflow /* i/o : overflow indicator */ ) { register Word16 i, j; Word16 temp; Word16 log_en; Word16 lsf[M]; Word16 lsp[M]; Word16 lsp_q[M]; Word32 L_lsp[M]; /* VOX mode computation of SID parameters */ if ((computeSidFlag != 0) || (st->log_en_index == 0)) { /* compute new SID frame if safe i.e don't * compute immediately after a talk spurt */ log_en = 0; for (i = M - 1; i >= 0; i--) { L_lsp[i] = 0; } /* average energy and lsp */ for (i = DTX_HIST_SIZE - 1; i >= 0; i--) { if (st->log_en_hist[i] < 0) { temp = ~((~(st->log_en_hist[i])) >> 2); } else { temp = st->log_en_hist[i] >> 2; } log_en = add(log_en, temp, pOverflow); for (j = M - 1; j >= 0; j--) { L_lsp[j] = L_add(L_lsp[j], (Word32)(st->lsp_hist[i * M + j]), pOverflow); } } if (log_en < 0) { log_en = ~((~log_en) >> 1); } else { log_en = log_en >> 1; } for (j = M - 1; j >= 0; j--) { /* divide by 8 */ if (L_lsp[j] < 0) { lsp[j] = (Word16)(~((~L_lsp[j]) >> 3)); } else { lsp[j] = (Word16)(L_lsp[j] >> 3); } } /* quantize logarithmic energy to 6 bits */ /* +2.5 in Q10 */ st->log_en_index = add(log_en, 2560, pOverflow); /* add 0.5/4 in Q10 */ st->log_en_index = add(st->log_en_index, 128, pOverflow); if (st->log_en_index < 0) { st->log_en_index = ~((~st->log_en_index) >> 8); } else { st->log_en_index = st->log_en_index >> 8; } /*---------------------------------------------*/ /* Limit to max and min allowable 6-bit values */ /* Note: For assembly implementation, use the */ /* following: */ /* if(st->long_en_index >> 6 != 0) */ /* { */ /* if(st->long_en_index < 0) */ /* { */ /* st->long_en_index = 0 */ /* } */ /* else */ /* { */ /* st->long_en_index = 63 */ /* } */ /* } */ /*---------------------------------------------*/ if (st->log_en_index > 63) { st->log_en_index = 63; } else if (st->log_en_index < 0) { st->log_en_index = 0; } /* update gain predictor memory */ /* Q11 and divide by 4 */ log_en = (Word16)(((Word32) st->log_en_index) << (-2 + 10)); log_en = sub(log_en, 11560, pOverflow); if (log_en > 0) { log_en = 0; } else if (log_en < -14436) { log_en = -14436; } /* past_qua_en for other modes than MR122 */ predState->past_qua_en[0] = log_en; predState->past_qua_en[1] = log_en; predState->past_qua_en[2] = log_en; predState->past_qua_en[3] = log_en; /* scale down by factor 20*log10(2) in Q15 */ log_en = (Word16)(((Word32)(5443 * log_en)) >> 15); /* past_qua_en for mode MR122 */ predState->past_qua_en_MR122[0] = log_en; predState->past_qua_en_MR122[1] = log_en; predState->past_qua_en_MR122[2] = log_en; predState->past_qua_en_MR122[3] = log_en; /* make sure that LSP's are ordered */ Lsp_lsf(lsp, lsf, M, pOverflow); Reorder_lsf(lsf, LSF_GAP, M, pOverflow); Lsf_lsp(lsf, lsp, M, pOverflow); /* Quantize lsp and put on parameter list */ Q_plsf_3(qSt, MRDTX, lsp, lsp_q, st->lsp_index, &st->init_lsf_vq_index, pOverflow); } *(*anap)++ = st->init_lsf_vq_index; /* 3 bits */ *(*anap)++ = st->lsp_index[0]; /* 8 bits */ *(*anap)++ = st->lsp_index[1]; /* 9 bits */ *(*anap)++ = st->lsp_index[2]; /* 9 bits */ *(*anap)++ = st->log_en_index; /* 6 bits */ /* = 35 bits */ } /****************************************************************************/ /* ------------------------------------------------------------------------------ FUNCTION NAME: dtx_buffer ------------------------------------------------------------------------------ INPUT AND OUTPUT DEFINITIONS Inputs: st = pointer to structures of type dtx_encState lsp_new = LSP vector whose elements are of type Word16; vector length is M speech = vector of speech samples of type Word16; vector length is BFR_SIZE_GSM Outputs: structure pointed to by st contains the new LSPs and logarithmic frame energy Returns: return_value = 0 (int) Global Variables Used: None Local Variables Needed: None ------------------------------------------------------------------------------ FUNCTION DESCRIPTION This function handles the DTX buffer. ------------------------------------------------------------------------------ REQUIREMENTS None ------------------------------------------------------------------------------ REFERENCES dtx_enc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 ------------------------------------------------------------------------------ PSEUDO-CODE int dtx_buffer(dtx_encState *st, // i/o : State struct Word16 lsp_new[], // i : LSP vector Word16 speech[] // i : speech samples ) { Word16 i; Word32 L_frame_en; Word16 log_en_e; Word16 log_en_m; Word16 log_en; // update pointer to circular buffer st->hist_ptr = add(st->hist_ptr, 1); if (sub(st->hist_ptr, DTX_HIST_SIZE) == 0) { st->hist_ptr = 0; } // copy lsp vector into buffer Copy(lsp_new, &st->lsp_hist[st->hist_ptr * M], M); // compute log energy based on frame energy L_frame_en = 0; // Q0 for (i=0; i < L_FRAME; i++) { L_frame_en = L_mac(L_frame_en, speech[i], speech[i]); } Log2(L_frame_en, &log_en_e, &log_en_m); // convert exponent and mantissa to Word16 Q10 log_en = shl(log_en_e, 10); // Q10 log_en = add(log_en, shr(log_en_m, 15-10)); // divide with L_FRAME i.e subtract with log2(L_FRAME) = 7.32193 log_en = sub(log_en, 8521); // insert into log energy buffer with division by 2 log_en = shr(log_en, 1); st->log_en_hist[st->hist_ptr] = log_en; // Q10 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 dtx_buffer(dtx_encState *st, /* i/o : State struct */ Word16 lsp_new[], /* i : LSP vector */ Word16 speech[], /* i : speech samples */ Flag *pOverflow /* i/o : overflow indicator */ ) { register Word16 i; Word32 L_frame_en; Word32 L_temp; Word16 log_en_e; Word16 log_en_m; Word16 log_en; Word16 *p_speech = &speech[0]; /* update pointer to circular buffer */ st->hist_ptr += 1; if (st->hist_ptr == DTX_HIST_SIZE) { st->hist_ptr = 0; } /* copy lsp vector into buffer */ memcpy(&st->lsp_hist[st->hist_ptr * M], lsp_new, M*sizeof(Word16)); /* compute log energy based on frame energy */ L_frame_en = 0; /* Q0 */ for (i = L_FRAME; i != 0; i--) { L_frame_en += (((Word32) * p_speech) * *(p_speech)) << 1; p_speech++; if (L_frame_en < 0) { L_frame_en = MAX_32; break; } } Log2(L_frame_en, &log_en_e, &log_en_m, pOverflow); /* convert exponent and mantissa to Word16 Q10 */ /* Q10 */ L_temp = ((Word32) log_en_e) << 10; if (L_temp != (Word32)((Word16) L_temp)) { *pOverflow = 1; log_en = (log_en_e > 0) ? MAX_16 : MIN_16; } else { log_en = (Word16) L_temp; } log_en += log_en_m >> (15 - 10); /* divide with L_FRAME i.e subtract with log2(L_FRAME) = 7.32193 */ log_en -= 8521; /* insert into log energy buffer with division by 2 */ st->log_en_hist[st->hist_ptr] = log_en >> 1; /* Q10 */ } /****************************************************************************/ /* ------------------------------------------------------------------------------ FUNCTION NAME: tx_dtx_handler ------------------------------------------------------------------------------ INPUT AND OUTPUT DEFINITIONS Inputs: st = pointer to structures of type dtx_encState vad_flag = VAD decision flag of type Word16 usedMode = pointer to the currently used mode of type enum Mode Outputs: structure pointed to by st contains the newly calculated speech hangover Returns: compute_new_sid_possible = flag to indicate a change in the used mode; store type is Word16 Global Variables Used: None Local Variables Needed: None ------------------------------------------------------------------------------ FUNCTION DESCRIPTION This function adds extra speech hangover to analyze speech on the decoding side. ------------------------------------------------------------------------------ REQUIREMENTS None ------------------------------------------------------------------------------ REFERENCES dtx_enc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 ------------------------------------------------------------------------------ PSEUDO-CODE Word16 tx_dtx_handler(dtx_encState *st, // i/o : State struct Word16 vad_flag, // i : vad decision enum Mode *usedMode // i/o : mode changed or not ) { Word16 compute_new_sid_possible; // this state machine is in synch with the GSMEFR txDtx machine st->decAnaElapsedCount = add(st->decAnaElapsedCount, 1); compute_new_sid_possible = 0; if (vad_flag != 0) { st->dtxHangoverCount = DTX_HANG_CONST; } else { // non-speech if (st->dtxHangoverCount == 0) { // out of decoder analysis hangover st->decAnaElapsedCount = 0; *usedMode = MRDTX; compute_new_sid_possible = 1; } else { // in possible analysis hangover st->dtxHangoverCount = sub(st->dtxHangoverCount, 1); // decAnaElapsedCount + dtxHangoverCount < DTX_ELAPSED_FRAMES_THRESH if (sub(add(st->decAnaElapsedCount, st->dtxHangoverCount), DTX_ELAPSED_FRAMES_THRESH) < 0) { *usedMode = MRDTX; // if short time since decoder update, do not add extra HO } // else // override VAD and stay in // speech mode *usedMode // and add extra hangover } } return compute_new_sid_possible; } ------------------------------------------------------------------------------ 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 tx_dtx_handler(dtx_encState *st, /* i/o : State struct */ Word16 vad_flag, /* i : vad decision */ enum Mode *usedMode, /* i/o : mode changed or not */ Flag *pOverflow /* i/o : overflow indicator */ ) { Word16 compute_new_sid_possible; Word16 count; /* this state machine is in synch with the GSMEFR txDtx machine */ st->decAnaElapsedCount = add(st->decAnaElapsedCount, 1, pOverflow); compute_new_sid_possible = 0; if (vad_flag != 0) { st->dtxHangoverCount = DTX_HANG_CONST; } else { /* non-speech */ if (st->dtxHangoverCount == 0) { /* out of decoder analysis hangover */ st->decAnaElapsedCount = 0; *usedMode = MRDTX; compute_new_sid_possible = 1; } else { /* in possible analysis hangover */ st->dtxHangoverCount -= 1; /* decAnaElapsedCount + dtxHangoverCount < */ /* DTX_ELAPSED_FRAMES_THRESH */ count = add(st->decAnaElapsedCount, st->dtxHangoverCount, pOverflow); if (count < DTX_ELAPSED_FRAMES_THRESH) { *usedMode = MRDTX; /* if short time since decoder update, */ /* do not add extra HO */ } } } return(compute_new_sid_possible); }