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

📄 dtx_decoder_amr_wb.cpp

📁 实现3GPP的GSM中AMR语音的CODECS。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    log_en += log_en_m >> 8;    /* Divide by L_FRAME = 256, i.e subtract 8 in Q7 = 1024 */    log_en -= 1024;    /* insert into log energy buffer */    st->log_en_hist[st->hist_ptr] = log_en;    return;}/*     Table of new SPD synthesis states                           |     previous SPD_synthesis_state     Incoming              |     frame_type            | SPEECH       | DTX           | DTX_MUTE     ---------------------------------------------------------------     RX_SPEECH_GOOD ,      |              |               |     RX_SPEECH_PR_DEGRADED | SPEECH       | SPEECH        | SPEECH     ----------------------------------------------------------------     RX_SPEECH_BAD,        | SPEECH       | DTX           | DTX_MUTE     ----------------------------------------------------------------     RX_SID_FIRST,         | DTX          | DTX/(DTX_MUTE)| DTX_MUTE     ----------------------------------------------------------------     RX_SID_UPDATE,        | DTX          | DTX           | DTX     ----------------------------------------------------------------     RX_SID_BAD,           | DTX          | DTX/(DTX_MUTE)| DTX_MUTE     ----------------------------------------------------------------     RX_NO_DATA,           | SPEECH       | DTX/(DTX_MUTE)| DTX_MUTE     RX_SPARE              |(class2 garb.)|               |     ----------------------------------------------------------------*//*----------------------------------------------------------------------------; FUNCTION CODE----------------------------------------------------------------------------*/int16 rx_amr_wb_dtx_handler(    dtx_decState * st,                    /* i/o : State struct     */    int16 frame_type                     /* i   : Frame type       */){    int16 newState;    int16 encState;    /* DTX if SID frame or previously in DTX{_MUTE} and (NO_RX OR BAD_SPEECH) */    if ((frame_type == RX_SID_FIRST)  ||            (frame_type == RX_SID_UPDATE) ||            (frame_type == RX_SID_BAD)    ||            (((st->dtxGlobalState == DTX) ||              (st->dtxGlobalState == DTX_MUTE)) &&             ((frame_type == RX_NO_DATA)    ||              (frame_type == RX_SPEECH_BAD) ||              (frame_type == RX_SPEECH_LOST))))    {        newState = DTX;        /* stay in mute for these input types */        if ((st->dtxGlobalState == DTX_MUTE) &&                ((frame_type == RX_SID_BAD) ||                 (frame_type == RX_SID_FIRST) ||                 (frame_type == RX_SPEECH_LOST) ||                 (frame_type == RX_NO_DATA)))        {            newState = DTX_MUTE;        }        /* evaluate if noise parameters are too old                     */        /* since_last_sid is reset when CN parameters have been updated */        st->since_last_sid = add_int16(st->since_last_sid, 1);        /* no update of sid parameters in DTX for a long while */        if (st->since_last_sid > DTX_MAX_EMPTY_THRESH)        {            newState = DTX_MUTE;        }    }    else    {        newState = SPEECH;        st->since_last_sid = 0;    }    /* reset the decAnaElapsed Counter when receiving CNI data the first time, to robustify counter missmatch     * after handover this might delay the bwd CNI analysis in the new decoder slightly. */    if ((st->data_updated == 0) &&            (frame_type == RX_SID_UPDATE))    {        st->decAnaElapsedCount = 0;    }    /* update the SPE-SPD DTX hangover synchronization */    /* to know when SPE has added dtx hangover         */    st->decAnaElapsedCount = add_int16(st->decAnaElapsedCount, 1);    st->dtxHangoverAdded = 0;    if ((frame_type == RX_SID_FIRST) ||            (frame_type == RX_SID_UPDATE) ||            (frame_type == RX_SID_BAD) ||            (frame_type == RX_NO_DATA))    {        encState = DTX;    }    else    {        encState = SPEECH;    }    if (encState == SPEECH)    {        st->dtxHangoverCount = DTX_HANG_CONST;    }    else    {        if (st->decAnaElapsedCount > DTX_ELAPSED_FRAMES_THRESH)        {            st->dtxHangoverAdded = 1;            st->decAnaElapsedCount = 0;            st->dtxHangoverCount = 0;        }        else if (st->dtxHangoverCount == 0)        {            st->decAnaElapsedCount = 0;        }        else        {            st->dtxHangoverCount--;        }    }    if (newState != SPEECH)    {        /* DTX or DTX_MUTE CN data is not in a first SID, first SIDs are marked as SID_BAD but will do         * backwards analysis if a hangover period has been added according to the state machine above */        st->sid_frame = 0;        st->valid_data = 0;        if (frame_type == RX_SID_FIRST)        {            st->sid_frame = 1;        }        else if (frame_type == RX_SID_UPDATE)        {            st->sid_frame = 1;            st->valid_data = 1;        }        else if (frame_type == RX_SID_BAD)        {            st->sid_frame = 1;            st->dtxHangoverAdded = 0;      /* use old data */        }    }    return newState;    /* newState is used by both SPEECH AND DTX synthesis routines */}/*----------------------------------------------------------------------------; FUNCTION CODE----------------------------------------------------------------------------*/void aver_isf_history(    int16 isf_old[],    int16 indices[],    int32 isf_aver[]){    int16 i, j, k;    int16 isf_tmp[2 * M];    int32 L_tmp;    /* Memorize in isf_tmp[][] the ISF vectors to be replaced by */    /* the median ISF vector prior to the averaging               */    for (k = 0; k < 2; k++)    {        if (indices[k] + 1 != 0)        {            for (i = 0; i < M; i++)            {                isf_tmp[k * M + i] = isf_old[indices[k] * M + i];                isf_old[indices[k] * M + i] = isf_old[indices[2] * M + i];            }        }    }    /* Perform the ISF averaging */    for (j = 0; j < M; j++)    {        L_tmp = 0;        for (i = 0; i < DTX_HIST_SIZE; i++)        {            L_tmp = add_int32(L_tmp, (int32)(isf_old[i * M + j]));        }        isf_aver[j] = L_tmp;    }    /* Retrieve from isf_tmp[][] the ISF vectors saved prior to averaging */    for (k = 0; k < 2; k++)    {        if (indices[k] + 1 != 0)        {            for (i = 0; i < M; i++)            {                isf_old[indices[k] * M + i] = isf_tmp[k * M + i];            }        }    }    return;}/*----------------------------------------------------------------------------; FUNCTION CODE----------------------------------------------------------------------------*/void find_frame_indices(    int16 isf_old_tx[],    int16 indices[],    dtx_encState * st){    int32 L_tmp, summin, summax, summax2nd;    int16 i, j, tmp;    int16 ptr;    /* Remove the effect of the oldest frame from the column */    /* sum sumD[0..DTX_HIST_SIZE-1]. sumD[DTX_HIST_SIZE] is    */    /* not updated since it will be removed later.           */    tmp = DTX_HIST_SIZE_MIN_ONE;    j = -1;    for (i = 0; i < DTX_HIST_SIZE_MIN_ONE; i++)    {        j += tmp;        st->sumD[i] = sub_int32(st->sumD[i], st->D[j]);        tmp--;    }    /* Shift the column sum sumD. The element sumD[DTX_HIST_SIZE-1]    */    /* corresponding to the oldest frame is removed. The sum of     */    /* the distances between the latest isf and other isfs, */    /* i.e. the element sumD[0], will be computed during this call. */    /* Hence this element is initialized to zero.                   */    for (i = DTX_HIST_SIZE_MIN_ONE; i > 0; i--)    {        st->sumD[i] = st->sumD[i - 1];    }    st->sumD[0] = 0;    /* Remove the oldest frame from the distance matrix.           */    /* Note that the distance matrix is replaced by a one-         */    /* dimensional array to save static memory.                    */    tmp = 0;    for (i = 27; i >= 12; i -= tmp)    {        tmp++;        for (j = tmp; j > 0; j--)        {            st->D[i - j + 1] = st->D[i - j - tmp];        }    }    /* Compute the first column of the distance matrix D            */    /* (squared Euclidean distances from isf1[] to isf_old_tx[][]). */    ptr = st->hist_ptr;    for (i = 1; i < DTX_HIST_SIZE; i++)    {        /* Compute the distance between the latest isf and the other isfs. */        ptr--;        if (ptr < 0)        {            ptr = DTX_HIST_SIZE_MIN_ONE;        }        L_tmp = 0;        for (j = 0; j < M; j++)        {            tmp = sub_int16(isf_old_tx[st->hist_ptr * M + j], isf_old_tx[ptr * M + j]);            L_tmp = mac_16by16_to_int32(L_tmp, tmp, tmp);        }        st->D[i - 1] = L_tmp;        /* Update also the column sums. */        st->sumD[0] = add_int32(st->sumD[0], st->D[i - 1]);        st->sumD[i] = add_int32(st->sumD[i], st->D[i - 1]);    }    /* Find the minimum and maximum distances */    summax = st->sumD[0];    summin = st->sumD[0];    indices[0] = 0;    indices[2] = 0;    for (i = 1; i < DTX_HIST_SIZE; i++)    {        if (st->sumD[i] > summax)        {            indices[0] = i;            summax = st->sumD[i];        }        if (st->sumD[i] < summin)        {            indices[2] = i;            summin = st->sumD[i];        }    }    /* Find the second largest distance */    summax2nd = -2147483647L;    indices[1] = -1;    for (i = 0; i < DTX_HIST_SIZE; i++)    {        if ((st->sumD[i] > summax2nd) && (i != indices[0]))        {            indices[1] = i;            summax2nd = st->sumD[i];        }    }    for (i = 0; i < 3; i++)    {        indices[i] = sub_int16(st->hist_ptr, indices[i]);        if (indices[i] < 0)        {            indices[i] = add_int16(indices[i], DTX_HIST_SIZE);        }    }    /* If maximum distance/MED_THRESH is smaller than minimum distance */    /* then the median ISF vector replacement is not performed         */    tmp = normalize_amr_wb(summax);    summax <<= tmp;    summin <<= tmp;    L_tmp = mul_16by16_to_int32(amr_wb_round(summax), INV_MED_THRESH);    if (L_tmp <= summin)    {        indices[0] = -1;    }    /* If second largest distance/MED_THRESH is smaller than     */    /* minimum distance then the median ISF vector replacement is    */    /* not performed                                                 */    summax2nd = shl_int32(summax2nd, tmp);    L_tmp = mul_16by16_to_int32(amr_wb_round(summax2nd), INV_MED_THRESH);    if (L_tmp <= summin)    {        indices[1] = -1;    }    return;}/*----------------------------------------------------------------------------; FUNCTION CODE----------------------------------------------------------------------------*/int16 dithering_control(dtx_encState * st){    int16 i, tmp, mean, CN_dith, gain_diff;    int32 ISF_diff;    /* determine how stationary the spectrum of background noise is */    ISF_diff = 0;    for (i = 0; i < 8; i++)    {        ISF_diff = add_int32(ISF_diff, st->sumD[i]);    }    if ((ISF_diff >> 26) > 0)    {        CN_dith = 1;    }    else    {        CN_dith = 0;    }    /* determine how stationary the energy of background noise is */    mean = 0;    for (i = 0; i < DTX_HIST_SIZE; i++)    {        mean = add_int16(mean, st->log_en_hist[i]);    }    mean >>= 3;    gain_diff = 0;    for (i = 0; i < DTX_HIST_SIZE; i++)    {        tmp = sub_int16(st->log_en_hist[i], mean);        tmp = tmp - (tmp < 0);        gain_diff += tmp ^(tmp >> 15);    /*  tmp ^sign(tmp)  */;    }    if (gain_diff > GAIN_THR)    {        CN_dith = 1;    }    return CN_dith;}/*----------------------------------------------------------------------------; FUNCTION CODE----------------------------------------------------------------------------*/void CN_dithering(    int16 isf[M],    int32 * L_log_en_int,    int16 * dither_seed){    int16 temp, temp1, i, dither_fac, rand_dith;    int16 rand_dith2;    /* Insert comfort noise dithering for energy parameter */    rand_dith = noise_gen_amrwb(dither_seed) >> 1;    rand_dith2 = noise_gen_amrwb(dither_seed) >> 1;    rand_dith += rand_dith2;    *L_log_en_int = add_int32(*L_log_en_int, mul_16by16_to_int32(rand_dith, GAIN_FACTOR));    if (*L_log_en_int < 0)    {        *L_log_en_int = 0;    }    /* Insert comfort noise dithering for spectral parameters (ISF-vector) */    dither_fac = ISF_FACTOR_LOW;    rand_dith = noise_gen_amrwb(dither_seed) >> 1;    rand_dith2 = noise_gen_amrwb(dither_seed) >> 1;    rand_dith +=  rand_dith2;    temp = add_int16(isf[0], mult_int16_r(rand_dith, dither_fac));    /* Make sure that isf[0] will not get negative values */    if (temp < ISF_GAP)    {        isf[0] = ISF_GAP;    }    else    {        isf[0] = temp;    }    for (i = 1; i < M - 1; i++)    {        dither_fac = add_int16(dither_fac, ISF_FACTOR_STEP);        rand_dith = noise_gen_amrwb(dither_seed) >> 1;        rand_dith2 = noise_gen_amrwb(dither_seed) >> 1;        rand_dith +=  rand_dith2;        temp = add_int16(isf[i], mult_int16_r(rand_dith, dither_fac));        temp1 = sub_int16(temp, isf[i - 1]);        /* Make sure that isf spacing remains at least ISF_DITH_GAP Hz */        if (temp1 < ISF_DITH_GAP)        {            isf[i] = isf[i - 1] + ISF_DITH_GAP;        }        else        {            isf[i] = temp;        }    }    /* Make sure that isf[M-2] will not get values above 16384 */    if (isf[M - 2] > 16384)    {        isf[M - 2] = 16384;    }    return;}

⌨️ 快捷键说明

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