FreeCalypso > hg > gsm-codec-lib
changeset 391:be8edf9e6bc1
libtwamr: integrate pitch_fr.c
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 06 May 2024 18:30:00 +0000 |
parents | bde9f5804670 |
children | a0f914a28371 |
files | libtwamr/Makefile libtwamr/namespace.list libtwamr/pitch_fr.c libtwamr/pitch_fr.h |
diffstat | 4 files changed, 622 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/libtwamr/Makefile Mon May 06 18:20:22 2024 +0000 +++ b/libtwamr/Makefile Mon May 06 18:30:00 2024 +0000 @@ -9,10 +9,11 @@ enc_lag6.o ex_ctrl.o g_adapt.o g_code.o g_pitch.o gain_q.o gains_tab.o \ gc_pred.o gmed_n.o graytab.o hp_max.o int_lpc.o int_lsf.o inter_36.o \ inv_sqrt.o lag_wind.o levinson.o log2.o lpc.o lsfwt.o lsp.o lsp_avg.o \ - lsp_az.o lsp_lsf.o lsp_tab.o mac_32.o oper_32b.o ph_disp.o pow2.o \ - prmno.o q_gain_c.o q_gain_p.o q_plsf.o q_plsf3_tab.o q_plsf5_tab.o \ - q_plsf_3.o q_plsf_5.o qgain475.o qgain795.o qua_gain.o qua_gain_tab.o \ - reorder.o s10_8pf.o set_sign.o sqrt_l.o tls_flags.o window.o + lsp_az.o lsp_lsf.o lsp_tab.o mac_32.o oper_32b.o ph_disp.o pitch_fr.o \ + pow2.o prmno.o q_gain_c.o q_gain_p.o q_plsf.o q_plsf3_tab.o \ + q_plsf5_tab.o q_plsf_3.o q_plsf_5.o qgain475.o qgain795.o qua_gain.o \ + qua_gain_tab.o reorder.o s10_8pf.o set_sign.o sqrt_l.o tls_flags.o \ + window.o HDRS= namespace.h LIB= libtwamr.a
--- a/libtwamr/namespace.list Mon May 06 18:20:22 2024 +0000 +++ b/libtwamr/namespace.list Mon May 06 18:30:00 2024 +0000 @@ -27,6 +27,7 @@ Int_lsf Interpol_3or6 Lag_window Levinson Levinson_reset Lsf_lsp Lsp_lsf Reorder_lsf Lsf_wt Lsp_Az +Pitch_fr Pitch_fr_reset Q_plsf_reset Q_plsf_3 Q_plsf_5 Qua_gain agc agc2 agc_reset
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libtwamr/pitch_fr.c Mon May 06 18:30:00 2024 +0000 @@ -0,0 +1,554 @@ +/* +******************************************************************************** +* +* GSM AMR-NB speech codec R98 Version 7.6.0 December 12, 2001 +* R99 Version 3.3.0 +* REL-4 Version 4.1.0 +* +******************************************************************************** +* +* File : pitch_fr.c +* Purpose : Find the pitch period with 1/3 or 1/6 subsample +* : resolution (closed loop). +* +******************************************************************************** +*/ +/* +******************************************************************************** +* MODULE INCLUDE FILE AND VERSION ID +******************************************************************************** +*/ +#include "namespace.h" +#include "pitch_fr.h" +/* +******************************************************************************** +* INCLUDE FILES +******************************************************************************** +*/ +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" +#include "no_count.h" +#include "cnst.h" +#include "enc_lag3.h" +#include "enc_lag6.h" +#include "inter_36.h" +#include "inv_sqrt.h" +#include "convolve.h" + +/* +******************************************************************************** +* LOCAL VARIABLES AND TABLES +******************************************************************************** +*/ + +/* + * mode dependent parameters used in Pitch_fr() + * Note: order of MRxx in 'enum Mode' is important! + */ +static const struct { + Word16 max_frac_lag; /* lag up to which fractional lags are used */ + Word16 flag3; /* enable 1/3 instead of 1/6 fract. resolution */ + Word16 first_frac; /* first fractional to check */ + Word16 last_frac; /* last fractional to check */ + Word16 delta_int_low; /* integer lag below TO to start search from */ + Word16 delta_int_range; /* integer range around T0 */ + Word16 delta_frc_low; /* fractional below T0 */ + Word16 delta_frc_range; /* fractional range around T0 */ + Word16 pit_min; /* minimum pitch */ +} mode_dep_parm[8] = { + /* MR475 */ { 84, 1, -2, 2, 5, 10, 5, 9, PIT_MIN }, + /* MR515 */ { 84, 1, -2, 2, 5, 10, 5, 9, PIT_MIN }, + /* MR59 */ { 84, 1, -2, 2, 3, 6, 5, 9, PIT_MIN }, + /* MR67 */ { 84, 1, -2, 2, 3, 6, 5, 9, PIT_MIN }, + /* MR74 */ { 84, 1, -2, 2, 3, 6, 5, 9, PIT_MIN }, + /* MR795 */ { 84, 1, -2, 2, 3, 6, 10, 19, PIT_MIN }, + /* MR102 */ { 84, 1, -2, 2, 3, 6, 5, 9, PIT_MIN }, + /* MR122 */ { 94, 0, -3, 3, 3, 6, 5, 9, PIT_MIN_MR122 } +}; + +/* +******************************************************************************** +* LOCAL PROGRAM CODE +******************************************************************************** +*/ +/************************************************************************* + * + * FUNCTION: Norm_Corr() + * + * PURPOSE: Find the normalized correlation between the target vector + * and the filtered past excitation. + * + * DESCRIPTION: + * The normalized correlation is given by the correlation between the + * target and filtered past excitation divided by the square root of + * the energy of filtered excitation. + * corr[k] = <x[], y_k[]>/sqrt(y_k[],y_k[]) + * where x[] is the target vector and y_k[] is the filtered past + * excitation at delay k. + * + *************************************************************************/ +static void Norm_Corr (Word16 exc[], Word16 xn[], Word16 h[], Word16 L_subfr, + Word16 t_min, Word16 t_max, Word16 corr_norm[]) +{ + Word16 i, j, k; + Word16 corr_h, corr_l, norm_h, norm_l; + Word32 s; + + /* Usally dynamic allocation of (L_subfr) */ + Word16 excf[L_SUBFR]; + Word16 scaling, h_fac, *s_excf, scaled_excf[L_SUBFR]; + + k = -t_min; move16 (); + + /* compute the filtered excitation for the first delay t_min */ + + Convolve (&exc[k], h, excf, L_subfr); + + /* scale "excf[]" to avoid overflow */ + + for (j = 0; j < L_subfr; j++) { + scaled_excf[j] = shr (excf[j], 2); move16 (); + } + + /* Compute 1/sqrt(energy of excf[]) */ + + s = 0; move32 (); + for (j = 0; j < L_subfr; j++) { + s = L_mac (s, excf[j], excf[j]); + } + test (); + if (L_sub (s, 67108864L) <= 0) { /* if (s <= 2^26) */ + s_excf = excf; move16 (); + h_fac = 15 - 12; move16 (); + scaling = 0; move16 (); + } + else { + /* "excf[]" is divided by 2 */ + s_excf = scaled_excf; move16 (); + h_fac = 15 - 12 - 2; move16 (); + scaling = 2; move16 (); + } + + /* loop for every possible period */ + + for (i = t_min; i <= t_max; i++) { + /* Compute 1/sqrt(energy of excf[]) */ + + s = 0; move32 (); + for (j = 0; j < L_subfr; j++) { + s = L_mac (s, s_excf[j], s_excf[j]); + } + + s = Inv_sqrt (s); + L_Extract (s, &norm_h, &norm_l); + + /* Compute correlation between xn[] and excf[] */ + + s = 0; move32 (); + for (j = 0; j < L_subfr; j++) { + s = L_mac (s, xn[j], s_excf[j]); + } + L_Extract (s, &corr_h, &corr_l); + + /* Normalize correlation = correlation * (1/sqrt(energy)) */ + + s = Mpy_32 (corr_h, corr_l, norm_h, norm_l); + + corr_norm[i] = extract_h (L_shl (s, 16)); + move16 (); + + /* modify the filtered excitation excf[] for the next iteration */ + + test (); + if (sub (i, t_max) != 0) { + k--; + for (j = L_subfr - 1; j > 0; j--) { + s = L_mult (exc[k], h[j]); + s = L_shl (s, h_fac); + s_excf[j] = add (extract_h (s), s_excf[j - 1]); move16 (); + } + s_excf[0] = shr (exc[k], scaling); move16 (); + } + } + return; +} + +/************************************************************************* + * + * FUNCTION: searchFrac() + * + * PURPOSE: Find fractional pitch + * + * DESCRIPTION: + * The function interpolates the normalized correlation at the + * fractional positions around lag T0. The position at which the + * interpolation function reaches its maximum is the fractional pitch. + * Starting point of the search is frac, end point is last_frac. + * frac is overwritten with the fractional pitch. + * + *************************************************************************/ +static void searchFrac ( + Word16 *lag, /* i/o : integer pitch */ + Word16 *frac, /* i/o : start point of search - + fractional pitch */ + Word16 last_frac, /* i : endpoint of search */ + Word16 corr[], /* i : normalized correlation */ + Word16 flag3 /* i : subsample resolution + (3: =1 / 6: =0) */ +) +{ + Word16 i; + Word16 max; + Word16 corr_int; + + /* Test the fractions around T0 and choose the one which maximizes */ + /* the interpolated normalized correlation. */ + + max = Interpol_3or6 (&corr[*lag], *frac, flag3); move16 (); /* function result */ + + for (i = add (*frac, 1); i <= last_frac; i++) { + corr_int = Interpol_3or6 (&corr[*lag], i, flag3); + move16 (); + test (); + if (sub (corr_int, max) > 0) { + max = corr_int; move16 (); + *frac = i; move16 (); + } + } + + test(); + if (flag3 == 0) { + /* Limit the fraction value in the interval [-2,-1,0,1,2,3] */ + + test (); + if (sub (*frac, -3) == 0) { + *frac = 3; move16 (); + *lag = sub (*lag, 1); + } + } + else { + /* limit the fraction value between -1 and 1 */ + + test (); + if (sub (*frac, -2) == 0) { + *frac = 1; move16 (); + *lag = sub (*lag, 1); + } + test (); + if (sub (*frac, 2) == 0) { + *frac = -1; move16 (); + *lag = add (*lag, 1); + } + } +} + +/************************************************************************* + * + * FUNCTION: getRange() + * + * PURPOSE: Sets range around open-loop pitch or integer pitch of last subframe + * + * DESCRIPTION: + * Takes integer pitch T0 and calculates a range around it with + * t0_min = T0-delta_low and t0_max = (T0-delta_low) + delta_range + * t0_min and t0_max are bounded by pitmin and pitmax + * + *************************************************************************/ +static void getRange ( + Word16 T0, /* i : integer pitch */ + Word16 delta_low, /* i : search start offset */ + Word16 delta_range, /* i : search range */ + Word16 pitmin, /* i : minimum pitch */ + Word16 pitmax, /* i : maximum pitch */ + Word16 *t0_min, /* o : search range minimum */ + Word16 *t0_max) /* o : search range maximum */ +{ + *t0_min = sub(T0, delta_low); + test (); + if (sub(*t0_min, pitmin) < 0) { + *t0_min = pitmin; move16(); + } + *t0_max = add(*t0_min, delta_range); + test (); + if (sub(*t0_max, pitmax) > 0) { + *t0_max = pitmax; move16(); + *t0_min = sub(*t0_max, delta_range); + } +} + +/* +******************************************************************************** +* PUBLIC PROGRAM CODE +******************************************************************************** +*/ + +/************************************************************************* +* +* Function: Pitch_fr_reset +* Purpose: Initializes state memory to zero +* +************************************************************************** +*/ +void Pitch_fr_reset (Pitch_frState *state) +{ + state->T0_prev_subframe = 0; +} + +/************************************************************************* + * + * FUNCTION: Pitch_fr() + * + * PURPOSE: Find the pitch period with 1/3 or 1/6 subsample resolution + * (closed loop). + * + * DESCRIPTION: + * - find the normalized correlation between the target and filtered + * past excitation in the search range. + * - select the delay with maximum normalized correlation. + * - interpolate the normalized correlation at fractions -3/6 to 3/6 + * with step 1/6 around the chosen delay. + * - The fraction which gives the maximum interpolated value is chosen. + * + *************************************************************************/ +Word16 Pitch_fr ( /* o : pitch period (integer) */ + Pitch_frState *st, /* i/o : State struct */ + enum Mode mode, /* i : codec mode */ + Word16 T_op[], /* i : open loop pitch lags */ + Word16 exc[], /* i : excitation buffer Q0 */ + Word16 xn[], /* i : target vector Q0 */ + Word16 h[], /* i : impulse response of synthesis and + weighting filters Q12 */ + Word16 L_subfr, /* i : Length of subframe */ + Word16 i_subfr, /* i : subframe offset */ + Word16 *pit_frac, /* o : pitch period (fractional) */ + Word16 *resu3, /* o : subsample resolution 1/3 (=1) or 1/6 (=0) */ + Word16 *ana_index /* o : index of encoding */ +) +{ + Word16 i; + Word16 t_min, t_max; + Word16 t0_min, t0_max; + Word16 max, lag, frac; + Word16 tmp_lag; + Word16 *corr; + Word16 corr_v[40]; /* Total length = t0_max-t0_min+1+2*L_INTER_SRCH */ + + Word16 max_frac_lag; + Word16 flag3, flag4; + Word16 last_frac; + Word16 delta_int_low, delta_int_range; + Word16 delta_frc_low, delta_frc_range; + Word16 pit_min; + Word16 frame_offset; + Word16 delta_search; + + /*-----------------------------------------------------------------------* + * set mode specific variables * + *-----------------------------------------------------------------------*/ + + max_frac_lag = mode_dep_parm[mode].max_frac_lag; move16 (); + flag3 = mode_dep_parm[mode].flag3; move16 (); + frac = mode_dep_parm[mode].first_frac; move16 (); + last_frac = mode_dep_parm[mode].last_frac; move16 (); + delta_int_low = mode_dep_parm[mode].delta_int_low; move16 (); + delta_int_range = mode_dep_parm[mode].delta_int_range; move16 (); + + delta_frc_low = mode_dep_parm[mode].delta_frc_low; move16 (); + delta_frc_range = mode_dep_parm[mode].delta_frc_range; move16 (); + pit_min = mode_dep_parm[mode].pit_min; move16 (); + + /*-----------------------------------------------------------------------* + * decide upon full or differential search * + *-----------------------------------------------------------------------*/ + + delta_search = 1; move16 (); + + test (); test (); + if ((i_subfr == 0) || (sub(i_subfr,L_FRAME_BY2) == 0)) { + + /* Subframe 1 and 3 */ + + test (); test (); test (); + if (((sub(mode, MR475) != 0) && (sub(mode, MR515) != 0)) || + (sub(i_subfr,L_FRAME_BY2) != 0)) { + + /* set t0_min, t0_max for full search */ + /* this is *not* done for mode MR475, MR515 in subframe 3 */ + + delta_search = 0; /* no differential search */ move16 (); + + /* calculate index into T_op which contains the open-loop */ + /* pitch estimations for the 2 big subframes */ + + frame_offset = 1; move16 (); + test (); + if (i_subfr == 0) + frame_offset = 0; move16 (); + + /* get T_op from the corresponding half frame and */ + /* set t0_min, t0_max */ + + getRange (T_op[frame_offset], delta_int_low, delta_int_range, + pit_min, PIT_MAX, &t0_min, &t0_max); + } + else { + + /* mode MR475, MR515 and 3. Subframe: delta search as well */ + getRange (st->T0_prev_subframe, delta_frc_low, delta_frc_range, + pit_min, PIT_MAX, &t0_min, &t0_max); + } + } + else { + + /* for Subframe 2 and 4 */ + /* get range around T0 of previous subframe for delta search */ + + getRange (st->T0_prev_subframe, delta_frc_low, delta_frc_range, + pit_min, PIT_MAX, &t0_min, &t0_max); + } + + /*-----------------------------------------------------------------------* + * Find interval to compute normalized correlation * + *-----------------------------------------------------------------------*/ + + t_min = sub (t0_min, L_INTER_SRCH); + t_max = add (t0_max, L_INTER_SRCH); + + corr = &corr_v[-t_min]; move16 (); + + /*-----------------------------------------------------------------------* + * Compute normalized correlation between target and filtered excitation * + *-----------------------------------------------------------------------*/ + + Norm_Corr (exc, xn, h, L_subfr, t_min, t_max, corr); + + /*-----------------------------------------------------------------------* + * Find integer pitch * + *-----------------------------------------------------------------------*/ + + max = corr[t0_min]; move16 (); + lag = t0_min; move16 (); + + for (i = t0_min + 1; i <= t0_max; i++) { + test (); + if (sub (corr[i], max) >= 0) { + max = corr[i]; move16 (); + lag = i; move16 (); + } + } + + /*-----------------------------------------------------------------------* + * Find fractional pitch * + *-----------------------------------------------------------------------*/ + test (); test (); + if ((delta_search == 0) && (sub (lag, max_frac_lag) > 0)) { + + /* full search and integer pitch greater than max_frac_lag */ + /* fractional search is not needed, set fractional to zero */ + + frac = 0; move16 (); + } + else { + + /* if differential search AND mode MR475 OR MR515 OR MR59 OR MR67 */ + /* then search fractional with 4 bits resolution */ + + test (); test (); test (); test (); test (); + if ((delta_search != 0) && + ((sub (mode, MR475) == 0) || + (sub (mode, MR515) == 0) || + (sub (mode, MR59) == 0) || + (sub (mode, MR67) == 0))) { + + /* modify frac or last_frac according to position of last */ + /* integer pitch: either search around integer pitch, */ + /* or only on left or right side */ + + tmp_lag = st->T0_prev_subframe; move16 (); + test (); + if ( sub( sub(tmp_lag, t0_min), 5) > 0) + tmp_lag = add (t0_min, 5); + test (); + if ( sub( sub(t0_max, tmp_lag), 4) > 0) + tmp_lag = sub (t0_max, 4); + + test (); test (); + if ((sub (lag, tmp_lag) == 0) || + (sub (lag, sub(tmp_lag, 1)) == 0)) { + + /* normal search in fractions around T0 */ + + searchFrac (&lag, &frac, last_frac, corr, flag3); + + } + else if (sub (lag, sub (tmp_lag, 2)) == 0) { + test (); + /* limit search around T0 to the right side */ + frac = 0; move16 (); + searchFrac (&lag, &frac, last_frac, corr, flag3); + } + else if (sub (lag, add(tmp_lag, 1)) == 0) { + test (); test (); + /* limit search around T0 to the left side */ + last_frac = 0; move16 (); + searchFrac (&lag, &frac, last_frac, corr, flag3); + } + else { + test (); test (); + /* no fractional search */ + frac = 0; move16 (); + } + } + else + /* test the fractions around T0 */ + searchFrac (&lag, &frac, last_frac, corr, flag3); + } + + /*-----------------------------------------------------------------------* + * encode pitch * + *-----------------------------------------------------------------------*/ + + test (); + if (flag3 != 0) { + /* flag4 indicates encoding with 4 bit resolution; */ + /* this is needed for mode MR475, MR515 and MR59 */ + + flag4 = 0; move16 (); + test (); test (); test (); test (); + if ( (sub (mode, MR475) == 0) || + (sub (mode, MR515) == 0) || + (sub (mode, MR59) == 0) || + (sub (mode, MR67) == 0) ) { + flag4 = 1; move16 (); + } + + /* encode with 1/3 subsample resolution */ + + *ana_index = Enc_lag3(lag, frac, st->T0_prev_subframe, + t0_min, t0_max, delta_search, flag4); move16 (); /* function result */ + + } + else + { + /* encode with 1/6 subsample resolution */ + + *ana_index = Enc_lag6(lag, frac, t0_min, delta_search); move16 (); /* function result */ + } + + /*-----------------------------------------------------------------------* + * update state variables * + *-----------------------------------------------------------------------*/ + + st->T0_prev_subframe = lag; move16 (); + + /*-----------------------------------------------------------------------* + * update output variables * + *-----------------------------------------------------------------------*/ + + *resu3 = flag3; move16 (); + + *pit_frac = frac; move16 (); + + return (lag); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libtwamr/pitch_fr.h Mon May 06 18:30:00 2024 +0000 @@ -0,0 +1,62 @@ +/* +******************************************************************************** +* +* GSM AMR-NB speech codec R98 Version 7.6.0 December 12, 2001 +* R99 Version 3.3.0 +* REL-4 Version 4.1.0 +* +******************************************************************************** +* +* File : pitch_fr.h +* Purpose : Find the pitch period with 1/3 or 1/6 subsample +* : resolution (closed loop). +* +******************************************************************************** +*/ +#ifndef pitch_fr_h +#define pitch_fr_h "$Id $" + +/* +******************************************************************************** +* INCLUDE FILES +******************************************************************************** +*/ +#include "tw_amr.h" +#include "typedef.h" + +/* +******************************************************************************** +* DEFINITION OF DATA TYPES +******************************************************************************** +*/ +typedef struct { + Word16 T0_prev_subframe; /* integer pitch lag of previous sub-frame */ +} Pitch_frState; + +/* +******************************************************************************** +* DECLARATION OF PROTOTYPES +******************************************************************************** +*/ + +void Pitch_fr_reset (Pitch_frState *st); +/* reset of pre processing state (i.e. set state memory to zero) + returns 0 on success + */ + +Word16 Pitch_fr ( /* o : pitch period (integer) */ + Pitch_frState *st, /* i/o : State struct */ + enum Mode mode, /* i : codec mode */ + Word16 T_op[], /* i : open loop pitch lags */ + Word16 exc[], /* i : excitation buffer */ + Word16 xn[], /* i : target vector */ + Word16 h[], /* i : impulse response of synthesis and + weighting filters */ + Word16 L_subfr, /* i : Length of subframe */ + Word16 i_subfr, /* i : subframe offset */ + Word16 *pit_frac, /* o : pitch period (fractional) */ + Word16 *resu3, /* o : subsample resolution 1/3 (=1) or 1/6 (=0) */ + Word16 *ana_index /* o : index of encoding */ +); + +#endif