📄 g729ev_tdbwe_generate_excitation.c
字号:
/* ITU-T G.729EV Optimization/Characterization Candidate *//* Version: 1.0.a *//* Revision Date: June 28, 2006 *//* ITU-T G.729EV Optimization/Characterization Candidate ANSI-C Source Code Copyright (c) 2006 France Telecom, Matsushita Electric, Mindspeed, Siemens AG, ETRI, VoiceAge Corp. All rights reserved*/#include "G729EV_TDBWE_generate_excitation.h"#include "G729EV_MAIN_DSPFUNC.h"#include "G729EV_G729_ld8k.h"/*--------------------------------------------------------------------------* * Function G729EV_TDBWE_rand() * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * TDBWE random generator, * * Same as Random() of G.729, except for seed type (Word32) * *--------------------------------------------------------------------------*/Word16 G729EV_TDBWE_rand(Word32 * seed) /* (i/o) */{ Word16 tmp; /* seed = seed*31821 + 13849; */ tmp = extract_l(*seed); *seed = L_add(L_shr(L_mult(tmp, 31821), 1), 13849L); return extract_l(*seed);}/*--------------------------------------------------------------------------* * Function G729EV_TDBWE_generate_excitation_initialize() * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * initialization of TDBWE excitation generator * *--------------------------------------------------------------------------*/void G729EV_TDBWE_generate_excitation_initialize(G729EV_TDBWE_generate_excitation_state * state) /* (i/o) */{ G729EV_G729_Set_zero(state->signal_tonal_buffer, G729EV_TDBWE_LENGTH_PULSE_SHAPE); G729EV_MAIN_init_lp3k(&(state->lowpass_3_kHz)); state->old_lag = 60; state->old_gain_tonal = 0; state->prev_pulse = G729EV_TDBWE_L_FRAME2; state->prev_pulse_frac = 0; state->seed = 0x78a426da; /* (((-1) ^ MASK) + 0x7fffffff) */#ifdef WMOPS move16(); move16(); move16(); move16(); move32();#endif}/*--------------------------------------------------------------------------* * Function G729EV_TDBWE_generate_excitation_initialize() * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * TDBWE excitation generator: produce pitch-synchronous excitation * * signal based on G.729 parameters * *--------------------------------------------------------------------------*/void G729EV_TDBWE_generate_excitation(G729EV_TDBWE_generate_excitation_state * state, /* (i/o) */ G729EV_TDBWE_g729_info * parameters, /* (i) parameters from G.729A+ (8k/12k layers) */ Word16 * output) /* (o) Q.12, output signal */{ Word16 i, l; Word16 gain_tonal[2]; Word16 new_gain_tonal; Word16 new_gain_tonal_sq; Word16 gain_noise[2]; Word16 lag[2] = { 0, 0 }; Word16 frac_lag[2] = { 0, 0 }; Word16 next_pulse; Word16 next_pulse_frac; Word16 signal_tonal[G729EV_TDBWE_L_FRAME2 + G729EV_TDBWE_LENGTH_PULSE_SHAPE]; Word16 lfr_raw, lfr; Word16 lfr_raw_nls, lfr_nls; Word32 lfrsquare32; Word16 lfrsq_nls; Word32 power_fix32; Word32 power_ltp32; Word16 power_fix; Word16 norm1, norm2, tmp; Word32 acc; Word16 lag_tmp, wlim; Word16 gain; Word16 *ps; const Word16 *psf; Word16 factor; Word16 error; Word16 new_lag; /* Compute ltp-to-fix power ratio (LFR) from NB excitation. We implicitly assume here that the adaptive codebook contributes only tonal components and the fixed codebook contributes noisy components only, and that the contributions are orthogonal. */ FOR(l = 0; l < 2; l++) /* for two 5ms subframes */ { power_fix32 = parameters->power_fix[l]; power_ltp32 = parameters->power_ltp[l];#ifdef WMOPS move32(); move32();#endif IF(power_fix32) { norm1 = norm_l(power_fix32); } ELSE { norm1 = 32;#ifdef WMOPS move16();#endif } IF(power_ltp32) { norm2 = sub(norm_l(power_ltp32), 1); } ELSE { norm2 = 31;#ifdef WMOPS move16();#endif } power_fix = round(L_shl(power_fix32, norm1)); power_ltp32 = L_shl(power_ltp32, norm2); /* for norm2==-1 this is a rightshift */ /* instantaneous ltp-to-fix ratio (LFR) */ IF(power_fix > 0) { lfr_raw = div_l(power_ltp32, power_fix); lfr_raw_nls = sub(add(norm2, 15), norm1); } ELSE { lfr_raw = 0; lfr_raw_nls = 16;#ifdef WMOPS move16(); move16();#endif } /* apply kind of "Wiener filtering" to get "nice" noise segments later */ /* lfr = lfr_raw * lfr_raw / ( 1.0f + lfr_raw ); */ lfrsquare32 = L_mult(lfr_raw, lfr_raw); lfrsq_nls = add(shl(lfr_raw_nls, 1), 1); IF(sub(lfr_raw_nls, 14) > 0) { lfr_raw = shr(lfr_raw, sub(lfr_raw_nls, 14)); lfr_raw_nls = 14;#ifdef WMOPS move16();#endif } IF(sub(lfr_raw, 0x4000) >= 0) { lfr_raw = shr(lfr_raw, 1); lfr_raw_nls = sub(lfr_raw_nls, 1); } lfr_raw = add(shl(1, lfr_raw_nls), lfr_raw); norm1 = norm_s(lfr_raw); norm2 = sub(norm_l(lfrsquare32), 1); lfr = div_l(L_shl(lfrsquare32, norm2), shl(lfr_raw, norm1)); lfr_nls = sub(sub(add(norm2, lfrsq_nls), add(norm1, lfr_raw_nls)), 1); /* determine gain factors (incl. gliding average length 2) */ IF(sub(lfr_nls, 14) > 0) { lfr = shr(lfr, sub(lfr_nls, 14)); lfr_nls = 14;#ifdef WMOPS move16();#endif } IF(sub(lfr, 0x4000) >= 0) { lfr = shr(lfr, 1); lfr_nls = sub(lfr_nls, 1); } tmp = add(shl(1, lfr_nls), lfr); norm1 = norm_s(tmp); lfr = div_s(shl(lfr, norm1), shl(tmp, norm1)); gain_tonal[l] = sqrt_q15(lfr); /* gain_tonal is Q.15 */#ifdef WMOPS move16();#endif acc = L_mult0(gain_tonal[l], gain_tonal[l]); acc = L_mac0(acc, state->old_gain_tonal, state->old_gain_tonal); new_gain_tonal_sq = round(acc); /* new_gain_tonal_sq is Q.15 */ new_gain_tonal = sqrt_q15(new_gain_tonal_sq); state->old_gain_tonal = gain_tonal[l]; gain_tonal[l] = new_gain_tonal;#ifdef WMOPS move16(); move16();#endif tmp = add(new_gain_tonal_sq, -32768); gain_noise[l] = sqrt_q15(negate(tmp)); /* gain_noise is Q.15 */#ifdef WMOPS move16();#endif } /* Remove certain obvious pitch-doubling errors from pitch lag contour. Here, we assume that a rise of the pitch lag by (about) an integer factor from one sub-frame to another corresponds to a beginning pitch-doubling error. A small drawback is that this mechanism may produce half-pitch errors. */ FOR(l = 0; l < 2; l++) /* for two 5ms subframes */ { lag_tmp = add(i_mult(6, (Word16) parameters->lag[l]), shl((Word16) parameters->frac_lag[l], 1)); /* (int) floor ( (REAL) lag[l] / (REAL) state->old_lag + 0.5 )); */ factor = shr(add(div_l(shl(lag_tmp, 2), state->old_lag), 1), 1); /* if factor>1 && factor<5 */ IF(sub(factor, 1) > 0) { IF(sub(factor, 5) < 0) { tmp = i_mult(factor, state->old_lag); norm1 = norm_s(tmp); norm2 = norm_s(lag_tmp); error = shr(div_s(shl(lag_tmp, sub(norm2, 1)), shl(tmp, norm1)), sub(norm2, norm1)); /* if ( fabs ( 1.0 - R_error ) < 0.1 ) */ IF(sub(abs_s(sub(16384, error)), 1638) < 0) { norm1 = norm_s(factor); norm2 = norm_s(lag_tmp); lag_tmp = shr(div_s(shl(lag_tmp, sub(norm2, 1)), shl(factor, norm1)), sub(add(norm2, 8), norm1)); /* lag[l] = (int) floor ( (REAL) lag[l] / (REAL) factor + 0.5 ); */ lag_tmp = shr(add(shr(lag_tmp, 5), 1), 1); } } } /* simple low-pass filtering (gliding average length 2) */ new_lag = shr(add(state->old_lag, lag_tmp), 1); state->old_lag = lag_tmp; lag[l] = div_l(shl(new_lag, 1), 6); frac_lag[l] = sub(new_lag, extract_l(L_mult0(6, lag[l])));#ifdef WMOPS move16(); move16(); move16();#endif } /* produce tonal contributions */ G729EV_G729_Copy(state->signal_tonal_buffer, signal_tonal, G729EV_TDBWE_LENGTH_PULSE_SHAPE); G729EV_G729_Set_zero(&signal_tonal[G729EV_TDBWE_LENGTH_PULSE_SHAPE], G729EV_TDBWE_L_FRAME2); state->prev_pulse = sub(state->prev_pulse, G729EV_TDBWE_L_FRAME2); next_pulse = add(state->prev_pulse, lag[0]); next_pulse_frac = add(state->prev_pulse_frac, frac_lag[0]); WHILE(sub(next_pulse_frac, 6) >= 0) { next_pulse_frac = sub(next_pulse_frac, 6); next_pulse = add(next_pulse, 1); } if (next_pulse < 0) { next_pulse = 0;#ifdef WMOPS move16();#endif } wlim = G729EV_TDBWE_L_FRAME4;#ifdef WMOPS move16();#endif FOR(l = 0; l < 2; l++) /* for two 5ms subframes */ { WHILE(next_pulse < wlim) { acc = L_mult0(frac_lag[l], 1); acc = L_mac0(acc, lag[l], 6); tmp = sqrt_qnls(extract_l(acc), 7); /* Q.0 -> Q.7 */ tmp = shl(tmp, 3); /* Q.7 -> Q.10 */ gain = round(L_mult(tmp, gain_tonal[l])); /* gain is Q.10 */ if (s_and(next_pulse, 1) == 0) gain = negate(gain); ps = &signal_tonal[next_pulse]; psf = &G729EV_TDBWE_pulse_shapes_frac6[i_mult(next_pulse_frac, G729EV_TDBWE_LENGTH_PULSE_SHAPE)]; FOR(i = 0; i < G729EV_TDBWE_LENGTH_PULSE_SHAPE; i++) { ps[i] = add(ps[i], round(L_mult0(gain, psf[i])));#ifdef WMOPS move16();#endif } state->prev_pulse = next_pulse; state->prev_pulse_frac = next_pulse_frac;#ifdef WMOPS move16(); move16();#endif next_pulse = add(state->prev_pulse, lag[l]); next_pulse_frac = add(state->prev_pulse_frac, frac_lag[l]); WHILE(sub(next_pulse_frac, 6) >= 0) { next_pulse_frac = sub(next_pulse_frac, 6); next_pulse = add(next_pulse, 1); } } wlim = add(wlim, G729EV_TDBWE_L_FRAME4); } G729EV_G729_Copy(signal_tonal, output, G729EV_TDBWE_L_FRAME2); G729EV_G729_Copy(&signal_tonal[G729EV_TDBWE_L_FRAME2], state->signal_tonal_buffer, G729EV_TDBWE_LENGTH_PULSE_SHAPE); /* produce and add noise contributions */ FOR(i = 0; i < G729EV_TDBWE_L_FRAME4; i++) { output[i] = add(output[i], round(L_mult(gain_noise[0], shr(G729EV_TDBWE_rand(&(state->seed)), 4))));#ifdef WMOPS move16();#endif } FOR(i = G729EV_TDBWE_L_FRAME4; i < G729EV_TDBWE_L_FRAME2; i++) { /* <================================= BUG WARNING ==================================> */ /* gain_noise[1] has to be used instead of gain_noise[0] below */ /* the impact on quality is very minor */ /* <================================= BUG WARNING ==================================> */ output[i] = add(output[i], round(L_mult(gain_noise[0], shr(G729EV_TDBWE_rand(&(state->seed)), 4))));#ifdef WMOPS move16();#endif } /* apply 3 kHz lowpass */ G729EV_MAIN_lp3k(&(state->lowpass_3_kHz), output, G729EV_TDBWE_L_FRAME2);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -