⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dtx.c

📁 语音编码G.729 语音编码G.729
💻 C
字号:
/*   ITU-T G.729 Annex C+ - Reference C code for floating point                         implementation of G.729 Annex C+                         (integration of Annexes B, D and E)                          Version 2.1 of October 1999*//* File : DTX.C*//* DTX and Comfort Noise Generator - Encoder part */#include <stdio.h>#include <stdlib.h>#include <math.h>#include "typedef.h"#include "ld8a.h"#include "tab_ld8a.h"#include "sid.h"#include "vad.h"#include "dtx.h"#include "tab_dtx.h"/* Local functions */static void calc_pastfilt(struct cod_cng_state_t *, FLOAT *Coeff);static void calc_RCoeff(FLOAT *Coeff, FLOAT *RCoeff);static int cmp_filt(FLOAT *RCoeff, FLOAT *acf, FLOAT alpha, FLOAT Thresh);static void calc_sum_acf(FLOAT *acf, FLOAT *sum, int nb);static void update_sumAcf(struct cod_cng_state_t *);/*-----------------------------------------------------------** procedure init_Cod_cng:                                   **           ~~~~~~~~~~~~                                    **   Initialize variables used for dtx at the encoder        **-----------------------------------------------------------*/void init_cod_cng(struct cod_cng_state_t * state){	set_zero(state->sumAcf, SIZ_SUMACF);	set_zero(state->Acf, SIZ_ACF);	set_zero(state->ener, NB_GAIN);        state->cur_gain = 0;    state->fr_cur = 0;    state->flag_chang = 0;}/*-----------------------------------------------------------** procedure cod_cng:                                        **           ~~~~~~~~                                        **   computes DTX decision                                   **   encodes SID frames                                      **   computes CNG excitation for encoder update              **-----------------------------------------------------------*/void cod_cng(struct cod_cng_state_t * state,    FLOAT *exc,          /* (i/o) : excitation array                     */    int pastVad,         /* (i)   : previous VAD decision                */    FLOAT *lsp_old_q,    /* (i/o) : previous quantized lsp               *///    FLOAT *old_A,          /* (i/o) : last stable filter LPC coefficients  *///    FLOAT *old_rc,          /* (i/o) : last stable filter Reflection coefficients.*/    FLOAT *Aq,           /* (o)   : set of interpolated LPC coefficients */    int *ana,            /* (o)   : coded SID parameters                 */    FLOAT freq_prev[MA_NP][M], /* (i/o) : previous LPS for quantization        */    INT16 *seed          /* (i/o) : random generator seed                */){    int i;        FLOAT curAcf[MP1];    FLOAT bid[MP1];    FLOAT curCoeff[MP1];    FLOAT lsp_new[M];    FLOAT *lpcCoeff;    int cur_igain;    FLOAT energyq;        /* Update Ener */    for(i = NB_GAIN-1; i>=1; i--) {        state->ener[i] = state->ener[i-1];    }        /* Compute current Acfs */    calc_sum_acf(state->Acf, curAcf, NB_CURACF);        /* Compute LPC coefficients and residual energy */    if(curAcf[0] == (F)0.) {        state->ener[0] = (F)0.;                /* should not happen */    }    else {        state->ener[0] = levinson(curAcf, curCoeff, bid);    }    /* if first frame of silence => SID frame */    if(pastVad != 0) {        ana[0] = 2;        state->count_fr0 = 0;        state->nb_ener = 1;        qua_Sidgain(state->ener, state->nb_ener, &energyq, &cur_igain);    }    else {        state->nb_ener++;        if(state->nb_ener > NB_GAIN) state->nb_ener = NB_GAIN;        qua_Sidgain(state->ener, state->nb_ener, &energyq, &cur_igain);        /* Compute stationarity of current filter   */        /* versus reference filter                  */        if(cmp_filt(state->RCoeff, curAcf, state->ener[0], THRESH1) != 0) {            state->flag_chang = 1;        }                /* compare energy difference between current frame and last frame */        if( (FLOAT)fabs(state->prev_energy - energyq) > (F)2.0) state->flag_chang = 1;                state->count_fr0++;        if(state->count_fr0 < FR_SID_MIN) {            ana[0] = 0; /* no transmission */        }        else {            if(state->flag_chang != 0) {                ana[0] = 2;             /* transmit SID frame */            }            else{                ana[0] = 0;            }            state->count_fr0 = FR_SID_MIN;   /* to avoid overflow */        }    }    if(ana[0] == 2) {        /* Reset frame count and change flag */        state->count_fr0 = 0;        state->flag_chang = 0;                /* Compute past average filter */        calc_pastfilt(state, state->pastCoeff);        calc_RCoeff(state->pastCoeff, state->RCoeff);                /* Compute stationarity of current filter   */        /* versus past average filter               */                /* if stationary */        /* transmit average filter => new ref. filter */        if(cmp_filt(state->RCoeff, curAcf, state->ener[0], THRESH2) == 0) {            lpcCoeff = state->pastCoeff;        }                /* else */        /* transmit current filter => new ref. filter */        else {            lpcCoeff = curCoeff;            calc_RCoeff(curCoeff, state->RCoeff);        }                /* Compute SID frame codes */        az_lsp(lpcCoeff, lsp_new, lsp_old_q); /* From A(z) to lsp */                /* LSP quantization */        lsfq_noise(&state->lsfq_s, lsp_new, state->lspSid_q, freq_prev, &ana[1]);                state->prev_energy = energyq;        ana[4] = cur_igain;        state->sid_gain = tab_Sidgain[cur_igain];            } /* end of SID frame case */        /* Compute new excitation */    if(pastVad != 0) {        state->cur_gain = state->sid_gain;    }    else {        state->cur_gain *= A_GAIN0;        state->cur_gain += A_GAIN1 * state->sid_gain;    }        calc_exc_rand(state->exc_err, state->cur_gain, exc, seed, FLAG_COD);        int_qlpc(lsp_old_q, state->lspSid_q, Aq);    /*for(i=0; i<M; i++) lsp_old_q[i] = state->lspSid_q[i];*/	copy(state->lspSid_q, lsp_old_q, M);            /* Update sumAcf if fr_cur = 0 */    if(state->fr_cur == 0) {        update_sumAcf(state);    }}/*-----------------------------------------------------------** procedure update_cng:                                     **           ~~~~~~~~~~                                      **   updates autocorrelation arrays                          **   used for DTX/CNG                                        **   If Vad=1 : updating of array sumAcf                     **-----------------------------------------------------------*/void update_cng(struct cod_cng_state_t * state,    FLOAT *r,         /* (i) :   frame autocorrelation               */    int Vad           /* (i) :   current Vad decision                */){    int i;    FLOAT *ptr1, *ptr2;        /* Update Acf */    ptr1 = state->Acf + SIZ_ACF - 1;    ptr2 = ptr1 - MP1;    for(i=0; i<(SIZ_ACF-MP1); i++) {        *ptr1-- = *ptr2--;    }        /* Save current Acf */    /*for(i=0; i<MP1; i++) state->Acf[i] = r[i];*/    copy(r, state->Acf, MP1);        state->fr_cur++;    if(state->fr_cur == NB_CURACF) {        state->fr_cur = 0;        if(Vad != 0) {            update_sumAcf(state);        }    }}/*-----------------------------------------------------------**         Local procedures                                  **         ~~~~~~~~~~~~~~~~                                  **-----------------------------------------------------------*//* Compute autocorr of LPC coefficients used for Itakura distance *//******************************************************************/static void calc_RCoeff(FLOAT *Coeff, FLOAT *RCoeff){    int i, j;    FLOAT temp;        /* RCoeff[0] = SUM(j=0->M) Coeff[j] ** 2 */    for(j=0, temp = (F)0.; j <= M; j++) {        temp += Coeff[j] * Coeff[j];    }    RCoeff[0] = temp;        /* RCoeff[i] = SUM(j=0->M-i) Coeff[j] * Coeff[j+i] */    for(i=1; i<=M; i++) {        for(j=0, temp=(F)0.; j<=M-i; j++) {            temp += Coeff[j] * Coeff[j+i];        }        RCoeff[i] = (F)2. * temp;    }}/* Compute Itakura distance and compare to threshold *//*****************************************************/static int cmp_filt(FLOAT *RCoeff, FLOAT *acf, FLOAT alpha, FLOAT Thresh){    FLOAT temp1, temp2;    int i;    int diff;        temp1 = (F)0.;    for(i=0; i <= M; i++) {        temp1 += RCoeff[i] * acf[i];    }        temp2 = alpha * Thresh;    if(temp1 > temp2) diff = 1;    else diff = 0;        return(diff);}/* Compute past average filter *//*******************************/static void calc_pastfilt(struct cod_cng_state_t * state, FLOAT *Coeff){    FLOAT s_sumAcf[MP1];    FLOAT bid[M];    calc_sum_acf(state->sumAcf, s_sumAcf, NB_SUMACF);        if(s_sumAcf[0] == (F)0.) {        Coeff[0] = (F)1.;        /*for(i=1; i<=M; i++) Coeff[i] = (F)0.;*/		set_zero(Coeff + 1, M);        return;    }    levinson(s_sumAcf, Coeff, bid);}/* Update sumAcf *//*****************/static void update_sumAcf(struct cod_cng_state_t * state){    FLOAT *ptr1, *ptr2;    int i;        /*** Move sumAcf ***/    ptr1 = state->sumAcf + SIZ_SUMACF - 1;    ptr2 = ptr1 - MP1;    for(i=0; i<(SIZ_SUMACF-MP1); i++) {        *ptr1-- = *ptr2--;    }        /* Compute new sumAcf */    calc_sum_acf(state->Acf, state->sumAcf, NB_CURACF);}/* Compute sum of acfs (curAcf, sumAcf or s_sumAcf) *//****************************************************/static void calc_sum_acf(FLOAT *acf, FLOAT *sum, int nb){        FLOAT *ptr1;    int i, j;        /*for(j=0; j<MP1; j++) sum[j] = (F)0.;*/	set_zero(sum, MP1);    ptr1 = acf;    for(i=0; i<nb; i++) {        for(j=0; j<MP1; j++) {            sum[j] += (*ptr1++);        }    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -