📄 dec_dtx.c
字号:
/*
*===================================================================
* 3GPP AMR Wideband Floating-point Speech Codec
*===================================================================
*/
#include <stdlib.h>
#include <memory.h>
#include <math.h>
#include "typedef.h"
#include "dec_dtx.h"
#include "dec_lpc.h"
#include "dec_util.h"
#include "..\include\options.h"
#define MAX_31 (Word32)0x3FFFFFFF
#define L_FRAME 256 /* Frame size */
#define RX_SPEECH_LOST 2
#define RX_SPEECH_BAD 3
#define RX_SID_FIRST 4
#define RX_SID_UPDATE 5
#define RX_SID_BAD 6
#define RX_NO_DATA 7
#define ISF_GAP 128 /* 50 */
#define D_DTX_MAX_EMPTY_THRESH 50
#define GAIN_FACTOR 75
#define ISF_FACTOR_LOW 256
#define ISF_FACTOR_STEP 2
#define ISF_DITH_GAP 448
#define D_DTX_HANG_CONST 7 /* yields eight frames of SP HANGOVER */
#define D_DTX_ELAPSED_FRAMES_THRESH (24 + 7 - 1)
#define RANDOM_INITSEED 21845 /* own random init value */
/*
* D_DTX_reset
*
* Parameters:
* st O: state struct
*
* Function:
* Initializes state memory
*
* Returns:
* non-zero with error, zero for ok
*/
int D_DTX_reset(D_DTX_State *st, const Word16 *isf_init)
{
Word32 i;
if(st == (D_DTX_State*)NULL)
{
return(-1);
}
st->mem_since_last_sid = 0;
st->mem_true_sid_period_inv = (1 << 13); /* 0.25 in Q15 */
st->mem_log_en = 3500;
st->mem_log_en_prev = 3500;
/* low level noise for better performance in DTX handover cases */
st->mem_cng_seed = RANDOM_INITSEED;
st->mem_hist_ptr = 0;
/* Init isf_hist[] and decoder log frame energy */
memcpy(st->mem_isf, isf_init, M * sizeof(Word16));
memcpy(st->mem_isf_prev, isf_init, M * sizeof(Word16));
for(i = 0; i < D_DTX_HIST_SIZE; i++)
{
memcpy(&st->mem_isf_buf[i * M], isf_init, M * sizeof(Word16));
st->mem_log_en_buf[i] = 3500;
}
st->mem_dtx_hangover_count = D_DTX_HANG_CONST;
st->mem_dec_ana_elapsed_count = 127;
st->mem_sid_frame = 0;
st->mem_valid_data = 0;
st->mem_dtx_hangover_added = 0;
st->mem_dtx_global_state = SPEECH;
st->mem_data_updated = 0;
st->mem_dither_seed = RANDOM_INITSEED;
st->mem_cn_dith = 0;
return(0);
}
/*
* D_DTX_init
*
* Parameters:
* st I/O: state struct
*
* Function:
* Allocates state memory and initializes state memory
*
* Returns:
* non-zero with error, zero for ok
*/
int D_DTX_init(D_DTX_State **st, const Word16 *isf_init)
{
D_DTX_State *s;
if(st == (D_DTX_State**)NULL)
{
return(-1);
}
*st = NULL;
/* allocate memory */
if((s = (D_DTX_State*)malloc(sizeof(D_DTX_State))) == NULL)
{
return(-1);
}
D_DTX_reset(s, isf_init);
*st = s;
return(0);
}
/*
* D_DTX_exit
*
* Parameters:
* state I/0: State struct
*
* Function:
* The memory used for state memory is freed
*
* Returns:
* void
*/
void D_DTX_exit(D_DTX_State **st)
{
if(st == NULL || *st == NULL)
{
return;
}
/* deallocate memory */
free(*st);
*st = NULL;
return;
}
/*
* D_DTX_rx_handler
*
* Parameters:
* st I/O: State struct
* frame_type I: Frame type
*
* Function:
* Analyze received frame
*
* Table of new SPD synthesis states
*
* | previous SPD_synthesis_state
* Incoming |
* frame_type | SPEECH | DTX | D_DTX_MUTE
* ---------------------------------------------------------------
* RX_SPEECH_GOOD , | | |
* RX_SPEECH_PR_DEGRADED | SPEECH | SPEECH | SPEECH
* ----------------------------------------------------------------
* RX_SPEECH_BAD, | SPEECH | DTX | D_DTX_MUTE
* ----------------------------------------------------------------
* RX_SID_FIRST, | DTX | DTX/(D_DTX_MUTE)| D_DTX_MUTE
* ----------------------------------------------------------------
* RX_SID_UPDATE, | DTX | DTX | DTX
* ----------------------------------------------------------------
* RX_SID_BAD, | DTX | DTX/(D_DTX_MUTE)| D_DTX_MUTE
* ----------------------------------------------------------------
* RX_NO_DATA, | SPEECH | DTX/(D_DTX_MUTE)| D_DTX_MUTE
* RX_SPARE |(class2 garb.)| |
* ----------------------------------------------------------------
*
* Returns:
* new state
*/
UWord8 D_DTX_rx_handler(D_DTX_State *st, UWord8 frame_type)
{
UWord8 newState;
UWord8 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->mem_dtx_global_state == DTX) |
(st->mem_dtx_global_state == D_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->mem_dtx_global_state == D_DTX_MUTE) &
((frame_type == RX_SID_BAD) | (frame_type == RX_SID_FIRST) |
(frame_type == RX_SPEECH_LOST) | (frame_type == RX_NO_DATA)))
{
newState = D_DTX_MUTE;
}
/* evaluate if noise parameters are too old */
/* since_last_sid is reset when CN parameters have been updated */
st->mem_since_last_sid = (UWord8)D_UTIL_saturate(st->mem_since_last_sid + 1);
/* no update of sid parameters in DTX for a Word32 while */
if(st->mem_since_last_sid > D_DTX_MAX_EMPTY_THRESH)
{
newState = D_DTX_MUTE;
}
}
else
{
newState = SPEECH;
st->mem_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->mem_data_updated == 0) & (frame_type == RX_SID_UPDATE))
{
st->mem_dec_ana_elapsed_count = 0;
}
/*
* update the SPE-SPD DTX hangover synchronization
* to know when SPE has added dtx hangover
*/
st->mem_dec_ana_elapsed_count++;
/* saturate */
if(st->mem_dec_ana_elapsed_count > 127)
{
st->mem_dec_ana_elapsed_count = 127;
}
st->mem_dtx_hangover_added = 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->mem_dtx_hangover_count = D_DTX_HANG_CONST;
}
else
{
if(st->mem_dec_ana_elapsed_count > D_DTX_ELAPSED_FRAMES_THRESH)
{
st->mem_dtx_hangover_added = 1;
st->mem_dec_ana_elapsed_count = 0;
st->mem_dtx_hangover_count = 0;
}
else if(st->mem_dtx_hangover_count == 0)
{
st->mem_dec_ana_elapsed_count = 0;
}
else
{
st->mem_dtx_hangover_count--;
}
}
if(newState != SPEECH)
{
/*
* DTX or D_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->mem_sid_frame = 0;
st->mem_valid_data = 0;
if(frame_type == RX_SID_FIRST)
{
st->mem_sid_frame = 1;
}
else if(frame_type == RX_SID_UPDATE)
{
st->mem_sid_frame = 1;
st->mem_valid_data = 1;
}
else if(frame_type == RX_SID_BAD)
{
st->mem_sid_frame = 1;
st->mem_dtx_hangover_added = 0; /* use old data */
}
}
return newState;
/* newState is used by both SPEECH AND DTX synthesis routines */
}
/*
* D_DTX_cn_dithering
*
* Parameters:
* isf I/O: CN ISF vector
* L_log_en_int I/O: energy parameter
* dither_seed I/O: random seed
*
* Function:
* Confort noise dithering
*
* Returns:
* void
*/
static void D_DTX_cn_dithering(Word16 isf[M], Word32 *L_log_en_int,
Word16 *dither_seed)
{
Word32 temp, temp1, i, dither_fac, rand_dith,rand_dith2;
/* Insert comfort noise dithering for energy parameter */
rand_dith = D_UTIL_random(dither_seed) >> 1;
rand_dith2 = D_UTIL_random(dither_seed) >>1;
rand_dith = rand_dith + rand_dith2;
*L_log_en_int = *L_log_en_int + ((rand_dith * GAIN_FACTOR) << 1);
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 = D_UTIL_random(dither_seed) >> 1;
rand_dith2 = D_UTIL_random(dither_seed) >> 1;
rand_dith = rand_dith + rand_dith2;
temp = isf[0] + (((rand_dith * dither_fac) + 0x4000) >> 15);
/* Make sure that isf[0] will not get negative values */
if(temp < ISF_GAP)
{
isf[0] = ISF_GAP;
}
else
{
isf[0] = (Word16)temp;
}
for(i = 1; i < M - 1; i++)
{
dither_fac = dither_fac + ISF_FACTOR_STEP;
rand_dith = D_UTIL_random(dither_seed) >> 1;
rand_dith2 = D_UTIL_random(dither_seed) >> 1;
rand_dith = rand_dith + rand_dith2;
temp = isf[i] + (((rand_dith * dither_fac) + 0x4000) >> 15);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -