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

📄 dtx.c

📁 通讯协议
💻 C
📖 第 1 页 / 共 3 页
字号:
/**************************************************************************
 *
 *
 * Function    : dtx_dec_reset
 *
 *
 **************************************************************************/
Word16 dtx_dec_reset(dtx_decState * st, Word16 isf_init[])
{
    Word16 i;

    test();
    if (st == (dtx_decState *) NULL)
    {
        fprintf(stderr, "dtx_dec_reset: invalid parameter\n");
        return -1;
    }
    st->since_last_sid = 0;                move16();
    st->true_sid_period_inv = (1 << 13);   move16();  /* 0.25 in Q15 */

    st->log_en = 3500;                     move16();
    st->old_log_en = 3500;                 move16();
    /* low level noise for better performance in  DTX handover cases */

    st->cng_seed = RANDOM_INITSEED;        move16();

    st->hist_ptr = 0;                      move16();

    /* Init isf_hist[] and decoder log frame energy */
    Copy(isf_init, st->isf, M);
    Copy(isf_init, st->isf_old, M);

    for (i = 0; i < DTX_HIST_SIZE; i++)
    {
        Copy(isf_init, &st->isf_hist[i * M], M);
        st->log_en_hist[i] = st->log_en;   move16();
    }

    st->dtxHangoverCount = DTX_HANG_CONST; move16();
    st->decAnaElapsedCount = 32767;        move16();

    st->sid_frame = 0;                     move16();
    st->valid_data = 0;                    move16();
    st->dtxHangoverAdded = 0;              move16();

    st->dtxGlobalState = SPEECH;           move16();
    st->data_updated = 0;                  move16();

    st->dither_seed = RANDOM_INITSEED;     move16();
    st->CN_dith = 0;

    return 0;
}

/**************************************************************************
 *
 *
 * Function    : dtx_dec_exit
 *
 *
 **************************************************************************/
void dtx_dec_exit(dtx_decState ** st)
{
    test();
    if (st == NULL || *st == NULL)
        return;

    /* deallocate memory */
    free(*st);
    *st = NULL;

    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    : dtx_dec
 *
 *
 **************************************************************************/
Word16 dtx_dec(
     dtx_decState * st,                    /* i/o : State struct                                          */
     Word16 * exc2,                        /* o   : CN excitation                                          */
     Word16 new_state,                     /* i   : New DTX state                                          */
     Word16 isf[],                         /* o   : CN ISF vector                                          */
     Word16 ** prms
)
{
    Word16 log_en_index;
    Word16 ind[7];
    Word16 i, j;
    Word16 int_fac;
    Word16 gain;

    Word32 L_isf[M], L_log_en_int, level32, ener32;
    Word16 ptr;
    Word16 tmp_int_length;
    Word16 tmp, exp, exp0, log_en_int_e, log_en_int_m, level;

    /* This function is called if synthesis state is not SPEECH the globally passed  inputs to this function
     * are st->sid_frame st->valid_data st->dtxHangoverAdded new_state  (SPEECH, DTX, DTX_MUTE) */
    test();test();
    if ((st->dtxHangoverAdded != 0) &&
        (st->sid_frame != 0))
    {
        /* sid_first after dtx hangover period */
        /* or sid_upd after dtxhangover        */

        /* consider  twice the last frame */
        ptr = add(st->hist_ptr, 1);
        test();
        if (sub(ptr, DTX_HIST_SIZE) == 0)
            ptr = 0;                       move16();

        Copy(&st->isf_hist[st->hist_ptr * M], &st->isf_hist[ptr * M], M);

        st->log_en_hist[ptr] = st->log_en_hist[st->hist_ptr];   move16();

        /* compute mean log energy and isf from decoded signal (SID_FIRST) */
        st->log_en = 0;                    move16();
        for (i = 0; i < M; i++)
        {
            L_isf[i] = 0;                  move32();
        }

        /* average energy and isf */
        for (i = 0; i < DTX_HIST_SIZE; i++)
        {
            /* Division by DTX_HIST_SIZE = 8 has been done in dtx_buffer log_en is in Q10 */
            st->log_en = add(st->log_en, st->log_en_hist[i]);   move16();

            for (j = 0; j < M; j++)
            {
                L_isf[j] = L_add(L_isf[j], L_deposit_l(st->isf_hist[i * M + j]));       move32();
            }
        }

        /* st->log_en in Q9 */
        st->log_en = shr(st->log_en, 1);   move16();

        /* Add 2 in Q9, in order to have only positive values for Pow2 */
        /* this value is subtracted back after Pow2 function */
        st->log_en = add(st->log_en, 1024);move16();
        test();
        if (st->log_en < 0)
            st->log_en = 0;                move16();

        for (j = 0; j < M; j++)
        {
            st->isf[j] = extract_l(L_shr(L_isf[j], 3)); move32();  /* divide by 8 */
        }

    }
    test();
    if (st->sid_frame != 0)
    {
        /* Set old SID parameters, always shift */
        /* even if there is no new valid_data   */

        Copy(st->isf, st->isf_old, M);
        st->old_log_en = st->log_en;       move16();
        test();
        if (st->valid_data != 0)           /* new data available (no CRC) */
        {
            /* st->true_sid_period_inv = 1.0f/st->since_last_sid; */
            /* Compute interpolation factor, since the division only works * for values of since_last_sid <
             * 32 we have to limit the      * interpolation to 32 frames                                  */
            tmp_int_length = st->since_last_sid;        move16();

            test();
            if (sub(tmp_int_length, 32) > 0)
            {
                tmp_int_length = 32;       move16();
            }
            test();
            if (sub(tmp_int_length, 2) >= 0)
            {
                move16();
                st->true_sid_period_inv = div_s(1 << 10, shl(tmp_int_length, 10));
            } else
            {
                st->true_sid_period_inv = 1 << 14;      /* 0.5 it Q15 */move16();
            }

            ind[0] = Serial_parm(6, prms); move16();
            ind[1] = Serial_parm(6, prms); move16();
            ind[2] = Serial_parm(6, prms); move16();
            ind[3] = Serial_parm(5, prms); move16();
            ind[4] = Serial_parm(5, prms); move16();

            Disf_ns(ind, st->isf);

            log_en_index = Serial_parm(6, prms);

            /* read background noise stationarity information */
            st->CN_dith = Serial_parm(1, prms); move16();

            /* st->log_en = (float)log_en_index / 2.625 - 2.0;  */
            /* log2(E) in Q9 (log2(E) lies in between -2:22) */
            st->log_en = shl(log_en_index, 15 - 6);     move16();

            /* Divide by 2.625  */
            st->log_en = mult(st->log_en, 12483);       move16();
            /* Subtract 2 in Q9 is done later, after Pow2 function  */

            /* no interpolation at startup after coder reset        */
            /* or when SID_UPD has been received right after SPEECH */
            test();test();
            if ((st->data_updated == 0) ||
                (sub(st->dtxGlobalState, SPEECH) == 0))
            {
                Copy(st->isf, st->isf_old, M);
                st->old_log_en = st->log_en;    move16();
            }
        }                                  /* endif valid_data */
    }                                      /* endif sid_frame */
    test();
    test();
    if ((st->sid_frame != 0) && (st->valid_data != 0))
    {
        st->since_last_sid = 0;            move16();
    }
    /* Interpolate SID info */
    int_fac = shl(st->since_last_sid, 10); /* Q10 */move16();
    int_fac = mult(int_fac, st->true_sid_period_inv);   /* Q10 * Q15 -> Q10 */

    /* Maximize to 1.0 in Q10 */
    test();
    if (sub(int_fac, 1024) > 0)
    {
        int_fac = 1024;                    move16();
    }
    int_fac = shl(int_fac, 4);             /* Q10 -> Q14 */

    L_log_en_int = L_mult(int_fac, st->log_en); /* Q14 * Q9 -> Q24 */

    for (i = 0; i < M; i++)
    {
        isf[i] = mult(int_fac, st->isf[i]);/* Q14 * Q15 -> Q14 */move16();
    }

    int_fac = sub(16384, int_fac);         /* 1-k in Q14 */move16();

    /* ( Q14 * Q9 -> Q24 ) + Q24 -> Q24 */
    L_log_en_int = L_mac(L_log_en_int, int_fac, st->old_log_en);

    for (i = 0; i < M; i++)
    {
        /* Q14 + (Q14 * Q15 -> Q14) -> Q14 */
        isf[i] = add(isf[i], mult(int_fac, st->isf_old[i]));    move16();
        isf[i] = shl(isf[i], 1);           /* Q14 -> Q15 */move16();
    }

    /* If background noise is non-stationary, insert comfort noise dithering */
    if (st->CN_dith != 0)
    {
        CN_dithering(isf, &L_log_en_int, &st->dither_seed);
    }
    /* L_log_en_int corresponds to log2(E)+2 in Q24, i.e log2(gain)+1 in Q25 */
    /* Q25 -> Q16 */
    L_log_en_int = L_shr(L_log_en_int, 9);

    /* Find integer part  */
    log_en_int_e = extract_h(L_log_en_int);

    /* Find fractional part */
    log_en_int_m = extract_l(L_shr(L_sub(L_log_en_int, L_deposit_h(log_en_int_e)), 1));

    /* Subtract 2 from L_log_en_int in Q9, i.e divide the gain by 2 (energy by 4) */
    /* Add 16 in order to have the result of pow2 in Q16 */
    log_en_int_e = add(log_en_int_e, 16 - 1);

    /* level = (float)( pow( 2.0f, log_en ) );  */
    level32 = Pow2(log_en_int_e, log_en_int_m); /* Q16 */
    exp0 = norm_l(level32);
    level32 = L_shl(level32, exp0);        /* level in Q31 */
    exp0 = sub(15, exp0);
    level = extract_h(level32);            /* level in Q15 */

    /* generate white noise vector */
    for (i = 0; i < L_FRAME; i++)
    {
        exc2[i] = shr(Random(&(st->cng_seed)), 4);      move16();
    }

    /* gain = level / sqrt(ener) * sqrt(L_FRAME) */

    /* energy of generated excitation */
    ener32 = Dot_product12(exc2, exc2, L_FRAME, &exp);

    Isqrt_n(&ener32, &exp);

    gain = extract_h(ener32);

    gain = mult(level, gain);              /* gain in Q15 */

    exp = add(exp0, exp);

    /* Multiply by sqrt(L_FRAME)=16, i.e. shift left by 4 */
    exp = add(exp, 4);

    for (i = 0; i < L_FRAME; i++)
    {
        tmp = mult(exc2[i], gain);         /* Q0 * Q15 */
        exc2[i] = shl(tmp, exp);           move16();
    }

    test();
    if (sub(new_state, DTX_MUTE) == 0)
    {
        /* mute comfort noise as it has been quite a long time since last SID update  was performed                            */

        tmp_int_length = st->since_last_sid;    move16();
        test();
        if (sub(tmp_int_length, 32) > 0)
        {
            tmp_int_length = 32;           move16();
        }
        move16();
        st->true_sid_period_inv = div_s(1 << 10, shl(tmp_int_length, 10));

        st->since_last_sid = 0;            move16();
        st->old_log_en = st->log_en;       move16();
        /* subtract 1/8 in Q9 (energy), i.e -3/8 dB */
        st->log_en = sub(st->log_en, 64);  move16();
    }
    /* reset interpolation length timer if data has been updated.        */
    test();test();test();test();
    if ((st->sid_frame != 0) &&
        ((st->valid_data != 0) ||
            ((st->valid_data == 0) && (st->dtxHangoverAdded) != 0)))
    {
        st->since_last_sid = 0;            move16();
        st->data_updated = 1;              move16();
    }
    return 0;
}


void dtx_dec_activity_update(
     dtx_decState * st,
     Word16 isf[],
     Word16 exc[])
{
    Word16 i;

    Word32 L_frame_en;
    Word16 log_en_e, log_en_m, log_en;


    st->hist_ptr = add(st->hist_ptr, 1);   move16();
    test();
    if (sub(st->hist_ptr, DTX_HIST_SIZE) == 0)
    {
        st->hist_ptr = 0;                  move16();
    }
    Copy(isf, &st->isf_hist[st->hist_ptr * M], M);

    /* compute log energy based on excitation frame energy in Q0 */
    L_frame_en = 0;                        move32();
    for (i = 0; i < L_FRAME; i++)
    {
        L_frame_en = L_mac(L_frame_en, exc[i], exc[i]);
    }
    L_frame_en = L_shr(L_frame_en, 1);

    /* log_en = (float)log10(L_frame_en/(float)L_FRAME)/(float)log10(2.0f); */
    Log2(L_frame_en, &log_en_e, &log_en_m);

    /* convert exponent and mantissa to Word16 Q7. Q7 is used to simplify averaging in dtx_enc */
    log_en = shl(log_en_e, 7);             /* Q7 */
    log_en = add(log_en, shr(log_en_m, 15 - 7));

    /* Divide by L_FRAME = 256, i.e subtract 8 in Q7 = 1024 */
    log_en = sub(log_en, 1024);

    /* insert into log energy buffer */
    st->log_en_hist[st->hist_ptr] = log_en;move16();

    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

⌨️ 快捷键说明

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