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

📄 dtx.c

📁 通讯协议
💻 C
📖 第 1 页 / 共 3 页
字号:
     RX_SPARE              |(class2 garb.)|               |
     ----------------------------------------------------------------
*/

Word16 rx_dtx_handler(
     dtx_decState * st,                    /* i/o : State struct     */
     Word16 frame_type                     /* i   : Frame type       */
)
{
    Word16 newState;
    Word16 encState;

    /* DTX if SID frame or previously in DTX{_MUTE} and (NO_RX OR BAD_SPEECH) */
    test();test();test();
    test();test();test();
    test();test();
    if ((sub(frame_type, RX_SID_FIRST) == 0) ||
        (sub(frame_type, RX_SID_UPDATE) == 0) ||
        (sub(frame_type, RX_SID_BAD) == 0) ||
        (((sub(st->dtxGlobalState, DTX) == 0) ||
                (sub(st->dtxGlobalState, DTX_MUTE) == 0)) &&
            ((sub(frame_type, RX_NO_DATA) == 0) ||
                (sub(frame_type, RX_SPEECH_BAD) == 0) ||
                (sub(frame_type, RX_SPEECH_LOST) == 0))))
    {
        newState = DTX;                    move16();

        /* stay in mute for these input types */
        test();test();test();test();test();
        if ((sub(st->dtxGlobalState, DTX_MUTE) == 0) &&
            ((sub(frame_type, RX_SID_BAD) == 0) ||
                (sub(frame_type, RX_SID_FIRST) == 0) ||
                (sub(frame_type, RX_SPEECH_LOST) == 0) ||
                (sub(frame_type, RX_NO_DATA) == 0)))
        {
            newState = DTX_MUTE;           move16();
        }
        /* evaluate if noise parameters are too old                     */
        /* since_last_sid is reset when CN parameters have been updated */
        st->since_last_sid = add(st->since_last_sid, 1);        move16();

        /* no update of sid parameters in DTX for a long while */
        test();
        if (sub(st->since_last_sid, DTX_MAX_EMPTY_THRESH) > 0)
        {
            newState = DTX_MUTE;           move16();
        }
    } else
    {
        newState = SPEECH;                 move16();
        st->since_last_sid = 0;            move16();
    }

    /* 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. */
    test();test();
    if ((st->data_updated == 0) &&
        (sub(frame_type, RX_SID_UPDATE) == 0))
    {
        st->decAnaElapsedCount = 0;        move16();
    }
    /* update the SPE-SPD DTX hangover synchronization */
    /* to know when SPE has added dtx hangover         */
    st->decAnaElapsedCount = add(st->decAnaElapsedCount, 1);    move16();
    st->dtxHangoverAdded = 0;              move16();

    test();test();test();test();
    if ((sub(frame_type, RX_SID_FIRST) == 0) ||
        (sub(frame_type, RX_SID_UPDATE) == 0) ||
        (sub(frame_type, RX_SID_BAD) == 0) ||
        (sub(frame_type, RX_NO_DATA) == 0))
    {
        encState = DTX;                    move16();
    } else
    {
        encState = SPEECH;                 move16();
    }

    test();
    if (sub(encState, SPEECH) == 0)
    {
        st->dtxHangoverCount = DTX_HANG_CONST;  move16();
    } else
    {
        test();test();
        if (sub(st->decAnaElapsedCount, DTX_ELAPSED_FRAMES_THRESH) > 0)
        {
            st->dtxHangoverAdded = 1;      move16();
            st->decAnaElapsedCount = 0;    move16();
            st->dtxHangoverCount = 0;      move16();
        } else if (test(), st->dtxHangoverCount == 0)
        {
            st->decAnaElapsedCount = 0;    move16();
        } else
        {
            st->dtxHangoverCount = sub(st->dtxHangoverCount, 1);        move16();
        }
    }
    test();
    if (sub(newState, SPEECH) != 0)
    {
        /* 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;                 move16();
        st->valid_data = 0;                move16();

        test();test();test();
        if (sub(frame_type, RX_SID_FIRST) == 0)
        {
            st->sid_frame = 1;             move16();
        } else if (test(), sub(frame_type, RX_SID_UPDATE) == 0)
        {
            st->sid_frame = 1;             move16();
            st->valid_data = 1;            move16();
        } else if (test(), sub(frame_type, RX_SID_BAD) == 0)
        {
            st->sid_frame = 1;             move16();
            st->dtxHangoverAdded = 0;      /* use old data */move16();
        }
    }
    return newState;
    /* newState is used by both SPEECH AND DTX synthesis routines */
}

static void aver_isf_history(
     Word16 isf_old[],
     Word16 indices[],
     Word32 isf_aver[]
)
{
    Word16 i, j, k;
    Word16 isf_tmp[2 * M];
    Word32 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++)
    {
        test();
        if (add(indices[k], 1) != 0)
        {
            for (i = 0; i < M; i++)
            {
                isf_tmp[k * M + i] = isf_old[indices[k] * M + i];       move16();
                isf_old[indices[k] * M + i] = isf_old[indices[2] * M + i];      move16();
            }
        }
    }

    /* Perform the ISF averaging */
    for (j = 0; j < M; j++)
    {
        L_tmp = 0;                         move32();

        for (i = 0; i < DTX_HIST_SIZE; i++)
        {
            L_tmp = L_add(L_tmp, L_deposit_l(isf_old[i * M + j]));
        }
        isf_aver[j] = L_tmp;               move32();
    }

    /* Retrieve from isf_tmp[][] the ISF vectors saved prior to averaging */
    for (k = 0; k < 2; k++)
    {
        test();
        if (add(indices[k], 1) != 0)
        {
            for (i = 0; i < M; i++)
            {
                isf_old[indices[k] * M + i] = isf_tmp[k * M + i];       move16();
            }
        }
    }

    return;
}

static void find_frame_indices(
     Word16 isf_old_tx[],
     Word16 indices[],
     dtx_encState * st
)
{
    Word32 L_tmp, summin, summax, summax2nd;
    Word16 i, j, tmp;
    Word16 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;           move16();
    j = -1;                                move16();
    for (i = 0; i < DTX_HIST_SIZE_MIN_ONE; i++)
    {
        j = add(j, tmp);
        st->sumD[i] = L_sub(st->sumD[i], st->D[j]);     move16();
        tmp = sub(tmp, 1);
    }

    /* 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];     move32();
    }
    st->sumD[0] = 0;                       move32();

    /* 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;                               move16();
    for (i = 27; i >= 12; i = (Word16) (i - tmp))
    {
        tmp = add(tmp, 1);
        for (j = tmp; j > 0; j--)
        {
            st->D[i - j + 1] = st->D[i - j - tmp];      move32();
        }
    }

    /* Compute the first column of the distance matrix D            */
    /* (squared Euclidean distances from isf1[] to isf_old_tx[][]). */

    ptr = st->hist_ptr;                    move16();
    for (i = 1; i < DTX_HIST_SIZE; i++)
    {
        /* Compute the distance between the latest isf and the other isfs. */
        ptr = sub(ptr, 1);
        test();
        if (ptr < 0)
        {
            ptr = DTX_HIST_SIZE_MIN_ONE;   move16();
        }
        L_tmp = 0;                         move32();
        for (j = 0; j < M; j++)
        {
            tmp = sub(isf_old_tx[st->hist_ptr * M + j], isf_old_tx[ptr * M + j]);
            L_tmp = L_mac(L_tmp, tmp, tmp);
        }
        st->D[i - 1] = L_tmp;              move32();

        /* Update also the column sums. */
        st->sumD[0] = L_add(st->sumD[0], st->D[i - 1]); move32();
        st->sumD[i] = L_add(st->sumD[i], st->D[i - 1]); move32();
    }

    /* Find the minimum and maximum distances */
    summax = st->sumD[0];                  move32();
    summin = st->sumD[0];                  move32();
    indices[0] = 0;                        move16();
    indices[2] = 0;                        move16();
    for (i = 1; i < DTX_HIST_SIZE; i++)
    {
        test();
        if (L_sub(st->sumD[i], summax) > 0)
        {
            indices[0] = i;                move16();
            summax = st->sumD[i];          move32();
        }
        test();
        if (L_sub(st->sumD[i], summin) < 0)
        {
            indices[2] = i;                move16();
            summin = st->sumD[i];          move32();
        }
    }

    /* Find the second largest distance */
    summax2nd = -2147483647L;              move32();
    indices[1] = -1;                       move16();
    for (i = 0; i < DTX_HIST_SIZE; i++)
    {
        test();
        if ((L_sub(st->sumD[i], summax2nd) > 0) && (sub(i, indices[0]) != 0))
        {
            indices[1] = i;                move16();
            summax2nd = st->sumD[i];       move32();
        }
    }

    for (i = 0; i < 3; i++)
    {
        indices[i] = sub(st->hist_ptr, indices[i]);     move16();
        test();
        if (indices[i] < 0)
        {
            indices[i] = add(indices[i], DTX_HIST_SIZE);        move16();
        }
    }

    /* If maximum distance/MED_THRESH is smaller than minimum distance */
    /* then the median ISF vector replacement is not performed         */
    tmp = norm_l(summax);
    summax = L_shl(summax, tmp);
    summin = L_shl(summin, tmp);
    L_tmp = L_mult(round(summax), INV_MED_THRESH);
    test();
    if (L_sub(L_tmp, summin) <= 0)
    {
        indices[0] = -1;                   move16();
    }
    /* If second largest distance/MED_THRESH is smaller than     */
    /* minimum distance then the median ISF vector replacement is    */
    /* not performed                                                 */
    summax2nd = L_shl(summax2nd, tmp);
    L_tmp = L_mult(round(summax2nd), INV_MED_THRESH);
    test();
    if (L_sub(L_tmp, summin) <= 0)
    {
        indices[1] = -1;                   move16();
    }
    return;
}

static Word16 dithering_control(
     dtx_encState * st
)
{
    Word16 i, tmp, mean, CN_dith, gain_diff;
    Word32 ISF_diff;

    /* determine how stationary the spectrum of background noise is */
    ISF_diff = 0;
    for (i = 0; i < 8; i++)
    {
        ISF_diff = L_add(ISF_diff, st->sumD[i]);
    }
    if (L_shr(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(mean, st->log_en_hist[i]);
    }
    mean = shr(mean, 3);
    gain_diff = 0;
    for (i = 0; i < DTX_HIST_SIZE; i++)
    {
        tmp = abs_s(sub(st->log_en_hist[i], mean));
        gain_diff = add(gain_diff, tmp);
    }
    if (sub(gain_diff, GAIN_THR) > 0)
    {
        CN_dith = 1;
    }
    return CN_dith;
}

static void CN_dithering(
     Word16 isf[M],
     Word32 * L_log_en_int,
     Word16 * dither_seed
)
{
    Word16 temp, temp1, i, dither_fac, rand_dith;
    Word16 rand_dith2;

    /* Insert comfort noise dithering for energy parameter */
    rand_dith = shr(Random(dither_seed), 1);
    rand_dith2 = shr(Random(dither_seed), 1);
    rand_dith = add(rand_dith, rand_dith2);
    *L_log_en_int = L_add(*L_log_en_int, L_mult(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 = shr(Random(dither_seed), 1);
    rand_dith2 = shr(Random(dither_seed), 1);
    rand_dith = add(rand_dith, rand_dith2);
    temp = add(isf[0], mult_r(rand_dith, dither_fac));

    /* Make sure that isf[0] will not get negative values */
    if (sub(temp, ISF_GAP) < 0)
    {
        isf[0] = ISF_GAP;
    } else
    {
        isf[0] = temp;
    }

    for (i = 1; i < M - 1; i++)
    {
        dither_fac = add(dither_fac, ISF_FACTOR_STEP);

        rand_dith = shr(Random(dither_seed), 1);
        rand_dith2 = shr(Random(dither_seed), 1);
        rand_dith = add(rand_dith, rand_dith2);
        temp = add(isf[i], mult_r(rand_dith, dither_fac));
        temp1 = sub(temp, isf[i - 1]);

        /* Make sure that isf spacing remains at least ISF_DITH_GAP Hz */
        if (sub(temp1, ISF_DITH_GAP) < 0)
        {
            isf[i] = add(isf[i - 1], ISF_DITH_GAP);
        } else
        {
            isf[i] = temp;
        }
    }

    /* Make sure that isf[M-2] will not get values above 16384 */
    if (sub(isf[M - 2], 16384) > 0)
    {
        isf[M - 2] = 16384;
    }
    return;
}

⌨️ 快捷键说明

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