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

📄 dtx_decoder_amr_wb.cpp

📁 实现3GPP的GSM中AMR语音的CODECS。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* ------------------------------------------------------------------ * Copyright (C) 2008 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.173    ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec    Available from http://www.3gpp.org(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)Permission to distribute, modify and use this file under the standard licenseterms listed above has been obtained from the copyright holder.****************************************************************************************//*------------------------------------------------------------------------------ Filename: dtx_decoder_amr_wb.cpp     Date: 05/08/2007------------------------------------------------------------------------------ REVISION HISTORY Description:------------------------------------------------------------------------------ INPUT AND OUTPUT DEFINITIONS------------------------------------------------------------------------------ FUNCTION DESCRIPTION    DTX functions------------------------------------------------------------------------------ REQUIREMENTS------------------------------------------------------------------------------ REFERENCES------------------------------------------------------------------------------ PSEUDO-CODE------------------------------------------------------------------------------*//*----------------------------------------------------------------------------; INCLUDES----------------------------------------------------------------------------*/#include "pv_amr_wb_type_defs.h"#include "pvamrwbdecoder_basic_op.h"#include "pvamrwb_math_op.h"#include "pvamrwbdecoder_cnst.h"#include "pvamrwbdecoder_acelp.h"  /* prototype of functions    */#include "get_amr_wb_bits.h"#include "dtx.h"/*----------------------------------------------------------------------------; MACROS; Define module specific macros here----------------------------------------------------------------------------*//*----------------------------------------------------------------------------; DEFINES; Include all pre-processor statements here. Include conditional; compile variables also.----------------------------------------------------------------------------*//*----------------------------------------------------------------------------; LOCAL FUNCTION DEFINITIONS; Function Prototype declaration----------------------------------------------------------------------------*//*----------------------------------------------------------------------------; LOCAL STORE/BUFFER/POINTER DEFINITIONS; Variable declaration - defined here and used outside this module----------------------------------------------------------------------------*//*----------------------------------------------------------------------------; EXTERNAL FUNCTION REFERENCES; Declare functions defined elsewhere and referenced in this module----------------------------------------------------------------------------*//*----------------------------------------------------------------------------; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES; Declare variables used in this module but defined elsewhere----------------------------------------------------------------------------*//*----------------------------------------------------------------------------; FUNCTION CODE----------------------------------------------------------------------------*//* * Function    : dtx_dec_amr_wb_reset */int16 dtx_dec_amr_wb_reset(dtx_decState * st, const int16 isf_init[]){    int16 i;    if (st == (dtx_decState *) NULL)    {        /* dtx_dec_amr_wb_reset invalid parameter */        return (-1);    }    st->since_last_sid = 0;    st->true_sid_period_inv = (1 << 13);      /* 0.25 in Q15 */    st->log_en = 3500;    st->old_log_en = 3500;    /* low level noise for better performance in  DTX handover cases */    st->cng_seed = RANDOM_INITSEED;    st->hist_ptr = 0;    /* Init isf_hist[] and decoder log frame energy */    pv_memcpy((void *)st->isf, (void *)isf_init, M*sizeof(*isf_init));    pv_memcpy((void *)st->isf_old, (void *)isf_init, M*sizeof(*isf_init));    for (i = 0; i < DTX_HIST_SIZE; i++)    {        pv_memcpy((void *)&st->isf_hist[i * M], (void *)isf_init, M*sizeof(*isf_init));        st->log_en_hist[i] = st->log_en;    }    st->dtxHangoverCount = DTX_HANG_CONST;    st->decAnaElapsedCount = 32767;    st->sid_frame = 0;    st->valid_data = 0;    st->dtxHangoverAdded = 0;    st->dtxGlobalState = SPEECH;    st->data_updated = 0;    st->dither_seed = RANDOM_INITSEED;    st->CN_dith = 0;    return 0;}/*     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----------------------------------------------------------------------------*//* * Function    : dtx_dec_amr_wb */int16 dtx_dec_amr_wb(    dtx_decState * st,                    /* i/o : State struct         */    int16 * exc2,                        /* o   : CN excitation        */    int16 new_state,                     /* i   : New DTX state        */    int16 isf[],                         /* o   : CN ISF vector        */    int16 ** prms){    int16 log_en_index;    int16 ind[7];    int16 i, j;    int16 int_fac;    int16 gain;    int32 L_isf[M], L_log_en_int, level32, ener32;    int16 ptr;    int16 tmp_int_length;    int16 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) */    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 = st->hist_ptr + 1;        if (ptr == DTX_HIST_SIZE)            ptr = 0;        pv_memcpy((void *)&st->isf_hist[ptr * M], (void *)&st->isf_hist[st->hist_ptr * M], M*sizeof(*st->isf_hist));        st->log_en_hist[ptr] = st->log_en_hist[st->hist_ptr];        /* compute mean log energy and isf from decoded signal (SID_FIRST) */        st->log_en = 0;        for (i = 0; i < M; i++)        {            L_isf[i] = 0;        }        /* 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_int16(st->log_en, st->log_en_hist[i]);            for (j = 0; j < M; j++)            {                L_isf[j] = add_int32(L_isf[j], (int32)(st->isf_hist[i * M + j]));            }        }        /* st->log_en in Q9 */        st->log_en >>=  1;        /* Add 2 in Q9, in order to have only positive values for Pow2 */        /* this value is subtracted back after Pow2 function */        st->log_en += 1024;        if (st->log_en < 0)            st->log_en = 0;        for (j = 0; j < M; j++)        {            st->isf[j] = (int16)(L_isf[j] >> 3);  /* divide by 8 */        }    }    if (st->sid_frame != 0)    {        /* Set old SID parameters, always shift */        /* even if there is no new valid_data   */        pv_memcpy((void *)st->isf_old, (void *)st->isf, M*sizeof(*st->isf));        st->old_log_en = st->log_en;        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;            if (tmp_int_length > 32)            {                tmp_int_length = 32;            }            if (tmp_int_length >= 2)            {                st->true_sid_period_inv = div_16by16(1 << 10, shl_int16(tmp_int_length, 10));            }            else            {                st->true_sid_period_inv = 1 << 14;      /* 0.5 it Q15 */            }            ind[0] = Serial_parm(6, prms);            ind[1] = Serial_parm(6, prms);            ind[2] = Serial_parm(6, prms);            ind[3] = Serial_parm(5, prms);            ind[4] = Serial_parm(5, prms);            Disf_ns(ind, st->isf);            log_en_index = Serial_parm(6, prms);            /* read background noise stationarity information */            st->CN_dith = Serial_parm_1bit(prms);            /* 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_int16(log_en_index, 15 - 6);            /* Divide by 2.625  */            st->log_en = mult_int16(st->log_en, 12483);            /* 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 */            if ((st->data_updated == 0) || (st->dtxGlobalState == SPEECH))            {                pv_memcpy((void *)st->isf_old, (void *)st->isf, M*sizeof(*st->isf));                st->old_log_en = st->log_en;            }        }                                  /* endif valid_data */    }                                      /* endif sid_frame */    if ((st->sid_frame != 0) && (st->valid_data != 0))    {        st->since_last_sid = 0;    }    /* Interpolate SID info */    int_fac = shl_int16(st->since_last_sid, 10); /* Q10 */    int_fac = mult_int16(int_fac, st->true_sid_period_inv);   /* Q10 * Q15 -> Q10 */    /* Maximize to 1.0 in Q10 */    if (int_fac > 1024)    {        int_fac = 1024;    }    int_fac = shl_int16(int_fac, 4);             /* Q10 -> Q14 */    L_log_en_int = mul_16by16_to_int32(int_fac, st->log_en); /* Q14 * Q9 -> Q24 */    for (i = 0; i < M; i++)    {        isf[i] = mult_int16(int_fac, st->isf[i]);/* Q14 * Q15 -> Q14 */    }    int_fac = 16384 - int_fac;         /* 1-k in Q14 */    /* ( Q14 * Q9 -> Q24 ) + Q24 -> Q24 */    L_log_en_int = mac_16by16_to_int32(L_log_en_int, int_fac, st->old_log_en);    for (i = 0; i < M; i++)    {        /* Q14 + (Q14 * Q15 -> Q14) -> Q14 */        isf[i] = add_int16(isf[i], mult_int16(int_fac, st->isf_old[i]));        isf[i] = shl_int16(isf[i], 1);           /* Q14 -> Q15 */    }    /* 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 >>= 9;    /* Find integer part  */    log_en_int_e = extract_h(L_log_en_int);    /* Find fractional part */    log_en_int_m = (int16)(sub_int32(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 += 15;    /* level = (float)( pow( 2.0f, log_en ) );  */    level32 = power_of_2(log_en_int_e, log_en_int_m); /* Q16 */    exp0 = normalize_amr_wb(level32);    level32 <<= exp0;        /* level in Q31 */    exp0 = 15 - exp0;    level = (int16)(level32 >> 16);          /* level in Q15 */    /* generate white noise vector */    for (i = 0; i < L_FRAME; i++)    {        exc2[i] = noise_gen_amrwb(&(st->cng_seed)) >> 4;    }    /* gain = level / sqrt(ener) * sqrt(L_FRAME) */    /* energy of generated excitation */    ener32 = Dot_product12(exc2, exc2, L_FRAME, &exp);    one_ov_sqrt_norm(&ener32, &exp);    gain = extract_h(ener32);    gain = mult_int16(level, gain);              /* gain in Q15 */    exp += exp0;    /* Multiply by sqrt(L_FRAME)=16, i.e. shift left by 4 */    exp += 4;    for (i = 0; i < L_FRAME; i++)    {        tmp = mult_int16(exc2[i], gain);         /* Q0 * Q15 */        exc2[i] = shl_int16(tmp, exp);    }    if (new_state == DTX_MUTE)    {        /* mute comfort noise as it has been quite a long time since last SID update  was performed                            */        tmp_int_length = st->since_last_sid;        if (tmp_int_length > 32)        {            tmp_int_length = 32;        }        st->true_sid_period_inv = div_16by16(1 << 10, shl_int16(tmp_int_length, 10));        st->since_last_sid = 0;        st->old_log_en = st->log_en;        /* subtract 1/8 in Q9 (energy), i.e -3/8 dB */        st->log_en -= 64;    }    /* reset interpolation length timer if data has been updated.        */    if ((st->sid_frame != 0) &&            ((st->valid_data != 0) ||             ((st->valid_data == 0) && (st->dtxHangoverAdded) != 0)))    {        st->since_last_sid = 0;        st->data_updated = 1;    }    return 0;}/*----------------------------------------------------------------------------; FUNCTION CODE----------------------------------------------------------------------------*/void dtx_dec_amr_wb_activity_update(    dtx_decState * st,    int16 isf[],    int16 exc[]){    int16 i;    int32 L_frame_en;    int16 log_en_e, log_en_m, log_en;    st->hist_ptr++;    if (st->hist_ptr == DTX_HIST_SIZE)    {        st->hist_ptr = 0;    }    pv_memcpy((void *)&st->isf_hist[st->hist_ptr * M], (void *)isf, M*sizeof(*isf));    /* compute log energy based on excitation frame energy in Q0 */    L_frame_en = 0;    for (i = 0; i < L_FRAME; i++)    {        L_frame_en = mac_16by16_to_int32(L_frame_en, exc[i], exc[i]);    }    L_frame_en >>= 1;    /* log_en = (float)log10(L_frame_en/(float)L_FRAME)/(float)log10(2.0f); */    amrwb_log_2(L_frame_en, &log_en_e, &log_en_m);    /* convert exponent and mantissa to int16 Q7. Q7 is used to simplify averaging in dtx_enc */    log_en = shl_int16(log_en_e, 7);             /* Q7 */

⌨️ 快捷键说明

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