FreeCalypso > hg > gsm-codec-lib
diff libgsmefr/pitch_ol.c @ 53:49dd1ac8e75b
libgsmefr: import most *.c files from ETSI source
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 25 Nov 2022 16:18:21 +0000 |
parents | |
children | 509ba99f5136 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgsmefr/pitch_ol.c Fri Nov 25 16:18:21 2022 +0000 @@ -0,0 +1,214 @@ +/************************************************************************* + * + * 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]> in the + * follwing three ranges of T : [18,35], [36,71], and [72, 143] + * - 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. + * + *************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" +#include "count.h" +#include "sig_proc.h" + +#define THRESHOLD 27853 + +/* local function */ + +static Word16 Lag_max ( /* output: lag found */ + Word16 scal_sig[], /* input : scaled signal */ + Word16 scal_fac, /* input : scaled signal factor */ + Word16 L_frame, /* input : length of frame to compute pitch */ + Word16 lag_max, /* input : maximum lag */ + Word16 lag_min, /* input : minimum lag */ + Word16 *cor_max); /* output: normalized correlation of selected lag */ + +Word16 Pitch_ol ( /* output: open loop pitch lag */ + Word16 signal[], /* input : signal used to compute the open loop pitch */ + /* signal[-pit_max] to signal[-1] should be known */ + Word16 pit_min, /* input : minimum pitch lag */ + Word16 pit_max, /* input : maximum pitch lag */ + Word16 L_frame /* input : length of frame to compute pitch */ +) +{ + Word16 i, j; + Word16 max1, max2, max3; + Word16 p_max1, p_max2, p_max3; + Word32 t0; + + /* Scaled signal */ + /* Can be allocated with memory allocation of(pit_max+L_frame) */ + + Word16 scaled_signal[512]; + Word16 *scal_sig, scal_fac; + + 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]>>2 * + * else if t0 < 1^22 -> scal_sig[i] = signal[i]<<2 * + * else -> scal_sig[i] = signal[i] * + *--------------------------------------------------------*/ + + /*--------------------------------------------------------* + * Verification for risk of overflow. * + *--------------------------------------------------------*/ + + test (); 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) */ + { + for (i = -pit_max; i < L_frame; i++) + { + scal_sig[i] = shl (signal[i], 3); move16 (); + } + scal_fac = -3; move16 (); + } + else + { + for (i = -pit_max; i < L_frame; i++) + { + scal_sig[i] = signal[i]; move16 (); + } + scal_fac = 0; move16 (); + } + + /*--------------------------------------------------------------------* + * 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 * + *-------------------------------------------------------------------*/ + + j = shl (pit_min, 2); + p_max1 = Lag_max (scal_sig, scal_fac, L_frame, pit_max, j, &max1); + + i = sub (j, 1); + j = shl (pit_min, 1); + p_max2 = Lag_max (scal_sig, scal_fac, L_frame, i, j, &max2); + + i = sub (j, 1); + p_max3 = Lag_max (scal_sig, scal_fac, L_frame, i, pit_min, &max3); + + /*--------------------------------------------------------------------* + * 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 (); + } + test (); + if (sub (mult (max1, THRESHOLD), max3) < 0) + { + p_max1 = p_max3; move16 (); + } + return (p_max1); +} + +/************************************************************************* + * + * 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 ( /* output: lag found */ + Word16 scal_sig[], /* input : scaled signal. */ + Word16 scal_fac, /* input : scaled signal factor. */ + Word16 L_frame, /* input : length of frame to compute pitch */ + Word16 lag_max, /* input : maximum lag */ + Word16 lag_min, /* input : minimum lag */ + Word16 *cor_max) /* output: normalized correlation of selected lag */ +{ + Word16 i, j; + Word16 *p, *p1; + Word32 max, t0; + Word16 max_h, max_l, ener_h, ener_l; + Word16 p_max; + + max = MIN_32; move32 (); + + for (i = lag_max; i >= lag_min; i--) + { + p = scal_sig; move16 (); + p1 = &scal_sig[-i]; move16 (); + t0 = 0; move32 (); + + for (j = 0; j < L_frame; j++, p++, p1++) + { + t0 = L_mac (t0, *p, *p1); + } + test (); + if (L_sub (t0, max) >= 0) + { + max = t0; 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) */ + + t0 = Inv_sqrt (t0); + 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); + t0 = L_shr (t0, scal_fac); + + *cor_max = extract_h (L_shl (t0, 15)); move16 (); /* divide by 2 */ + + return (p_max); +}