📄 dtx_decoder_amr_wb.cpp
字号:
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 + -