FreeCalypso > hg > gsm-codec-lib
diff libtwamr/pitch_ol.c @ 415:01c4becb9fda
libtwamr: integrate pitch_ol.c
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 07 May 2024 03:01:01 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libtwamr/pitch_ol.c Tue May 07 03:01:01 2024 +0000 @@ -0,0 +1,347 @@ +/* +******************************************************************************** +* +* 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_ol.c +* Purpose : Compute the open loop pitch lag. +* +******************************************************************************** +*/ +/* +******************************************************************************** +* MODULE INCLUDE FILE AND VERSION ID +******************************************************************************** +*/ +#include "namespace.h" +#include "pitch_ol.h" +/* +******************************************************************************** +* INCLUDE FILES +******************************************************************************** +*/ +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" +#include "no_count.h" +#include "cnst.h" +#include "inv_sqrt.h" +#include "vad.h" +#include "calc_cor.h" +#include "hp_max.h" + +/* +******************************************************************************** +* LOCAL VARIABLES AND TABLES +******************************************************************************** +*/ +#define THRESHOLD 27853 + +/* +******************************************************************************** +* LOCAL PROGRAM CODE +******************************************************************************** +*/ +/************************************************************************* + * + * FUNCTION: Lag_max + * + * PURPOSE: Find the lag that has maximum correlation of scal_sig[] in a + * given delay range. + * + * DESCRIPTION: + * The correlation is given by + * cor[t] = <scal_sig[n],scal_sig[n-t]>, t=lag_min,...,lag_max + * The functions outputs the maximum correlation after normalization + * and the corresponding lag. + * + *************************************************************************/ +static Word16 Lag_max ( /* o : lag found */ + vadState *vadSt, /* i/o : VAD state struct */ + Word32 corr[], /* i : correlation vector. */ + Word16 scal_sig[], /* i : scaled signal. */ + Word16 scal_fac, /* i : scaled signal factor. */ + Word16 scal_flag, /* i : if 1 use EFR compatible scaling */ + Word16 L_frame, /* i : length of frame to compute pitch */ + Word16 lag_max, /* i : maximum lag */ + Word16 lag_min, /* i : minimum lag */ + Word16 *cor_max, /* o : normalized correlation of selected lag */ + Word32 *rmax, /* o : max(<s[i]*s[j]>) */ + Word32 *r0, /* o : residual energy */ + Flag dtx /* i : dtx flag; use dtx=1, do not use dtx=0 */ + ) +{ + Word16 i, j; + Word16 *p; + Word32 max, t0; + Word16 max_h, max_l, ener_h, ener_l; + Word16 p_max = 0; /* initialization only needed to keep gcc silent */ + + max = MIN_32; move32 (); + p_max = lag_max; move16 (); + + for (i = lag_max, j = (PIT_MAX-lag_max-1); i >= lag_min; i--, j--) + { + test (); + if (L_sub (corr[-i], max) >= 0) + { + max = corr[-i]; move32 (); + p_max = i; move16 (); + } + } + + /* compute energy */ + + t0 = 0; move32 (); + p = &scal_sig[-p_max]; move16 (); + for (i = 0; i < L_frame; i++, p++) + { + t0 = L_mac (t0, *p, *p); + } + /* 1/sqrt(energy) */ + + if (dtx) + { /* no test() call since this if is only in simulation env */ + *rmax = max; move32(); + *r0 = t0; move32(); + /* check tone */ + if (!vadSt->use_vad2) + vad_tone_detection (&vadSt->u.v1, max, t0); + } + + t0 = Inv_sqrt (t0); move32 (); /* function result */ + + test(); + if (scal_flag) + { + t0 = L_shl (t0, 1); + } + + /* max = max/sqrt(energy) */ + + L_Extract (max, &max_h, &max_l); + L_Extract (t0, &ener_h, &ener_l); + + t0 = Mpy_32 (max_h, max_l, ener_h, ener_l); + + test(); + if (scal_flag) + { + t0 = L_shr (t0, scal_fac); + *cor_max = extract_h (L_shl (t0, 15)); /* divide by 2 */ + } + else + { + *cor_max = extract_l(t0); + } + + return (p_max); +} + +/* +******************************************************************************** +* PUBLIC PROGRAM CODE +******************************************************************************** +*/ +/************************************************************************* + * + * FUNCTION: Pitch_ol + * + * PURPOSE: Compute the open loop pitch lag. + * + * DESCRIPTION: + * The open-loop pitch lag is determined based on the perceptually + * weighted speech signal. This is done in the following steps: + * - find three maxima of the correlation <sw[n],sw[n-T]>, + * dividing the search range into three parts: + * pit_min ... 2*pit_min-1 + * 2*pit_min ... 4*pit_min-1 + * 4*pit_min ... pit_max + * - divide each maximum by <sw[n-t], sw[n-t]> where t is the delay at + * that maximum correlation. + * - select the delay of maximum normalized correlation (among the + * three candidates) while favoring the lower delay ranges. + * + *************************************************************************/ +Word16 Pitch_ol ( /* o : open loop pitch lag */ + vadState *vadSt, /* i/o : VAD state struct */ + enum Mode mode, /* i : coder mode */ + Word16 signal[], /* i : signal used to compute the open loop pitch */ + /* signal[-pit_max] to signal[-1] should be known */ + Word16 pit_min, /* i : minimum pitch lag */ + Word16 pit_max, /* i : maximum pitch lag */ + Word16 L_frame, /* i : length of frame to compute pitch */ + Word16 idx, /* i : frame index */ + Flag dtx /* i : dtx flag; use dtx=1, do not use dtx=0 */ + ) +{ + Word16 i, j; + Word16 max1, max2, max3; + Word16 p_max1, p_max2, p_max3; + Word16 scal_flag = 0; + Word32 t0; + Word32 r01, r02, r03; + Word32 rmax1, rmax2, rmax3; + Word16 corr_hp_max; + Word32 corr[PIT_MAX+1], *corr_ptr; + + /* Scaled signal */ + + Word16 scaled_signal[L_FRAME + PIT_MAX]; + Word16 *scal_sig, scal_fac; + + if (dtx && !vadSt->use_vad2) + { /* no test() call since this if is only in simulation env */ + /* update tone detection */ + test(); test(); + if ((sub(mode, MR475) == 0) || (sub(mode, MR515) == 0)) + { + vad_tone_detection_update (&vadSt->u.v1, 1); + } + else + { + vad_tone_detection_update (&vadSt->u.v1, 0); + } + } + + scal_sig = &scaled_signal[pit_max]; move16 (); + + t0 = 0L; move32 (); + for (i = -pit_max; i < L_frame; i++) + { + t0 = L_mac (t0, signal[i], signal[i]); + } + + /*--------------------------------------------------------* + * Scaling of input signal. * + * * + * if Overflow -> scal_sig[i] = signal[i]>>3 * + * else if t0 < 1^20 -> scal_sig[i] = signal[i]<<3 * + * else -> scal_sig[i] = signal[i] * + *--------------------------------------------------------*/ + + /*--------------------------------------------------------* + * Verification for risk of overflow. * + *--------------------------------------------------------*/ + + test (); + if (L_sub (t0, MAX_32) == 0L) /* Test for overflow */ + { + for (i = -pit_max; i < L_frame; i++) + { + scal_sig[i] = shr (signal[i], 3); move16 (); + } + scal_fac = 3; move16 (); + } + else if (L_sub (t0, (Word32) 1048576L) < (Word32) 0) + /* if (t0 < 2^20) */ + { + test (); + for (i = -pit_max; i < L_frame; i++) + { + scal_sig[i] = shl (signal[i], 3); move16 (); + } + scal_fac = -3; move16 (); + } + else + { + test (); + for (i = -pit_max; i < L_frame; i++) + { + scal_sig[i] = signal[i]; move16 (); + } + scal_fac = 0; move16 (); + } + + /* calculate all coreelations of scal_sig, from pit_min to pit_max */ + corr_ptr = &corr[pit_max]; move32 (); + comp_corr (scal_sig, L_frame, pit_max, pit_min, corr_ptr); + + /*--------------------------------------------------------------------* + * The pitch lag search is divided in three sections. * + * Each section cannot have a pitch multiple. * + * We find a maximum for each section. * + * We compare the maximum of each section by favoring small lags. * + * * + * First section: lag delay = pit_max downto 4*pit_min * + * Second section: lag delay = 4*pit_min-1 downto 2*pit_min * + * Third section: lag delay = 2*pit_min-1 downto pit_min * + *--------------------------------------------------------------------*/ + + /* mode dependent scaling in Lag_max */ + test (); + if (sub(mode, MR122) == 0) + { + scal_flag = 1; move16 (); + } + else + { + scal_flag = 0; move16 (); + } + + j = shl (pit_min, 2); + p_max1 = Lag_max (vadSt, corr_ptr, scal_sig, scal_fac, scal_flag, L_frame, + pit_max, j, &max1, &rmax1, &r01, dtx); + + i = sub (j, 1); + j = shl (pit_min, 1); + p_max2 = Lag_max (vadSt, corr_ptr, scal_sig, scal_fac, scal_flag, L_frame, + i, j, &max2, &rmax2, &r02, dtx); + + i = sub (j, 1); + p_max3 = Lag_max (vadSt, corr_ptr, scal_sig, scal_fac, scal_flag, L_frame, + i, pit_min, &max3, &rmax3, &r03, dtx); + + if (dtx && !vadSt->use_vad2) + { /* no test() call since this if is only in simulation env */ + test (); + if (sub(idx, 1) == 0) + { + /* calculate max high-passed filtered correlation of all lags */ + hp_max (corr_ptr, scal_sig, L_frame, pit_max, pit_min, &corr_hp_max); + + /* update complex background detector */ + vad_complex_detection_update(&vadSt->u.v1, corr_hp_max); + } + } + + /*--------------------------------------------------------------------* + * Compare the 3 sections maximum, and favor small lag. * + *--------------------------------------------------------------------*/ + + test (); + if (sub (mult (max1, THRESHOLD), max2) < 0) + { + max1 = max2; move16 (); + p_max1 = p_max2; move16 (); + if (dtx) + { + rmax1 = rmax2; move32 (); + r01 = r02; move32 (); + } + } + test (); + if (sub (mult (max1, THRESHOLD), max3) < 0) + { + p_max1 = p_max3; move16 (); + if (dtx) + { + rmax1 = rmax3; move32 (); + r01 = r03; move32 (); + } + } + + if (dtx && vadSt->use_vad2) + { + /* Save max correlation */ + vadSt->u.v2.L_Rmax = L_add(vadSt->u.v2.L_Rmax, rmax1); + /* Save max energy */ + vadSt->u.v2.L_R0 = L_add(vadSt->u.v2.L_R0, r01); + } + + return (p_max1); +}