ref: 0925455043d9bafe48052fc0734a54753bd5fb87
parent: f54982203e17a06ba080a28723382bd04c09d303
author: robs <robs>
date: Thu Feb 15 18:22:20 EST 2007
Add AMR-WB format
--- a/AUTHORS
+++ b/AUTHORS
@@ -88,9 +88,9 @@
Build system makeover, Lua scripting, Secret Rabbit
Code resampling, much cleanup.
Rob Sykes robs@users.sourceforge.net
- Bass & treble effects, FLAC support, initial 24bit
+ Bass & treble effects, FLAC & AMR-WB formats, initial 24bit
support, filters makeover inc. octave plots, new flanger,
- file merging, speed via resampling, pad effect,
- various small fixes, enhancements and clean-ups,
+ file merging, speed via resampling, soft-knee companding,
+ pad effect, various fixes, enhancements and clean-ups,
much manual improvement and expansion, play multiple
files with mixed format types.
--- a/ChangeLog
+++ b/ChangeLog
@@ -12,6 +12,8 @@
o Added support for ADPCM-encoded PRC files, based on Danny Smith's
rec2wav and sndcmp.
+ o Added AMR-WB format. (robs)
+
Effects:
o Add soft-knee companding. (robs)
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,8 +2,8 @@
ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = @LIBGSM_SUBDIR@ src
-DIST_SUBDIRS = src/libgsm src
+SUBDIRS = amr-wb @LIBGSM_SUBDIR@ src
+DIST_SUBDIRS = amr-wb src/libgsm src
# man pages are not considered to be sources, so need to add "dist_"
# prefix to ensure they are added to the distribution.
--- /dev/null
+++ b/amr-wb/acelp.h
@@ -1,0 +1,493 @@
+/*--------------------------------------------------------------------------*
+ * ACELP.H *
+ *--------------------------------------------------------------------------*
+ * Function *
+ *--------------------------------------------------------------------------*/
+
+#include "typedef.h"
+
+/*-----------------------------------------------------------------*
+ * LPC prototypes *
+ *-----------------------------------------------------------------*/
+
+void Isf_Extrapolation(Word16 HfIsf[]);
+
+void Init_Lagconc(Word16 lag_hist[]);
+void lagconc(
+ Word16 gain_hist[], /* (i) : Gain history */
+ Word16 lag_hist[], /* (i) : Subframe size */
+ Word16 * T0,
+ Word16 * old_T0,
+ Word16 * seed,
+ Word16 unusable_frame
+);
+
+void agc2(
+ Word16 * sig_in, /* input : postfilter input signal */
+ Word16 * sig_out, /* in/out: postfilter output signal */
+ Word16 l_trm /* input : subframe size */
+);
+
+void Init_Filt_7k(Word16 mem[]);
+void Filt_7k(
+ Word16 signal[], /* input: signal */
+ Word16 lg, /* input: length of input */
+ Word16 mem[] /* in/out: memory (size=30) */
+);
+
+Word16 median5(Word16 x[]);
+
+void Autocorr(
+ Word16 x[], /* (i) : Input signal */
+ Word16 m, /* (i) : LPC order */
+ Word16 r_h[], /* (o) : Autocorrelations (msb) */
+ Word16 r_l[] /* (o) : Autocorrelations (lsb) */
+);
+void Lag_window(
+ Word16 r_h[], /* (i/o) : Autocorrelations (msb) */
+ Word16 r_l[] /* (i/o) : Autocorrelations (lsb) */
+);
+void Init_Levinson(
+ Word16 * mem /* output :static memory (18 words) */
+);
+void Levinson(
+ Word16 Rh[], /* (i) : Rh[M+1] Vector of autocorrelations (msb) */
+ Word16 Rl[], /* (i) : Rl[M+1] Vector of autocorrelations (lsb) */
+ Word16 A[], /* (o) Q12 : A[M] LPC coefficients (m = 16) */
+ Word16 rc[], /* (o) Q15 : rc[M] Reflection coefficients. */
+ Word16 * mem /* (i/o) :static memory (18 words) */
+);
+
+void Az_isp(
+ Word16 a[], /* (i) Q12 : predictor coefficients */
+ Word16 isp[], /* (o) Q15 : Immittance spectral pairs */
+ Word16 old_isp[] /* (i) : old isp[] (in case not found M roots) */
+);
+void Isp_Az(
+ Word16 isp[], /* (i) Q15 : Immittance spectral pairs */
+ Word16 a[], /* (o) Q12 : predictor coefficients (order = M) */
+ Word16 m,
+ Word16 adaptive_scaling /* (i) 0 : adaptive scaling disabled */
+ /* 1 : adaptive scaling enabled */
+);
+void Isp_isf(
+ Word16 isp[], /* (i) Q15 : isp[m] (range: -1<=val<1) */
+ Word16 isf[], /* (o) Q15 : isf[m] normalized (range: 0.0<=val<=0.5) */
+ Word16 m /* (i) : LPC order */
+);
+void Isf_isp(
+ Word16 isf[], /* (i) Q15 : isf[m] normalized (range: 0.0<=val<=0.5) */
+ Word16 isp[], /* (o) Q15 : isp[m] (range: -1<=val<1) */
+ Word16 m /* (i) : LPC order */
+);
+void Int_isp(
+ Word16 isp_old[], /* input : isps from past frame */
+ Word16 isp_new[], /* input : isps from present frame */
+ Word16 frac[], /* input : fraction for 3 first subfr (Q15) */
+ Word16 Az[] /* output: LP coefficients in 4 subframes */
+);
+void Weight_a(
+ Word16 a[], /* (i) Q12 : a[m+1] LPC coefficients */
+ Word16 ap[], /* (o) Q12 : Spectral expanded LPC coefficients */
+ Word16 gamma, /* (i) Q15 : Spectral expansion factor. */
+ Word16 m /* (i) : LPC order. */
+);
+
+
+/*-----------------------------------------------------------------*
+ * isf quantizers *
+ *-----------------------------------------------------------------*/
+
+void Qpisf_2s_46b(
+ Word16 * isf1, /* (i) Q15 : ISF in the frequency domain (0..0.5) */
+ Word16 * isf_q, /* (o) Q15 : quantized ISF (0..0.5) */
+ Word16 * past_isfq, /* (io)Q15 : past ISF quantizer */
+ Word16 * indice, /* (o) : quantization indices */
+ Word16 nb_surv /* (i) : number of survivor (1, 2, 3 or 4) */
+);
+void Qpisf_2s_36b(
+ Word16 * isf1, /* (i) Q15 : ISF in the frequency domain (0..0.5) */
+ Word16 * isf_q, /* (o) Q15 : quantized ISF (0..0.5) */
+ Word16 * past_isfq, /* (io)Q15 : past ISF quantizer */
+ Word16 * indice, /* (o) : quantization indices */
+ Word16 nb_surv /* (i) : number of survivor (1, 2, 3 or 4) */
+);
+void Dpisf_2s_46b(
+ Word16 * indice, /* input: quantization indices */
+ Word16 * isf_q, /* output: quantized ISF in frequency domain (0..0.5) */
+ Word16 * past_isfq, /* i/0 : past ISF quantizer */
+ Word16 * isfold, /* input : past quantized ISF */
+ Word16 * isf_buf, /* input : isf buffer */
+ Word16 bfi, /* input : Bad frame indicator */
+ Word16 enc_dec
+);
+void Dpisf_2s_36b(
+ Word16 * indice, /* input: quantization indices */
+ Word16 * isf_q, /* output: quantized ISF in frequency domain (0..0.5) */
+ Word16 * past_isfq, /* i/0 : past ISF quantizer */
+ Word16 * isfold, /* input : past quantized ISF */
+ Word16 * isf_buf, /* input : isf buffer */
+ Word16 bfi, /* input : Bad frame indicator */
+ Word16 enc_dec
+);
+void Qisf_ns(
+ Word16 * isf1, /* input : ISF in the frequency domain (0..0.5) */
+ Word16 * isf_q, /* output: quantized ISF */
+ Word16 * indice /* output: quantization indices */
+);
+void Disf_ns(
+ Word16 * indice, /* input: quantization indices */
+ Word16 * isf_q /* input : ISF in the frequency domain (0..0.5) */
+);
+Word16 Sub_VQ( /* output: return quantization index */
+ Word16 * x, /* input : ISF residual vector */
+ Word16 * dico, /* input : quantization codebook */
+ Word16 dim, /* input : dimention of vector */
+ Word16 dico_size, /* input : size of quantization codebook */
+ Word32 * distance /* output: error of quantization */
+);
+void Reorder_isf(
+ Word16 * isf, /* (i/o) Q15: ISF in the frequency domain (0..0.5) */
+ Word16 min_dist, /* (i) Q15 : minimum distance to keep */
+ Word16 n /* (i) : number of ISF */
+);
+
+/*-----------------------------------------------------------------*
+ * filter prototypes *
+ *-----------------------------------------------------------------*/
+
+void Init_Decim_12k8(
+ Word16 mem[] /* output: memory (2*NB_COEF_DOWN) set to zeros */
+);
+void Decim_12k8(
+ Word16 sig16k[], /* input: signal to downsampling */
+ Word16 lg, /* input: length of input */
+ Word16 sig12k8[], /* output: decimated signal */
+ Word16 mem[] /* in/out: memory (2*NB_COEF_DOWN) */
+);
+
+void Init_Oversamp_16k(
+ Word16 mem[] /* output: memory (2*NB_COEF_UP) set to zeros */
+);
+void Oversamp_16k(
+ Word16 sig12k8[], /* input: signal to oversampling */
+ Word16 lg, /* input: length of input */
+ Word16 sig16k[], /* output: oversampled signal */
+ Word16 mem[] /* in/out: memory (2*NB_COEF_UP) */
+);
+
+void Init_HP50_12k8(Word16 mem[]);
+void HP50_12k8(
+ Word16 signal[], /* input/output signal */
+ Word16 lg, /* lenght of signal */
+ Word16 mem[] /* filter memory [6] */
+);
+void Init_HP400_12k8(Word16 mem[]);
+void HP400_12k8(
+ Word16 signal[], /* input/output signal */
+ Word16 lg, /* lenght of signal */
+ Word16 mem[] /* filter memory [6] */
+);
+
+void Init_Filt_6k_7k(Word16 mem[]);
+void Filt_6k_7k(
+ Word16 signal[], /* input: signal */
+ Word16 lg, /* input: length of input */
+ Word16 mem[] /* in/out: memory (size=30) */
+);
+
+void LP_Decim2(
+ Word16 x[], /* in/out: signal to process */
+ Word16 l, /* input : size of filtering */
+ Word16 mem[] /* in/out: memory (size=3) */
+);
+
+void Preemph(
+ Word16 x[], /* (i/o) : input signal overwritten by the output */
+ Word16 mu, /* (i) Q15 : preemphasis coefficient */
+ Word16 lg, /* (i) : lenght of filtering */
+ Word16 * mem /* (i/o) : memory (x[-1]) */
+);
+void Preemph2(
+ Word16 x[], /* (i/o) : input signal overwritten by the output */
+ Word16 mu, /* (i) Q15 : preemphasis coefficient */
+ Word16 lg, /* (i) : lenght of filtering */
+ Word16 * mem /* (i/o) : memory (x[-1]) */
+);
+void Deemph(
+ Word16 x[], /* (i/o) : input signal overwritten by the output */
+ Word16 mu, /* (i) Q15 : deemphasis factor */
+ Word16 L, /* (i) : vector size */
+ Word16 * mem /* (i/o) : memory (y[-1]) */
+);
+void Deemph2(
+ Word16 x[], /* (i/o) : input signal overwritten by the output */
+ Word16 mu, /* (i) Q15 : deemphasis factor */
+ Word16 L, /* (i) : vector size */
+ Word16 * mem /* (i/o) : memory (y[-1]) */
+);
+void Deemph_32(
+ Word16 x_hi[], /* (i) : input signal (bit31..16) */
+ Word16 x_lo[], /* (i) : input signal (bit15..4) */
+ Word16 y[], /* (o) : output signal (x16) */
+ Word16 mu, /* (i) Q15 : deemphasis factor */
+ Word16 L, /* (i) : vector size */
+ Word16 * mem /* (i/o) : memory (y[-1]) */
+);
+
+void Convolve(
+ Word16 x[], /* (i) : input vector */
+ Word16 h[], /* (i) Q15 : impulse response */
+ Word16 y[], /* (o) 12 bits: output vector */
+ Word16 L /* (i) : vector size */
+);
+
+void Residu(
+ Word16 a[], /* (i) Q12 : prediction coefficients */
+ Word16 m, /* (i) : order of LP filter */
+ Word16 x[], /* (i) : speech (values x[-m..-1] are needed */
+ Word16 y[], /* (o) : residual signal */
+ Word16 lg /* (i) : size of filtering */
+);
+void Syn_filt(
+ Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */
+ Word16 m, /* (i) : order of LP filter */
+ Word16 x[], /* (i) : input signal */
+ Word16 y[], /* (o) : output signal */
+ Word16 lg, /* (i) : size of filtering */
+ Word16 mem[], /* (i/o) : memory associated with this filtering. */
+ Word16 update /* (i) : 0=no update, 1=update of memory. */
+);
+void Syn_filt_32(
+ Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */
+ Word16 m, /* (i) : order of LP filter */
+ Word16 exc[], /* (i) Qnew: excitation (exc[i] >> Qnew) */
+ Word16 Qnew, /* (i) : exc scaling = 0(min) to 8(max) */
+ Word16 sig_hi[], /* (o) /16 : synthesis high */
+ Word16 sig_lo[], /* (o) /16 : synthesis low */
+ Word16 lg /* (i) : size of filtering */
+);
+
+/*-----------------------------------------------------------------*
+ * pitch prototypes *
+ *-----------------------------------------------------------------*/
+
+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 Pitch_med_ol( /* output: open loop pitch lag */
+ Word16 wsp[], /* input : signal used to compute the open loop pitch */
+/* wsp[-pit_max] to wsp[-1] should be known */
+ Word16 L_min, /* input : minimum pitch lag */
+ Word16 L_max, /* input : maximum pitch lag */
+ Word16 L_frame, /* input : length of frame to compute pitch */
+ Word16 L_0, /* input : old_ open-loop pitch */
+ Word16 * gain, /* output: normalize correlation of hp_wsp for the Lag */
+ Word16 * hp_wsp_mem, /* i:o : memory of the hypass filter for hp_wsp[] (lg=9) */
+ Word16 * old_hp_wsp, /* i:o : hypass wsp[] */
+ Word16 wght_flg /* input : is weighting function used */
+);
+Word16 Med_olag( /* output : median of 5 previous open-loop lags */
+ Word16 prev_ol_lag, /* input : previous open-loop lag */
+ Word16 old_ol_lag[5]
+);
+void Init_Hp_wsp(Word16 mem[]);
+void scale_mem_Hp_wsp(Word16 mem[], Word16 exp);
+void Hp_wsp(
+ Word16 wsp[], /* i : wsp[] signal */
+ Word16 hp_wsp[], /* o : hypass wsp[] */
+ Word16 lg, /* i : lenght of signal */
+ Word16 mem[] /* i/o : filter memory [9] */
+);
+
+Word16 Pitch_fr4( /* (o) : pitch period. */
+ Word16 exc[], /* (i) : excitation buffer */
+ Word16 xn[], /* (i) : target vector */
+ Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */
+ Word16 t0_min, /* (i) : minimum value in the searched range. */
+ Word16 t0_max, /* (i) : maximum value in the searched range. */
+ Word16 * pit_frac, /* (o) : chosen fraction (0, 1, 2 or 3). */
+ Word16 i_subfr, /* (i) : indicator for first subframe. */
+ Word16 t0_fr2, /* (i) : minimum value for resolution 1/2 */
+ Word16 t0_fr1, /* (i) : minimum value for resolution 1 */
+ Word16 L_subfr /* (i) : Length of subframe */
+);
+void Pred_lt4(
+ Word16 exc[], /* in/out: excitation buffer */
+ Word16 T0, /* input : integer pitch lag */
+ Word16 frac, /* input : fraction of lag */
+ Word16 L_subfr /* input : subframe size */
+);
+
+
+/*-----------------------------------------------------------------*
+ * gain prototypes *
+ *-----------------------------------------------------------------*/
+
+Word16 G_pitch( /* (o) Q14 : Gain of pitch lag saturated to 1.2 */
+ Word16 xn[], /* (i) : Pitch target. */
+ Word16 y1[], /* (i) : filtered adaptive codebook. */
+ Word16 g_coeff[], /* : Correlations need for gain quantization. */
+ Word16 L_subfr /* : Length of subframe. */
+);
+void Init_Q_gain2(
+ Word16 * mem /* output :static memory (2 words) */
+);
+Word16 Q_gain2( /* Return index of quantization. */
+ Word16 xn[], /* (i) Q_xn:Target vector. */
+ Word16 y1[], /* (i) Q_xn:Adaptive codebook. */
+ Word16 Q_xn, /* (i) :xn and y1 format */
+ Word16 y2[], /* (i) Q9 :Filtered innovative vector. */
+ Word16 code[], /* (i) Q9 :Innovative vector. */
+ Word16 g_coeff[], /* (i) :Correlations <xn y1> <y1 y1> */
+/* Compute in G_pitch(). */
+ Word16 L_subfr, /* (i) :Subframe lenght. */
+ Word16 nbits, /* (i) : number of bits (6 or 7) */
+ Word16 * gain_pit, /* (i/o)Q14:Pitch gain. */
+ Word32 * gain_cod, /* (o) Q16 :Code gain. */
+ Word16 gp_clip, /* (i) : Gp Clipping flag */
+ Word16 * mem /* (i/o) :static memory (2 words) */
+);
+
+void Init_D_gain2(
+ Word16 * mem /* output :static memory (4 words) */
+);
+void D_gain2(
+ Word16 index, /* (i) :index of quantization. */
+ Word16 nbits, /* (i) : number of bits (6 or 7) */
+ Word16 code[], /* (i) Q9 :Innovative vector. */
+ Word16 L_subfr, /* (i) :Subframe lenght. */
+ Word16 * gain_pit, /* (o) Q14 :Pitch gain. */
+ Word32 * gain_cod, /* (o) Q16 :Code gain. */
+ Word16 bfi, /* (i) :bad frame indicator */
+ Word16 prev_bfi, /* (i) : Previous BF indicator */
+ Word16 state, /* (i) : State of BFH */
+ Word16 unusable_frame, /* (i) : UF indicator */
+ Word16 vad_hist, /* (i) :number of non-speech frames */
+ Word16 * mem /* (i/o) :static memory (4 words) */
+);
+
+/*-----------------------------------------------------------------*
+ * acelp prototypes *
+ *-----------------------------------------------------------------*/
+
+void cor_h_x(
+ Word16 h[], /* (i) Q12 : impulse response of weighted synthesis filter */
+ Word16 x[], /* (i) Q0 : target vector */
+ Word16 dn[] /* (o) <12bit : correlation between target and h[] */
+);
+void ACELP_2t64_fx(
+ Word16 dn[], /* (i) <12b : correlation between target x[] and H[] */
+ Word16 cn[], /* (i) <12b : residual after long term prediction */
+ Word16 H[], /* (i) Q12: impulse response of weighted synthesis filter */
+ Word16 code[], /* (o) Q9 : algebraic (fixed) codebook excitation */
+ Word16 y[], /* (o) Q9 : filtered fixed codebook excitation */
+ Word16 * index /* (o) : index (12): 5+1+5+1 = 11 bits. */
+);
+void DEC_ACELP_2t64_fx(
+ Word16 index, /* (i) : 12 bits index */
+ Word16 code[] /* (o) :Q9 algebraic (fixed) codebook excitation */
+);
+void ACELP_4t64_fx(
+ Word16 dn[], /* (i) <12b : correlation between target x[] and H[] */
+ Word16 cn[], /* (i) <12b : residual after long term prediction */
+ Word16 H[], /* (i) Q12: impulse response of weighted synthesis filter */
+ Word16 code[], /* (o) Q9 : algebraic (fixed) codebook excitation */
+ Word16 y[], /* (o) Q9 : filtered fixed codebook excitation */
+ Word16 nbbits, /* (i) : 20, 36, 44, 52, 64, 72 or 88 bits */
+ Word16 ser_size, /* (i) : bit rate */
+ Word16 _index[] /* (o) : index (20): 5+5+5+5 = 20 bits. */
+ /* (o) : index (36): 9+9+9+9 = 36 bits. */
+ /* (o) : index (44): 13+9+13+9 = 44 bits. */
+ /* (o) : index (52): 13+13+13+13 = 52 bits. */
+ /* (o) : index (64): 2+2+2+2+14+14+14+14 = 64 bits. */
+ /* (o) : index (72): 10+2+10+2+10+14+10+14 = 72 bits. */
+ /* (o) : index (88): 11+11+11+11+11+11+11+11 = 88 bits. */
+);
+void DEC_ACELP_4t64_fx(
+ Word16 index[], /* (i) : index (20): 5+5+5+5 = 20 bits. */
+ /* (i) : index (36): 9+9+9+9 = 36 bits. */
+ /* (i) : index (44): 13+9+13+9 = 44 bits. */
+ /* (i) : index (52): 13+13+13+13 = 52 bits. */
+ /* (i) : index (64): 2+2+2+2+14+14+14+14 = 64 bits. */
+ /* (i) : index (72): 10+2+10+2+10+14+10+14 = 72 bits. */
+ /* (i) : index (88): 11+11+11+11+11+11+11+11 = 88 bits. */
+ Word16 nbbits, /* (i) : 20, 36, 44, 52, 64, 72 or 88 bits */
+ Word16 code[] /* (o) Q9: algebraic (fixed) codebook excitation */
+);
+void Pit_shrp(
+ Word16 * x, /* in/out: impulse response (or algebraic code) */
+ Word16 pit_lag, /* input : pitch lag */
+ Word16 sharp, /* input : pitch sharpening factor (Q15) */
+ Word16 L_subfr /* input : subframe size */
+);
+
+
+/*-----------------------------------------------------------------*
+ * others prototypes *
+ *-----------------------------------------------------------------*/
+
+void Copy(
+ Word16 x[], /* (i) : input vector */
+ Word16 y[], /* (o) : output vector */
+ Word16 L /* (i) : vector length */
+);
+void Set_zero(
+ Word16 x[], /* (o) : vector to clear */
+ Word16 L /* (i) : length of vector */
+);
+void Updt_tar(
+ Word16 * x, /* (i) Q0 : old target (for pitch search) */
+ Word16 * x2, /* (o) Q0 : new target (for codebook search) */
+ Word16 * y, /* (i) Q0 : filtered adaptive codebook vector */
+ Word16 gain, /* (i) Q14 : adaptive codebook gain */
+ Word16 L /* (i) : subframe size */
+);
+Word16 voice_factor( /* (o) Q15 : factor (-1=unvoiced to 1=voiced) */
+ Word16 exc[], /* (i) Q_exc: pitch excitation */
+ Word16 Q_exc, /* (i) : exc format */
+ Word16 gain_pit, /* (i) Q14 : gain of pitch */
+ Word16 code[], /* (i) Q9 : Fixed codebook excitation */
+ Word16 gain_code, /* (i) Q0 : gain of code */
+ Word16 L_subfr /* (i) : subframe length */
+);
+void Scale_sig(
+ Word16 x[], /* (i/o) : signal to scale */
+ Word16 lg, /* (i) : size of x[] */
+ Word16 exp /* (i) : exponent: x = round(x << exp) */
+);
+
+void snr(Word16 x[], Word16 y[], Word16 l, Word16 Q_x);
+
+Word16 Random(Word16 * seed);
+
+void Init_gp_clip(
+ Word16 mem[] /* (o) : memory of gain of pitch clipping algorithm */
+);
+Word16 Gp_clip(
+ Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */
+);
+void Gp_clip_test_isf(
+ Word16 isf[], /* (i) : isf values (in frequency domain) */
+ Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */
+);
+void Gp_clip_test_gain_pit(
+ Word16 gain_pit, /* (i) : gain of quantized pitch */
+ Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */
+);
+
+void Init_Phase_dispersion(
+ Word16 disp_mem[] /* (i/o): static memory (size = 8) */
+);
+void Phase_dispersion(
+ Word16 gain_code, /* (i) Q0 : gain of code */
+ Word16 gain_pit, /* (i) Q14 : gain of pitch */
+ Word16 code[], /* (i/o) : code vector */
+ Word16 mode, /* (i) : level, 0=hi, 1=lo, 2=off */
+ Word16 disp_mem[] /* (i/o) : static memory (size = 8) */
+);
--- /dev/null
+++ b/amr-wb/agc2.c
@@ -1,0 +1,89 @@
+/*------------------------------------------------------------------------*
+ * AGC2.C *
+ *------------------------------------------------------------------------*
+ * Performs adaptive gain control *
+ *------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cnst.h"
+#include "acelp.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+#include "math_op.h"
+
+void agc2(
+ Word16 * sig_in, /* (i) : postfilter input signal */
+ Word16 * sig_out, /* (i/o) : postfilter output signal */
+ Word16 l_trm /* (i) : subframe size */
+)
+{
+
+ Word16 i, exp;
+ Word16 gain_in, gain_out, g0;
+ Word32 s;
+
+ Word16 temp;
+
+ /* calculate gain_out with exponent */
+
+ temp = shr(sig_out[0], 2);
+ s = L_mult(temp, temp);
+ for (i = 1; i < l_trm; i++)
+ {
+ temp = shr(sig_out[i], 2);
+ s = L_mac(s, temp, temp);
+ }
+
+ test();
+ if (s == 0)
+ {
+ return;
+ }
+ exp = sub(norm_l(s), 1);
+ gain_out = round(L_shl(s, exp));
+
+ /* calculate gain_in with exponent */
+
+ temp = shr(sig_in[0], 2);
+ s = L_mult(temp, temp);
+ for (i = 1; i < l_trm; i++)
+ {
+ temp = shr(sig_in[i], 2);
+ s = L_mac(s, temp, temp);
+ }
+
+ test();
+ if (s == 0)
+ {
+ g0 = 0;
+ move16();
+ } else
+ {
+ i = norm_l(s);
+ gain_in = round(L_shl(s, i));
+ exp = sub(exp, i);
+
+ /*---------------------------------------------------*
+ * g0 = sqrt(gain_in/gain_out); *
+ *---------------------------------------------------*/
+
+ s = L_deposit_l(div_s(gain_out, gain_in));
+ s = L_shl(s, 7); /* s = gain_out / gain_in */
+ s = L_shr(s, exp); /* add exponent */
+
+ s = Isqrt(s);
+ g0 = round(L_shl(s, 9));
+ }
+ /* sig_out(n) = gain(n) sig_out(n) */
+
+ for (i = 0; i < l_trm; i++)
+ {
+ sig_out[i] = extract_h(L_shl(L_mult(sig_out[i], g0), 2));
+ move16();
+ }
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/amr-wb.h
@@ -1,0 +1,9 @@
+#include "typedef.h"
+#include "basic_op.h"
+#include "acelp.h"
+#include "cnst.h"
+#include "main.h"
+#include "bits.h"
+#include "dtx.h"
+#include "count.h"
+#include "cod_main.h"
--- /dev/null
+++ b/amr-wb/autocorr.c
@@ -1,0 +1,81 @@
+/*------------------------------------------------------------------------*
+ * AUTOCORR.C *
+ *------------------------------------------------------------------------*
+ * Compute autocorrelations of signal with windowing *
+ * *
+ *------------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "acelp.h"
+#include "count.h"
+
+#include "ham_wind.tab"
+
+
+void Autocorr(
+ Word16 x[], /* (i) : Input signal */
+ Word16 m, /* (i) : LPC order */
+ Word16 r_h[], /* (o) Q15: Autocorrelations (msb) */
+ Word16 r_l[] /* (o) : Autocorrelations (lsb) */
+)
+{
+ Word16 i, j, norm, shift, y[L_WINDOW];
+ Word32 L_sum, L_tmp;
+
+ /* Windowing of signal */
+
+ for (i = 0; i < L_WINDOW; i++)
+ {
+ y[i] = mult_r(x[i], window[i]); move16();
+ }
+
+ /* calculate energy of signal */
+
+ L_sum = L_deposit_h(16); /* sqrt(256), avoid overflow after rounding */
+ for (i = 0; i < L_WINDOW; i++)
+ {
+ L_tmp = L_mult(y[i], y[i]);
+ L_tmp = L_shr(L_tmp, 8);
+ L_sum = L_add(L_sum, L_tmp);
+ }
+
+ /* scale signal to avoid overflow in autocorrelation */
+
+ norm = norm_l(L_sum);
+ shift = sub(4, shr(norm, 1));
+ test();
+ if (shift < 0)
+ {
+ shift = 0; move16();
+ }
+ for (i = 0; i < L_WINDOW; i++)
+ {
+ y[i] = shr_r(y[i], shift); move16();
+ }
+
+ /* Compute and normalize r[0] */
+
+ L_sum = 1; move32();
+ for (i = 0; i < L_WINDOW; i++)
+ L_sum = L_mac(L_sum, y[i], y[i]);
+
+ norm = norm_l(L_sum);
+ L_sum = L_shl(L_sum, norm);
+ L_Extract(L_sum, &r_h[0], &r_l[0]); /* Put in DPF format (see oper_32b) */
+
+ /* Compute r[1] to r[m] */
+
+ for (i = 1; i <= m; i++)
+ {
+ L_sum = 0; move32();
+ for (j = 0; j < L_WINDOW - i; j++)
+ L_sum = L_mac(L_sum, y[j], y[j + i]);
+
+ L_sum = L_shl(L_sum, norm);
+ L_Extract(L_sum, &r_h[i], &r_l[i]);
+ }
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/az_isp.c
@@ -1,0 +1,275 @@
+/*-----------------------------------------------------------------------*
+ * Az_isp.C *
+ *-----------------------------------------------------------------------*
+ * Compute the ISPs from the LPC coefficients (order=M) *
+ *-----------------------------------------------------------------------*
+ * *
+ * The ISPs are the roots of the two polynomials F1(z) and F2(z) *
+ * defined as *
+ * F1(z) = A(z) + z^-m A(z^-1) *
+ * and F2(z) = A(z) - z^-m A(z^-1) *
+ * *
+ * For a even order m=2n, F1(z) has M/2 conjugate roots on the unit *
+ * circle and F2(z) has M/2-1 conjugate roots on the unit circle in *
+ * addition to two roots at 0 and pi. *
+ * *
+ * For a 16th order LP analysis, F1(z) and F2(z) can be written as *
+ * *
+ * F1(z) = (1 + a[M]) PRODUCT (1 - 2 cos(w_i) z^-1 + z^-2 ) *
+ * i=0,2,4,6,8,10,12,14 *
+ * *
+ * F2(z) = (1 - a[M]) (1 - z^-2) PRODUCT (1 - 2 cos(w_i) z^-1 + z^-2 ) *
+ * i=1,3,5,7,9,11,13 *
+ * *
+ * The ISPs are the M-1 frequencies w_i, i=0...M-2 plus the last *
+ * predictor coefficient a[M]. *
+ *-----------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "stdio.h"
+#include "count.h"
+
+#include "grid100.tab"
+
+#define M 16
+#define NC (M/2)
+
+/* local function */
+static Word16 Chebps2(Word16 x, Word16 f[], Word16 n);
+
+void Az_isp(
+ Word16 a[], /* (i) Q12 : predictor coefficients */
+ Word16 isp[], /* (o) Q15 : Immittance spectral pairs */
+ Word16 old_isp[] /* (i) : old isp[] (in case not found M roots) */
+)
+{
+ Word16 i, j, nf, ip, order;
+ Word16 xlow, ylow, xhigh, yhigh, xmid, ymid, xint;
+ Word16 x, y, sign, exp;
+ Word16 *coef;
+ Word16 f1[NC + 1], f2[NC];
+ Word32 t0;
+
+ /*-------------------------------------------------------------*
+ * find the sum and diff polynomials F1(z) and F2(z) *
+ * F1(z) = [A(z) + z^M A(z^-1)] *
+ * F2(z) = [A(z) - z^M A(z^-1)]/(1-z^-2) *
+ * *
+ * for (i=0; i<NC; i++) *
+ * { *
+ * f1[i] = a[i] + a[M-i]; *
+ * f2[i] = a[i] - a[M-i]; *
+ * } *
+ * f1[NC] = 2.0*a[NC]; *
+ * *
+ * for (i=2; i<NC; i++) Divide by (1-z^-2) *
+ * f2[i] += f2[i-2]; *
+ *-------------------------------------------------------------*/
+
+ for (i = 0; i < NC; i++)
+ {
+ t0 = L_mult(a[i], 16384);
+ f1[i] = round(L_mac(t0, a[M - i], 16384)); move16(); /* =(a[i]+a[M-i])/2 */
+ f2[i] = round(L_msu(t0, a[M - i], 16384)); move16(); /* =(a[i]-a[M-i])/2 */
+ }
+ f1[NC] = a[NC]; move16();
+
+ for (i = 2; i < NC; i++) /* Divide by (1-z^-2) */
+ f2[i] = add(f2[i], f2[i - 2]); move16();
+
+ /*---------------------------------------------------------------------*
+ * Find the ISPs (roots of F1(z) and F2(z) ) using the *
+ * Chebyshev polynomial evaluation. *
+ * The roots of F1(z) and F2(z) are alternatively searched. *
+ * We start by finding the first root of F1(z) then we switch *
+ * to F2(z) then back to F1(z) and so on until all roots are found. *
+ * *
+ * - Evaluate Chebyshev pol. at grid points and check for sign change.*
+ * - If sign change track the root by subdividing the interval *
+ * 2 times and ckecking sign change. *
+ *---------------------------------------------------------------------*/
+
+ nf = 0; move16(); /* number of found frequencies */
+ ip = 0; move16(); /* indicator for f1 or f2 */
+
+ coef = f1; move16();
+ order = NC; move16();
+
+ xlow = grid[0]; move16();
+ ylow = Chebps2(xlow, coef, order);
+
+ j = 0;
+ test();test();
+ while ((nf < M - 1) && (j < GRID_POINTS))
+ {
+ j = add(j, 1);
+ xhigh = xlow; move16();
+ yhigh = ylow; move16();
+ xlow = grid[j]; move16();
+ ylow = Chebps2(xlow, coef, order);
+
+ test();
+ if (L_mult(ylow, yhigh) <= (Word32) 0)
+ {
+ /* divide 2 times the interval */
+
+ for (i = 0; i < 2; i++)
+ {
+ xmid = add(shr(xlow, 1), shr(xhigh, 1)); /* xmid = (xlow + xhigh)/2 */
+
+ ymid = Chebps2(xmid, coef, order);
+
+ test();
+ if (L_mult(ylow, ymid) <= (Word32) 0)
+ {
+ yhigh = ymid; move16();
+ xhigh = xmid; move16();
+ } else
+ {
+ ylow = ymid; move16();
+ xlow = xmid; move16();
+ }
+ }
+
+ /*-------------------------------------------------------------*
+ * Linear interpolation *
+ * xint = xlow - ylow*(xhigh-xlow)/(yhigh-ylow); *
+ *-------------------------------------------------------------*/
+
+ x = sub(xhigh, xlow);
+ y = sub(yhigh, ylow);
+
+ test();
+ if (y == 0)
+ {
+ xint = xlow; move16();
+ } else
+ {
+ sign = y; move16();
+ y = abs_s(y);
+ exp = norm_s(y);
+ y = shl(y, exp);
+ y = div_s((Word16) 16383, y);
+ t0 = L_mult(x, y);
+ t0 = L_shr(t0, sub(20, exp));
+ y = extract_l(t0); /* y= (xhigh-xlow)/(yhigh-ylow) in Q11 */
+
+ test();
+ if (sign < 0)
+ y = negate(y);
+
+ t0 = L_mult(ylow, y); /* result in Q26 */
+ t0 = L_shr(t0, 11); /* result in Q15 */
+ xint = sub(xlow, extract_l(t0)); /* xint = xlow - ylow*y */
+ }
+
+ isp[nf] = xint; move16();
+ xlow = xint; move16();
+ nf++; move16();
+
+ test();
+ if (ip == 0)
+ {
+ ip = 1; move16();
+ coef = f2; move16();
+ order = NC - 1; move16();
+ } else
+ {
+ ip = 0; move16();
+ coef = f1; move16();
+ order = NC; move16();
+ }
+ ylow = Chebps2(xlow, coef, order);
+ }
+ test();test();
+ }
+
+ /* Check if M-1 roots found */
+
+ test();
+ if (sub(nf, M - 1) < 0)
+ {
+ for (i = 0; i < M; i++)
+ {
+ isp[i] = old_isp[i]; move16();
+ }
+ } else
+ {
+ isp[M - 1] = shl(a[M], 3); move16(); /* From Q12 to Q15 with saturation */
+ }
+
+ return;
+}
+
+
+/*--------------------------------------------------------------*
+ * function Chebps2: *
+ * ~~~~~~~ *
+ * Evaluates the Chebishev polynomial series *
+ *--------------------------------------------------------------*
+ * *
+ * The polynomial order is *
+ * n = M/2 (M is the prediction order) *
+ * The polynomial is given by *
+ * C(x) = f(0)T_n(x) + f(1)T_n-1(x) + ... +f(n-1)T_1(x) + f(n)/2 *
+ * Arguments: *
+ * x: input value of evaluation; x = cos(frequency) in Q15 *
+ * f[]: coefficients of the pol. in Q11 *
+ * n: order of the pol. *
+ * *
+ * The value of C(x) is returned. (Satured to +-1.99 in Q14) *
+ * *
+ *--------------------------------------------------------------*/
+
+static Word16 Chebps2(Word16 x, Word16 f[], Word16 n)
+{
+ Word16 i, cheb;
+ Word16 b0_h, b0_l, b1_h, b1_l, b2_h, b2_l;
+ Word32 t0;
+
+ /* Note: All computation are done in Q24. */
+
+ t0 = L_mult(f[0], 4096);
+ L_Extract(t0, &b2_h, &b2_l); /* b2 = f[0] in Q24 DPF */
+
+ t0 = Mpy_32_16(b2_h, b2_l, x); /* t0 = 2.0*x*b2 */
+ t0 = L_shl(t0, 1);
+ t0 = L_mac(t0, f[1], 4096); /* + f[1] in Q24 */
+ L_Extract(t0, &b1_h, &b1_l); /* b1 = 2*x*b2 + f[1] */
+
+ for (i = 2; i < n; i++)
+ {
+ t0 = Mpy_32_16(b1_h, b1_l, x); /* t0 = 2.0*x*b1 */
+
+ t0 = L_mac(t0, b2_h, -16384);
+ t0 = L_mac(t0, f[i], 2048);
+ t0 = L_shl(t0, 1);
+ t0 = L_msu(t0, b2_l, 1); /* t0 = 2.0*x*b1 - b2 + f[i]; */
+
+ L_Extract(t0, &b0_h, &b0_l); /* b0 = 2.0*x*b1 - b2 + f[i]; */
+
+ b2_l = b1_l; move16(); /* b2 = b1; */
+ b2_h = b1_h; move16();
+ b1_l = b0_l; move16(); /* b1 = b0; */
+ b1_h = b0_h; move16();
+ }
+
+ t0 = Mpy_32_16(b1_h, b1_l, x); /* t0 = x*b1; */
+ t0 = L_mac(t0, b2_h, (Word16) - 32768);/* t0 = x*b1 - b2 */
+ t0 = L_msu(t0, b2_l, 1);
+ t0 = L_mac(t0, f[n], 2048); /* t0 = x*b1 - b2 + f[i]/2 */
+
+ t0 = L_shl(t0, 6); /* Q24 to Q30 with saturation */
+
+ cheb = extract_h(t0); /* Result in Q14 */
+
+ test();
+ if (sub(cheb, -32768) == 0)
+ {
+ cheb = -32767; /* to avoid saturation in Az_isp */
+ move16();
+ }
+ return (cheb);
+}
--- /dev/null
+++ b/amr-wb/basic_op.h
@@ -1,0 +1,67 @@
+/*___________________________________________________________________________
+ | |
+ | Constants and Globals |
+ | |
+ | $Id $
+ |___________________________________________________________________________|
+*/
+extern Flag Overflow;
+extern Flag Carry;
+
+#define MAX_32 (Word32)0x7fffffffL
+#define MIN_32 (Word32)0x80000000L
+
+#define MAX_16 (Word16)+32767 /* 0x7fff */
+#define MIN_16 (Word16)-32768 /* 0x8000 */
+
+/*___________________________________________________________________________
+ | |
+ | Prototypes for basic arithmetic operators |
+ |___________________________________________________________________________|
+*/
+
+Word16 add (Word16 var1, Word16 var2); /* Short add, 1 */
+Word16 sub (Word16 var1, Word16 var2); /* Short sub, 1 */
+Word16 abs_s (Word16 var1); /* Short abs, 1 */
+Word16 shl (Word16 var1, Word16 var2); /* Short shift left, 1 */
+Word16 shr (Word16 var1, Word16 var2); /* Short shift right, 1 */
+Word16 mult (Word16 var1, Word16 var2); /* Short mult, 1 */
+//Word32 L_mult (Word16 var1, Word16 var2); /* Long mult, 1 */
+#define L_mult(a,b) ((a)*(b)<<1)
+Word16 negate (Word16 var1); /* Short negate, 1 */
+Word16 extract_h (Word32 L_var1); /* Extract high, 1 */
+Word16 extract_l (Word32 L_var1); /* Extract low, 1 */
+Word16 round (Word32 L_var1); /* Round, 1 */
+Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2); /* Mac, 1 */
+Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2); /* Msu, 1 */
+Word32 L_macNs (Word32 L_var3, Word16 var1, Word16 var2); /* Mac without
+ sat, 1 */
+Word32 L_msuNs (Word32 L_var3, Word16 var1, Word16 var2); /* Msu without
+ sat, 1 */
+Word32 L_add (Word32 L_var1, Word32 L_var2); /* Long add, 2 */
+Word32 L_add (Word32 L_var1, Word32 L_var2); /* Long add, 2 */
+Word32 L_sub (Word32 L_var1, Word32 L_var2); /* Long sub, 2 */
+Word32 L_add_c (Word32 L_var1, Word32 L_var2); /* Long add with c, 2 */
+Word32 L_sub_c (Word32 L_var1, Word32 L_var2); /* Long sub with c, 2 */
+Word32 L_negate (Word32 L_var1); /* Long negate, 2 */
+Word16 mult_r (Word16 var1, Word16 var2); /* Mult with round, 2 */
+Word32 L_shl (Word32 L_var1, Word16 var2); /* Long shift left, 2 */
+Word32 L_shr (Word32 L_var1, Word16 var2); /* Long shift right, 2*/
+Word16 shr_r (Word16 var1, Word16 var2); /* Shift right with
+ round, 2 */
+Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2); /* Mac with
+ rounding,2 */
+Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2); /* Msu with
+ rounding,2 */
+Word32 L_deposit_h (Word16 var1); /* 16 bit var1 -> MSB, 2 */
+Word32 L_deposit_l (Word16 var1); /* 16 bit var1 -> LSB, 2 */
+
+Word32 L_shr_r (Word32 L_var1, Word16 var2); /* Long shift right with
+ round, 3 */
+Word32 L_abs (Word32 L_var1); /* Long abs, 3 */
+Word32 L_sat (Word32 L_var1); /* Long saturation, 4 */
+Word16 norm_s (Word16 var1); /* Short norm, 15 */
+Word16 div_s (Word16 var1, Word16 var2); /* Short division, 18 */
+Word16 norm_l (Word32 L_var1); /* Long norm, 30 */
+
+
--- /dev/null
+++ b/amr-wb/basicop2.c
@@ -1,0 +1,2136 @@
+/*___________________________________________________________________________
+ | |
+ | Basic arithmetic operators. |
+ | |
+ | $Id $
+ |___________________________________________________________________________|
+*/
+
+/*___________________________________________________________________________
+ | |
+ | Include-Files |
+ |___________________________________________________________________________|
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "typedef.h"
+#include "basic_op.h"
+
+#if (WMOPS)
+#include "count.h"
+extern BASIC_OP multiCounter[MAXCOUNTERS];
+extern int currCounter;
+
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | Local Functions |
+ |___________________________________________________________________________|
+*/
+Word16 saturate (Word32 L_var1);
+
+/*___________________________________________________________________________
+ | |
+ | Constants and Globals |
+ |___________________________________________________________________________|
+*/
+Flag Overflow = 0;
+Flag Carry = 0;
+
+/*___________________________________________________________________________
+ | |
+ | Functions |
+ |___________________________________________________________________________|
+*/
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : saturate |
+ | |
+ | Purpose : |
+ | |
+ | Limit the 32 bit input to the range of a 16 bit word. |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+Word16
+saturate (Word32 L_var1)
+{
+ Word16 var_out;
+
+ if (L_var1 > 0X00007fffL)
+ {
+ Overflow = 1;
+ var_out = MAX_16;
+ }
+ else if (L_var1 < (Word32) 0xffff8000L)
+ {
+ Overflow = 1;
+ var_out = MIN_16;
+ }
+ else
+ {
+ var_out = extract_l (L_var1);
+#if (WMOPS)
+ multiCounter[currCounter].extract_l--;
+#endif
+ }
+
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : add |
+ | |
+ | Purpose : |
+ | |
+ | Performs the addition (var1+var2) with overflow control and saturation;|
+ | the 16 bit result is set at +32767 when overflow occurs or at -32768 |
+ | when underflow occurs. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+Word16 add (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 L_sum;
+
+ L_sum = (Word32) var1 + var2;
+ var_out = saturate (L_sum);
+#if (WMOPS)
+ multiCounter[currCounter].add++;
+#endif
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : sub |
+ | |
+ | Purpose : |
+ | |
+ | Performs the subtraction (var1+var2) with overflow control and satu- |
+ | ration; the 16 bit result is set at +32767 when overflow occurs or at |
+ | -32768 when underflow occurs. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+Word16 sub (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 L_diff;
+
+ L_diff = (Word32) var1 - var2;
+ var_out = saturate (L_diff);
+#if (WMOPS)
+ multiCounter[currCounter].sub++;
+#endif
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : abs_s |
+ | |
+ | Purpose : |
+ | |
+ | Absolute value of var1; abs_s(-32768) = 32767. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+Word16 abs_s (Word16 var1)
+{
+ Word16 var_out;
+
+ if (var1 == MIN_16)
+ {
+ var_out = MAX_16;
+ }
+ else
+ {
+ if (var1 < 0)
+ {
+ var_out = (Word16)-var1;
+ }
+ else
+ {
+ var_out = var1;
+ }
+ }
+#if (WMOPS)
+ multiCounter[currCounter].abs_s++;
+#endif
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : shl |
+ | |
+ | Purpose : |
+ | |
+ | Arithmetically shift the 16 bit input var1 left var2 positions.Zero fill|
+ | the var2 LSB of the result. If var2 is negative, arithmetically shift |
+ | var1 right by -var2 with sign extension. Saturate the result in case of |
+ | underflows or overflows. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+Word16 shl (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 result;
+
+ if (var2 < 0)
+ {
+ if (var2 < -16)
+ var2 = -16;
+ var_out = shr (var1, (Word16)-var2);
+#if (WMOPS)
+ multiCounter[currCounter].shr--;
+#endif
+ }
+ else
+ {
+ result = (Word32) var1 *((Word32) 1 << var2);
+
+ if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result)))
+ {
+ Overflow = 1;
+ var_out = (Word16)((var1 > 0) ? MAX_16 : MIN_16);
+ }
+ else
+ {
+ var_out = extract_l (result);
+#if (WMOPS)
+ multiCounter[currCounter].extract_l--;
+#endif
+ }
+ }
+#if (WMOPS)
+ multiCounter[currCounter].shl++;
+#endif
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : shr |
+ | |
+ | Purpose : |
+ | |
+ | Arithmetically shift the 16 bit input var1 right var2 positions with |
+ | sign extension. If var2 is negative, arithmetically shift var1 left by |
+ | -var2 with sign extension. Saturate the result in case of underflows or |
+ | overflows. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+Word16 shr (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ if (var2 < 0)
+ {
+ if (var2 < -16)
+ var2 = -16;
+ var_out = shl (var1, (Word16)-var2);
+#if (WMOPS)
+ multiCounter[currCounter].shl--;
+#endif
+ }
+ else
+ {
+ if (var2 >= 15)
+ {
+ var_out = (Word16)((var1 < 0) ? -1 : 0);
+ }
+ else
+ {
+ if (var1 < 0)
+ {
+ var_out = (Word16)(~((~var1) >> var2));
+ }
+ else
+ {
+ var_out = (Word16)(var1 >> var2);
+ }
+ }
+ }
+
+#if (WMOPS)
+ multiCounter[currCounter].shr++;
+#endif
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : mult |
+ | |
+ | Purpose : |
+ | |
+ | Performs the multiplication of var1 by var2 and gives a 16 bit result |
+ | which is scaled i.e.: |
+ | mult(var1,var2) = extract_l(L_shr((var1 times var2),15)) and |
+ | mult(-32768,-32768) = 32767. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+Word16 mult (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 L_product;
+
+ L_product = (Word32) var1 *(Word32) var2;
+
+ L_product = (L_product & (Word32) 0xffff8000L) >> 15;
+
+ if (L_product & (Word32) 0x00010000L)
+ L_product = L_product | (Word32) 0xffff0000L;
+
+ var_out = saturate (L_product);
+#if (WMOPS)
+ multiCounter[currCounter].mult++;
+#endif
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_mult |
+ | |
+ | Purpose : |
+ | |
+ | L_mult is the 32 bit result of the multiplication of var1 times var2 |
+ | with one shift left i.e.: |
+ | L_mult(var1,var2) = L_shl((var1 times var2),1) and |
+ | L_mult(-32768,-32768) = 2147483647. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+
+Word32 _L_mult (Word16 var1, Word16 var2)
+{
+ Word32 L_var_out;
+
+ L_var_out = (Word32) var1 *(Word32) var2;
+
+ if (L_var_out != (Word32) 0x40000000L)
+ {
+ L_var_out *= 2;
+ }
+ else
+ {
+ Overflow = 1;
+ L_var_out = MAX_32;
+ }
+
+#if (WMOPS)
+ multiCounter[currCounter].L_mult++;
+#endif
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : negate |
+ | |
+ | Purpose : |
+ | |
+ | Negate var1 with saturation, saturate in the case where input is -32768:|
+ | negate(var1) = sub(0,var1). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+Word16 negate (Word16 var1)
+{
+ Word16 var_out;
+
+ var_out = (Word16)((var1 == MIN_16) ? MAX_16 : -var1);
+#if (WMOPS)
+ multiCounter[currCounter].negate++;
+#endif
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : extract_h |
+ | |
+ | Purpose : |
+ | |
+ | Return the 16 MSB of L_var1. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32 ) whose value falls in the |
+ | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+Word16 extract_h (Word32 L_var1)
+{
+ Word16 var_out;
+
+ var_out = (Word16) (L_var1 >> 16);
+#if (WMOPS)
+ multiCounter[currCounter].extract_h++;
+#endif
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : extract_l |
+ | |
+ | Purpose : |
+ | |
+ | Return the 16 LSB of L_var1. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32 ) whose value falls in the |
+ | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+Word16 extract_l (Word32 L_var1)
+{
+ Word16 var_out;
+
+ var_out = (Word16) L_var1;
+#if (WMOPS)
+ multiCounter[currCounter].extract_l++;
+#endif
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : round |
+ | |
+ | Purpose : |
+ | |
+ | Round the lower 16 bits of the 32 bit input number into the MS 16 bits |
+ | with saturation. Shift the resulting bits right by 16 and return the 16 |
+ | bit number: |
+ | round(L_var1) = extract_h(L_add(L_var1,32768)) |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32 ) whose value falls in the |
+ | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+Word16 round (Word32 L_var1)
+{
+ Word16 var_out;
+ Word32 L_rounded;
+
+ L_rounded = L_add (L_var1, (Word32) 0x00008000L);
+#if (WMOPS)
+ multiCounter[currCounter].L_add--;
+#endif
+ var_out = extract_h (L_rounded);
+#if (WMOPS)
+ multiCounter[currCounter].extract_h--;
+ multiCounter[currCounter].round++;
+#endif
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_mac |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit |
+ | result to L_var3 with saturation, return a 32 bit result: |
+ | L_mac(L_var3,var1,var2) = L_add(L_var3,L_mult(var1,var2)). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word32 L_var_out;
+ Word32 L_product;
+
+ L_product = L_mult (var1, var2);
+#if (WMOPS)
+ multiCounter[currCounter].L_mult--;
+#endif
+ L_var_out = L_add (L_var3, L_product);
+#if (WMOPS)
+ multiCounter[currCounter].L_add--;
+ multiCounter[currCounter].L_mac++;
+#endif
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_msu |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 |
+ | bit result to L_var3 with saturation, return a 32 bit result: |
+ | L_msu(L_var3,var1,var2) = L_sub(L_var3,L_mult(var1,var2)). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word32 L_var_out;
+ Word32 L_product;
+
+ L_product = L_mult (var1, var2);
+#if (WMOPS)
+ multiCounter[currCounter].L_mult--;
+#endif
+ L_var_out = L_sub (L_var3, L_product);
+#if (WMOPS)
+ multiCounter[currCounter].L_sub--;
+ multiCounter[currCounter].L_msu++;
+#endif
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_macNs |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit |
+ | result to L_var3 without saturation, return a 32 bit result. Generate |
+ | carry and overflow values : |
+ | L_macNs(L_var3,var1,var2) = L_add_c(L_var3,L_mult(var1,var2)). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ | |
+ | Caution : |
+ | |
+ | In some cases the Carry flag has to be cleared or set before using |
+ | operators which take into account its value. |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_macNs (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word32 L_var_out;
+
+ L_var_out = L_mult (var1, var2);
+#if (WMOPS)
+ multiCounter[currCounter].L_mult--;
+#endif
+ L_var_out = L_add_c (L_var3, L_var_out);
+#if (WMOPS)
+ multiCounter[currCounter].L_add_c--;
+ multiCounter[currCounter].L_macNs++;
+#endif
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_msuNs |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 |
+ | bit result from L_var3 without saturation, return a 32 bit result. Ge- |
+ | nerate carry and overflow values : |
+ | L_msuNs(L_var3,var1,var2) = L_sub_c(L_var3,L_mult(var1,var2)). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ | |
+ | Caution : |
+ | |
+ | In some cases the Carry flag has to be cleared or set before using |
+ | operators which take into account its value. |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_msuNs (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word32 L_var_out;
+
+ L_var_out = L_mult (var1, var2);
+#if (WMOPS)
+ multiCounter[currCounter].L_mult--;
+#endif
+ L_var_out = L_sub_c (L_var3, L_var_out);
+#if (WMOPS)
+ multiCounter[currCounter].L_sub_c--;
+ multiCounter[currCounter].L_msuNs++;
+#endif
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_add |
+ | |
+ | Purpose : |
+ | |
+ | 32 bits addition of the two 32 bits variables (L_var1+L_var2) with |
+ | overflow control and saturation; the result is set at +2147483647 when |
+ | overflow occurs or at -2147483648 when underflow occurs. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | L_var2 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_add (Word32 L_var1, Word32 L_var2)
+{
+ Word32 L_var_out;
+
+ L_var_out = L_var1 + L_var2;
+
+ if (((L_var1 ^ L_var2) & MIN_32) == 0)
+ {
+ if ((L_var_out ^ L_var1) & MIN_32)
+ {
+ L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32;
+ Overflow = 1;
+ }
+ }
+#if (WMOPS)
+ multiCounter[currCounter].L_add++;
+#endif
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_sub |
+ | |
+ | Purpose : |
+ | |
+ | 32 bits subtraction of the two 32 bits variables (L_var1-L_var2) with |
+ | overflow control and saturation; the result is set at +2147483647 when |
+ | overflow occurs or at -2147483648 when underflow occurs. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | L_var2 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_sub (Word32 L_var1, Word32 L_var2)
+{
+ Word32 L_var_out;
+
+ L_var_out = L_var1 - L_var2;
+
+ if (((L_var1 ^ L_var2) & MIN_32) != 0)
+ {
+ if ((L_var_out ^ L_var1) & MIN_32)
+ {
+ L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32;
+ Overflow = 1;
+ }
+ }
+#if (WMOPS)
+ multiCounter[currCounter].L_sub++;
+#endif
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_add_c |
+ | |
+ | Purpose : |
+ | |
+ | Performs 32 bits addition of the two 32 bits variables (L_var1+L_var2+C)|
+ | with carry. No saturation. Generate carry and Overflow values. The car- |
+ | ry and overflow values are binary variables which can be tested and as- |
+ | signed values. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | L_var2 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ | |
+ | Caution : |
+ | |
+ | In some cases the Carry flag has to be cleared or set before using |
+ | operators which take into account its value. |
+ |___________________________________________________________________________|
+*/
+Word32 L_add_c (Word32 L_var1, Word32 L_var2)
+{
+ Word32 L_var_out;
+ Word32 L_test;
+ Flag carry_int = 0;
+
+ L_var_out = L_var1 + L_var2 + Carry;
+
+ L_test = L_var1 + L_var2;
+
+ if ((L_var1 > 0) && (L_var2 > 0) && (L_test < 0))
+ {
+ Overflow = 1;
+ carry_int = 0;
+ }
+ else
+ {
+ if ((L_var1 < 0) && (L_var2 < 0))
+ {
+ if (L_test >= 0)
+ {
+ Overflow = 1;
+ carry_int = 1;
+ }
+ else
+ {
+ Overflow = 0;
+ carry_int = 1;
+ }
+ }
+ else
+ {
+ if (((L_var1 ^ L_var2) < 0) && (L_test >= 0))
+ {
+ Overflow = 0;
+ carry_int = 1;
+ }
+ else
+ {
+ Overflow = 0;
+ carry_int = 0;
+ }
+ }
+ }
+
+ if (Carry)
+ {
+ if (L_test == MAX_32)
+ {
+ Overflow = 1;
+ Carry = carry_int;
+ }
+ else
+ {
+ if (L_test == (Word32) 0xFFFFFFFFL)
+ {
+ Carry = 1;
+ }
+ else
+ {
+ Carry = carry_int;
+ }
+ }
+ }
+ else
+ {
+ Carry = carry_int;
+ }
+
+#if (WMOPS)
+ multiCounter[currCounter].L_add_c++;
+#endif
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_sub_c |
+ | |
+ | Purpose : |
+ | |
+ | Performs 32 bits subtraction of the two 32 bits variables with carry |
+ | (borrow) : L_var1-L_var2-C. No saturation. Generate carry and Overflow |
+ | values. The carry and overflow values are binary variables which can |
+ | be tested and assigned values. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | L_var2 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ | |
+ | Caution : |
+ | |
+ | In some cases the Carry flag has to be cleared or set before using |
+ | operators which take into account its value. |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_sub_c (Word32 L_var1, Word32 L_var2)
+{
+ Word32 L_var_out;
+ Word32 L_test;
+ Flag carry_int = 0;
+
+ if (Carry)
+ {
+ Carry = 0;
+ if (L_var2 != MIN_32)
+ {
+ L_var_out = L_add_c (L_var1, -L_var2);
+#if (WMOPS)
+ multiCounter[currCounter].L_add_c--;
+#endif
+ }
+ else
+ {
+ L_var_out = L_var1 - L_var2;
+ if (L_var1 > 0L)
+ {
+ Overflow = 1;
+ Carry = 0;
+ }
+ }
+ }
+ else
+ {
+ L_var_out = L_var1 - L_var2 - (Word32) 0X00000001L;
+ L_test = L_var1 - L_var2;
+
+ if ((L_test < 0) && (L_var1 > 0) && (L_var2 < 0))
+ {
+ Overflow = 1;
+ carry_int = 0;
+ }
+ else if ((L_test > 0) && (L_var1 < 0) && (L_var2 > 0))
+ {
+ Overflow = 1;
+ carry_int = 1;
+ }
+ else if ((L_test > 0) && ((L_var1 ^ L_var2) > 0))
+ {
+ Overflow = 0;
+ carry_int = 1;
+ }
+ if (L_test == MIN_32)
+ {
+ Overflow = 1;
+ Carry = carry_int;
+ }
+ else
+ {
+ Carry = carry_int;
+ }
+ }
+
+#if (WMOPS)
+ multiCounter[currCounter].L_sub_c++;
+#endif
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_negate |
+ | |
+ | Purpose : |
+ | |
+ | Negate the 32 bit variable L_var1 with saturation; saturate in the case |
+ | where input is -2147483648 (0x8000 0000). |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_negate (Word32 L_var1)
+{
+ Word32 L_var_out;
+
+ L_var_out = (L_var1 == MIN_32) ? MAX_32 : -L_var1;
+#if (WMOPS)
+ multiCounter[currCounter].L_negate++;
+#endif
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : mult_r |
+ | |
+ | Purpose : |
+ | |
+ | Same as mult with rounding, i.e.: |
+ | mult_r(var1,var2) = extract_l(L_shr(((var1 * var2) + 16384),15)) and |
+ | mult_r(-32768,-32768) = 32767. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+Word16 mult_r (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 L_product_arr;
+
+ L_product_arr = (Word32) var1 *(Word32) var2; /* product */
+ L_product_arr += (Word32) 0x00004000L; /* round */
+ L_product_arr &= (Word32) 0xffff8000L;
+ L_product_arr >>= 15; /* shift */
+
+ if (L_product_arr & (Word32) 0x00010000L) /* sign extend when necessary */
+ {
+ L_product_arr |= (Word32) 0xffff0000L;
+ }
+ var_out = saturate (L_product_arr);
+#if (WMOPS)
+ multiCounter[currCounter].mult_r++;
+#endif
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_shl |
+ | |
+ | Purpose : |
+ | |
+ | Arithmetically shift the 32 bit input L_var1 left var2 positions. Zero |
+ | fill the var2 LSB of the result. If var2 is negative, arithmetically |
+ | shift L_var1 right by -var2 with sign extension. Saturate the result in |
+ | case of underflows or overflows. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_shl (Word32 L_var1, Word16 var2)
+{
+ Word32 L_var_out = 0L;
+
+ if (var2 <= 0)
+ {
+ if (var2 < -32)
+ var2 = -32;
+ L_var_out = L_shr (L_var1, (Word16)-var2);
+#if (WMOPS)
+ multiCounter[currCounter].L_shr--;
+#endif
+ }
+ else
+ {
+ for (; var2 > 0; var2--)
+ {
+ if (L_var1 > (Word32) 0X3fffffffL)
+ {
+ Overflow = 1;
+ L_var_out = MAX_32;
+ break;
+ }
+ else
+ {
+ if (L_var1 < (Word32) 0xc0000000L)
+ {
+ Overflow = 1;
+ L_var_out = MIN_32;
+ break;
+ }
+ }
+ L_var1 *= 2;
+ L_var_out = L_var1;
+ }
+ }
+#if (WMOPS)
+ multiCounter[currCounter].L_shl++;
+#endif
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_shr |
+ | |
+ | Purpose : |
+ | |
+ | Arithmetically shift the 32 bit input L_var1 right var2 positions with |
+ | sign extension. If var2 is negative, arithmetically shift L_var1 left |
+ | by -var2 and zero fill the -var2 LSB of the result. Saturate the result |
+ | in case of underflows or overflows. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_shr (Word32 L_var1, Word16 var2)
+{
+ Word32 L_var_out;
+
+ if (var2 < 0)
+ {
+ if (var2 < -32)
+ var2 = -32;
+ L_var_out = L_shl (L_var1, (Word16)-var2);
+#if (WMOPS)
+ multiCounter[currCounter].L_shl--;
+#endif
+ }
+ else
+ {
+ if (var2 >= 31)
+ {
+ L_var_out = (L_var1 < 0L) ? -1 : 0;
+ }
+ else
+ {
+ if (L_var1 < 0)
+ {
+ L_var_out = ~((~L_var1) >> var2);
+ }
+ else
+ {
+ L_var_out = L_var1 >> var2;
+ }
+ }
+ }
+#if (WMOPS)
+ multiCounter[currCounter].L_shr++;
+#endif
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : shr_r |
+ | |
+ | Purpose : |
+ | |
+ | Same as shr(var1,var2) but with rounding. Saturate the result in case of|
+ | underflows or overflows : |
+ | - If var2 is greater than zero : |
+ | if (sub(shl(shr(var1,var2),1),shr(var1,sub(var2,1)))) |
+ | is equal to zero |
+ | then |
+ | shr_r(var1,var2) = shr(var1,var2) |
+ | else |
+ | shr_r(var1,var2) = add(shr(var1,var2),1) |
+ | - If var2 is less than or equal to zero : |
+ | shr_r(var1,var2) = shr(var1,var2). |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+Word16 shr_r (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ if (var2 > 15)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ var_out = shr (var1, var2);
+#if (WMOPS)
+ multiCounter[currCounter].shr--;
+#endif
+
+ if (var2 > 0)
+ {
+ if ((var1 & ((Word16) 1 << (var2 - 1))) != 0)
+ {
+ var_out++;
+ }
+ }
+ }
+#if (WMOPS)
+ multiCounter[currCounter].shr_r++;
+#endif
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : mac_r |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit |
+ | result to L_var3 with saturation. Round the LS 16 bits of the result |
+ | into the MS 16 bits with saturation and shift the result right by 16. |
+ | Return a 16 bit result. |
+ | mac_r(L_var3,var1,var2) = round(L_mac(L_var3,var1,var2)) |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 8000 <= L_var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ L_var3 = L_mac (L_var3, var1, var2);
+#if (WMOPS)
+ multiCounter[currCounter].L_mac--;
+#endif
+ L_var3 = L_add (L_var3, (Word32) 0x00008000L);
+#if (WMOPS)
+ multiCounter[currCounter].L_add--;
+#endif
+ var_out = extract_h (L_var3);
+#if (WMOPS)
+ multiCounter[currCounter].extract_h--;
+ multiCounter[currCounter].mac_r++;
+#endif
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : msu_r |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 |
+ | bit result to L_var3 with saturation. Round the LS 16 bits of the res- |
+ | ult into the MS 16 bits with saturation and shift the result right by |
+ | 16. Return a 16 bit result. |
+ | msu_r(L_var3,var1,var2) = round(L_msu(L_var3,var1,var2)) |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 8000 <= L_var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ L_var3 = L_msu (L_var3, var1, var2);
+#if (WMOPS)
+ multiCounter[currCounter].L_msu--;
+#endif
+ L_var3 = L_add (L_var3, (Word32) 0x00008000L);
+#if (WMOPS)
+ multiCounter[currCounter].L_add--;
+#endif
+ var_out = extract_h (L_var3);
+#if (WMOPS)
+ multiCounter[currCounter].extract_h--;
+ multiCounter[currCounter].msu_r++;
+#endif
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_deposit_h |
+ | |
+ | Purpose : |
+ | |
+ | Deposit the 16 bit var1 into the 16 MS bits of the 32 bit output. The |
+ | 16 LS bits of the output are zeroed. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var_out <= 0x7fff 0000. |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_deposit_h (Word16 var1)
+{
+ Word32 L_var_out;
+
+ L_var_out = (Word32) var1 << 16;
+#if (WMOPS)
+ multiCounter[currCounter].L_deposit_h++;
+#endif
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_deposit_l |
+ | |
+ | Purpose : |
+ | |
+ | Deposit the 16 bit var1 into the 16 LS bits of the 32 bit output. The |
+ | 16 MS bits of the output are sign extended. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0xFFFF 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_deposit_l (Word16 var1)
+{
+ Word32 L_var_out;
+
+ L_var_out = (Word32) var1;
+#if (WMOPS)
+ multiCounter[currCounter].L_deposit_l++;
+#endif
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_shr_r |
+ | |
+ | Purpose : |
+ | |
+ | Same as L_shr(L_var1,var2) but with rounding. Saturate the result in |
+ | case of underflows or overflows : |
+ | - If var2 is greater than zero : |
+ | if (L_sub(L_shl(L_shr(L_var1,var2),1),L_shr(L_var1,sub(var2,1))))|
+ | is equal to zero |
+ | then |
+ | L_shr_r(L_var1,var2) = L_shr(L_var1,var2) |
+ | else |
+ | L_shr_r(L_var1,var2) = L_add(L_shr(L_var1,var2),1) |
+ | - If var2 is less than or equal to zero : |
+ | L_shr_r(L_var1,var2) = L_shr(L_var1,var2). |
+ | |
+ | Complexity weight : 3 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_shr_r (Word32 L_var1, Word16 var2)
+{
+ Word32 L_var_out;
+
+ if (var2 > 31)
+ {
+ L_var_out = 0;
+ }
+ else
+ {
+ L_var_out = L_shr (L_var1, var2);
+#if (WMOPS)
+ multiCounter[currCounter].L_shr--;
+#endif
+ if (var2 > 0)
+ {
+ if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0)
+ {
+ L_var_out++;
+ }
+ }
+ }
+#if (WMOPS)
+ multiCounter[currCounter].L_shr_r++;
+#endif
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_abs |
+ | |
+ | Purpose : |
+ | |
+ | Absolute value of L_var1; Saturate in case where the input is |
+ | -214783648 |
+ | |
+ | Complexity weight : 3 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_abs (Word32 L_var1)
+{
+ Word32 L_var_out;
+
+ if (L_var1 == MIN_32)
+ {
+ L_var_out = MAX_32;
+ }
+ else
+ {
+ if (L_var1 < 0)
+ {
+ L_var_out = -L_var1;
+ }
+ else
+ {
+ L_var_out = L_var1;
+ }
+ }
+
+#if (WMOPS)
+ multiCounter[currCounter].L_abs++;
+#endif
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_sat |
+ | |
+ | Purpose : |
+ | |
+ | 32 bit L_var1 is set to 2147483647 if an overflow occured or to |
+ | -2147483648 if an underflow occured on the most recent L_add_c, |
+ | L_sub_c, L_macNs or L_msuNs operations. The carry and overflow values |
+ | are binary values which can be tested and assigned values. |
+ | |
+ | Complexity weight : 4 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_sat (Word32 L_var1)
+{
+ Word32 L_var_out;
+
+ L_var_out = L_var1;
+
+ if (Overflow)
+ {
+
+ if (Carry)
+ {
+ L_var_out = MIN_32;
+ }
+ else
+ {
+ L_var_out = MAX_32;
+ }
+
+ Carry = 0;
+ Overflow = 0;
+ }
+#if (WMOPS)
+ multiCounter[currCounter].L_sat++;
+#endif
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : norm_s |
+ | |
+ | Purpose : |
+ | |
+ | Produces the number of left shift needed to normalize the 16 bit varia- |
+ | ble var1 for positive values on the interval with minimum of 16384 and |
+ | maximum of 32767, and for negative values on the interval with minimum |
+ | of -32768 and maximum of -16384; in order to normalize the result, the |
+ | following operation must be done : |
+ | norm_var1 = shl(var1,norm_s(var1)). |
+ | |
+ | Complexity weight : 15 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x0000 000f. |
+ |___________________________________________________________________________|
+*/
+
+Word16 norm_s (Word16 var1)
+{
+ Word16 var_out;
+
+ if (var1 == 0)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ if (var1 == -1)
+ {
+ var_out = 15;
+ }
+ else
+ {
+ if (var1 < 0)
+ {
+ var1 = (Word16)~var1;
+ }
+ for (var_out = 0; var1 < 0x4000; var_out++)
+ {
+ var1 <<= 1;
+ }
+ }
+ }
+
+#if (WMOPS)
+ multiCounter[currCounter].norm_s++;
+#endif
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : div_s |
+ | |
+ | Purpose : |
+ | |
+ | Produces a result which is the fractional integer division of var1 by |
+ | var2; var1 and var2 must be positive and var2 must be greater or equal |
+ | to var1; the result is positive (leading bit equal to 0) and truncated |
+ | to 16 bits. |
+ | If var1 = var2 then div(var1,var2) = 32767. |
+ | |
+ | Complexity weight : 18 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var1 <= var2 and var2 != 0. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : var1 <= var2 <= 0x0000 7fff and var2 != 0. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x0000 7fff. |
+ | It's a Q15 value (point between b15 and b14). |
+ |___________________________________________________________________________|
+*/
+
+Word16 div_s (Word16 var1, Word16 var2)
+{
+ Word16 var_out = 0;
+ Word16 iteration;
+ Word32 L_num;
+ Word32 L_denom;
+
+ if ((var1 > var2) || (var1 < 0) || (var2 < 0))
+ {
+ printf ("Division Error var1=%d var2=%d\n", var1, var2);
+ abort(); /* exit (0); */
+ }
+ if (var2 == 0)
+ {
+ printf ("Division by 0, Fatal error \n");
+ abort(); /* exit (0); */
+ }
+ if (var1 == 0)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ if (var1 == var2)
+ {
+ var_out = MAX_16;
+ }
+ else
+ {
+ L_num = L_deposit_l (var1);
+#if (WMOPS)
+ multiCounter[currCounter].L_deposit_l--;
+#endif
+ L_denom = L_deposit_l (var2);
+#if (WMOPS)
+ multiCounter[currCounter].L_deposit_l--;
+#endif
+
+ for (iteration = 0; iteration < 15; iteration++)
+ {
+ var_out <<= 1;
+ L_num <<= 1;
+
+ if (L_num >= L_denom)
+ {
+ L_num = L_sub (L_num, L_denom);
+#if (WMOPS)
+ multiCounter[currCounter].L_sub--;
+#endif
+ var_out = add (var_out, 1);
+#if (WMOPS)
+ multiCounter[currCounter].add--;
+#endif
+ }
+ }
+ }
+ }
+
+#if (WMOPS)
+ multiCounter[currCounter].div_s++;
+#endif
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : norm_l |
+ | |
+ | Purpose : |
+ | |
+ | Produces the number of left shifts needed to normalize the 32 bit varia-|
+ | ble L_var1 for positive values on the interval with minimum of |
+ | 1073741824 and maximum of 2147483647, and for negative values on the in-|
+ | terval with minimum of -2147483648 and maximum of -1073741824; in order |
+ | to normalize the result, the following operation must be done : |
+ | norm_L_var1 = L_shl(L_var1,norm_l(L_var1)). |
+ | |
+ | Complexity weight : 30 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x0000 001f. |
+ |___________________________________________________________________________|
+*/
+
+Word16 norm_l (Word32 L_var1)
+{
+ Word16 var_out;
+
+ if (L_var1 == 0)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ if (L_var1 == (Word32) 0xffffffffL)
+ {
+ var_out = 31;
+ }
+ else
+ {
+ if (L_var1 < 0)
+ {
+ L_var1 = ~L_var1;
+ }
+ for (var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++)
+ {
+ L_var1 <<= 1;
+ }
+ }
+ }
+
+#if (WMOPS)
+ multiCounter[currCounter].norm_l++;
+#endif
+ return (var_out);
+}
--- /dev/null
+++ b/amr-wb/bits.c
@@ -1,0 +1,532 @@
+/*------------------------------------------------------------------------*
+ * BITS.C *
+ *------------------------------------------------------------------------*
+ * Performs bit stream manipulation *
+ *------------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+#include "bits.h"
+#include "acelp.h"
+#include "count.h"
+#include "dtx.h"
+
+#include "mime_io.tab"
+
+/*-----------------------------------------------------*
+ * Write_serial -> write serial stream into a file *
+ *-----------------------------------------------------*/
+
+Word16 Init_write_serial(TX_State ** st)
+{
+ TX_State *s;
+
+ /* allocate memory */
+ test();
+ if ((s = (TX_State *) malloc(sizeof(TX_State))) == NULL)
+ {
+ fprintf(stderr, "write_serial_init: can not malloc state structure\n");
+ return -1;
+ }
+ Reset_write_serial(s);
+ *st = s;
+
+ return 0;
+}
+
+Word16 Close_write_serial(TX_State *st)
+{
+ /* allocate memory */
+ test();
+ if (st != NULL)
+ {
+ free(st);
+ st = NULL;
+ return 0;
+ }
+ return 1;
+}
+
+void Reset_write_serial(TX_State * st)
+{
+ st->sid_update_counter = 3;
+ st->sid_handover_debt = 0;
+ st->prev_ft = TX_SPEECH;
+}
+
+void Write_serial(FILE * fp, Word16 prms[], Word16 coding_mode, Word16 mode, TX_State *st, Word16 bitstreamformat)
+{
+ Word16 i, frame_type;
+ Word16 stream[SIZE_MAX];
+ UWord8 temp;
+ UWord8 *stream_ptr;
+
+ if (coding_mode == MRDTX)
+ {
+ st->sid_update_counter--;
+
+ if (st->prev_ft == TX_SPEECH)
+ {
+ frame_type = TX_SID_FIRST;
+ st->sid_update_counter = 3;
+ } else
+ {
+ if ((st->sid_handover_debt > 0) &&
+ (st->sid_update_counter > 2))
+ {
+ /* ensure extra updates are properly delayed after a possible SID_FIRST */
+ frame_type = TX_SID_UPDATE;
+ st->sid_handover_debt--;
+ } else
+ {
+ if (st->sid_update_counter == 0)
+ {
+ frame_type = TX_SID_UPDATE;
+ st->sid_update_counter = 8;
+ } else
+ {
+ frame_type = TX_NO_DATA;
+ }
+ }
+ }
+ } else
+ {
+ st->sid_update_counter = 8;
+ frame_type = TX_SPEECH;
+ }
+ st->prev_ft = frame_type;
+
+
+ if(bitstreamformat == 0) /* default file format */
+ {
+ stream[0] = TX_FRAME_TYPE;
+ stream[1] = frame_type;
+ stream[2] = mode;
+ for (i = 0; i < nb_of_bits[coding_mode]; i++)
+ {
+ stream[3 + i] = prms[i];
+ }
+
+ fwrite(stream, sizeof(Word16), 3 + nb_of_bits[coding_mode], fp);
+
+ } else
+ {
+ if (bitstreamformat == 1) /* ITU file format */
+ {
+ stream[0] = 0x6b21;
+
+ if(frame_type != TX_NO_DATA && frame_type != TX_SID_FIRST)
+ {
+ stream[1]=nb_of_bits[coding_mode];
+ for (i = 0; i < nb_of_bits[coding_mode]; i++)
+ {
+ if(prms[i] == BIT_0){
+ stream[2 + i] = BIT_0_ITU;
+ }
+ else{
+ stream[2 + i] = BIT_1_ITU;
+ }
+ }
+ fwrite(stream, sizeof(Word16), 2 + nb_of_bits[coding_mode], fp);
+ } else
+ {
+ stream[1] = 0;
+ fwrite(stream, sizeof(Word16), 2, fp);
+ }
+ } else /* MIME/storage file format */
+ {
+#define MRSID 9
+ /* change mode index in case of SID frame */
+ if (coding_mode == MRDTX)
+ {
+ coding_mode = MRSID;
+
+ if (frame_type == TX_SID_FIRST)
+ {
+ for (i = 0; i < NBBITS_SID; i++) prms[i] = BIT_0;
+ }
+ }
+
+ /* we cannot handle unspecified frame types (modes 10 - 13) */
+ /* -> force NO_DATA frame */
+ if (coding_mode < 0 || coding_mode > 15 || (coding_mode > MRSID && coding_mode < 14))
+ {
+ coding_mode = 15;
+ }
+
+ /* mark empty frames between SID updates as NO_DATA frames */
+ if (coding_mode == MRSID && frame_type == TX_NO_DATA)
+ {
+ coding_mode = 15;
+ }
+
+ /* set pointer for packed frame, note that we handle data as bytes */
+ stream_ptr = (UWord8*)stream;
+
+ /* insert table of contents (ToC) byte at the beginning of the packet */
+ *stream_ptr = toc_byte[coding_mode];
+ stream_ptr++;
+
+ temp = 0;
+
+ /* sort and pack AMR-WB speech or SID bits */
+ for (i = 1; i < unpacked_size[coding_mode] + 1; i++)
+ {
+ if (prms[sort_ptr[coding_mode][i-1]] == BIT_1)
+ {
+ temp++;
+ }
+
+ if (i % 8)
+ {
+ temp <<= 1;
+ }
+ else
+ {
+ *stream_ptr = temp;
+ stream_ptr++;
+ temp = 0;
+ }
+ }
+
+ /* insert SID type indication and speech mode in case of SID frame */
+ if (coding_mode == MRSID)
+ {
+ if (frame_type == TX_SID_UPDATE)
+ {
+ temp++;
+ }
+ temp <<= 4;
+
+ temp += mode & 0x000F;
+ }
+
+ /* insert unused bits (zeros) at the tail of the last byte */
+ if (unused_size[coding_mode])
+ {
+ temp <<= (unused_size[coding_mode] - 1);
+ }
+ *stream_ptr = temp;
+
+ /* write packed frame into file (1 byte added to cover ToC entry) */
+ fwrite(stream, sizeof(UWord8), 1 + packed_size[coding_mode], fp);
+ }
+ }
+ return;
+}
+
+
+/*-----------------------------------------------------*
+ * Read_serial -> read serial stream into a file *
+ *-----------------------------------------------------*/
+
+Word16 Init_read_serial(RX_State ** st)
+{
+ RX_State *s;
+
+ /* allocate memory */
+ test();
+ if ((s = (RX_State *) malloc(sizeof(RX_State))) == NULL)
+ {
+ fprintf(stderr, "read_serial_init: can not malloc state structure\n");
+ return -1;
+ }
+ Reset_read_serial(s);
+ *st = s;
+
+ return 0;
+}
+
+Word16 Close_read_serial(RX_State *st)
+{
+ /* allocate memory */
+ test();
+ if (st != NULL)
+ {
+ free(st);
+ st = NULL;
+ return 0;
+ }
+ return 1;
+}
+
+void Reset_read_serial(RX_State * st)
+{
+ st->prev_ft = RX_SPEECH_GOOD;
+ st->prev_mode = 0;
+}
+
+
+Word16 Read_serial(FILE * fp, Word16 prms[], Word16 * frame_type, Word16 * mode, RX_State *st, Word16 bitstreamformat)
+{
+ Word16 n, n1, type_of_frame_type, coding_mode, datalen, i;
+ UWord8 toc, q, temp, *packet_ptr, packet[64];
+
+ if(bitstreamformat == 0) /* default file format */
+ {
+ n = (Word16) fread(&type_of_frame_type, sizeof(Word16), 1, fp);
+ n = (Word16) (n + fread(frame_type, sizeof(Word16), 1, fp));
+ n = (Word16) (n + fread(mode, sizeof(Word16), 1, fp));
+ coding_mode = *mode;
+ if(*mode < 0 || *mode > NUM_OF_MODES-1)
+ {
+ fprintf(stderr, "Invalid mode received: %d (check file format).\n", *mode);
+ exit(-1);
+ }
+ if (n == 3)
+ {
+ if (type_of_frame_type == TX_FRAME_TYPE)
+ {
+ switch (*frame_type)
+ {
+ case TX_SPEECH:
+ *frame_type = RX_SPEECH_GOOD;
+ break;
+ case TX_SID_FIRST:
+ *frame_type = RX_SID_FIRST;
+ break;
+ case TX_SID_UPDATE:
+ *frame_type = RX_SID_UPDATE;
+ break;
+ case TX_NO_DATA:
+ *frame_type = RX_NO_DATA;
+ break;
+ }
+ } else if (type_of_frame_type != RX_FRAME_TYPE)
+ {
+ fprintf(stderr, "Wrong type of frame type:%d.\n", type_of_frame_type);
+ }
+
+ if ((*frame_type == RX_SID_FIRST) | (*frame_type == RX_SID_UPDATE) | (*frame_type == RX_NO_DATA) | (*frame_type == RX_SID_BAD))
+ {
+ coding_mode = MRDTX;
+ }
+ n = (Word16) fread(prms, sizeof(Word16), nb_of_bits[coding_mode], fp);
+ if (n != nb_of_bits[coding_mode])
+ n = 0;
+ }
+ return (n);
+ } else
+ {
+ if (bitstreamformat == 1) /* ITU file format */
+ {
+ n = (Word16) fread(&type_of_frame_type, sizeof(Word16), 1, fp);
+ n = (Word16)(n+fread(&datalen, sizeof(Word16), 1, fp));
+
+ if(n == 2)
+ {
+ if(type_of_frame_type == 0x6b20) /* bad frame */
+ {
+ *frame_type = RX_SPEECH_LOST;
+ *mode = st->prev_mode;
+ }
+ else if(type_of_frame_type == 0x6b21) /* good frame */
+ {
+ if(datalen == 0) /* RX_NO_DATA frame type */
+ {
+ if(st->prev_ft == RX_SPEECH_GOOD)
+ {
+ *frame_type = RX_SID_FIRST;
+ }
+ else
+ {
+ *frame_type = RX_NO_DATA;
+ }
+ *mode = st->prev_mode;
+ }
+ else
+ {
+ coding_mode = -1;
+ for(i=NUM_OF_MODES-1; i>=0; i--)
+ {
+ if(datalen == nb_of_bits[i])
+ {
+ coding_mode = i;
+ }
+ }
+
+ if(coding_mode == -1)
+ {
+ fprintf(stderr, "\n\n ERROR: Invalid number of data bits received [%d]\n\n", datalen);
+ exit(-1);
+ }
+
+ if(coding_mode == NUM_OF_MODES-1) /* DTX frame type */
+ {
+ *frame_type = RX_SID_UPDATE;
+ *mode = st->prev_mode;
+ }
+ else
+ {
+ *frame_type = RX_SPEECH_GOOD;
+ *mode = coding_mode;
+ }
+ }
+ st->prev_mode = *mode;
+ st->prev_ft = *frame_type;
+ }
+ else {
+ fprintf(stderr, "\n\n ERROR: Invalid ITU file format \n\n");
+ exit(-1);
+ }
+ }
+ n1 = fread(prms, sizeof(Word16), datalen, fp);
+ n += n1;
+ for(i=0; i<n1; i++)
+ {
+ if(prms[i] <= BIT_0_ITU) prms[i] = BIT_0;
+ else prms[i] = BIT_1;
+ }
+ return(n);
+
+ } else /* MIME/storage file format */
+ {
+ /* read ToC byte, return immediately if no more data available */
+ if (fread(&toc, sizeof(UWord8), 1, fp) == 0)
+ {
+ return 0;
+ }
+
+ /* extract q and mode from ToC */
+ q = (toc >> 2) & 0x01;
+ *mode = (toc >> 3) & 0x0F;
+
+ /* read speech bits, return with empty frame if mismatch between mode info and available data */
+ if ((Word16)fread(packet, sizeof(UWord8), packed_size[*mode], fp) != packed_size[*mode])
+ {
+ return 0;
+ }
+
+ packet_ptr = (UWord8*)packet;
+ temp = *packet_ptr;
+ packet_ptr++;
+
+ /* unpack and unsort speech or SID bits */
+ for (i = 1; i < unpacked_size[*mode] + 1; i++)
+ {
+ if (temp & 0x80) prms[sort_ptr[*mode][i-1]] = BIT_1;
+ else prms[sort_ptr[*mode][i-1]] = BIT_0;
+
+ if (i % 8)
+ {
+ temp <<= 1;
+ }
+ else
+ {
+ temp = *packet_ptr;
+ packet_ptr++;
+ }
+ }
+
+ /* set frame type */
+ switch (*mode)
+ {
+ case MODE_7k:
+ case MODE_9k:
+ case MODE_12k:
+ case MODE_14k:
+ case MODE_16k:
+ case MODE_18k:
+ case MODE_20k:
+ case MODE_23k:
+ case MODE_24k:
+ if (q) *frame_type = RX_SPEECH_GOOD;
+ else *frame_type = RX_SPEECH_BAD;
+ break;
+ case MRSID:
+ if (q)
+ {
+ if (temp & 0x80) *frame_type = RX_SID_UPDATE;
+ else *frame_type = RX_SID_FIRST;
+ }
+ else
+ {
+ *frame_type = RX_SID_BAD;
+ }
+
+ /* read speech mode indication */
+ coding_mode = (temp >> 3) & 0x0F;
+
+ /* set mode index */
+ *mode = st->prev_mode;
+ break;
+ case 14: /* SPEECH_LOST */
+ *frame_type = RX_SPEECH_LOST;
+ *mode = st->prev_mode;
+ break;
+ case 15: /* NO_DATA */
+ *frame_type = RX_NO_DATA;
+ *mode = st->prev_mode;
+ break;
+ default: /* replace frame with unused mode index by NO_DATA frame */
+ *frame_type = RX_NO_DATA;
+ *mode = st->prev_mode;
+ break;
+ }
+
+ st->prev_mode = *mode;
+
+ /* return 1 to indicate succesfully parsed frame */
+ return 1;
+ }
+#undef MRSID
+ }
+
+}
+
+
+/*-----------------------------------------------------*
+ * Parm_serial -> convert parameters to serial stream *
+ *-----------------------------------------------------*/
+
+void Parm_serial(
+ Word16 value, /* input : parameter value */
+ Word16 no_of_bits, /* input : number of bits */
+ Word16 ** prms
+)
+{
+ Word16 i, bit;
+
+ *prms += no_of_bits; move16();
+
+ for (i = 0; i < no_of_bits; i++)
+ {
+ bit = (Word16) (value & 0x0001); logic16(); /* get lsb */
+ test();move16();
+ if (bit == 0)
+ *--(*prms) = BIT_0;
+ else
+ *--(*prms) = BIT_1;
+ value = shr(value, 1); move16();
+ }
+ *prms += no_of_bits; move16();
+ return;
+}
+
+
+/*----------------------------------------------------*
+ * Serial_parm -> convert serial stream to parameters *
+ *----------------------------------------------------*/
+
+Word16 Serial_parm( /* Return the parameter */
+ Word16 no_of_bits, /* input : number of bits */
+ Word16 ** prms
+)
+{
+ Word16 value, i;
+ Word16 bit;
+
+ value = 0; move16();
+ for (i = 0; i < no_of_bits; i++)
+ {
+ value = shl(value, 1);
+ bit = *((*prms)++); move16();
+ test();move16();
+ if (bit == BIT_1)
+ value = add(value, 1);
+ }
+ return (value);
+}
--- /dev/null
+++ b/amr-wb/bits.h
@@ -1,0 +1,77 @@
+/*--------------------------------------------------------------------------*
+ * BITS.H *
+ *--------------------------------------------------------------------------*
+ * Number of bits for different modes *
+ *--------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include "typedef.h"
+#include "cnst.h"
+
+#define NBBITS_7k 132 /* 6.60k */
+#define NBBITS_9k 177 /* 8.85k */
+#define NBBITS_12k 253 /* 12.65k */
+#define NBBITS_14k 285 /* 14.25k */
+#define NBBITS_16k 317 /* 15.85k */
+#define NBBITS_18k 365 /* 18.25k */
+#define NBBITS_20k 397 /* 19.85k */
+#define NBBITS_23k 461 /* 23.05k */
+#define NBBITS_24k 477 /* 23.85k */
+
+#define NBBITS_SID 35
+#define NB_BITS_MAX NBBITS_24k
+
+#define BIT_0 (Word16)-127
+#define BIT_1 (Word16)127
+#define BIT_0_ITU (Word16)0x007F
+#define BIT_1_ITU (Word16)0x0081
+
+#define SIZE_MAX (3+NB_BITS_MAX) /* serial size max */
+#define TX_FRAME_TYPE (Word16)0x6b21
+#define RX_FRAME_TYPE (Word16)0x6b20
+
+static const Word16 nb_of_bits[NUM_OF_MODES] = {
+ NBBITS_7k,
+ NBBITS_9k,
+ NBBITS_12k,
+ NBBITS_14k,
+ NBBITS_16k,
+ NBBITS_18k,
+ NBBITS_20k,
+ NBBITS_23k,
+ NBBITS_24k,
+NBBITS_SID};
+
+typedef struct
+{
+ Word16 sid_update_counter;
+ Word16 sid_handover_debt;
+ Word16 prev_ft;
+} TX_State;
+
+
+typedef struct
+{
+ Word16 prev_ft;
+ Word16 prev_mode;
+} RX_State;
+
+
+Word16 Init_write_serial(TX_State ** st);
+Word16 Close_write_serial(TX_State *st);
+void Reset_write_serial(TX_State * st);
+Word16 Init_read_serial(RX_State ** st);
+Word16 Close_read_serial(RX_State *st);
+void Reset_read_serial(RX_State * st);
+void Write_serial(FILE * fp, Word16 prms[], Word16 coding_mode, Word16 mode, TX_State *st, Word16 bitstreamformat);
+Word16 Read_serial(FILE * fp, Word16 prms[], Word16 * frame_type, Word16 * mode, RX_State *st, Word16 bitstreamformat);
+
+void Parm_serial(
+ Word16 value, /* input : parameter value */
+ Word16 no_of_bits, /* input : number of bits */
+ Word16 ** prms
+);
+Word16 Serial_parm( /* Return the parameter */
+ Word16 no_of_bits, /* input : number of bits */
+ Word16 ** prms
+);
--- /dev/null
+++ b/amr-wb/c2t64fx.c
@@ -1,0 +1,310 @@
+/*------------------------------------------------------------------------*
+ * C2T64FX.C *
+ *------------------------------------------------------------------------*
+ * Performs algebraic codebook search for 6.60 kbit/s mode *
+ *------------------------------------------------------------------------*/
+
+
+/*-----------------------------------------------------------------------*
+ * Function ACELP_2t64_fx() *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * 12 bits algebraic codebook. *
+ * 2 tracks x 32 positions per track = 64 samples. *
+ * *
+ * 12 bits --> 2 pulses in a frame of 64 samples. *
+ * *
+ * All pulses can have two (2) possible amplitudes: +1 or -1. *
+ * Each pulse can have 32 possible positions. *
+ *-----------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "math_op.h"
+#include "acelp.h"
+#include "count.h"
+#include "cnst.h"
+
+#define NB_TRACK 2
+#define STEP 2
+#define NB_POS 32
+#define MSIZE 1024
+
+
+void ACELP_2t64_fx(
+ Word16 dn[], /* (i) <12b : correlation between target x[] and H[] */
+ Word16 cn[], /* (i) <12b : residual after long term prediction */
+ Word16 H[], /* (i) Q12: impulse response of weighted synthesis filter */
+ Word16 code[], /* (o) Q9 : algebraic (fixed) codebook excitation */
+ Word16 y[], /* (o) Q9 : filtered fixed codebook excitation */
+ Word16 * index /* (o) : index (12): 5+1+5+1 = 11 bits. */
+)
+{
+ Word16 i, j, k, i0, i1, ix, iy, pos, pos2;
+ Word16 ps, psk, ps1, ps2, alpk, alp1, alp2, sq;
+ Word16 alp, val, exp, k_cn, k_dn;
+ Word16 *p0, *p1, *p2, *psign;
+ Word16 *h, *h_inv, *ptr_h1, *ptr_h2, *ptr_hf;
+
+ Word16 sign[L_SUBFR], vec[L_SUBFR], dn2[L_SUBFR];
+ Word16 h_buf[4 * L_SUBFR];
+ Word16 rrixix[NB_TRACK][NB_POS];
+ Word16 rrixiy[MSIZE];
+
+ Word32 s, cor;
+
+ /*----------------------------------------------------------------*
+ * Find sign for each pulse position. *
+ *----------------------------------------------------------------*/
+
+ alp = 8192; move16(); /* alp = 2.0 (Q12) */
+
+ /* calculate energy for normalization of cn[] and dn[] */
+
+ /* set k_cn = 32..32767 (ener_cn = 2^30..256-0) */
+ s = Dot_product12(cn, cn, L_SUBFR, &exp);
+ Isqrt_n(&s, &exp);
+ s = L_shl(s, add(exp, 5)); /* saturation can occur here */
+ k_cn = round(s);
+
+ /* set k_dn = 32..512 (ener_dn = 2^30..2^22) */
+ s = Dot_product12(dn, dn, L_SUBFR, &exp);
+ Isqrt_n(&s, &exp);
+ k_dn = round(L_shl(s, add(exp, 5 + 3))); /* k_dn = 256..4096 */
+ k_dn = mult_r(alp, k_dn); /* alp in Q12 */
+
+ /* mix normalized cn[] and dn[] */
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ s = L_mac(L_mult(k_cn, cn[i]), k_dn, dn[i]);
+ dn2[i] = extract_h(L_shl(s, 8)); move16();
+ }
+
+ /* set sign according to dn2[] = k_cn*cn[] + k_dn*dn[] */
+
+ for (k = 0; k < NB_TRACK; k++)
+ {
+ for (i = k; i < L_SUBFR; i += STEP)
+ {
+ val = dn[i]; move16();
+ ps = dn2[i]; move16();
+
+ test();
+ if (ps >= 0)
+ {
+ sign[i] = 32767; move16(); /* sign = +1 (Q12) */
+ vec[i] = -32768; move16();
+ } else
+ {
+ sign[i] = -32768; move16(); /* sign = -1 (Q12) */
+ vec[i] = 32767; move16();
+ val = negate(val);
+ }
+ dn[i] = val; move16(); /* modify dn[] according to the fixed sign */
+ }
+ }
+
+ /*------------------------------------------------------------*
+ * Compute h_inv[i]. *
+ *------------------------------------------------------------*/
+
+ /* impulse response buffer for fast computation */
+
+ h = h_buf; move16();
+ h_inv = h_buf + (2 * L_SUBFR); move16();
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ *h++ = 0; move16();
+ *h_inv++ = 0; move16();
+ }
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ h[i] = H[i]; move16();
+ h_inv[i] = negate(h[i]); move16();
+ }
+
+ /*------------------------------------------------------------*
+ * Compute rrixix[][] needed for the codebook search. *
+ * Result is multiplied by 0.5 *
+ *------------------------------------------------------------*/
+
+ /* Init pointers to last position of rrixix[] */
+ p0 = &rrixix[0][NB_POS - 1]; move16();
+ p1 = &rrixix[1][NB_POS - 1]; move16();
+
+ ptr_h1 = h; move16();
+ cor = 0x00010000L; move32(); /* for rounding */
+ for (i = 0; i < NB_POS; i++)
+ {
+ move16();move16();
+ cor = L_mac(cor, *ptr_h1, *ptr_h1);
+ ptr_h1++;
+ *p1-- = extract_h(cor); move16();
+ cor = L_mac(cor, *ptr_h1, *ptr_h1);
+ ptr_h1++;
+ *p0-- = extract_h(cor); move16();
+ }
+
+ p0 = rrixix[0]; move16();
+ p1 = rrixix[1]; move16();
+ for (i = 0; i < NB_POS; i++)
+ {
+ *p0 = shr(*p0, 1); move16();
+ p0++;
+ *p1 = shr(*p1, 1); move16();
+ p1++;
+ }
+
+ /*------------------------------------------------------------*
+ * Compute rrixiy[][] needed for the codebook search. *
+ *------------------------------------------------------------*/
+
+ pos = MSIZE - 1; move16();
+ pos2 = MSIZE - 2; move16();
+ ptr_hf = h + 1; move16();
+
+ for (k = 0; k < NB_POS; k++)
+ {
+ p1 = &rrixiy[pos]; move16();
+ p0 = &rrixiy[pos2]; move16();
+
+ cor = 0x00008000L; move32(); /* for rounding */
+ ptr_h1 = h; move16();
+ ptr_h2 = ptr_hf; move16();
+
+ for (i = (Word16) (k + 1); i < NB_POS; i++)
+ {
+ cor = L_mac(cor, *ptr_h1, *ptr_h2);
+ ptr_h1++;
+ ptr_h2++;
+ *p1 = extract_h(cor); move16();
+ cor = L_mac(cor, *ptr_h1, *ptr_h2);
+ ptr_h1++;
+ ptr_h2++;
+ *p0 = extract_h(cor); move16();
+
+ p1 -= (NB_POS + 1);
+ p0 -= (NB_POS + 1);
+ }
+ cor = L_mac(cor, *ptr_h1, *ptr_h2);
+ ptr_h1++;
+ ptr_h2++;
+ *p1 = extract_h(cor); move16();
+
+ pos -= NB_POS;
+ pos2--;
+ ptr_hf += STEP;
+ }
+
+ /*------------------------------------------------------------*
+ * Modification of rrixiy[][] to take signs into account. *
+ *------------------------------------------------------------*/
+
+ p0 = rrixiy; move16();
+
+ for (i = 0; i < L_SUBFR; i += STEP)
+ {
+ psign = sign; move16();
+ test();
+ if (psign[i] < 0)
+ {
+ psign = vec; move16();
+ }
+ for (j = 1; j < L_SUBFR; j += STEP)
+ {
+ *p0 = mult(*p0, psign[j]); move16();
+ p0++;
+ }
+ }
+
+ /*-------------------------------------------------------------------*
+ * search 2 pulses: *
+ * ~@~~~~~~~~~~~~~~ *
+ * 32 pos x 32 pos = 1024 tests (all combinaisons is tested) *
+ *-------------------------------------------------------------------*/
+
+ p0 = rrixix[0]; move16();
+ p1 = rrixix[1]; move16();
+ p2 = rrixiy; move16();
+
+ psk = -1; move16();
+ alpk = 1; move16();
+ ix = 0; move16();
+ iy = 1; move16();
+
+ for (i0 = 0; i0 < L_SUBFR; i0 += STEP)
+ {
+ ps1 = dn[i0]; move16();
+ alp1 = (*p0++); move16();
+
+ pos = -1; move16();
+ for (i1 = 1; i1 < L_SUBFR; i1 += STEP)
+ {
+ ps2 = add(ps1, dn[i1]);
+ alp2 = add(alp1, add(*p1++, *p2++));
+
+ sq = mult(ps2, ps2);
+
+ s = L_msu(L_mult(alpk, sq), psk, alp2);
+
+ test();
+ if (s > 0)
+ {
+ psk = sq; move16();
+ alpk = alp2; move16();
+ pos = i1; move16();
+ }
+ }
+ p1 -= NB_POS;
+
+ test();
+ if (pos >= 0)
+ {
+ ix = i0; move16();
+ iy = pos; move16();
+ }
+ }
+
+ /*-------------------------------------------------------------------*
+ * Build the codeword, the filtered codeword and index of codevector.*
+ *-------------------------------------------------------------------*/
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ code[i] = 0; move16();
+ }
+
+ i0 = shr(ix, 1); /* pos of pulse 1 (0..31) */
+ i1 = shr(iy, 1); /* pos of pulse 2 (0..31) */
+ test();
+ if (sign[ix] > 0)
+ {
+ code[ix] = 512; move16(); /* codeword in Q9 format */
+ p0 = h - ix; move16();
+ } else
+ {
+ code[ix] = -512; move16();
+ i0 += NB_POS; move16();
+ p0 = h_inv - ix; move16();
+ }
+ test();
+ if (sign[iy] > 0)
+ {
+ code[iy] = 512; move16();
+ p1 = h - iy; move16();
+ } else
+ {
+ code[iy] = -512; move16();
+ i1 += NB_POS; move16();
+ p1 = h_inv - iy; move16();
+ }
+
+ *index = add(shl(i0, 6), i1); move16();
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ y[i] = shr_r(add(*p0++, *p1++), 3);move16();
+ }
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/c4t64fx.c
@@ -1,0 +1,911 @@
+/*------------------------------------------------------------------------*
+ * C4T64FX.C *
+ *------------------------------------------------------------------------*
+ * Performs algebraic codebook search for higher modes *
+ *------------------------------------------------------------------------*/
+
+
+/*-----------------------------------------------------------------------*
+ * Function ACELP_4t64_fx() *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * 20, 36, 44, 52, 64, 72, 88 bits algebraic codebook. *
+ * 4 tracks x 16 positions per track = 64 samples. *
+ * *
+ * 20 bits --> 4 pulses in a frame of 64 samples. *
+ * 36 bits --> 8 pulses in a frame of 64 samples. *
+ * 44 bits --> 10 pulses in a frame of 64 samples. *
+ * 52 bits --> 12 pulses in a frame of 64 samples. *
+ * 64 bits --> 16 pulses in a frame of 64 samples. *
+ * 72 bits --> 18 pulses in a frame of 64 samples. *
+ * 88 bits --> 24 pulses in a frame of 64 samples. *
+ * *
+ * All pulses can have two (2) possible amplitudes: +1 or -1. *
+ * Each pulse can have sixteen (16) possible positions. *
+ *-----------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "math_op.h"
+#include "acelp.h"
+#include "count.h"
+#include "cnst.h"
+
+#include "q_pulse.h"
+
+static Word16 tipos[36] = {
+ 0, 1, 2, 3, /* starting point &ipos[0], 1st iter */
+ 1, 2, 3, 0, /* starting point &ipos[4], 2nd iter */
+ 2, 3, 0, 1, /* starting point &ipos[8], 3rd iter */
+ 3, 0, 1, 2, /* starting point &ipos[12], 4th iter */
+ 0, 1, 2, 3,
+ 1, 2, 3, 0,
+ 2, 3, 0, 1,
+ 3, 0, 1, 2,
+ 0, 1, 2, 3}; /* end point for 24 pulses &ipos[35], 4th iter */
+
+#define NB_PULSE_MAX 24
+
+#define L_SUBFR 64
+#define NB_TRACK 4
+#define STEP 4
+#define NB_POS 16
+#define MSIZE 256
+#define NB_MAX 8
+#define NPMAXPT ((NB_PULSE_MAX+NB_TRACK-1)/NB_TRACK)
+
+
+/* locals functions */
+
+static void cor_h_vec(
+ Word16 h[], /* (i) scaled impulse response */
+ Word16 vec[], /* (i) scaled vector (/8) to correlate with h[] */
+ Word16 track, /* (i) track to use */
+ Word16 sign[], /* (i) sign vector */
+ Word16 rrixix[][NB_POS], /* (i) correlation of h[x] with h[x] */
+ Word16 cor[] /* (o) result of correlation (NB_POS elements) */
+);
+static void search_ixiy(
+ Word16 nb_pos_ix, /* (i) nb of pos for pulse 1 (1..8) */
+ Word16 track_x, /* (i) track of pulse 1 */
+ Word16 track_y, /* (i) track of pulse 2 */
+ Word16 * ps, /* (i/o) correlation of all fixed pulses */
+ Word16 * alp, /* (i/o) energy of all fixed pulses */
+ Word16 * ix, /* (o) position of pulse 1 */
+ Word16 * iy, /* (o) position of pulse 2 */
+ Word16 dn[], /* (i) corr. between target and h[] */
+ Word16 dn2[], /* (i) vector of selected positions */
+ Word16 cor_x[], /* (i) corr. of pulse 1 with fixed pulses */
+ Word16 cor_y[], /* (i) corr. of pulse 2 with fixed pulses */
+ Word16 rrixiy[][MSIZE] /* (i) corr. of pulse 1 with pulse 2 */
+);
+
+
+void ACELP_4t64_fx(
+ Word16 dn[], /* (i) <12b : correlation between target x[] and H[] */
+ Word16 cn[], /* (i) <12b : residual after long term prediction */
+ Word16 H[], /* (i) Q12: impulse response of weighted synthesis filter */
+ Word16 code[], /* (o) Q9 : algebraic (fixed) codebook excitation */
+ Word16 y[], /* (o) Q9 : filtered fixed codebook excitation */
+ Word16 nbbits, /* (i) : 20, 36, 44, 52, 64, 72 or 88 bits */
+ Word16 ser_size, /* (i) : bit rate */
+ Word16 _index[] /* (o) : index (20): 5+5+5+5 = 20 bits. */
+ /* (o) : index (36): 9+9+9+9 = 36 bits. */
+ /* (o) : index (44): 13+9+13+9 = 44 bits. */
+ /* (o) : index (52): 13+13+13+13 = 52 bits. */
+ /* (o) : index (64): 2+2+2+2+14+14+14+14 = 64 bits. */
+ /* (o) : index (72): 10+2+10+2+10+14+10+14 = 72 bits. */
+ /* (o) : index (88): 11+11+11+11+11+11+11+11 = 88 bits. */
+)
+{
+ Word16 i, j, k, st, ix, iy, pos, index, track, nb_pulse, nbiter;
+ Word16 psk, ps, alpk, alp, val, k_cn, k_dn, exp;
+ Word16 *p0, *p1, *p2, *p3, *psign;
+ Word16 *h, *h_inv, *ptr_h1, *ptr_h2, *ptr_hf, h_shift;
+ Word32 s, cor, L_tmp, L_index;
+
+ Word16 dn2[L_SUBFR], sign[L_SUBFR], vec[L_SUBFR];
+ Word16 ind[NPMAXPT * NB_TRACK];
+ Word16 codvec[NB_PULSE_MAX], nbpos[10];
+ Word16 cor_x[NB_POS], cor_y[NB_POS], pos_max[NB_TRACK];
+ Word16 h_buf[4 * L_SUBFR];
+ Word16 rrixix[NB_TRACK][NB_POS], rrixiy[NB_TRACK][MSIZE];
+ Word16 ipos[NB_PULSE_MAX];
+
+ switch (nbbits)
+ {
+ case 20: /* 20 bits, 4 pulses, 4 tracks */
+ nbiter = 4; move16(); /* 4x16x16=1024 loop */
+ alp = 8192; move16(); /* alp = 2.0 (Q12) */
+ nb_pulse = 4; move16();
+ nbpos[0] = 4; move16();
+ nbpos[1] = 8; move16();
+ break;
+ case 36: /* 36 bits, 8 pulses, 4 tracks */
+ nbiter = 4; move16(); /* 4x20x16=1280 loop */
+ alp = 4096; move16(); /* alp = 1.0 (Q12) */
+ nb_pulse = 8; move16();
+ nbpos[0] = 4; move16();
+ nbpos[1] = 8; move16();
+ nbpos[2] = 8; move16();
+ break;
+ case 44: /* 44 bits, 10 pulses, 4 tracks */
+ nbiter = 4; move16(); /* 4x26x16=1664 loop */
+ alp = 4096; move16(); /* alp = 1.0 (Q12) */
+ nb_pulse = 10; move16();
+ nbpos[0] = 4; move16();
+ nbpos[1] = 6; move16();
+ nbpos[2] = 8; move16();
+ nbpos[3] = 8; move16();
+ break;
+ case 52: /* 52 bits, 12 pulses, 4 tracks */
+ nbiter = 4; move16(); /* 4x26x16=1664 loop */
+ alp = 4096; move16(); /* alp = 1.0 (Q12) */
+ nb_pulse = 12; move16();
+ nbpos[0] = 4; move16();
+ nbpos[1] = 6; move16();
+ nbpos[2] = 8; move16();
+ nbpos[3] = 8; move16();
+ break;
+ case 64: /* 64 bits, 16 pulses, 4 tracks */
+ nbiter = 3; move16(); /* 3x36x16=1728 loop */
+ alp = 3277; move16(); /* alp = 0.8 (Q12) */
+ nb_pulse = 16; move16();
+ nbpos[0] = 4; move16();
+ nbpos[1] = 4; move16();
+ nbpos[2] = 6; move16();
+ nbpos[3] = 6; move16();
+ nbpos[4] = 8; move16();
+ nbpos[5] = 8; move16();
+ break;
+ case 72: /* 72 bits, 18 pulses, 4 tracks */
+ nbiter = 3; move16(); /* 3x35x16=1680 loop */
+ alp = 3072; move16(); /* alp = 0.75 (Q12) */
+ nb_pulse = 18; move16();
+ nbpos[0] = 2; move16();
+ nbpos[1] = 3; move16();
+ nbpos[2] = 4; move16();
+ nbpos[3] = 5; move16();
+ nbpos[4] = 6; move16();
+ nbpos[5] = 7; move16();
+ nbpos[6] = 8; move16();
+ break;
+ case 88: /* 88 bits, 24 pulses, 4 tracks */
+ test();move16();
+ if (sub(ser_size, 462) > 0)
+ nbiter = 1;
+ else
+ nbiter = 2; /* 2x53x16=1696 loop */
+
+ alp = 2048; move16(); /* alp = 0.5 (Q12) */
+ nb_pulse = 24; move16();
+ nbpos[0] = 2; move16();
+ nbpos[1] = 2; move16();
+ nbpos[2] = 3; move16();
+ nbpos[3] = 4; move16();
+ nbpos[4] = 5; move16();
+ nbpos[5] = 6; move16();
+ nbpos[6] = 7; move16();
+ nbpos[7] = 8; move16();
+ nbpos[8] = 8; move16();
+ nbpos[9] = 8; move16();
+ break;
+ default:
+ nbiter = 0;
+ alp = 0;
+ nb_pulse = 0;
+ }
+
+ for (i = 0; i < nb_pulse; i++)
+ {
+ codvec[i] = i; move16();
+ }
+
+ /*----------------------------------------------------------------*
+ * Find sign for each pulse position. *
+ *----------------------------------------------------------------*/
+
+ /* calculate energy for normalization of cn[] and dn[] */
+
+ /* set k_cn = 32..32767 (ener_cn = 2^30..256-0) */
+ s = Dot_product12(cn, cn, L_SUBFR, &exp);
+ Isqrt_n(&s, &exp);
+ s = L_shl(s, add(exp, 5)); /* saturation can occur here */
+ k_cn = round(s);
+
+ /* set k_dn = 32..512 (ener_dn = 2^30..2^22) */
+ s = Dot_product12(dn, dn, L_SUBFR, &exp);
+ Isqrt_n(&s, &exp);
+ k_dn = round(L_shl(s, add(exp, 5 + 3))); /* k_dn = 256..4096 */
+ k_dn = mult_r(alp, k_dn); /* alp in Q12 */
+
+ /* mix normalized cn[] and dn[] */
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ s = L_mac(L_mult(k_cn, cn[i]), k_dn, dn[i]);
+ dn2[i] = extract_h(L_shl(s, 8)); move16();
+ }
+
+ /* set sign according to dn2[] = k_cn*cn[] + k_dn*dn[] */
+
+ for (k = 0; k < NB_TRACK; k++)
+ {
+ for (i = k; i < L_SUBFR; i += STEP)
+ {
+ val = dn[i]; move16();
+ ps = dn2[i]; move16();
+
+ test();
+ if (ps >= 0)
+ {
+ sign[i] = 32767; move16(); /* sign = +1 (Q12) */
+ vec[i] = -32768; move16();
+ } else
+ {
+ sign[i] = -32768; move16(); /* sign = -1 (Q12) */
+ vec[i] = 32767; move16();
+ val = negate(val);
+ ps = negate(ps);
+ }
+ dn[i] = val; move16(); /* modify dn[] according to the fixed sign */
+ dn2[i] = ps; move16(); /* dn2[] = mix of dn[] and cn[] */
+ }
+ }
+
+ /*----------------------------------------------------------------*
+ * Select NB_MAX position per track according to max of dn2[]. *
+ *----------------------------------------------------------------*/
+
+ pos = 0;
+ for (i = 0; i < NB_TRACK; i++)
+ {
+ for (k = 0; k < NB_MAX; k++)
+ {
+ ps = -1; move16();
+ for (j = i; j < L_SUBFR; j += STEP)
+ {
+ test();
+ if (sub(dn2[j], ps) > 0)
+ {
+ ps = dn2[j]; move16();
+ pos = j; move16();
+ }
+ }
+ move16();
+ dn2[pos] = sub(k, NB_MAX); /* dn2 < 0 when position is selected */
+ test();
+ if (k == 0)
+ {
+ pos_max[i] = pos; move16();
+ }
+ }
+ }
+
+ /*--------------------------------------------------------------*
+ * Scale h[] to avoid overflow and to get maximum of precision *
+ * on correlation. *
+ * *
+ * Maximum of h[] (h[0]) is fixed to 2048 (MAX16 / 16). *
+ * ==> This allow addition of 16 pulses without saturation. *
+ * *
+ * Energy worst case (on resonant impulse response), *
+ * - energy of h[] is approximately MAX/16. *
+ * - During search, the energy is divided by 8 to avoid *
+ * overflow on "alp". (energy of h[] = MAX/128). *
+ * ==> "alp" worst case detected is 22854 on sinusoidal wave. *
+ *--------------------------------------------------------------*/
+
+ /* impulse response buffer for fast computation */
+
+ h = h_buf; move16();
+ h_inv = h_buf + (2 * L_SUBFR); move16();
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ *h++ = 0; move16();
+ *h_inv++ = 0; move16();
+ }
+
+ /* scale h[] down (/2) when energy of h[] is high with many pulses used */
+ L_tmp = 0;
+ for (i = 0; i < L_SUBFR; i++)
+ L_tmp = L_mac(L_tmp, H[i], H[i]);
+ val = extract_h(L_tmp);
+
+ h_shift = 0; move16();
+
+ test();test();
+ if ((sub(nb_pulse, 12) >= 0) && (sub(val, 1024) > 0))
+ {
+ h_shift = 1; move16();
+ }
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ h[i] = shr(H[i], h_shift); move16();
+ h_inv[i] = negate(h[i]); move16();
+ }
+
+ /*------------------------------------------------------------*
+ * Compute rrixix[][] needed for the codebook search. *
+ * This algorithm compute impulse response energy of all *
+ * positions (16) in each track (4). Total = 4x16 = 64. *
+ *------------------------------------------------------------*/
+
+ /* storage order --> i3i3, i2i2, i1i1, i0i0 */
+
+ /* Init pointers to last position of rrixix[] */
+ p0 = &rrixix[0][NB_POS - 1]; move16();
+ p1 = &rrixix[1][NB_POS - 1]; move16();
+ p2 = &rrixix[2][NB_POS - 1]; move16();
+ p3 = &rrixix[3][NB_POS - 1]; move16();
+
+ ptr_h1 = h; move16();
+ cor = 0x00008000L; move32(); /* for rounding */
+ for (i = 0; i < NB_POS; i++)
+ {
+ cor = L_mac(cor, *ptr_h1, *ptr_h1);
+ ptr_h1++;
+ *p3-- = extract_h(cor); move16();
+ cor = L_mac(cor, *ptr_h1, *ptr_h1);
+ ptr_h1++;
+ *p2-- = extract_h(cor); move16();
+ cor = L_mac(cor, *ptr_h1, *ptr_h1);
+ ptr_h1++;
+ *p1-- = extract_h(cor); move16();
+ cor = L_mac(cor, *ptr_h1, *ptr_h1);
+ ptr_h1++;
+ *p0-- = extract_h(cor); move16();
+ }
+
+ /*------------------------------------------------------------*
+ * Compute rrixiy[][] needed for the codebook search. *
+ * This algorithm compute correlation between 2 pulses *
+ * (2 impulses responses) in 4 possible adjacents tracks. *
+ * (track 0-1, 1-2, 2-3 and 3-0). Total = 4x16x16 = 1024. *
+ *------------------------------------------------------------*/
+
+ /* storage order --> i2i3, i1i2, i0i1, i3i0 */
+
+ pos = MSIZE - 1; move16();
+ ptr_hf = h + 1; move16();
+
+ for (k = 0; k < NB_POS; k++)
+ {
+ p3 = &rrixiy[2][pos]; move16();
+ p2 = &rrixiy[1][pos]; move16();
+ p1 = &rrixiy[0][pos]; move16();
+ p0 = &rrixiy[3][pos - NB_POS]; move16();
+
+ cor = 0x00008000L; move32(); /* for rounding */
+ ptr_h1 = h; move16();
+ ptr_h2 = ptr_hf; move16();
+
+ for (i = add(k, 1); i < NB_POS; i++)
+ {
+ cor = L_mac(cor, *ptr_h1, *ptr_h2);
+ ptr_h1++;
+ ptr_h2++;
+ *p3 = extract_h(cor); move16();
+ cor = L_mac(cor, *ptr_h1, *ptr_h2);
+ ptr_h1++;
+ ptr_h2++;
+ *p2 = extract_h(cor); move16();
+ cor = L_mac(cor, *ptr_h1, *ptr_h2);
+ ptr_h1++;
+ ptr_h2++;
+ *p1 = extract_h(cor); move16();
+ cor = L_mac(cor, *ptr_h1, *ptr_h2);
+ ptr_h1++;
+ ptr_h2++;
+ *p0 = extract_h(cor); move16();
+
+ p3 -= (NB_POS + 1);
+ p2 -= (NB_POS + 1);
+ p1 -= (NB_POS + 1);
+ p0 -= (NB_POS + 1);
+ }
+ cor = L_mac(cor, *ptr_h1, *ptr_h2);
+ ptr_h1++;
+ ptr_h2++;
+ *p3 = extract_h(cor); move16();
+ cor = L_mac(cor, *ptr_h1, *ptr_h2);
+ ptr_h1++;
+ ptr_h2++;
+ *p2 = extract_h(cor); move16();
+ cor = L_mac(cor, *ptr_h1, *ptr_h2);
+ ptr_h1++;
+ ptr_h2++;
+ *p1 = extract_h(cor); move16();
+
+ pos -= NB_POS;
+ ptr_hf += STEP;
+ }
+
+ /* storage order --> i3i0, i2i3, i1i2, i0i1 */
+
+ pos = MSIZE - 1; move16();
+ ptr_hf = h + 3; move16();
+
+ for (k = 0; k < NB_POS; k++)
+ {
+ p3 = &rrixiy[3][pos]; move16();
+ p2 = &rrixiy[2][pos - 1]; move16();
+ p1 = &rrixiy[1][pos - 1]; move16();
+ p0 = &rrixiy[0][pos - 1]; move16();
+
+ cor = 0x00008000L; move32(); /* for rounding */
+ ptr_h1 = h; move16();
+ ptr_h2 = ptr_hf; move16();
+
+ for (i = add(k, 1); i < NB_POS; i++)
+ {
+ cor = L_mac(cor, *ptr_h1, *ptr_h2);
+ ptr_h1++;
+ ptr_h2++;
+ *p3 = extract_h(cor); move16();
+ cor = L_mac(cor, *ptr_h1, *ptr_h2);
+ ptr_h1++;
+ ptr_h2++;
+ *p2 = extract_h(cor); move16();
+ cor = L_mac(cor, *ptr_h1, *ptr_h2);
+ ptr_h1++;
+ ptr_h2++;
+ *p1 = extract_h(cor); move16();
+ cor = L_mac(cor, *ptr_h1, *ptr_h2);
+ ptr_h1++;
+ ptr_h2++;
+ *p0 = extract_h(cor); move16();
+
+ p3 -= (NB_POS + 1);
+ p2 -= (NB_POS + 1);
+ p1 -= (NB_POS + 1);
+ p0 -= (NB_POS + 1);
+ }
+ cor = L_mac(cor, *ptr_h1, *ptr_h2);
+ ptr_h1++;
+ ptr_h2++;
+ *p3 = extract_h(cor); move16();
+
+ pos--;
+ ptr_hf += STEP;
+ }
+
+ /*------------------------------------------------------------*
+ * Modification of rrixiy[][] to take signs into account. *
+ *------------------------------------------------------------*/
+
+ p0 = &rrixiy[0][0]; move16();
+
+ for (k = 0; k < NB_TRACK; k++)
+ {
+ for (i = k; i < L_SUBFR; i += STEP)
+ {
+ psign = sign; move16();
+ test();
+ if (psign[i] < 0)
+ {
+ psign = vec; move16();
+ }
+ for (j = (Word16) ((k + 1) % NB_TRACK); j < L_SUBFR; j += STEP)
+ {
+ *p0 = mult(*p0, psign[j]); move16();
+ p0++;
+ }
+ }
+ }
+
+ /*-------------------------------------------------------------------*
+ * Deep first search *
+ *-------------------------------------------------------------------*/
+
+ psk = -1; move16();
+ alpk = 1; move16();
+
+ for (k = 0; k < nbiter; k++)
+ {
+ for (i = 0; i < nb_pulse; i++)
+ ipos[i] = tipos[(k * 4) + i];
+
+ test();test();test();
+ if (sub(nbbits, 20) == 0)
+ {
+ pos = 0; move16();
+ ps = 0; move16();
+ alp = 0; move16();
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ vec[i] = 0; move16();
+ }
+ } else if ((sub(nbbits, 36) == 0) || (sub(nbbits, 44) == 0))
+ {
+ /* first stage: fix 2 pulses */
+ pos = 2;
+
+ ix = ind[0] = pos_max[ipos[0]];move16();move16();
+ iy = ind[1] = pos_max[ipos[1]];move16();move16();
+ ps = add(dn[ix], dn[iy]);
+ i = shr(ix, 2); /* ix / STEP */
+ j = shr(iy, 2); /* iy / STEP */
+ s = L_mult(rrixix[ipos[0]][i], 4096);
+ s = L_mac(s, rrixix[ipos[1]][j], 4096);
+ i = add(shl(i, 4), j); /* (ix/STEP)*NB_POS + (iy/STEP) */
+ s = L_mac(s, rrixiy[ipos[0]][i], 8192);
+ alp = round(s);
+ test();move16();move16();
+ if (sign[ix] < 0)
+ p0 = h_inv - ix;
+ else
+ p0 = h - ix;
+ test();move16();move16();
+ if (sign[iy] < 0)
+ p1 = h_inv - iy;
+ else
+ p1 = h - iy;
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ vec[i] = add(*p0++, *p1++);move16();
+ }
+
+ test();
+ if (sub(nbbits, 44) == 0)
+ {
+ ipos[8] = 0; move16();
+ ipos[9] = 1; move16();
+ }
+ } else
+ {
+ /* first stage: fix 4 pulses */
+ pos = 4;
+
+ ix = ind[0] = pos_max[ipos[0]]; move16();move16();
+ iy = ind[1] = pos_max[ipos[1]]; move16();move16();
+ i = ind[2] = pos_max[ipos[2]]; move16();move16();
+ j = ind[3] = pos_max[ipos[3]]; move16();move16();
+ ps = add(add(add(dn[ix], dn[iy]), dn[i]), dn[j]);
+
+ test();move16();move16();
+ if (sign[ix] < 0)
+ p0 = h_inv - ix;
+ else
+ p0 = h - ix;
+ test();move16();move16();
+ if (sign[iy] < 0)
+ p1 = h_inv - iy;
+ else
+ p1 = h - iy;
+ test();move16();move16();
+ if (sign[i] < 0)
+ p2 = h_inv - i;
+ else
+ p2 = h - i;
+ test();move16();move16();
+ if (sign[j] < 0)
+ p3 = h_inv - j;
+ else
+ p3 = h - j;
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ vec[i] = add(add(add(*p0++, *p1++), *p2++), *p3++);
+ move16();
+ }
+
+ L_tmp = 0L; move32();
+ for (i = 0; i < L_SUBFR; i++)
+ L_tmp = L_mac(L_tmp, vec[i], vec[i]);
+
+ alp = round(L_shr(L_tmp, 3));
+
+ if (sub(nbbits, 72) == 0)
+ {
+ ipos[16] = 0; move16();
+ ipos[17] = 1; move16();
+ }
+ }
+
+ /* other stages of 2 pulses */
+
+ for (j = pos, st = 0; j < nb_pulse; j += 2, st++)
+ {
+ /*--------------------------------------------------*
+ * Calculate correlation of all possible positions *
+ * of the next 2 pulses with previous fixed pulses. *
+ * Each pulse can have 16 possible positions. *
+ *--------------------------------------------------*/
+
+ cor_h_vec(h, vec, ipos[j], sign, rrixix, cor_x);
+ cor_h_vec(h, vec, ipos[j + 1], sign, rrixix, cor_y);
+
+ /*--------------------------------------------------*
+ * Find best positions of 2 pulses. *
+ *--------------------------------------------------*/
+
+ search_ixiy(nbpos[st], ipos[j], ipos[j + 1], &ps, &alp,
+ &ix, &iy, dn, dn2, cor_x, cor_y, rrixiy);
+
+ ind[j] = ix; move16();
+ ind[j + 1] = iy; move16();
+
+ test();move16();move16();
+ if (sign[ix] < 0)
+ p0 = h_inv - ix;
+ else
+ p0 = h - ix;
+ test();move16();move16();
+ if (sign[iy] < 0)
+ p1 = h_inv - iy;
+ else
+ p1 = h - iy;
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ vec[i] = add(vec[i], add(*p0++, *p1++)); /* can saturate here. */
+ move16();
+ }
+ }
+
+ /* memorise the best codevector */
+
+ ps = mult(ps, ps);
+ s = L_msu(L_mult(alpk, ps), psk, alp);
+ test();
+ if (s > 0)
+ {
+ psk = ps; move16();
+ alpk = alp; move16();
+ for (i = 0; i < nb_pulse; i++)
+ {
+ codvec[i] = ind[i]; move16();
+ }
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ y[i] = vec[i]; move16();
+ }
+ }
+ }
+
+ /*-------------------------------------------------------------------*
+ * Build the codeword, the filtered codeword and index of codevector.*
+ *-------------------------------------------------------------------*/
+
+ for (i = 0; i < NPMAXPT * NB_TRACK; i++)
+ {
+ ind[i] = -1; move16();
+ }
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ code[i] = 0; move16();
+ y[i] = shr_r(y[i], 3); move16(); /* Q12 to Q9 */
+ }
+
+ val = shr(512, h_shift); /* codeword in Q9 format */
+
+ for (k = 0; k < nb_pulse; k++)
+ {
+ i = codvec[k]; move16(); /* read pulse position */
+ j = sign[i]; move16(); /* read sign */
+
+ index = shr(i, 2); /* index = pos of pulse (0..15) */
+ track = (Word16) (i & 0x03); logic16(); /* track = i % NB_TRACK (0..3) */
+
+ if (j > 0)
+ {
+ code[i] = add(code[i], val); move16();
+ codvec[k] = add(codvec[k], (2 * L_SUBFR)); move16();
+ } else
+ {
+ code[i] = sub(code[i], val); move16();
+ index = add(index, NB_POS); move16();
+ }
+
+ i = extract_l(L_shr(L_mult(track, NPMAXPT), 1));
+
+ test();move16();
+ while (ind[i] >= 0)
+ {
+ i = add(i, 1);
+ }
+ ind[i] = index; move16();
+ }
+
+ k = 0; move16();
+ /* Build index of codevector */
+ test();test();test();test();test();test();test();
+ if (sub(nbbits, 20) == 0)
+ {
+ for (track = 0; track < NB_TRACK; track++)
+ {
+ _index[track] = extract_l(quant_1p_N1(ind[k], 4));
+ k += NPMAXPT;
+ }
+ } else if (sub(nbbits, 36) == 0)
+ {
+ for (track = 0; track < NB_TRACK; track++)
+ {
+ _index[track] = extract_l(quant_2p_2N1(ind[k], ind[k + 1], 4));
+ k += NPMAXPT;
+ }
+ } else if (sub(nbbits, 44) == 0)
+ {
+ for (track = 0; track < NB_TRACK - 2; track++)
+ {
+ _index[track] = extract_l(quant_3p_3N1(ind[k], ind[k + 1], ind[k + 2], 4));
+ k += NPMAXPT;
+ }
+ for (track = 2; track < NB_TRACK; track++)
+ {
+ _index[track] = extract_l(quant_2p_2N1(ind[k], ind[k + 1], 4));
+ k += NPMAXPT;
+ }
+ } else if (sub(nbbits, 52) == 0)
+ {
+ for (track = 0; track < NB_TRACK; track++)
+ {
+ _index[track] = extract_l(quant_3p_3N1(ind[k], ind[k + 1], ind[k + 2], 4));
+ k += NPMAXPT;
+ }
+ } else if (sub(nbbits, 64) == 0)
+ {
+ for (track = 0; track < NB_TRACK; track++)
+ {
+ L_index = quant_4p_4N(&ind[k], 4);
+ _index[track] = extract_l(L_shr(L_index, 14) & 3);
+ _index[track + NB_TRACK] = extract_l(L_index & 0x3FFF);
+ k += NPMAXPT;
+ }
+ } else if (sub(nbbits, 72) == 0)
+ {
+ for (track = 0; track < NB_TRACK - 2; track++)
+ {
+ L_index = quant_5p_5N(&ind[k], 4);
+ _index[track] = extract_l(L_shr(L_index, 10) & 0x03FF);
+ _index[track + NB_TRACK] = extract_l(L_index & 0x03FF);
+ k += NPMAXPT;
+ }
+ for (track = 2; track < NB_TRACK; track++)
+ {
+ L_index = quant_4p_4N(&ind[k], 4);
+ _index[track] = extract_l(L_shr(L_index, 14) & 3);
+ _index[track + NB_TRACK] = extract_l(L_index & 0x3FFF);
+ k += NPMAXPT;
+ }
+ } else if (sub(nbbits, 88) == 0)
+ {
+ for (track = 0; track < NB_TRACK; track++)
+ {
+ L_index = quant_6p_6N_2(&ind[k], 4);
+ _index[track] = extract_l(L_shr(L_index, 11) & 0x07FF);
+ _index[track + NB_TRACK] = extract_l(L_index & 0x07FF);
+ k += NPMAXPT;
+ }
+ }
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * Function cor_h_vec() *
+ * ~~~~~~~~~~~~~~~~~~~~~ *
+ * Compute correlations of h[] with vec[] for the specified track. *
+ *-------------------------------------------------------------------*/
+static void cor_h_vec(
+ Word16 h[], /* (i) scaled impulse response */
+ Word16 vec[], /* (i) scaled vector (/8) to correlate with h[] */
+ Word16 track, /* (i) track to use */
+ Word16 sign[], /* (i) sign vector */
+ Word16 rrixix[][NB_POS], /* (i) correlation of h[x] with h[x] */
+ Word16 cor[] /* (o) result of correlation (NB_POS elements) */
+)
+{
+ Word16 i, j, pos, corr;
+ Word16 *p0, *p1, *p2;
+ Word32 L_sum;
+
+ p0 = rrixix[track]; move16();
+
+ pos = track; move16();
+ for (i = 0; i < NB_POS; i++, pos += STEP)
+ {
+ L_sum = 0L; move32();
+ p1 = h; move16();
+ p2 = &vec[pos]; move16();
+ for (j = pos; j < L_SUBFR; j++)
+ L_sum = L_mac(L_sum, *p1++, *p2++);
+
+ L_sum = L_shl(L_sum, 1);
+
+ corr = round(L_sum);
+
+ cor[i] = add(mult(corr, sign[pos]), *p0++); move16();
+
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * Function search_ixiy() *
+ * ~~~~~~~~~~~~~~~~~~~~~~~ *
+ * Find the best positions of 2 pulses in a subframe. *
+ *-------------------------------------------------------------------*/
+
+static void search_ixiy(
+ Word16 nb_pos_ix, /* (i) nb of pos for pulse 1 (1..8) */
+ Word16 track_x, /* (i) track of pulse 1 */
+ Word16 track_y, /* (i) track of pulse 2 */
+ Word16 * ps, /* (i/o) correlation of all fixed pulses */
+ Word16 * alp, /* (i/o) energy of all fixed pulses */
+ Word16 * ix, /* (o) position of pulse 1 */
+ Word16 * iy, /* (o) position of pulse 2 */
+ Word16 dn[], /* (i) corr. between target and h[] */
+ Word16 dn2[], /* (i) vector of selected positions */
+ Word16 cor_x[], /* (i) corr. of pulse 1 with fixed pulses */
+ Word16 cor_y[], /* (i) corr. of pulse 2 with fixed pulses */
+ Word16 rrixiy[][MSIZE] /* (i) corr. of pulse 1 with pulse 2 */
+)
+{
+ Word16 x, y, pos, thres_ix;
+ Word16 ps1, ps2, sq, sqk;
+ Word16 alp_16, alpk;
+ Word16 *p0, *p1, *p2;
+ Word32 s, alp0, alp1, alp2;
+
+ p0 = cor_x; move16();
+ p1 = cor_y; move16();
+ p2 = rrixiy[track_x]; move16();
+
+ thres_ix = sub(nb_pos_ix, NB_MAX);
+
+ alp0 = L_deposit_h(*alp);
+ alp0 = L_add(alp0, 0x00008000L); /* for rounding */
+
+ sqk = -1; move16();
+ alpk = 1; move16();
+
+ for (x = track_x; x < L_SUBFR; x += STEP)
+ {
+ ps1 = add(*ps, dn[x]);
+ alp1 = L_mac(alp0, *p0++, 4096);
+
+ test();
+ if (sub(dn2[x], thres_ix) < 0)
+ {
+ pos = -1; move16();
+ for (y = track_y; y < L_SUBFR; y += STEP)
+ {
+ ps2 = add(ps1, dn[y]);
+ alp2 = L_mac(alp1, *p1++, 4096);
+ alp2 = L_mac(alp2, *p2++, 8192);
+ alp_16 = extract_h(alp2);
+
+ sq = mult(ps2, ps2);
+
+ s = L_msu(L_mult(alpk, sq), sqk, alp_16);
+
+ test();
+ if (s > 0)
+ {
+ sqk = sq; move16();
+ alpk = alp_16; move16();
+ pos = y; move16();
+ }
+ }
+ p1 -= NB_POS;
+
+ test();
+ if (pos >= 0)
+ {
+ *ix = x; move16();
+ *iy = pos; move16();
+ }
+ } else
+ {
+ p2 += NB_POS;
+ }
+ }
+
+ *ps = add(*ps, add(dn[*ix], dn[*iy])); move16();
+ *alp = alpk; move16();
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/cnst.h
@@ -1,0 +1,60 @@
+/*--------------------------------------------------------------------------*
+ * CNST.H *
+ *--------------------------------------------------------------------------*
+ * Codec constant parameters (coder and decoder) *
+ *--------------------------------------------------------------------------*/
+
+#define CODEC_VERSION "6.1.0"
+
+#define L_FRAME16k 320 /* Frame size at 16kHz */
+#define L_FRAME 256 /* Frame size */
+#define L_SUBFR16k 80 /* Subframe size at 16kHz */
+
+#define L_SUBFR 64 /* Subframe size */
+#define NB_SUBFR 4 /* Number of subframe per frame */
+
+#define L_NEXT 64 /* Overhead in LP analysis */
+#define L_WINDOW 384 /* window size in LP analysis */
+#define L_TOTAL 384 /* Total size of speech buffer. */
+#define M 16 /* Order of LP filter */
+#define M16k 20
+
+#define L_FILT16k 15 /* Delay of down-sampling filter */
+#define L_FILT 12 /* Delay of up-sampling filter */
+
+#define GP_CLIP 15565 /* Pitch gain clipping = 0.95 Q14 */
+#define PIT_SHARP 27853 /* pitch sharpening factor = 0.85 Q15 */
+
+#define PIT_MIN 34 /* Minimum pitch lag with resolution 1/4 */
+#define PIT_FR2 128 /* Minimum pitch lag with resolution 1/2 */
+#define PIT_FR1_9b 160 /* Minimum pitch lag with resolution 1 */
+#define PIT_FR1_8b 92 /* Minimum pitch lag with resolution 1 */
+#define PIT_MAX 231 /* Maximum pitch lag */
+#define L_INTERPOL (16+1) /* Length of filter for interpolation */
+
+#define OPL_DECIM 2 /* Decimation in open-loop pitch analysis */
+
+#define PREEMPH_FAC 22282 /* preemphasis factor (0.68 in Q15) */
+#define GAMMA1 30147 /* Weighting factor (numerator) (0.92 in Q15) */
+#define TILT_FAC 22282 /* tilt factor (denominator) (0.68 in Q15) */
+
+#define Q_MAX 8 /* scaling max for signal (see syn_filt_32) */
+
+#define RANDOM_INITSEED 21845 /* own random init value */
+
+#define L_MEANBUF 3
+#define ONE_PER_MEANBUF 10923
+
+#define MODE_7k 0
+#define MODE_9k 1
+#define MODE_12k 2
+#define MODE_14k 3
+#define MODE_16k 4
+#define MODE_18k 5
+#define MODE_20k 6
+#define MODE_23k 7
+#define MODE_24k 8
+#define MRDTX 9
+#define NUM_OF_MODES 10 /* see bits.h for bits definition */
+
+#define EHF_MASK (Word16)0x0008 /* homing frame pattern */
--- /dev/null
+++ b/amr-wb/cod_main.c
@@ -1,0 +1,1621 @@
+/*------------------------------------------------------------------------*
+ * COD_MAIN.C *
+ *------------------------------------------------------------------------*
+ * Performs the main encoder routine *
+ *------------------------------------------------------------------------*/
+
+/*___________________________________________________________________________
+ | |
+ | Fixed-point C simulation of AMR WB ACELP coding algorithm with 20 ms |
+ | speech frames for wideband speech signals. |
+ |___________________________________________________________________________|
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "math_op.h"
+#include "cnst.h"
+#include "acelp.h"
+#include "cod_main.h"
+#include "bits.h"
+#include "count.h"
+#include "main.h"
+
+
+/* LPC interpolation coef {0.45, 0.8, 0.96, 1.0}; in Q15 */
+static Word16 interpol_frac[NB_SUBFR] = {14746, 26214, 31457, 32767};
+
+/* isp tables for initialization */
+
+static Word16 isp_init[M] =
+{
+ 32138, 30274, 27246, 23170, 18205, 12540, 6393, 0,
+ -6393, -12540, -18205, -23170, -27246, -30274, -32138, 1475
+};
+
+static Word16 isf_init[M] =
+{
+ 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192,
+ 9216, 10240, 11264, 12288, 13312, 14336, 15360, 3840
+};
+
+/* High Band encoding */
+static const Word16 HP_gain[16] =
+{
+ 3624, 4673, 5597, 6479, 7425, 8378, 9324, 10264,
+ 11210, 12206, 13391, 14844, 16770, 19655, 24289, 32728
+};
+
+static Word16 synthesis(
+ Word16 Aq[], /* A(z) : quantized Az */
+ Word16 exc[], /* (i) : excitation at 12kHz */
+ Word16 Q_new, /* (i) : scaling performed on exc */
+ Word16 synth16k[], /* (o) : 16kHz synthesis signal */
+ Coder_State * st /* (i/o) : State structure */
+);
+
+/*-----------------------------------------------------------------*
+ * Funtion init_coder *
+ * ~~~~~~~~~~ *
+ * ->Initialization of variables for the coder section. *
+ *-----------------------------------------------------------------*/
+
+void Init_coder(void **spe_state)
+{
+ Coder_State *st;
+
+ *spe_state = NULL;
+
+ /*-------------------------------------------------------------------------*
+ * Memory allocation for coder state. *
+ *-------------------------------------------------------------------------*/
+
+ if ((st = (Coder_State *) malloc(sizeof(Coder_State))) == NULL)
+ {
+ printf("Can not malloc Coder_State structure!\n");
+ return;
+ }
+ st->vadSt = NULL; move16();
+ st->dtx_encSt = NULL; move16();
+
+ wb_vad_init(&(st->vadSt));
+ dtx_enc_init(&(st->dtx_encSt), isf_init);
+
+ Reset_encoder((void *) st, 1);
+
+ *spe_state = (void *) st;
+
+ return;
+}
+
+
+void Reset_encoder(void *st, Word16 reset_all)
+{
+ Word16 i;
+
+ Coder_State *cod_state;
+
+ cod_state = (Coder_State *) st;
+
+ Set_zero(cod_state->old_exc, PIT_MAX + L_INTERPOL);
+ Set_zero(cod_state->mem_syn, M);
+ Set_zero(cod_state->past_isfq, M);
+
+ cod_state->mem_w0 = 0; move16();
+ cod_state->tilt_code = 0; move16();
+ cod_state->first_frame = 1; move16();
+
+ Init_gp_clip(cod_state->gp_clip);
+
+ cod_state->L_gc_thres = 0; move16();
+
+ if (reset_all != 0)
+ {
+ /* Static vectors to zero */
+
+ Set_zero(cod_state->old_speech, L_TOTAL - L_FRAME);
+ Set_zero(cod_state->old_wsp, (PIT_MAX / OPL_DECIM));
+ Set_zero(cod_state->mem_decim2, 3);
+
+ /* routines initialization */
+
+ Init_Decim_12k8(cod_state->mem_decim);
+ Init_HP50_12k8(cod_state->mem_sig_in);
+ Init_Levinson(cod_state->mem_levinson);
+ Init_Q_gain2(cod_state->qua_gain);
+ Init_Hp_wsp(cod_state->hp_wsp_mem);
+
+ /* isp initialization */
+
+ Copy(isp_init, cod_state->ispold, M);
+ Copy(isp_init, cod_state->ispold_q, M);
+
+ /* variable initialization */
+
+ cod_state->mem_preemph = 0; move16();
+ cod_state->mem_wsp = 0; move16();
+ cod_state->Q_old = 15; move16();
+ cod_state->Q_max[0] = 15; move16();
+ cod_state->Q_max[1] = 15; move16();
+ cod_state->old_wsp_max = 0; move16();
+ cod_state->old_wsp_shift = 0; move16();
+
+ /* pitch ol initialization */
+
+ cod_state->old_T0_med = 40; move16();
+ cod_state->ol_gain = 0; move16();
+ cod_state->ada_w = 0; move16();
+ cod_state->ol_wght_flg = 0; move16();
+ for (i = 0; i < 5; i++)
+ {
+ cod_state->old_ol_lag[i] = 40; move16();
+ }
+ Set_zero(cod_state->old_hp_wsp, (L_FRAME / 2) / OPL_DECIM + (PIT_MAX / OPL_DECIM));
+
+ Set_zero(cod_state->mem_syn_hf, M);
+ Set_zero(cod_state->mem_syn_hi, M);
+ Set_zero(cod_state->mem_syn_lo, M);
+
+ Init_HP50_12k8(cod_state->mem_sig_out);
+ Init_Filt_6k_7k(cod_state->mem_hf);
+ Init_HP400_12k8(cod_state->mem_hp400);
+
+ Copy(isf_init, cod_state->isfold, M);
+
+ cod_state->mem_deemph = 0; move16();
+
+ cod_state->seed2 = 21845; move16();
+
+ Init_Filt_6k_7k(cod_state->mem_hf2);
+ cod_state->gain_alpha = 32767; move16();
+
+ cod_state->vad_hist = 0;
+
+ wb_vad_reset(cod_state->vadSt);
+ dtx_enc_reset(cod_state->dtx_encSt, isf_init);
+ }
+ return;
+}
+
+void Close_coder(void *spe_state)
+{
+ wb_vad_exit(&(((Coder_State *) spe_state)->vadSt));
+ dtx_enc_exit(&(((Coder_State *) spe_state)->dtx_encSt));
+ free(spe_state);
+
+ return;
+}
+
+/*-----------------------------------------------------------------*
+ * Funtion coder *
+ * ~~~~~ *
+ * ->Main coder routine. *
+ * *
+ *-----------------------------------------------------------------*/
+
+void coder(
+ Word16 * mode, /* input : used mode */
+ Word16 speech16k[], /* input : 320 new speech samples (at 16 kHz) */
+ Word16 prms[], /* output: output parameters */
+ Word16 * ser_size, /* output: bit rate of the used mode */
+ void *spe_state, /* i/o : State structure */
+ Word16 allow_dtx /* input : DTX ON/OFF */
+)
+{
+
+ /* Coder states */
+ Coder_State *st;
+
+ /* Speech vector */
+ Word16 old_speech[L_TOTAL];
+ Word16 *new_speech, *speech, *p_window;
+
+ /* Weighted speech vector */
+ Word16 old_wsp[L_FRAME + (PIT_MAX / OPL_DECIM)];
+ Word16 *wsp;
+
+ /* Excitation vector */
+ Word16 old_exc[(L_FRAME + 1) + PIT_MAX + L_INTERPOL];
+ Word16 *exc;
+
+ /* LPC coefficients */
+
+ Word16 r_h[M + 1], r_l[M + 1]; /* Autocorrelations of windowed speech */
+ Word16 rc[M]; /* Reflection coefficients. */
+ Word16 Ap[M + 1]; /* A(z) with spectral expansion */
+ Word16 ispnew[M]; /* immittance spectral pairs at 4nd sfr */
+ Word16 ispnew_q[M]; /* quantized ISPs at 4nd subframe */
+ Word16 isf[M]; /* ISF (frequency domain) at 4nd sfr */
+ Word16 *p_A, *p_Aq; /* ptr to A(z) for the 4 subframes */
+ Word16 A[NB_SUBFR * (M + 1)]; /* A(z) unquantized for the 4 subframes */
+ Word16 Aq[NB_SUBFR * (M + 1)]; /* A(z) quantized for the 4 subframes */
+
+ /* Other vectors */
+
+ Word16 xn[L_SUBFR]; /* Target vector for pitch search */
+ Word16 xn2[L_SUBFR]; /* Target vector for codebook search */
+ Word16 dn[L_SUBFR]; /* Correlation between xn2 and h1 */
+ Word16 cn[L_SUBFR]; /* Target vector in residual domain */
+
+ Word16 h1[L_SUBFR]; /* Impulse response vector */
+ Word16 h2[L_SUBFR]; /* Impulse response vector */
+ Word16 code[L_SUBFR]; /* Fixed codebook excitation */
+ Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */
+ Word16 y2[L_SUBFR]; /* Filtered adaptive excitation */
+ Word16 error[M + L_SUBFR]; /* error of quantization */
+ Word16 synth[L_SUBFR]; /* 12.8kHz synthesis vector */
+ Word16 exc2[L_FRAME]; /* excitation vector */
+ Word16 buf[L_FRAME]; /* VAD buffer */
+
+ /* Scalars */
+
+ Word16 i, j, i_subfr, select, pit_flag, clip_gain, vad_flag;
+ Word16 codec_mode;
+ Word16 T_op, T_op2, T0, T0_min, T0_max, T0_frac, index;
+ Word16 gain_pit, gain_code, g_coeff[4], g_coeff2[4];
+ Word16 tmp, gain1, gain2, exp, Q_new, mu, shift, max;
+ Word16 voice_fac;
+ Word16 indice[8];
+
+ Word32 L_tmp, L_gain_code, L_max;
+
+ Word16 code2[L_SUBFR]; /* Fixed codebook excitation */
+ Word16 stab_fac, fac, gain_code_lo;
+
+ Word16 corr_gain;
+
+ st = (Coder_State *) spe_state;
+
+ *ser_size = nb_of_bits[*mode]; move16();
+ codec_mode = *mode; move16();
+
+ /*--------------------------------------------------------------------------*
+ * Initialize pointers to speech vector. *
+ * *
+ * *
+ * |-------|-------|-------|-------|-------|-------| *
+ * past sp sf1 sf2 sf3 sf4 L_NEXT *
+ * <------- Total speech buffer (L_TOTAL) ------> *
+ * old_speech *
+ * <------- LPC analysis window (L_WINDOW) ------> *
+ * | <-- present frame (L_FRAME) ----> *
+ * p_window | <----- new speech (L_FRAME) ----> *
+ * | | *
+ * speech | *
+ * new_speech *
+ *--------------------------------------------------------------------------*/
+
+ new_speech = old_speech + L_TOTAL - L_FRAME - L_FILT; move16(); /* New speech */
+ speech = old_speech + L_TOTAL - L_FRAME - L_NEXT; move16(); /* Present frame */
+ p_window = old_speech + L_TOTAL - L_WINDOW; move16();
+
+ exc = old_exc + PIT_MAX + L_INTERPOL; move16();
+ wsp = old_wsp + (PIT_MAX / OPL_DECIM); move16();
+
+ /* copy coder memory state into working space (internal memory for DSP) */
+
+ Copy(st->old_speech, old_speech, L_TOTAL - L_FRAME);
+ Copy(st->old_wsp, old_wsp, PIT_MAX / OPL_DECIM);
+ Copy(st->old_exc, old_exc, PIT_MAX + L_INTERPOL);
+
+ /*---------------------------------------------------------------*
+ * Down sampling signal from 16kHz to 12.8kHz *
+ * -> The signal is extended by L_FILT samples (padded to zero) *
+ * to avoid additional delay (L_FILT samples) in the coder. *
+ * The last L_FILT samples are approximated after decimation and *
+ * are used (and windowed) only in autocorrelations. *
+ *---------------------------------------------------------------*/
+
+ Decim_12k8(speech16k, L_FRAME16k, new_speech, st->mem_decim);
+
+ /* last L_FILT samples for autocorrelation window */
+ Copy(st->mem_decim, code, 2 * L_FILT16k);
+ Set_zero(error, L_FILT16k); /* set next sample to zero */
+ Decim_12k8(error, L_FILT16k, new_speech + L_FRAME, code);
+
+ /*---------------------------------------------------------------*
+ * Perform 50Hz HP filtering of input signal. *
+ *---------------------------------------------------------------*/
+
+ HP50_12k8(new_speech, L_FRAME, st->mem_sig_in);
+
+ /* last L_FILT samples for autocorrelation window */
+ Copy(st->mem_sig_in, code, 6);
+ HP50_12k8(new_speech + L_FRAME, L_FILT, code);
+
+ /*---------------------------------------------------------------*
+ * Perform fixed preemphasis through 1 - g z^-1 *
+ * Scale signal to get maximum of precision in filtering *
+ *---------------------------------------------------------------*/
+
+ mu = shr(PREEMPH_FAC, 1); /* Q15 --> Q14 */
+
+ /* get max of new preemphased samples (L_FRAME+L_FILT) */
+
+ L_tmp = L_mult(new_speech[0], 16384);
+ L_tmp = L_msu(L_tmp, st->mem_preemph, mu);
+ L_max = L_abs(L_tmp);
+
+ for (i = 1; i < L_FRAME + L_FILT; i++)
+ {
+ L_tmp = L_mult(new_speech[i], 16384);
+ L_tmp = L_msu(L_tmp, new_speech[i - 1], mu);
+ L_tmp = L_abs(L_tmp);
+ test();
+ if (L_sub(L_tmp, L_max) > (Word32) 0)
+ {
+ L_max = L_tmp; move32();
+ }
+ }
+
+ /* get scaling factor for new and previous samples */
+ /* limit scaling to Q_MAX to keep dynamic for ringing in low signal */
+ /* limit scaling to Q_MAX also to avoid a[0]<1 in syn_filt_32 */
+ tmp = extract_h(L_max);
+ test();
+ if (tmp == 0)
+ {
+ shift = Q_MAX; move16();
+ } else
+ {
+ shift = sub(norm_s(tmp), 1);
+ test();
+ if (shift < 0)
+ {
+ shift = 0; move16();
+ }
+ test();
+ if (sub(shift, Q_MAX) > 0)
+ {
+ shift = Q_MAX; move16();
+ }
+ }
+ Q_new = shift; move16();
+ test();
+ if (sub(Q_new, st->Q_max[0]) > 0)
+ {
+ Q_new = st->Q_max[0]; move16();
+ }
+ test();
+ if (sub(Q_new, st->Q_max[1]) > 0)
+ {
+ Q_new = st->Q_max[1]; move16();
+ }
+ exp = sub(Q_new, st->Q_old);
+ st->Q_old = Q_new; move16();
+ st->Q_max[1] = st->Q_max[0]; move16();
+ st->Q_max[0] = shift; move16();
+
+ /* preemphasis with scaling (L_FRAME+L_FILT) */
+
+ tmp = new_speech[L_FRAME - 1]; move16();
+
+ for (i = L_FRAME + L_FILT - 1; i > 0; i--)
+ {
+ L_tmp = L_mult(new_speech[i], 16384);
+ L_tmp = L_msu(L_tmp, new_speech[i - 1], mu);
+ L_tmp = L_shl(L_tmp, Q_new);
+ new_speech[i] = round(L_tmp); move16();
+ }
+
+ L_tmp = L_mult(new_speech[0], 16384);
+ L_tmp = L_msu(L_tmp, st->mem_preemph, mu);
+ L_tmp = L_shl(L_tmp, Q_new);
+ new_speech[0] = round(L_tmp); move16();
+
+ st->mem_preemph = tmp; move16();
+
+ /* scale previous samples and memory */
+
+ Scale_sig(old_speech, L_TOTAL - L_FRAME - L_FILT, exp);
+ Scale_sig(old_exc, PIT_MAX + L_INTERPOL, exp);
+
+ Scale_sig(st->mem_syn, M, exp);
+ Scale_sig(st->mem_decim2, 3, exp);
+ Scale_sig(&(st->mem_wsp), 1, exp);
+ Scale_sig(&(st->mem_w0), 1, exp);
+
+ /*------------------------------------------------------------------------*
+ * Call VAD *
+ * Preemphesis scale down signal in low frequency and keep dynamic in HF.*
+ * Vad work slightly in futur (new_speech = speech + L_NEXT - L_FILT). *
+ *------------------------------------------------------------------------*/
+
+ Copy(new_speech, buf, L_FRAME);
+
+ Scale_sig(buf, L_FRAME, sub(1, Q_new));
+
+ vad_flag = wb_vad(st->vadSt, buf);
+ if (vad_flag == 0)
+ {
+ st->vad_hist = add(st->vad_hist, 1); move16();
+ } else
+ {
+ st->vad_hist = 0; move16();
+ }
+
+ /* DTX processing */
+ test();
+ if (allow_dtx != 0)
+ {
+ /* Note that mode may change here */
+ tx_dtx_handler(st->dtx_encSt, vad_flag, mode);
+ *ser_size = nb_of_bits[*mode]; move16();
+ }
+
+ test();
+ if (sub(*mode, MRDTX) != 0)
+ {
+ Parm_serial(vad_flag, 1, &prms);
+ }
+ /*------------------------------------------------------------------------*
+ * Perform LPC analysis *
+ * ~~~~~~~~~~~~~~~~~~~~ *
+ * - autocorrelation + lag windowing *
+ * - Levinson-durbin algorithm to find a[] *
+ * - convert a[] to isp[] *
+ * - convert isp[] to isf[] for quantization *
+ * - quantize and code the isf[] *
+ * - convert isf[] to isp[] for interpolation *
+ * - find the interpolated ISPs and convert to a[] for the 4 subframes *
+ *------------------------------------------------------------------------*/
+
+ /* LP analysis centered at 4nd subframe */
+ Autocorr(p_window, M, r_h, r_l); /* Autocorrelations */
+ Lag_window(r_h, r_l); /* Lag windowing */
+ Levinson(r_h, r_l, A, rc, st->mem_levinson); /* Levinson Durbin */
+ Az_isp(A, ispnew, st->ispold); /* From A(z) to ISP */
+
+ /* Find the interpolated ISPs and convert to a[] for all subframes */
+ Int_isp(st->ispold, ispnew, interpol_frac, A);
+
+ /* update ispold[] for the next frame */
+ Copy(ispnew, st->ispold, M);
+
+ /* Convert ISPs to frequency domain 0..6400 */
+ Isp_isf(ispnew, isf, M);
+
+ /* check resonance for pitch clipping algorithm */
+ Gp_clip_test_isf(isf, st->gp_clip);
+
+ /*----------------------------------------------------------------------*
+ * Perform PITCH_OL analysis *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * - Find the residual res[] for the whole speech frame *
+ * - Find the weighted input speech wsp[] for the whole speech frame *
+ * - scale wsp[] to avoid overflow in pitch estimation *
+ * - Find open loop pitch lag for whole speech frame *
+ *----------------------------------------------------------------------*/
+
+ p_A = A; move16();
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ Weight_a(p_A, Ap, GAMMA1, M);
+ Residu(Ap, M, &speech[i_subfr], &wsp[i_subfr], L_SUBFR);
+ p_A += (M + 1); move16();
+ }
+ Deemph2(wsp, TILT_FAC, L_FRAME, &(st->mem_wsp));
+
+ /* find maximum value on wsp[] for 12 bits scaling */
+ max = 0; move16();
+ for (i = 0; i < L_FRAME; i++)
+ {
+ tmp = abs_s(wsp[i]);
+ test();
+ if (sub(tmp, max) > 0)
+ {
+ max = tmp; move16();
+ }
+ }
+ tmp = st->old_wsp_max; move16();
+ test();
+ if (sub(max, tmp) > 0)
+ {
+ tmp = max; /* tmp = max(wsp_max, old_wsp_max) */
+ move16();
+ }
+ st->old_wsp_max = max; move16();
+
+ shift = sub(norm_s(tmp), 3);
+ test();
+ if (shift > 0)
+ {
+ shift = 0; /* shift = 0..-3 */
+ move16();
+ }
+ /* decimation of wsp[] to search pitch in LF and to reduce complexity */
+ LP_Decim2(wsp, L_FRAME, st->mem_decim2);
+
+ /* scale wsp[] in 12 bits to avoid overflow */
+ Scale_sig(wsp, L_FRAME / OPL_DECIM, shift);
+
+ /* scale old_wsp (warning: exp must be Q_new-Q_old) */
+ exp = add(exp, sub(shift, st->old_wsp_shift));
+ st->old_wsp_shift = shift;
+ Scale_sig(old_wsp, PIT_MAX / OPL_DECIM, exp);
+ Scale_sig(st->old_hp_wsp, PIT_MAX / OPL_DECIM, exp);
+ scale_mem_Hp_wsp(st->hp_wsp_mem, exp);
+
+ /* Find open loop pitch lag for whole speech frame */
+
+ test();
+ if (sub(*ser_size, NBBITS_7k) == 0)
+ {
+ /* Find open loop pitch lag for whole speech frame */
+ T_op = Pitch_med_ol(wsp, PIT_MIN / OPL_DECIM, PIT_MAX / OPL_DECIM,
+ L_FRAME / OPL_DECIM, st->old_T0_med, &(st->ol_gain), st->hp_wsp_mem, st->old_hp_wsp, st->ol_wght_flg);
+ } else
+ {
+ /* Find open loop pitch lag for first 1/2 frame */
+ T_op = Pitch_med_ol(wsp, PIT_MIN / OPL_DECIM, PIT_MAX / OPL_DECIM,
+ (L_FRAME / 2) / OPL_DECIM, st->old_T0_med, &(st->ol_gain), st->hp_wsp_mem, st->old_hp_wsp, st->ol_wght_flg);
+ }
+
+ test();
+ if (sub(st->ol_gain, 19661) > 0) /* 0.6 in Q15 */
+ {
+ st->old_T0_med = Med_olag(T_op, st->old_ol_lag); move16();
+ st->ada_w = 32767; move16();
+ } else
+ {
+ st->ada_w = mult(st->ada_w, 29491);move16();
+ }
+
+ test();move16();
+ if (sub(st->ada_w, 26214) < 0)
+ st->ol_wght_flg = 0;
+ else
+ st->ol_wght_flg = 1;
+
+ wb_vad_tone_detection(st->vadSt, st->ol_gain);
+
+ T_op *= OPL_DECIM; move16();
+
+ test();
+ if (sub(*ser_size, NBBITS_7k) != 0)
+ {
+ /* Find open loop pitch lag for second 1/2 frame */
+ T_op2 = Pitch_med_ol(wsp + ((L_FRAME / 2) / OPL_DECIM), PIT_MIN / OPL_DECIM, PIT_MAX / OPL_DECIM,
+ (L_FRAME / 2) / OPL_DECIM, st->old_T0_med, &(st->ol_gain), st->hp_wsp_mem, st->old_hp_wsp, st->ol_wght_flg);
+
+ test();
+ if (sub(st->ol_gain, 19661) > 0) /* 0.6 in Q15 */
+ {
+ st->old_T0_med = Med_olag(T_op2, st->old_ol_lag); move16();
+ st->ada_w = 32767; move16();
+ } else
+ {
+ st->ada_w = mult(st->ada_w, 29491); move16();
+ }
+
+ test();move16();
+ if (sub(st->ada_w, 26214) < 0)
+ st->ol_wght_flg = 0;
+ else
+ st->ol_wght_flg = 1;
+
+ wb_vad_tone_detection(st->vadSt, st->ol_gain);
+
+ T_op2 *= OPL_DECIM; move16();
+
+ } else
+ {
+ T_op2 = T_op; move16();
+ }
+
+
+ /*----------------------------------------------------------------------*
+ * DTX-CNG *
+ *----------------------------------------------------------------------*/
+
+ test();
+ if (sub(*mode, MRDTX) == 0) /* CNG mode */
+ {
+ /* Buffer isf's and energy */
+ Residu(&A[3 * (M + 1)], M, speech, exc, L_FRAME);
+
+ for (i = 0; i < L_FRAME; i++)
+ {
+ exc2[i] = shr(exc[i], Q_new); move16();
+ }
+
+ L_tmp = 0; move32();
+ for (i = 0; i < L_FRAME; i++)
+ L_tmp = L_mac(L_tmp, exc2[i], exc2[i]);
+ L_tmp = L_shr(L_tmp, 1);
+
+ dtx_buffer(st->dtx_encSt, isf, L_tmp, codec_mode);
+
+ /* Quantize and code the ISFs */
+ dtx_enc(st->dtx_encSt, isf, exc2, &prms);
+
+ /* Convert ISFs to the cosine domain */
+ Isf_isp(isf, ispnew_q, M);
+ Isp_Az(ispnew_q, Aq, M, 0);
+
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ corr_gain = synthesis(Aq, &exc2[i_subfr], 0, &speech16k[i_subfr * 5 / 4], st);
+ }
+ Copy(isf, st->isfold, M);
+
+
+ /* reset speech coder memories */
+ Reset_encoder(st, 0);
+
+ /*--------------------------------------------------*
+ * Update signal for next frame. *
+ * -> save past of speech[] and wsp[]. *
+ *--------------------------------------------------*/
+
+ Copy(&old_speech[L_FRAME], st->old_speech, L_TOTAL - L_FRAME);
+ Copy(&old_wsp[L_FRAME / OPL_DECIM], st->old_wsp, PIT_MAX / OPL_DECIM);
+
+ return;
+ }
+ /*----------------------------------------------------------------------*
+ * ACELP *
+ *----------------------------------------------------------------------*/
+
+ /* Quantize and code the ISFs */
+
+ test();
+ if (sub(*ser_size, NBBITS_7k) <= 0)
+ {
+ Qpisf_2s_36b(isf, isf, st->past_isfq, indice, 4);
+
+ Parm_serial(indice[0], 8, &prms);
+ Parm_serial(indice[1], 8, &prms);
+ Parm_serial(indice[2], 7, &prms);
+ Parm_serial(indice[3], 7, &prms);
+ Parm_serial(indice[4], 6, &prms);
+ } else
+ {
+ Qpisf_2s_46b(isf, isf, st->past_isfq, indice, 4);
+
+ Parm_serial(indice[0], 8, &prms);
+ Parm_serial(indice[1], 8, &prms);
+ Parm_serial(indice[2], 6, &prms);
+ Parm_serial(indice[3], 7, &prms);
+ Parm_serial(indice[4], 7, &prms);
+ Parm_serial(indice[5], 5, &prms);
+ Parm_serial(indice[6], 5, &prms);
+ }
+
+ /* Check stability on isf : distance between old isf and current isf */
+
+ L_tmp = 0; move32();
+ for (i = 0; i < M - 1; i++)
+ {
+ tmp = sub(isf[i], st->isfold[i]);
+ L_tmp = L_mac(L_tmp, tmp, tmp);
+ }
+
+ tmp = extract_h(L_shl(L_tmp, 8)); /* saturation can occur here */
+
+ tmp = mult(tmp, 26214); /* tmp = L_tmp*0.8/256 */
+ tmp = sub(20480, tmp); /* 1.25 - tmp (in Q14) */
+
+ stab_fac = shl(tmp, 1); /* saturation can occur here */
+
+ test();
+ if (stab_fac < 0)
+ {
+ stab_fac = 0; move16();
+ }
+ Copy(isf, st->isfold, M);
+
+ /* Convert ISFs to the cosine domain */
+ Isf_isp(isf, ispnew_q, M);
+
+ test();
+ if (st->first_frame != 0)
+ {
+ st->first_frame = 0; move16();
+ Copy(ispnew_q, st->ispold_q, M);
+ }
+ /* Find the interpolated ISPs and convert to a[] for all subframes */
+
+ Int_isp(st->ispold_q, ispnew_q, interpol_frac, Aq);
+
+ /* update ispold[] for the next frame */
+ Copy(ispnew_q, st->ispold_q, M);
+
+ p_Aq = Aq;
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ Residu(p_Aq, M, &speech[i_subfr], &exc[i_subfr], L_SUBFR);
+ p_Aq += (M + 1); move16();
+ }
+
+ /* Buffer isf's and energy for dtx on non-speech frame */
+
+ test();
+ if (vad_flag == 0)
+ {
+ for (i = 0; i < L_FRAME; i++)
+ {
+ exc2[i] = shr(exc[i], Q_new); move16();
+ }
+ L_tmp = 0; move32();
+ for (i = 0; i < L_FRAME; i++)
+ L_tmp = L_mac(L_tmp, exc2[i], exc2[i]);
+ L_tmp = L_shr(L_tmp, 1);
+
+ dtx_buffer(st->dtx_encSt, isf, L_tmp, codec_mode);
+ }
+ /* range for closed loop pitch search in 1st subframe */
+
+ T0_min = sub(T_op, 8);
+ test();
+ if (sub(T0_min, PIT_MIN) < 0)
+ {
+ T0_min = PIT_MIN; move16();
+ }
+ T0_max = add(T0_min, 15);
+ test();
+ if (sub(T0_max, PIT_MAX) > 0)
+ {
+ T0_max = PIT_MAX; move16();
+ T0_min = sub(T0_max, 15); move16();
+ }
+ /*------------------------------------------------------------------------*
+ * Loop for every subframe in the analysis frame *
+ *------------------------------------------------------------------------*
+ * To find the pitch and innovation parameters. The subframe size is *
+ * L_SUBFR and the loop is repeated L_FRAME/L_SUBFR times. *
+ * - compute the target signal for pitch search *
+ * - compute impulse response of weighted synthesis filter (h1[]) *
+ * - find the closed-loop pitch parameters *
+ * - encode the pitch dealy *
+ * - find 2 lt prediction (with / without LP filter for lt pred) *
+ * - find 2 pitch gains and choose the best lt prediction. *
+ * - find target vector for codebook search *
+ * - update the impulse response h1[] for codebook search *
+ * - correlation between target vector and impulse response *
+ * - codebook search and encoding *
+ * - VQ of pitch and codebook gains *
+ * - find voicing factor and tilt of code for next subframe. *
+ * - update states of weighting filter *
+ * - find excitation and synthesis speech *
+ *------------------------------------------------------------------------*/
+
+ p_A = A; move16();
+ p_Aq = Aq; move16();
+
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ pit_flag = i_subfr; move16();
+ test();test();
+ if ((sub(i_subfr, 2 * L_SUBFR) == 0) && (sub(*ser_size, NBBITS_7k) > 0))
+ {
+ pit_flag = 0; move16();
+
+ /* range for closed loop pitch search in 3rd subframe */
+
+ T0_min = sub(T_op2, 8);
+ test();
+ if (sub(T0_min, PIT_MIN) < 0)
+ {
+ T0_min = PIT_MIN; move16();
+ }
+ T0_max = add(T0_min, 15);
+ test();
+ if (sub(T0_max, PIT_MAX) > 0)
+ {
+ T0_max = PIT_MAX; move16();
+ T0_min = sub(T0_max, 15);
+ }
+ }
+ /*-----------------------------------------------------------------------*
+ * *
+ * Find the target vector for pitch search: *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * *
+ * |------| res[n] *
+ * speech[n]---| A(z) |-------- *
+ * |------| | |--------| error[n] |------| *
+ * zero -- (-)--| 1/A(z) |-----------| W(z) |-- target *
+ * exc |--------| |------| *
+ * *
+ * Instead of subtracting the zero-input response of filters from *
+ * the weighted input speech, the above configuration is used to *
+ * compute the target vector. *
+ * *
+ *-----------------------------------------------------------------------*/
+
+ for (i = 0; i < M; i++)
+ {
+ error[i] = sub(speech[i + i_subfr - M], st->mem_syn[i]); move16();
+ }
+ Residu(p_Aq, M, &speech[i_subfr], &exc[i_subfr], L_SUBFR);
+
+ Syn_filt(p_Aq, M, &exc[i_subfr], error + M, L_SUBFR, error, 0);
+
+ Weight_a(p_A, Ap, GAMMA1, M);
+ Residu(Ap, M, error + M, xn, L_SUBFR);
+
+ Deemph2(xn, TILT_FAC, L_SUBFR, &(st->mem_w0));
+
+ /*----------------------------------------------------------------------*
+ * Find approx. target in residual domain "cn[]" for inovation search. *
+ *----------------------------------------------------------------------*/
+
+ /* first half: xn[] --> cn[] */
+ Set_zero(code, M);
+ Copy(xn, code + M, L_SUBFR / 2);
+ tmp = 0; move16();
+ Preemph2(code + M, TILT_FAC, L_SUBFR / 2, &tmp);
+ Weight_a(p_A, Ap, GAMMA1, M);
+ Syn_filt(Ap, M, code + M, code + M, L_SUBFR / 2, code, 0);
+ Residu(p_Aq, M, code + M, cn, L_SUBFR / 2);
+
+ /* second half: res[] --> cn[] (approximated and faster) */
+ Copy(&exc[i_subfr + (L_SUBFR / 2)], cn + (L_SUBFR / 2), L_SUBFR / 2);
+
+ /*---------------------------------------------------------------*
+ * Compute impulse response, h1[], of weighted synthesis filter *
+ *---------------------------------------------------------------*/
+
+ Set_zero(error, M + L_SUBFR);
+ Weight_a(p_A, error + M, GAMMA1, M);
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ L_tmp = L_mult(error[i + M], 16384); /* x4 (Q12 to Q14) */
+ for (j = 1; j <= M; j++)
+ L_tmp = L_msu(L_tmp, p_Aq[j], error[i + M - j]);
+
+ h1[i] = error[i + M] = round(L_shl(L_tmp, 3)); move16();move16();
+ }
+ /* deemph without division by 2 -> Q14 to Q15 */
+ tmp = 0; move16();
+ Deemph2(h1, TILT_FAC, L_SUBFR, &tmp); /* h1 in Q14 */
+
+ /* h2 in Q12 for codebook search */
+ Copy(h1, h2, L_SUBFR);
+ Scale_sig(h2, L_SUBFR, -2);
+
+ /*---------------------------------------------------------------*
+ * scale xn[] and h1[] to avoid overflow in dot_product12() *
+ *---------------------------------------------------------------*/
+
+ Scale_sig(xn, L_SUBFR, shift); /* scaling of xn[] to limit dynamic at 12 bits */
+ Scale_sig(h1, L_SUBFR, add(1, shift)); /* set h1[] in Q15 with scaling for convolution */
+
+ /*----------------------------------------------------------------------*
+ * Closed-loop fractional pitch search *
+ *----------------------------------------------------------------------*/
+
+ /* find closed loop fractional pitch lag */
+
+ test();
+ if (sub(*ser_size, NBBITS_9k) <= 0)
+ {
+ T0 = Pitch_fr4(&exc[i_subfr], xn, h1, T0_min, T0_max, &T0_frac,
+ pit_flag, PIT_MIN, PIT_FR1_8b, L_SUBFR);
+
+ /* encode pitch lag */
+
+ test();
+ if (pit_flag == 0) /* if 1st/3rd subframe */
+ {
+ /*--------------------------------------------------------------*
+ * The pitch range for the 1st/3rd subframe is encoded with *
+ * 8 bits and is divided as follows: *
+ * PIT_MIN to PIT_FR1-1 resolution 1/2 (frac = 0 or 2) *
+ * PIT_FR1 to PIT_MAX resolution 1 (frac = 0) *
+ *--------------------------------------------------------------*/
+
+ test();
+ if (sub(T0, PIT_FR1_8b) < 0)
+ {
+ index = sub(add(shl(T0, 1), shr(T0_frac, 1)), (PIT_MIN * 2));
+ } else
+ {
+ index = add(sub(T0, PIT_FR1_8b), ((PIT_FR1_8b - PIT_MIN) * 2));
+ }
+
+ Parm_serial(index, 8, &prms);
+
+ /* find T0_min and T0_max for subframe 2 and 4 */
+
+ T0_min = sub(T0, 8);
+ test();
+ if (sub(T0_min, PIT_MIN) < 0)
+ {
+ T0_min = PIT_MIN; move16();
+ }
+ T0_max = add(T0_min, 15);
+ test();
+ if (sub(T0_max, PIT_MAX) > 0)
+ {
+ T0_max = PIT_MAX; move16();
+ T0_min = sub(T0_max, 15);
+ }
+ } else
+ { /* if subframe 2 or 4 */
+ /*--------------------------------------------------------------*
+ * The pitch range for subframe 2 or 4 is encoded with 5 bits: *
+ * T0_min to T0_max resolution 1/2 (frac = 0 or 2) *
+ *--------------------------------------------------------------*/
+
+ i = sub(T0, T0_min);
+ index = add(shl(i, 1), shr(T0_frac, 1));
+
+ Parm_serial(index, 5, &prms);
+ }
+ } else
+ {
+ T0 = Pitch_fr4(&exc[i_subfr], xn, h1, T0_min, T0_max, &T0_frac,
+ pit_flag, PIT_FR2, PIT_FR1_9b, L_SUBFR);
+
+ /* encode pitch lag */
+
+ test();
+ if (pit_flag == 0) /* if 1st/3rd subframe */
+ {
+ /*--------------------------------------------------------------*
+ * The pitch range for the 1st/3rd subframe is encoded with *
+ * 9 bits and is divided as follows: *
+ * PIT_MIN to PIT_FR2-1 resolution 1/4 (frac = 0,1,2 or 3) *
+ * PIT_FR2 to PIT_FR1-1 resolution 1/2 (frac = 0 or 1) *
+ * PIT_FR1 to PIT_MAX resolution 1 (frac = 0) *
+ *--------------------------------------------------------------*/
+
+ test();test();
+ if (sub(T0, PIT_FR2) < 0)
+ {
+ index = sub(add(shl(T0, 2), T0_frac), (PIT_MIN * 4));
+ } else if (sub(T0, PIT_FR1_9b) < 0)
+ {
+ index = add(sub(add(shl(T0, 1), shr(T0_frac, 1)), (PIT_FR2 * 2)), ((PIT_FR2 - PIT_MIN) * 4));
+ } else
+ {
+ index = add(add(sub(T0, PIT_FR1_9b), ((PIT_FR2 - PIT_MIN) * 4)), ((PIT_FR1_9b - PIT_FR2) * 2));
+ }
+
+ Parm_serial(index, 9, &prms);
+
+ /* find T0_min and T0_max for subframe 2 and 4 */
+
+ T0_min = sub(T0, 8);
+ test();
+ if (sub(T0_min, PIT_MIN) < 0)
+ {
+ T0_min = PIT_MIN; move16();
+ }
+ T0_max = add(T0_min, 15);
+ test();
+ if (sub(T0_max, PIT_MAX) > 0)
+ {
+ T0_max = PIT_MAX; move16();
+ T0_min = sub(T0_max, 15);
+ }
+ } else
+ { /* if subframe 2 or 4 */
+ /*--------------------------------------------------------------*
+ * The pitch range for subframe 2 or 4 is encoded with 6 bits: *
+ * T0_min to T0_max resolution 1/4 (frac = 0,1,2 or 3) *
+ *--------------------------------------------------------------*/
+
+ i = sub(T0, T0_min);
+ index = add(shl(i, 2), T0_frac);
+
+ Parm_serial(index, 6, &prms);
+ }
+ }
+
+ /*-----------------------------------------------------------------*
+ * Gain clipping test to avoid unstable synthesis on frame erasure *
+ *-----------------------------------------------------------------*/
+
+ clip_gain = Gp_clip(st->gp_clip);
+
+ /*-----------------------------------------------------------------*
+ * - find unity gain pitch excitation (adaptive codebook entry) *
+ * with fractional interpolation. *
+ * - find filtered pitch exc. y1[]=exc[] convolved with h1[]) *
+ * - compute pitch gain1 *
+ *-----------------------------------------------------------------*/
+
+ /* find pitch exitation */
+
+ Pred_lt4(&exc[i_subfr], T0, T0_frac, L_SUBFR + 1);
+ test();
+ if (sub(*ser_size, NBBITS_9k) > 0)
+ {
+ Convolve(&exc[i_subfr], h1, y1, L_SUBFR);
+ gain1 = G_pitch(xn, y1, g_coeff, L_SUBFR);
+
+ /* clip gain if necessary to avoid problem at decoder */
+ test();test();
+ if ((clip_gain != 0) && (sub(gain1, GP_CLIP) > 0))
+ {
+ gain1 = GP_CLIP; move16();
+ }
+ /* find energy of new target xn2[] */
+ Updt_tar(xn, dn, y1, gain1, L_SUBFR); /* dn used temporary */
+ } else
+ {
+ gain1 = 0; move16();
+ }
+
+ /*-----------------------------------------------------------------*
+ * - find pitch excitation filtered by 1st order LP filter. *
+ * - find filtered pitch exc. y2[]=exc[] convolved with h1[]) *
+ * - compute pitch gain2 *
+ *-----------------------------------------------------------------*/
+
+ /* find pitch excitation with lp filter */
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ L_tmp = L_mult(5898, exc[i - 1 + i_subfr]);
+ L_tmp = L_mac(L_tmp, 20972, exc[i + i_subfr]);
+ L_tmp = L_mac(L_tmp, 5898, exc[i + 1 + i_subfr]);
+ code[i] = round(L_tmp); move16();
+ }
+
+ Convolve(code, h1, y2, L_SUBFR);
+ gain2 = G_pitch(xn, y2, g_coeff2, L_SUBFR);
+
+ /* clip gain if necessary to avoid problem at decoder */
+ test();test();
+ if ((clip_gain != 0) && (sub(gain2, GP_CLIP) > 0))
+ {
+ gain2 = GP_CLIP; move16();
+ }
+ /* find energy of new target xn2[] */
+ Updt_tar(xn, xn2, y2, gain2, L_SUBFR);
+
+ /*-----------------------------------------------------------------*
+ * use the best prediction (minimise quadratic error). *
+ *-----------------------------------------------------------------*/
+
+ select = 0; move16();
+ test();
+ if (sub(*ser_size, NBBITS_9k) > 0)
+ {
+ L_tmp = 0L; move32();
+ for (i = 0; i < L_SUBFR; i++)
+ L_tmp = L_mac(L_tmp, dn[i], dn[i]);
+ for (i = 0; i < L_SUBFR; i++)
+ L_tmp = L_msu(L_tmp, xn2[i], xn2[i]);
+
+ test();
+ if (L_tmp <= 0)
+ {
+ select = 1; move16();
+ }
+ Parm_serial(select, 1, &prms);
+ }
+ test();
+ if (select == 0)
+ {
+ /* use the lp filter for pitch excitation prediction */
+ gain_pit = gain2; move16();
+ Copy(code, &exc[i_subfr], L_SUBFR);
+ Copy(y2, y1, L_SUBFR);
+ Copy(g_coeff2, g_coeff, 4);
+ } else
+ {
+ /* no filter used for pitch excitation prediction */
+ gain_pit = gain1; move16();
+ Copy(dn, xn2, L_SUBFR); /* target vector for codebook search */
+ }
+
+ /*-----------------------------------------------------------------*
+ * - update cn[] for codebook search *
+ *-----------------------------------------------------------------*/
+
+ Updt_tar(cn, cn, &exc[i_subfr], gain_pit, L_SUBFR);
+
+ Scale_sig(cn, L_SUBFR, shift); /* scaling of cn[] to limit dynamic at 12 bits */
+
+ /*-----------------------------------------------------------------*
+ * - include fixed-gain pitch contribution into impulse resp. h1[] *
+ *-----------------------------------------------------------------*/
+
+ tmp = 0; move16();
+ Preemph(h2, st->tilt_code, L_SUBFR, &tmp);
+
+ test();
+ if (T0_frac > 2)
+ T0 = add(T0, 1);
+ Pit_shrp(h2, T0, PIT_SHARP, L_SUBFR);
+
+ /*-----------------------------------------------------------------*
+ * - Correlation between target xn2[] and impulse response h1[] *
+ * - Innovative codebook search *
+ *-----------------------------------------------------------------*/
+
+ cor_h_x(h2, xn2, dn);
+
+ test();test();test();test();test();test();test();
+ if (sub(*ser_size, NBBITS_7k) <= 0)
+ {
+ ACELP_2t64_fx(dn, cn, h2, code, y2, indice);
+
+ Parm_serial(indice[0], 12, &prms);
+ } else if (sub(*ser_size, NBBITS_9k) <= 0)
+ {
+ ACELP_4t64_fx(dn, cn, h2, code, y2, 20, *ser_size, indice);
+
+ Parm_serial(indice[0], 5, &prms);
+ Parm_serial(indice[1], 5, &prms);
+ Parm_serial(indice[2], 5, &prms);
+ Parm_serial(indice[3], 5, &prms);
+ } else if (sub(*ser_size, NBBITS_12k) <= 0)
+ {
+ ACELP_4t64_fx(dn, cn, h2, code, y2, 36, *ser_size, indice);
+
+ Parm_serial(indice[0], 9, &prms);
+ Parm_serial(indice[1], 9, &prms);
+ Parm_serial(indice[2], 9, &prms);
+ Parm_serial(indice[3], 9, &prms);
+ } else if (sub(*ser_size, NBBITS_14k) <= 0)
+ {
+ ACELP_4t64_fx(dn, cn, h2, code, y2, 44, *ser_size, indice);
+
+ Parm_serial(indice[0], 13, &prms);
+ Parm_serial(indice[1], 13, &prms);
+ Parm_serial(indice[2], 9, &prms);
+ Parm_serial(indice[3], 9, &prms);
+ } else if (sub(*ser_size, NBBITS_16k) <= 0)
+ {
+ ACELP_4t64_fx(dn, cn, h2, code, y2, 52, *ser_size, indice);
+
+ Parm_serial(indice[0], 13, &prms);
+ Parm_serial(indice[1], 13, &prms);
+ Parm_serial(indice[2], 13, &prms);
+ Parm_serial(indice[3], 13, &prms);
+ } else if (sub(*ser_size, NBBITS_18k) <= 0)
+ {
+ ACELP_4t64_fx(dn, cn, h2, code, y2, 64, *ser_size, indice);
+
+ Parm_serial(indice[0], 2, &prms);
+ Parm_serial(indice[1], 2, &prms);
+ Parm_serial(indice[2], 2, &prms);
+ Parm_serial(indice[3], 2, &prms);
+ Parm_serial(indice[4], 14, &prms);
+ Parm_serial(indice[5], 14, &prms);
+ Parm_serial(indice[6], 14, &prms);
+ Parm_serial(indice[7], 14, &prms);
+ } else if (sub(*ser_size, NBBITS_20k) <= 0)
+ {
+ ACELP_4t64_fx(dn, cn, h2, code, y2, 72, *ser_size, indice);
+
+ Parm_serial(indice[0], 10, &prms);
+ Parm_serial(indice[1], 10, &prms);
+ Parm_serial(indice[2], 2, &prms);
+ Parm_serial(indice[3], 2, &prms);
+ Parm_serial(indice[4], 10, &prms);
+ Parm_serial(indice[5], 10, &prms);
+ Parm_serial(indice[6], 14, &prms);
+ Parm_serial(indice[7], 14, &prms);
+ } else
+ {
+ ACELP_4t64_fx(dn, cn, h2, code, y2, 88, *ser_size, indice);
+
+ Parm_serial(indice[0], 11, &prms);
+ Parm_serial(indice[1], 11, &prms);
+ Parm_serial(indice[2], 11, &prms);
+ Parm_serial(indice[3], 11, &prms);
+ Parm_serial(indice[4], 11, &prms);
+ Parm_serial(indice[5], 11, &prms);
+ Parm_serial(indice[6], 11, &prms);
+ Parm_serial(indice[7], 11, &prms);
+ }
+
+ /*-------------------------------------------------------*
+ * - Add the fixed-gain pitch contribution to code[]. *
+ *-------------------------------------------------------*/
+
+ tmp = 0; move16();
+ Preemph(code, st->tilt_code, L_SUBFR, &tmp);
+
+ Pit_shrp(code, T0, PIT_SHARP, L_SUBFR);
+
+ /*----------------------------------------------------------*
+ * - Compute the fixed codebook gain *
+ * - quantize fixed codebook gain *
+ *----------------------------------------------------------*/
+
+ test();
+ if (sub(*ser_size, NBBITS_9k) <= 0)
+ {
+ index = Q_gain2(xn, y1, add(Q_new, shift), y2, code, g_coeff, L_SUBFR, 6,
+ &gain_pit, &L_gain_code, clip_gain, st->qua_gain);
+ Parm_serial(index, 6, &prms);
+ } else
+ {
+ index = Q_gain2(xn, y1, add(Q_new, shift), y2, code, g_coeff, L_SUBFR, 7,
+ &gain_pit, &L_gain_code, clip_gain, st->qua_gain);
+ Parm_serial(index, 7, &prms);
+ }
+
+ /* test quantized gain of pitch for pitch clipping algorithm */
+ Gp_clip_test_gain_pit(gain_pit, st->gp_clip);
+
+ L_tmp = L_shl(L_gain_code, Q_new); /* saturation can occur here */
+ gain_code = round(L_tmp); /* scaled gain_code with Qnew */
+
+ /*----------------------------------------------------------*
+ * Update parameters for the next subframe. *
+ * - tilt of code: 0.0 (unvoiced) to 0.5 (voiced) *
+ *----------------------------------------------------------*/
+
+ /* find voice factor in Q15 (1=voiced, -1=unvoiced) */
+
+ Copy(&exc[i_subfr], exc2, L_SUBFR);
+ Scale_sig(exc2, L_SUBFR, shift);
+
+ voice_fac = voice_factor(exc2, shift, gain_pit, code, gain_code, L_SUBFR);
+
+ /* tilt of code for next subframe: 0.5=voiced, 0=unvoiced */
+
+ st->tilt_code = add(shr(voice_fac, 2), 8192); move16();
+
+ /*------------------------------------------------------*
+ * - Update filter's memory "mem_w0" for finding the *
+ * target vector in the next subframe. *
+ * - Find the total excitation *
+ * - Find synthesis speech to update mem_syn[]. *
+ *------------------------------------------------------*/
+
+ /* y2 in Q9, gain_pit in Q14 */
+ L_tmp = L_mult(gain_code, y2[L_SUBFR - 1]);
+ L_tmp = L_shl(L_tmp, add(5, shift));
+ L_tmp = L_negate(L_tmp);
+ L_tmp = L_mac(L_tmp, xn[L_SUBFR - 1], 16384);
+ L_tmp = L_msu(L_tmp, y1[L_SUBFR - 1], gain_pit);
+ L_tmp = L_shl(L_tmp, sub(1, shift));
+ st->mem_w0 = round(L_tmp); move16();
+
+ if (sub(*ser_size, NBBITS_24k) >= 0)
+ Copy(&exc[i_subfr], exc2, L_SUBFR);
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ /* code in Q9, gain_pit in Q14 */
+ L_tmp = L_mult(gain_code, code[i]);
+ L_tmp = L_shl(L_tmp, 5);
+ L_tmp = L_mac(L_tmp, exc[i + i_subfr], gain_pit);
+ L_tmp = L_shl(L_tmp, 1); /* saturation can occur here */
+ exc[i + i_subfr] = round(L_tmp); move16();
+ }
+
+ Syn_filt(p_Aq, M, &exc[i_subfr], synth, L_SUBFR, st->mem_syn, 1);
+
+ if (sub(*ser_size, NBBITS_24k) >= 0)
+ {
+ /*------------------------------------------------------------*
+ * phase dispersion to enhance noise in low bit rate *
+ *------------------------------------------------------------*/
+
+ /* L_gain_code in Q16 */
+ L_Extract(L_gain_code, &gain_code, &gain_code_lo);
+
+ /*------------------------------------------------------------*
+ * noise enhancer *
+ * ~~~~~~~~~~~~~~ *
+ * - Enhance excitation on noise. (modify gain of code) *
+ * If signal is noisy and LPC filter is stable, move gain *
+ * of code 1.5 dB toward gain of code threshold. *
+ * This decrease by 3 dB noise energy variation. *
+ *------------------------------------------------------------*/
+
+ tmp = sub(16384, shr(voice_fac, 1)); /* 1=unvoiced, 0=voiced */
+ fac = mult(stab_fac, tmp);
+
+ L_tmp = L_gain_code; move32();
+ test();
+ if (L_sub(L_tmp, st->L_gc_thres) < 0)
+ {
+ L_tmp = L_add(L_tmp, Mpy_32_16(gain_code, gain_code_lo, 6226));
+ test();
+ if (L_sub(L_tmp, st->L_gc_thres) > 0)
+ {
+ L_tmp = st->L_gc_thres;move32();
+ }
+ } else
+ {
+ L_tmp = Mpy_32_16(gain_code, gain_code_lo, 27536);
+ test();
+ if (L_sub(L_tmp, st->L_gc_thres) < 0)
+ {
+ L_tmp = st->L_gc_thres;move32();
+ }
+ }
+ st->L_gc_thres = L_tmp; move32();
+
+ L_gain_code = Mpy_32_16(gain_code, gain_code_lo, sub(32767, fac));
+ L_Extract(L_tmp, &gain_code, &gain_code_lo);
+ L_gain_code = L_add(L_gain_code, Mpy_32_16(gain_code, gain_code_lo, fac));
+
+ /*------------------------------------------------------------*
+ * pitch enhancer *
+ * ~~~~~~~~~~~~~~ *
+ * - Enhance excitation on voice. (HP filtering of code) *
+ * On voiced signal, filtering of code by a smooth fir HP *
+ * filter to decrease energy of code in low frequency. *
+ *------------------------------------------------------------*/
+
+ tmp = add(shr(voice_fac, 3), 4096); /* 0.25=voiced, 0=unvoiced */
+
+ L_tmp = L_deposit_h(code[0]);
+ L_tmp = L_msu(L_tmp, code[1], tmp);
+ code2[0] = round(L_tmp); move16();
+
+ for (i = 1; i < L_SUBFR - 1; i++)
+ {
+ L_tmp = L_deposit_h(code[i]);
+ L_tmp = L_msu(L_tmp, code[i + 1], tmp);
+ L_tmp = L_msu(L_tmp, code[i - 1], tmp);
+ code2[i] = round(L_tmp); move16();
+ }
+
+ L_tmp = L_deposit_h(code[L_SUBFR - 1]);
+ L_tmp = L_msu(L_tmp, code[L_SUBFR - 2], tmp);
+ code2[L_SUBFR - 1] = round(L_tmp); move16();
+
+ /* build excitation */
+
+ gain_code = round(L_shl(L_gain_code, Q_new));
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ L_tmp = L_mult(code2[i], gain_code);
+ L_tmp = L_shl(L_tmp, 5);
+ L_tmp = L_mac(L_tmp, exc2[i], gain_pit);
+ L_tmp = L_shl(L_tmp, 1); /* saturation can occur here */
+ exc2[i] = round(L_tmp); move16();
+ }
+
+ corr_gain = synthesis(p_Aq, exc2, Q_new, &speech16k[i_subfr * 5 / 4], st);
+ Parm_serial(corr_gain, 4, &prms);
+ }
+ p_A += (M + 1);
+ move16();
+ p_Aq += (M + 1);
+ move16();
+
+ } /* end of subframe loop */
+
+ /*--------------------------------------------------*
+ * Update signal for next frame. *
+ * -> save past of speech[], wsp[] and exc[]. *
+ *--------------------------------------------------*/
+
+ Copy(&old_speech[L_FRAME], st->old_speech, L_TOTAL - L_FRAME);
+ Copy(&old_wsp[L_FRAME / OPL_DECIM], st->old_wsp, PIT_MAX / OPL_DECIM);
+ Copy(&old_exc[L_FRAME], st->old_exc, PIT_MAX + L_INTERPOL);
+
+ return;
+}
+
+/*-----------------------------------------------------*
+ * Function synthesis() *
+ * *
+ * Synthesis of signal at 16kHz with HF extension. *
+ * *
+ *-----------------------------------------------------*/
+
+static Word16 synthesis(
+ Word16 Aq[], /* A(z) : quantized Az */
+ Word16 exc[], /* (i) : excitation at 12kHz */
+ Word16 Q_new, /* (i) : scaling performed on exc */
+ Word16 synth16k[], /* (o) : 16kHz synthesis signal */
+ Coder_State * st /* (i/o) : State structure */
+)
+{
+ Word16 i, fac, tmp, exp;
+ Word16 ener, exp_ener;
+ Word32 L_tmp;
+
+ Word16 synth_hi[M + L_SUBFR], synth_lo[M + L_SUBFR];
+ Word16 synth[L_SUBFR];
+ Word16 HF[L_SUBFR16k]; /* High Frequency vector */
+ Word16 Ap[M + 1];
+
+ Word16 HF_SP[L_SUBFR16k]; /* High Frequency vector (from original signal) */
+
+ Word16 HP_est_gain, HP_calc_gain, HP_corr_gain;
+ Word16 dist_min, dist;
+ Word16 HP_gain_ind = 0;
+ Word16 gain1, gain2;
+ Word16 weight1, weight2;
+
+ /*------------------------------------------------------------*
+ * speech synthesis *
+ * ~~~~~~~~~~~~~~~~ *
+ * - Find synthesis speech corresponding to exc2[]. *
+ * - Perform fixed deemphasis and hp 50hz filtering. *
+ * - Oversampling from 12.8kHz to 16kHz. *
+ *------------------------------------------------------------*/
+
+
+ Copy(st->mem_syn_hi, synth_hi, M);
+ Copy(st->mem_syn_lo, synth_lo, M);
+
+ Syn_filt_32(Aq, M, exc, Q_new, synth_hi + M, synth_lo + M, L_SUBFR);
+
+ Copy(synth_hi + L_SUBFR, st->mem_syn_hi, M);
+ Copy(synth_lo + L_SUBFR, st->mem_syn_lo, M);
+
+ Deemph_32(synth_hi + M, synth_lo + M, synth, PREEMPH_FAC, L_SUBFR, &(st->mem_deemph));
+
+ HP50_12k8(synth, L_SUBFR, st->mem_sig_out);
+
+ /* Original speech signal as reference for high band gain quantisation */
+ for (i = 0; i < L_SUBFR16k; i++)
+ {
+ HF_SP[i] = synth16k[i]; move16();
+ }
+
+ /*------------------------------------------------------*
+ * HF noise synthesis *
+ * ~~~~~~~~~~~~~~~~~~ *
+ * - Generate HF noise between 5.5 and 7.5 kHz. *
+ * - Set energy of noise according to synthesis tilt. *
+ * tilt > 0.8 ==> - 14 dB (voiced) *
+ * tilt 0.5 ==> - 6 dB (voiced or noise) *
+ * tilt < 0.0 ==> 0 dB (noise) *
+ *------------------------------------------------------*/
+
+ /* generate white noise vector */
+ for (i = 0; i < L_SUBFR16k; i++)
+ {
+ HF[i] = shr(Random(&(st->seed2)), 3); move16();
+ }
+
+ /* energy of excitation */
+
+ Scale_sig(exc, L_SUBFR, -3);
+ Q_new = sub(Q_new, 3);
+
+ ener = extract_h(Dot_product12(exc, exc, L_SUBFR, &exp_ener));
+ exp_ener = sub(exp_ener, add(Q_new, Q_new));
+
+ /* set energy of white noise to energy of excitation */
+
+ tmp = extract_h(Dot_product12(HF, HF, L_SUBFR16k, &exp));
+
+ test();
+ if (sub(tmp, ener) > 0)
+ {
+ tmp = shr(tmp, 1); /* Be sure tmp < ener */
+ exp = add(exp, 1);
+ }
+ L_tmp = L_deposit_h(div_s(tmp, ener)); /* result is normalized */
+ exp = sub(exp, exp_ener);
+ Isqrt_n(&L_tmp, &exp);
+ L_tmp = L_shl(L_tmp, add(exp, 1)); /* L_tmp x 2, L_tmp in Q31 */
+ tmp = extract_h(L_tmp); /* tmp = 2 x sqrt(ener_exc/ener_hf) */
+
+ for (i = 0; i < L_SUBFR16k; i++)
+ {
+ HF[i] = mult(HF[i], tmp); move16();
+ }
+
+ /* find tilt of synthesis speech (tilt: 1=voiced, -1=unvoiced) */
+
+ HP400_12k8(synth, L_SUBFR, st->mem_hp400);
+
+ L_tmp = 1L; move32();
+ for (i = 0; i < L_SUBFR; i++)
+ L_tmp = L_mac(L_tmp, synth[i], synth[i]);
+
+ exp = norm_l(L_tmp);
+ ener = extract_h(L_shl(L_tmp, exp)); /* ener = r[0] */
+
+ L_tmp = 1L; move32();
+ for (i = 1; i < L_SUBFR; i++)
+ L_tmp = L_mac(L_tmp, synth[i], synth[i - 1]);
+
+ tmp = extract_h(L_shl(L_tmp, exp)); /* tmp = r[1] */
+
+ test();
+ if (tmp > 0)
+ {
+ fac = div_s(tmp, ener);
+ } else
+ {
+ fac = 0; move16();
+ }
+
+
+ /* modify energy of white noise according to synthesis tilt */
+ gain1 = sub(32767, fac);
+ gain2 = mult(sub(32767, fac), 20480);
+ gain2 = shl(gain2, 1);
+
+ test();
+ if (st->vad_hist > 0)
+ {
+ weight1 = 0;
+ weight2 = 32767;
+ } else
+ {
+ weight1 = 32767;
+ weight2 = 0;
+ }
+ tmp = mult(weight1, gain1);
+ tmp = add(tmp, mult(weight2, gain2));
+
+ test();
+ if (tmp != 0)
+ {
+ tmp = add(tmp, 1);
+ }
+ HP_est_gain = tmp;
+
+ test();
+ if (sub(HP_est_gain, 3277) < 0)
+ {
+ HP_est_gain = 3277; /* 0.1 in Q15 */
+ move16();
+ }
+ /* synthesis of noise: 4.8kHz..5.6kHz --> 6kHz..7kHz */
+ Weight_a(Aq, Ap, 19661, M); /* fac=0.6 */
+ Syn_filt(Ap, M, HF, HF, L_SUBFR16k, st->mem_syn_hf, 1);
+
+ /* noise High Pass filtering (1ms of delay) */
+ Filt_6k_7k(HF, L_SUBFR16k, st->mem_hf);
+
+ /* filtering of the original signal */
+ Filt_6k_7k(HF_SP, L_SUBFR16k, st->mem_hf2);
+
+ /* check the gain difference */
+ Scale_sig(HF_SP, L_SUBFR16k, -1);
+
+ ener = extract_h(Dot_product12(HF_SP, HF_SP, L_SUBFR16k, &exp_ener));
+
+ /* set energy of white noise to energy of excitation */
+ tmp = extract_h(Dot_product12(HF, HF, L_SUBFR16k, &exp));
+
+ test();
+ if (sub(tmp, ener) > 0)
+ {
+ tmp = shr(tmp, 1); /* Be sure tmp < ener */
+ exp = add(exp, 1);
+ }
+ L_tmp = L_deposit_h(div_s(tmp, ener)); /* result is normalized */
+ exp = sub(exp, exp_ener);
+ Isqrt_n(&L_tmp, &exp);
+ L_tmp = L_shl(L_tmp, exp); /* L_tmp, L_tmp in Q31 */
+ HP_calc_gain = extract_h(L_tmp); /* tmp = sqrt(ener_input/ener_hf) */
+
+ /* st->gain_alpha *= st->dtx_encSt->dtxHangoverCount/7 */
+ L_tmp = L_shl(L_mult(st->dtx_encSt->dtxHangoverCount, 4681), 15);
+ st->gain_alpha = mult(st->gain_alpha, extract_h(L_tmp));
+
+ test();
+ if (sub(st->dtx_encSt->dtxHangoverCount, 6) > 0)
+ st->gain_alpha = 32767;
+ HP_est_gain = shr(HP_est_gain, 1); /* From Q15 to Q14 */
+ HP_corr_gain = add(mult(HP_calc_gain, st->gain_alpha), mult(sub(32767, st->gain_alpha), HP_est_gain));
+
+ /* Quantise the correction gain */
+ dist_min = 32767;
+ for (i = 0; i < 16; i++)
+ {
+ dist = mult(sub(HP_corr_gain, HP_gain[i]), sub(HP_corr_gain, HP_gain[i]));
+ test();
+ if (dist_min > dist)
+ {
+ dist_min = dist;
+ HP_gain_ind = i;
+ }
+ }
+
+ HP_corr_gain = HP_gain[HP_gain_ind];
+
+ /* return the quantised gain index when using the highest mode, otherwise zero */
+ return (HP_gain_ind);
+
+}
--- /dev/null
+++ b/amr-wb/cod_main.h
@@ -1,0 +1,63 @@
+/*--------------------------------------------------------------------------*
+ * COD_MAIN.H *
+ *--------------------------------------------------------------------------*
+ * Static memory in the encoder *
+ *--------------------------------------------------------------------------*/
+
+#include "cnst.h" /* coder constant parameters */
+
+#include "wb_vad.h"
+#include "dtx.h"
+
+typedef struct
+{
+ Word16 mem_decim[2 * L_FILT16k]; /* speech decimated filter memory */
+ Word16 mem_sig_in[6]; /* hp50 filter memory */
+ Word16 mem_preemph; /* speech preemph filter memory */
+ Word16 old_speech[L_TOTAL - L_FRAME]; /* old speech vector at 12.8kHz */
+ Word16 old_wsp[PIT_MAX / OPL_DECIM]; /* old decimated weighted speech vector */
+ Word16 old_exc[PIT_MAX + L_INTERPOL]; /* old excitation vector */
+ Word16 mem_levinson[M + 2]; /* levinson routine memory */
+ Word16 ispold[M]; /* old isp (immittance spectral pairs) */
+ Word16 ispold_q[M]; /* quantized old isp */
+ Word16 past_isfq[M]; /* past isf quantizer */
+ Word16 mem_wsp; /* wsp vector memory */
+ Word16 mem_decim2[3]; /* wsp decimation filter memory */
+ Word16 mem_w0; /* target vector memory */
+ Word16 mem_syn[M]; /* synthesis memory */
+ Word16 tilt_code; /* tilt of code */
+ Word16 old_wsp_max; /* old wsp maximum value */
+ Word16 old_wsp_shift; /* old wsp shift */
+ Word16 Q_old; /* old scaling factor */
+ Word16 Q_max[2]; /* old maximum scaling factor */
+ Word16 gp_clip[2]; /* gain of pitch clipping memory */
+ Word16 qua_gain[4]; /* gain quantizer memory */
+
+ Word16 old_T0_med;
+ Word16 ol_gain;
+ Word16 ada_w;
+ Word16 ol_wght_flg;
+ Word16 old_ol_lag[5];
+ Word16 hp_wsp_mem[9];
+ Word16 old_hp_wsp[L_FRAME / OPL_DECIM + (PIT_MAX / OPL_DECIM)];
+ VadVars *vadSt;
+ dtx_encState *dtx_encSt;
+ Word16 first_frame;
+
+ Word16 isfold[M]; /* old isf (frequency domain) */
+ Word32 L_gc_thres; /* threshold for noise enhancer */
+ Word16 mem_syn_hi[M]; /* modified synthesis memory (MSB) */
+ Word16 mem_syn_lo[M]; /* modified synthesis memory (LSB) */
+ Word16 mem_deemph; /* speech deemph filter memory */
+ Word16 mem_sig_out[6]; /* hp50 filter memory for synthesis */
+ Word16 mem_hp400[6]; /* hp400 filter memory for synthesis */
+ Word16 mem_oversamp[2 * L_FILT]; /* synthesis oversampled filter memory */
+ Word16 mem_syn_hf[M]; /* HF synthesis memory */
+ Word16 mem_hf[2 * L_FILT16k]; /* HF band-pass filter memory */
+ Word16 mem_hf2[2 * L_FILT16k]; /* HF band-pass filter memory */
+ Word16 seed2; /* random memory for HF generation */
+ Word16 vad_hist;
+
+ Word16 gain_alpha;
+
+} Coder_State;
--- /dev/null
+++ b/amr-wb/convolve.c
@@ -1,0 +1,33 @@
+/*------------------------------------------------------------------------*
+ * CONVOLVE.C *
+ *------------------------------------------------------------------------*
+ * Perform the convolution between two vectors x[] and h[] and *
+ * write the result in the vector y[]. *
+ * All vectors are of length L. *
+ *------------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+void Convolve(
+ Word16 x[], /* (i) : input vector */
+ Word16 h[], /* (i) Q15 : impulse response */
+ Word16 y[], /* (o) 12 bits: output vector */
+ Word16 L /* (i) : vector size */
+)
+{
+ Word16 i, n;
+ Word32 L_sum;
+
+ for (n = 0; n < L; n++)
+ {
+ L_sum = 0L; move32();
+ for (i = 0; i <= n; i++)
+ L_sum = L_mac(L_sum, x[i], h[n - i]);
+
+ y[n] = round(L_sum); move16();
+ }
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/cor_h_x.c
@@ -1,0 +1,66 @@
+/*-------------------------------------------------------------------*
+ * cor_h_x.C *
+ *-------------------------------------------------------------------*
+ * Compute correlation between target "x[]" and "h[]". *
+ * Designed for codebook search (24 pulses, 4 tracks, 4 pulses per *
+ * track, 16 positions in each track) to avoid saturation. *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "math_op.h"
+#include "count.h"
+
+#define L_SUBFR 64
+#define NB_TRACK 4
+#define STEP 4
+
+
+void cor_h_x(
+ Word16 h[], /* (i) Q12 : impulse response of weighted synthesis filter */
+ Word16 x[], /* (i) Q0 : target vector */
+ Word16 dn[] /* (o) <12bit : correlation between target and h[] */
+)
+{
+ Word16 i, j, k;
+ Word32 L_tmp, y32[L_SUBFR], L_max, L_tot;
+
+ /* first keep the result on 32 bits and find absolute maximum */
+
+ L_tot = 1L; move32();
+
+ for (k = 0; k < NB_TRACK; k++)
+ {
+ L_max = 0; move32();
+ for (i = k; i < L_SUBFR; i += STEP)
+ {
+ L_tmp = 1L; move32(); /* 1 -> to avoid null dn[] */
+ for (j = i; j < L_SUBFR; j++)
+ L_tmp = L_mac(L_tmp, x[j], h[j - i]);
+
+ y32[i] = L_tmp; move32();
+ L_tmp = L_abs(L_tmp);
+ test();
+ if (L_sub(L_tmp, L_max) > (Word32) 0)
+ {
+ L_max = L_tmp; move32();
+ }
+ }
+ /* tot += 3*max / 8 */
+ L_max = L_shr(L_max, 2);
+ L_tot = L_add(L_tot, L_max); /* +max/4 */
+ L_tot = L_add(L_tot, L_shr(L_max, 1)); /* +max/8 */
+ }
+
+ /* Find the number of right shifts to do on y32[] so that */
+ /* 6.0 x sumation of max of dn[] in each track not saturate. */
+
+ j = sub(norm_l(L_tot), 4); /* 4 -> 16 x tot */
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ dn[i] = round(L_shl(y32[i], j)); move16();
+ }
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/count.c
@@ -1,0 +1,295 @@
+/***********************************************************************
+ *
+ * This file contains functions for the automatic complexity calculation
+ * $Id: count.c,v 1.1 2007/02/15 23:22:35 robs Exp $
+ *************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "typedef.h"
+#include "count.h"
+
+/* Global counter variable for calculation of complexity weight */
+
+BASIC_OP multiCounter[MAXCOUNTERS];
+int currCounter=0; /* Zero equals global counter */
+
+/*BASIC_OP counter;*/
+const BASIC_OP op_weight =
+{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 4, 15, 18, 30, 1, 2, 1, 2, 2
+};
+
+/* function prototypes */
+Word32 TotalWeightedOperation (void);
+Word32 DeltaWeightedOperation (void);
+
+/* local variable */
+#if WMOPS
+
+/* Counters for separating counting for different objects */
+static int maxCounter=0;
+static char* objectName[MAXCOUNTERS+1];
+static Word16 fwc_corr[MAXCOUNTERS+1];
+
+#define NbFuncMax 1024
+
+static Word16 funcid[MAXCOUNTERS], nbframe[MAXCOUNTERS];
+static Word32 glob_wc[MAXCOUNTERS], wc[MAXCOUNTERS][NbFuncMax];
+static float total_wmops[MAXCOUNTERS];
+
+static Word32 LastWOper[MAXCOUNTERS];
+
+static char* my_strdup(const char *s)
+/*
+ * duplicates UNIX function strdup() which is not ANSI standard:
+ * -- malloc() memory area big enough to hold the string s
+ * -- copy string into new area
+ * -- return pointer to new area
+ *
+ * returns NULL if either s==NULL or malloc() fails
+ */
+{
+ char *dup;
+
+ if (s == NULL)
+ return NULL;
+
+ /* allocate memory for copy of ID string (including string terminator) */
+ /* NOTE: the ID strings will never be deallocated because there is no
+ way to "destroy" a counter that is not longer needed */
+ if ((dup = (char *) malloc(strlen(s)+1)) == NULL)
+ return NULL;
+
+ return strcpy(dup, s);
+}
+
+#endif
+
+int getCounterId(char *objectNameArg)
+{
+#if WMOPS
+ if(maxCounter>=MAXCOUNTERS-1) return 0;
+ objectName[++maxCounter]=my_strdup(objectNameArg);
+ return maxCounter;
+#else
+ return 0; /* Dummy */
+#endif
+}
+
+void setCounter(int counterId)
+{
+#if WMOPS
+ if(counterId>maxCounter || counterId<0)
+ {
+ currCounter=0;
+ return;
+ }
+ currCounter=counterId;
+#endif
+}
+
+#if WMOPS
+static Word32 WMOPS_frameStat()
+/* calculate the WMOPS seen so far and update the global
+ per-frame maximum (glob_wc)
+ */
+{
+ Word32 tot;
+
+ tot = TotalWeightedOperation ();
+ if (tot > glob_wc[currCounter])
+ glob_wc[currCounter] = tot;
+
+ /* check if fwc() was forgotten at end of last frame */
+ if (tot > LastWOper[currCounter]) {
+ if (!fwc_corr[currCounter]) {
+ fprintf(stderr,
+ "count: operations counted after last fwc() for '%s'; "
+ "-> fwc() called\n",
+ objectName[currCounter]?objectName[currCounter]:"");
+ }
+ fwc();
+ }
+
+ return tot;
+}
+
+static void WMOPS_clearMultiCounter()
+{
+ Word16 i;
+
+ Word32 *ptr = (Word32 *) &multiCounter[currCounter];
+ for (i = 0; i < (sizeof (multiCounter[currCounter])/ sizeof (Word32)); i++)
+ {
+ *ptr++ = 0;
+ }
+}
+#endif
+
+Word32 TotalWeightedOperation ()
+{
+#if WMOPS
+ Word16 i;
+ Word32 tot, *ptr, *ptr2;
+
+ tot = 0;
+ ptr = (Word32 *) &multiCounter[currCounter];
+ ptr2 = (Word32 *) &op_weight;
+ for (i = 0; i < (sizeof (multiCounter[currCounter])/ sizeof (Word32)); i++)
+ {
+ tot += ((*ptr++) * (*ptr2++));
+ }
+
+ return ((Word32) tot);
+#else
+ return 0; /* Dummy */
+#endif
+}
+
+Word32 DeltaWeightedOperation ()
+{
+#if WMOPS
+ Word32 NewWOper, delta;
+
+ NewWOper = TotalWeightedOperation ();
+ delta = NewWOper - LastWOper[currCounter];
+ LastWOper[currCounter] = NewWOper;
+ return (delta);
+#else
+ return 0; /* Dummy */
+#endif
+}
+
+void move16 (void)
+{
+#if WMOPS
+ multiCounter[currCounter].DataMove16++;
+#endif
+}
+
+void move32 (void)
+{
+#if WMOPS
+ multiCounter[currCounter].DataMove32++;
+#endif
+}
+
+void test (void)
+{
+#if WMOPS
+ multiCounter[currCounter].Test++;
+#endif
+}
+
+void logic16 (void)
+{
+#if WMOPS
+ multiCounter[currCounter].Logic16++;
+#endif
+}
+
+void logic32 (void)
+{
+#if WMOPS
+ multiCounter[currCounter].Logic32++;
+#endif
+}
+
+void Init_WMOPS_counter (void)
+{
+#if WMOPS
+ Word16 i;
+
+ /* reset function weight operation counter variable */
+
+ for (i = 0; i < NbFuncMax; i++)
+ wc[currCounter][i] = (Word32) 0;
+ glob_wc[currCounter] = 0;
+ nbframe[currCounter] = 0;
+ total_wmops[currCounter] = 0.0;
+
+ /* initially clear all counters */
+ WMOPS_clearMultiCounter();
+ LastWOper[currCounter] = 0;
+ funcid[currCounter] = 0;
+#endif
+}
+
+
+void Reset_WMOPS_counter (void)
+{
+#if WMOPS
+ Word32 tot = WMOPS_frameStat();
+
+ /* increase the frame counter --> a frame is counted WHEN IT BEGINS */
+ nbframe[currCounter]++;
+ /* add wmops used in last frame to count, then reset counter */
+ /* (in first frame, this is a no-op */
+ total_wmops[currCounter] += ((float) tot) * 0.00005f;
+
+ /* clear counter before new frame starts */
+ WMOPS_clearMultiCounter();
+ LastWOper[currCounter] = 0;
+ funcid[currCounter] = 0; /* new frame, set function id to zero */
+#endif
+}
+
+Word32 fwc (void) /* function worst case */
+{
+#if WMOPS
+ Word32 tot;
+
+ tot = DeltaWeightedOperation ();
+ if (tot > wc[currCounter][funcid[currCounter]])
+ wc[currCounter][funcid[currCounter]] = tot;
+
+ funcid[currCounter]++;
+
+ return (tot);
+#else
+ return 0; /* Dummy */
+#endif
+}
+
+void WMOPS_output (Word16 dtx_mode)
+{
+#if WMOPS
+ Word16 i;
+ Word32 tot, tot_wm, tot_wc;
+
+ /* get operations since last reset (or init),
+ but do not update the counters (except the glob_wc[] maximum)
+ so output CAN be called in each frame without problems.
+ The frame counter is NOT updated!
+ */
+ tot = WMOPS_frameStat();
+ tot_wm = (Word32)(total_wmops[currCounter] + ((float) tot) * 0.00005f);
+
+ fprintf (stdout, "%10s:WMOPS=%.3f",
+ objectName[currCounter]?objectName[currCounter]:"",
+ ((float) tot) * 0.00005);
+
+ if (nbframe[currCounter] != 0)
+ fprintf (stdout, " Average=%.3f",
+ tot_wm / (float) nbframe[currCounter]);
+
+ fprintf (stdout, " WorstCase=%.3f",
+ ((float) glob_wc[currCounter]) * 0.00005);
+
+ /* Worst worst case printed only when not in DTX mode */
+ if (dtx_mode == 0)
+ {
+ tot_wc = 0L;
+ for (i = 0; i < funcid[currCounter]; i++)
+ tot_wc += wc[currCounter][i];
+ fprintf (stdout, " WorstWC=%.3f", ((float) tot_wc) * 0.00005);
+ }
+ fprintf (stdout, " (%d frames)\n", nbframe[currCounter]);
+
+#endif
+}
+
--- /dev/null
+++ b/amr-wb/count.h
@@ -1,0 +1,175 @@
+/*
+ * functions for counting operations
+ *
+ * These functions, and the ones in basic_op.h, makes it possible to measure
+ * the wMOPS of a codec.
+ *
+ * All functions in this file, and in basic_op.h, uppdates a structure so that
+ * it will be possible the see how many calls to add, mul mulAdd ... that the
+ * code made, and estimate the wMOPS (and MIPS) for a sertain part of code
+ *
+ * It is also possible to measure the wMOPS separatly for different parts
+ * of the codec.
+ *
+ * This is done by creating a counter group (getCounterId) for each part of the
+ * code that one wants a separte measure for. Before a part of the code
+ * is executed a call to the "setCounter" function is needed to identify
+ * which counter group to use.
+ *
+ * Currently there is a limit of 255 different counter groups.
+ *
+ * In the end of this file there is a pice of code illustration how the
+ * functions can be used.
+ */
+#ifndef count_h
+#define count_h "$Id: count.h,v 1.1 2007/02/15 23:22:35 robs Exp $"
+
+#define MAXCOUNTERS 256
+
+int getCounterId(char *objectName);
+/*
+ * Create a counter group, the "objectname" will be used when printing
+ * statistics for this counter group.
+ *
+ * Returns 0 if no more counter groups are available.
+ */
+
+void setCounter(int counterId);
+/*
+ * Defines which counter group to use, default is zero.
+ */
+
+void Init_WMOPS_counter (void);
+/*
+ * Initiates the current counter group.
+ */
+
+void Reset_WMOPS_counter (void);
+/*
+ * Resets the current counter group.
+ */
+
+void WMOPS_output (Word16 notPrintWorstWorstCase);
+/*
+ * Prints the statistics to the screen, if the argument if non zero
+ * the statistics for worst worst case will not be printed. This is typically
+ * done for dtx frames.
+ *
+ */
+
+Word32 fwc (void);
+/*
+ * worst worst case counter.
+ *
+ * This function calculates the worst possible case that can be reached.
+ *
+ * This is done by calling this function for each subpart of the calculations
+ * for a frame. This function then stores the maximum wMOPS for each part.
+ *
+ * The WMOPS_output function add together all parts and presents the sum.
+ */
+
+void move16 (void);
+void move32 (void);
+void logic16 (void);
+void logic32 (void);
+void test (void);
+/*
+ * The functions above increases the corresponding operation counter for
+ * the current counter group.
+ */
+
+typedef struct
+{
+ Word32 add; /* Complexity Weight of 1 */
+ Word32 sub;
+ Word32 abs_s;
+ Word32 shl;
+ Word32 shr;
+ Word32 extract_h;
+ Word32 extract_l;
+ Word32 mult;
+ Word32 L_mult;
+ Word32 negate;
+ Word32 round;
+ Word32 L_mac;
+ Word32 L_msu;
+ Word32 L_macNs;
+ Word32 L_msuNs;
+ Word32 L_add; /* Complexity Weight of 2 */
+ Word32 L_sub;
+ Word32 L_add_c;
+ Word32 L_sub_c;
+ Word32 L_negate;
+ Word32 L_shl;
+ Word32 L_shr;
+ Word32 mult_r;
+ Word32 shr_r;
+ Word32 shift_r;
+ Word32 mac_r;
+ Word32 msu_r;
+ Word32 L_deposit_h;
+ Word32 L_deposit_l;
+ Word32 L_shr_r; /* Complexity Weight of 3 */
+ Word32 L_shift_r;
+ Word32 L_abs;
+ Word32 L_sat; /* Complexity Weight of 4 */
+ Word32 norm_s; /* Complexity Weight of 15 */
+ Word32 div_s; /* Complexity Weight of 18 */
+ Word32 norm_l; /* Complexity Weight of 30 */
+ Word32 DataMove16; /* Complexity Weight of 1 */
+ Word32 DataMove32; /* Complexity Weight of 2 */
+ Word32 Logic16; /* Complexity Weight of 1 */
+ Word32 Logic32; /* Complexity Weight of 2 */
+ Word32 Test; /* Complexity Weight of 2 */
+}
+BASIC_OP;
+
+/*
+ * Example of how count.h could be used.
+ *
+ * In the example below it is assumed that the init_OBJECT functions
+ * does not use any calls to counter.h or basic_op.h. If this is the case
+ * a call to the function Reset_WMOPS_counter() must be done after each call
+ * to init_OBJECT if these operations is not to be included in the statistics.
+
+int main(){
+ int spe1Id,spe2Id,cheId;
+
+ // initiate counters and objects
+ spe1Id=getCounterId("Spe 5k8");
+ setCounter(spe1Id);
+ Init_WMOPS_counter ();
+ init_spe1(...);
+
+ spe2Id=getCounterId("Spe 12k2");
+ setCounter(spe2Id);
+ Init_WMOPS_counter ();
+ init_spe2(...);
+
+ cheId=getCounterId("Channel encoder");
+ setCounter(cheId);
+ Init_WMOPS_counter ();
+ init_che(...);
+ ...
+ while(data){
+ test(); // Note this call to test();
+ if(useSpe1)
+ setCounter(spe1Id);
+ else
+ setCounter(spe2Id);
+ Reset_WMOPS_counter();
+ speEncode(...);
+ WMOPS_output(0); // Normal routine for displaying WMOPS info
+
+ setCounter(cheId);
+ Reset_WMOPS_counter();
+ preChannelInter(...); fwc(); // Note the call to fwc() for each part
+ convolve(...); fwc(); // of the channel encoder.
+ interleave(...); fwc();
+ WMOPS_output(0); // Normal routine for displaying WMOPS info
+}
+*/
+
+#endif
+
--- /dev/null
+++ b/amr-wb/d2t64fx.c
@@ -1,0 +1,53 @@
+/*-------------------------------------------------------------------*
+ * D2T64FX.C *
+ *-------------------------------------------------------------------*
+ * 12 bits algebraic codebook decoder. *
+ * 2 tracks x 32 positions per track = 64 samples. *
+ * *
+ * 12 bits --> 2 pulses in a frame of 64 samples. *
+ * *
+ * All pulses can have two (2) possible amplitudes: +1 or -1. *
+ * Each pulse can have 32 possible positions. *
+ * *
+ * See dec2t64.c for more details of the algebraic code. *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+#include "cnst.h"
+
+#define L_CODE 64 /* codevector length */
+#define NB_TRACK 2 /* number of track */
+#define NB_POS 32 /* number of position */
+
+
+void DEC_ACELP_2t64_fx(
+ Word16 index, /* (i) : 12 bits index */
+ Word16 code[] /* (o) :Q9 algebraic (fixed) codebook excitation */
+)
+{
+ Word16 i, i0, i1;
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ code[i] = 0; move16();
+ }
+
+ /* decode the positions and signs of pulses and build the codeword */
+
+ i0 = (Word16) (shr(index, 5) & 0x003E);logic16();
+ i1 = (Word16) (add(shl((Word16) (index & 0x001F), 1), 1)); logic16();
+ test();logic16();
+ if ((shr(index, 6) & NB_POS) == 0)
+ code[i0] = 512;
+ else
+ code[i0] = -512;
+
+ test();logic16();
+ if ((index & NB_POS) == 0)
+ code[i1] = 512;
+ else
+ code[i1] = -512;
+ return;
+}
--- /dev/null
+++ b/amr-wb/d4t64fx.c
@@ -1,0 +1,147 @@
+/*-------------------------------------------------------------------*
+ * D2T64FX.C *
+ *-------------------------------------------------------------------*
+ * 20, 36, 44, 52, 64, 72, 88 bits algebraic codebook decoder. *
+ * 4 tracks x 16 positions per track = 64 samples. *
+ * *
+ * 20 bits --> 4 pulses in a frame of 64 samples. *
+ * 36 bits --> 8 pulses in a frame of 64 samples. *
+ * 44 bits --> 10 pulses in a frame of 64 samples. *
+ * 52 bits --> 12 pulses in a frame of 64 samples. *
+ * 64 bits --> 16 pulses in a frame of 64 samples. *
+ * 72 bits --> 18 pulses in a frame of 64 samples. *
+ * 88 bits --> 24 pulses in a frame of 64 samples. *
+ * *
+ * All pulses can have two (2) possible amplitudes: +1 or -1. *
+ * Each pulse can have sixteen (16) possible positions. *
+ * *
+ * See c36_64fx.c for more details of the algebraic code. *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+#include "cnst.h"
+
+#include "q_pulse.h"
+
+#define L_CODE 64 /* codevector length */
+#define NB_TRACK 4 /* number of track */
+#define NB_POS 16 /* number of position */
+
+/* local function */
+
+static void add_pulses(Word16 pos[], Word16 nb_pulse, Word16 track, Word16 code[]);
+void DEC_ACELP_4t64_fx(
+ Word16 index[], /* (i) : index (20): 5+5+5+5 = 20 bits. */
+ /* (i) : index (36): 9+9+9+9 = 36 bits. */
+ /* (i) : index (44): 13+9+13+9 = 44 bits. */
+ /* (i) : index (52): 13+13+13+13 = 52 bits. */
+ /* (i) : index (64): 2+2+2+2+14+14+14+14 = 64 bits. */
+ /* (i) : index (72): 10+2+10+2+10+14+10+14 = 72 bits. */
+ /* (i) : index (88): 11+11+11+11+11+11+11+11 = 88 bits. */
+ Word16 nbbits, /* (i) : 20, 36, 44, 52, 64, 72 or 88 bits */
+ Word16 code[] /* (o) Q9: algebraic (fixed) codebook excitation */
+)
+{
+ Word16 i, k, pos[6];
+ Word32 L_index;
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ code[i] = 0; move16();
+ }
+
+ /* decode the positions and signs of pulses and build the codeword */
+ test();test();test();test();test();test();test();
+ if (sub(nbbits, 20) == 0)
+ {
+ for (k = 0; k < NB_TRACK; k++)
+ {
+ L_index = index[k]; move32();
+ dec_1p_N1(L_index, 4, 0, pos);
+ add_pulses(pos, 1, k, code);
+ }
+ } else if (sub(nbbits, 36) == 0)
+ {
+ for (k = 0; k < NB_TRACK; k++)
+ {
+ L_index = index[k]; move32();
+ dec_2p_2N1(L_index, 4, 0, pos);
+ add_pulses(pos, 2, k, code);
+ }
+ } else if (sub(nbbits, 44) == 0)
+ {
+ for (k = 0; k < NB_TRACK - 2; k++)
+ {
+ L_index = index[k]; move32();
+ dec_3p_3N1(L_index, 4, 0, pos);
+ add_pulses(pos, 3, k, code);
+ }
+ for (k = 2; k < NB_TRACK; k++)
+ {
+ L_index = index[k]; move32();
+ dec_2p_2N1(L_index, 4, 0, pos);
+ add_pulses(pos, 2, k, code);
+ }
+ } else if (sub(nbbits, 52) == 0)
+ {
+ for (k = 0; k < NB_TRACK; k++)
+ {
+ L_index = index[k]; move32();
+ dec_3p_3N1(L_index, 4, 0, pos);
+ add_pulses(pos, 3, k, code);
+ }
+ } else if (sub(nbbits, 64) == 0)
+ {
+ for (k = 0; k < NB_TRACK; k++)
+ {
+ L_index = L_add(L_shl(index[k], 14), index[k + NB_TRACK]);
+ dec_4p_4N(L_index, 4, 0, pos);
+ add_pulses(pos, 4, k, code);
+ }
+ } else if (sub(nbbits, 72) == 0)
+ {
+ for (k = 0; k < NB_TRACK - 2; k++)
+ {
+ L_index = L_add(L_shl(index[k], 10), index[k + NB_TRACK]);
+ dec_5p_5N(L_index, 4, 0, pos);
+ add_pulses(pos, 5, k, code);
+ }
+ for (k = 2; k < NB_TRACK; k++)
+ {
+ L_index = L_add(L_shl(index[k], 14), index[k + NB_TRACK]);
+ dec_4p_4N(L_index, 4, 0, pos);
+ add_pulses(pos, 4, k, code);
+ }
+ } else if (sub(nbbits, 88) == 0)
+ {
+ for (k = 0; k < NB_TRACK; k++)
+ {
+ L_index = L_add(L_shl(index[k], 11), index[k + NB_TRACK]);
+ dec_6p_6N_2(L_index, 4, 0, pos);
+ add_pulses(pos, 6, k, code);
+ }
+ }
+ return;
+}
+
+
+
+static void add_pulses(Word16 pos[], Word16 nb_pulse, Word16 track, Word16 code[])
+{
+ Word16 i, k;
+
+ for (k = 0; k < nb_pulse; k++)
+ {
+ /* i = ((pos[k] & (NB_POS-1))*NB_TRACK) + track; */
+ i = (Word16) (add(shl((Word16) (pos[k] & (NB_POS - 1)), 2), track)); logic16();
+ test();logic16();
+ if ((pos[k] & NB_POS) == 0)
+ code[i] = add(code[i], 512);
+ else
+ code[i] = sub(code[i], 512);
+ }
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/d_gain2.c
@@ -1,0 +1,290 @@
+/*-------------------------------------------------------------------*
+ * D_GAIN2.C *
+ *-------------------------------------------------------------------*
+ * Decode the pitch and codebook gains *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "math_op.h"
+#include "log2.h"
+#include "cnst.h"
+#include "acelp.h"
+#include "count.h"
+
+#include "q_gain2.tab"
+
+#define MEAN_ENER 30
+#define PRED_ORDER 4
+
+#define L_LTPHIST 5
+
+const Word16 pdown_unusable[7] = {32767, 31130, 29491, 24576, 7537, 1638, 328};
+const Word16 cdown_unusable[7] = {32767, 16384, 8192, 8192, 8192, 4915, 3277};
+
+const Word16 pdown_usable[7] = {32767, 32113, 31457, 24576, 7537, 1638, 328};
+const Word16 cdown_usable[7] = {32767, 32113, 32113, 32113, 32113, 32113, 22938};
+
+
+/* MA prediction coeff ={0.5, 0.4, 0.3, 0.2} in Q13 */
+static Word16 pred[PRED_ORDER] = {4096, 3277, 2458, 1638};
+
+void Init_D_gain2(
+ Word16 * mem /* output :static memory (4 words) */
+)
+{
+ Word16 i;
+
+ /* 4nd order quantizer energy predictor (init to -14.0 in Q10) */
+ mem[0] = -14336; move16(); /* past_qua_en[0] */
+ mem[1] = -14336; move16(); /* past_qua_en[1] */
+ mem[2] = -14336; move16(); /* past_qua_en[2] */
+ mem[3] = -14336; move16(); /* past_qua_en[3] */
+
+ mem[4] = 0; move16(); /* *past_gain_pit */
+ mem[5] = 0; move16(); /* *past_gain_code */
+ mem[6] = 0; move16(); /* *prev_gc */
+
+ for (i = 0; i < 5; i++)
+ {
+ mem[i + 7] = 0; move16(); /* pbuf[i] */
+ }
+ for (i = 0; i < 5; i++)
+ {
+ mem[i + 12] = 0; move16(); /* gbuf[i] */
+ }
+ for (i = 0; i < 5; i++)
+ {
+ mem[i + 17] = 0; move16(); /* pbuf2[i] */
+ }
+ mem[22] = 21845; /* seed */
+
+ return;
+}
+
+
+void D_gain2(
+ Word16 index, /* (i) : index of quantization. */
+ Word16 nbits, /* (i) : number of bits (6 or 7) */
+ Word16 code[], /* (i) Q9 : Innovative vector. */
+ Word16 L_subfr, /* (i) : Subframe lenght. */
+ Word16 * gain_pit, /* (o) Q14 : Pitch gain. */
+ Word32 * gain_cod, /* (o) Q16 : Code gain. */
+ Word16 bfi, /* (i) : bad frame indicator */
+ Word16 prev_bfi, /* (i) : Previous BF indicator */
+ Word16 state, /* (i) : State of BFH */
+ Word16 unusable_frame, /* (i) : UF indicator */
+ Word16 vad_hist, /* (i) : number of non-speech frames */
+ Word16 * mem /* (i/o) : static memory (4 words) */
+)
+{
+ Word16 *p, *past_gain_pit, *past_gain_code, *past_qua_en, *gbuf, *pbuf, *prev_gc;
+ Word16 *pbuf2, *seed;
+ Word16 i, tmp, exp, frac, gcode0, exp_gcode0, qua_ener, gcode_inov;
+ Word16 g_code;
+ Word32 L_tmp;
+
+ past_qua_en = mem; move16();
+ past_gain_pit = mem + 4; move16();
+ past_gain_code = mem + 5; move16();
+ prev_gc = mem + 6; move16();
+ pbuf = mem + 7; move16();
+ gbuf = mem + 12; move16();
+ pbuf2 = mem + 17; move16();
+ seed = mem + 22; move16();
+
+ /*-----------------------------------------------------------------*
+ * Find energy of code and compute: *
+ * *
+ * L_tmp = 1.0 / sqrt(energy of code/ L_subfr) *
+ *-----------------------------------------------------------------*/
+
+ L_tmp = Dot_product12(code, code, L_subfr, &exp);
+ exp = sub(exp, 18 + 6); /* exp: -18 (code in Q9), -6 (/L_subfr) */
+
+ Isqrt_n(&L_tmp, &exp);
+
+ gcode_inov = extract_h(L_shl(L_tmp, sub(exp, 3))); /* g_code_inov in Q12 */
+
+ /*-------------------------------*
+ * Case of erasure. *
+ *-------------------------------*/
+ test();
+ if (bfi != 0)
+ {
+ tmp = median5(&pbuf[2]);
+ *past_gain_pit = tmp; move16();
+ test();move16();
+ if (sub(*past_gain_pit, 15565) > 0)
+ {
+ *past_gain_pit = 15565; /* 0.95 in Q14 */
+ move16();
+ }
+ test();
+ if (unusable_frame != 0)
+ {
+ *gain_pit = mult(pdown_unusable[state], *past_gain_pit); move16();
+ } else
+ {
+ *gain_pit = mult(pdown_usable[state], *past_gain_pit); move16();
+ }
+ tmp = median5(&gbuf[2]);
+ test();
+ if (sub(vad_hist, 2) > 0)
+ {
+ *past_gain_code = tmp; move16();
+ } else
+ {
+ test();
+ if (unusable_frame != 0)
+ {
+ *past_gain_code = mult(cdown_unusable[state], tmp); move16();
+ } else
+ {
+ *past_gain_code = mult(cdown_usable[state], tmp); move16();
+ }
+ }
+
+ /* update table of past quantized energies */
+
+ L_tmp = L_mult(past_qua_en[0], 8192); /* x 0.25 */
+ L_tmp = L_mac(L_tmp, past_qua_en[1], 8192); /* x 0.25 */
+ L_tmp = L_mac(L_tmp, past_qua_en[2], 8192); /* x 0.25 */
+ L_tmp = L_mac(L_tmp, past_qua_en[3], 8192); /* x 0.25 */
+ qua_ener = extract_h(L_tmp);
+
+ qua_ener = sub(qua_ener, 3072); /* -3 in Q10 */
+ test();
+ if (sub(qua_ener, -14336) < 0)
+ qua_ener = -14336; move16(); /* -14 in Q10 */
+
+ past_qua_en[3] = past_qua_en[2]; move16();
+ past_qua_en[2] = past_qua_en[1]; move16();
+ past_qua_en[1] = past_qua_en[0]; move16();
+ past_qua_en[0] = qua_ener; move16();
+
+ for (i = 1; i < 5; i++)
+ {
+ gbuf[i - 1] = gbuf[i]; move16();
+ }
+ gbuf[4] = *past_gain_code; move16();
+
+ for (i = 1; i < 5; i++)
+ {
+ pbuf[i - 1] = pbuf[i]; move16();
+ }
+ pbuf[4] = *past_gain_pit; move16();
+
+ /* adjust gain according to energy of code */
+ /* past_gain_code(Q3) * gcode_inov(Q12) => Q16 */
+ *gain_cod = L_mult(*past_gain_code, gcode_inov); move32();
+
+ return;
+ }
+ /*-----------------------------------------------------------------*
+ * Compute gcode0. *
+ * = Sum(i=0,1) pred[i]*past_qua_en[i] + mean_ener - ener_code *
+ *-----------------------------------------------------------------*/
+
+ L_tmp = L_deposit_h(MEAN_ENER); /* MEAN_ENER in Q16 */
+ L_tmp = L_shl(L_tmp, 8); /* From Q16 to Q24 */
+ L_tmp = L_mac(L_tmp, pred[0], past_qua_en[0]); /* Q13*Q10 -> Q24 */
+ L_tmp = L_mac(L_tmp, pred[1], past_qua_en[1]); /* Q13*Q10 -> Q24 */
+ L_tmp = L_mac(L_tmp, pred[2], past_qua_en[2]); /* Q13*Q10 -> Q24 */
+ L_tmp = L_mac(L_tmp, pred[3], past_qua_en[3]); /* Q13*Q10 -> Q24 */
+
+ gcode0 = extract_h(L_tmp); /* From Q24 to Q8 */
+
+ /*-----------------------------------------------------------------*
+ * gcode0 = pow(10.0, gcode0/20) *
+ * = pow(2, 3.321928*gcode0/20) *
+ * = pow(2, 0.166096*gcode0) *
+ *-----------------------------------------------------------------*/
+
+ L_tmp = L_mult(gcode0, 5443); /* *0.166096 in Q15 -> Q24 */
+ L_tmp = L_shr(L_tmp, 8); /* From Q24 to Q16 */
+ L_Extract(L_tmp, &exp_gcode0, &frac); /* Extract exponant of gcode0 */
+
+ gcode0 = extract_l(Pow2(14, frac)); /* Put 14 as exponant so that */
+ /* output of Pow2() will be: */
+ /* 16384 < Pow2() <= 32767 */
+ exp_gcode0 = sub(exp_gcode0, 14);
+
+ /* Read the quantized gains */
+ test();
+ if (sub(nbits, 6) == 0)
+ {
+ p = &t_qua_gain6b[add(index, index)]; move16();
+ } else
+ {
+ p = &t_qua_gain7b[add(index, index)]; move16();
+ }
+ *gain_pit = *p++; move16(); /* selected pitch gain in Q14 */
+ g_code = *p++; move16(); /* selected code gain in Q11 */
+
+ L_tmp = L_mult(g_code, gcode0); /* Q11*Q0 -> Q12 */
+ L_tmp = L_shl(L_tmp, add(exp_gcode0, 4)); /* Q12 -> Q16 */
+
+ *gain_cod = L_tmp; move16(); /* gain of code in Q16 */
+ test();
+ if ((sub(prev_bfi, 1) == 0))
+ {
+ L_tmp = L_mult(*prev_gc, 5120); /* prev_gc(Q3) * 1.25(Q12) = Q16 */
+ /* if((*gain_cod > ((*prev_gc) * 1.25)) && (*gain_cod > 100.0)) */
+ test();test();
+ if ((L_sub(*gain_cod, L_tmp) > 0) && (L_sub(*gain_cod, 6553600) > 0))
+ {
+ *gain_cod = L_tmp; move32();
+ }
+ }
+ /* keep past gain code in Q3 for frame erasure (can saturate) */
+ *past_gain_code = round(L_shl(*gain_cod, 3)); move16();
+ *past_gain_pit = *gain_pit; move16();
+
+ *prev_gc = *past_gain_code; move16();
+ for (i = 1; i < 5; i++)
+ {
+ gbuf[i - 1] = gbuf[i]; move16();
+ }
+ gbuf[4] = *past_gain_code; move16();
+
+ for (i = 1; i < 5; i++)
+ {
+ pbuf[i - 1] = pbuf[i]; move16();
+ }
+ pbuf[4] = *past_gain_pit; move16();
+
+ for (i = 1; i < 5; i++)
+ {
+ pbuf2[i - 1] = pbuf2[i]; move16();
+ }
+ pbuf2[4] = *past_gain_pit; move16();
+
+ /* adjust gain according to energy of code */
+ L_Extract(*gain_cod, &exp, &frac);
+ L_tmp = Mpy_32_16(exp, frac, gcode_inov);
+ *gain_cod = L_shl(L_tmp, 3); move32(); /* gcode_inov in Q12 */
+
+ /*---------------------------------------------------*
+ * qua_ener = 20*log10(g_code) *
+ * = 6.0206*log2(g_code) *
+ * = 6.0206*(log2(g_codeQ11) - 11) *
+ *---------------------------------------------------*/
+
+ L_tmp = L_deposit_l(g_code);
+ Log2(L_tmp, &exp, &frac);
+ exp = sub(exp, 11);
+ L_tmp = Mpy_32_16(exp, frac, 24660); /* x 6.0206 in Q12 */
+
+ qua_ener = extract_l(L_shr(L_tmp, 3)); /* result in Q10 */
+
+ /* update table of past quantized energies */
+
+ past_qua_en[3] = past_qua_en[2]; move16();
+ past_qua_en[2] = past_qua_en[1]; move16();
+ past_qua_en[1] = past_qua_en[0]; move16();
+ past_qua_en[0] = qua_ener; move16();
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/dec_main.c
@@ -1,0 +1,1145 @@
+/*------------------------------------------------------------------------*
+ * DEC_MAIN.C *
+ *------------------------------------------------------------------------*
+ * Performs the main decoder routine *
+ *------------------------------------------------------------------------*/
+
+/*___________________________________________________________________________
+ | |
+ | Fixed-point C simulation of AMR WB ACELP coding algorithm with 20 ms |
+ | speech frames for wideband speech signals. |
+ |___________________________________________________________________________|
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "cnst.h"
+#include "acelp.h"
+#include "dec_main.h"
+#include "bits.h"
+#include "count.h"
+#include "math_op.h"
+#include "main.h"
+
+
+/* LPC interpolation coef {0.45, 0.8, 0.96, 1.0}; in Q15 */
+static Word16 interpol_frac[NB_SUBFR] = {14746, 26214, 31457, 32767};
+
+/* High Band encoding */
+static const Word16 HP_gain[16] =
+{
+ 3624, 4673, 5597, 6479, 7425, 8378, 9324, 10264,
+ 11210, 12206, 13391, 14844, 16770, 19655, 24289, 32728
+};
+
+/* isp tables for initialization */
+
+static Word16 isp_init[M] =
+{
+ 32138, 30274, 27246, 23170, 18205, 12540, 6393, 0,
+ -6393, -12540, -18205, -23170, -27246, -30274, -32138, 1475
+};
+
+static Word16 isf_init[M] =
+{
+ 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192,
+ 9216, 10240, 11264, 12288, 13312, 14336, 15360, 3840
+};
+
+static void synthesis(
+ Word16 Aq[], /* A(z) : quantized Az */
+ Word16 exc[], /* (i) : excitation at 12kHz */
+ Word16 Q_new, /* (i) : scaling performed on exc */
+ Word16 synth16k[], /* (o) : 16kHz synthesis signal */
+ Word16 prms, /* (i) : parameter */
+ Word16 HfIsf[],
+ Word16 nb_bits,
+ Word16 newDTXState,
+ Decoder_State * st, /* (i/o) : State structure */
+ Word16 bfi /* (i) : bad frame indicator */
+);
+
+/*-----------------------------------------------------------------*
+ * Funtion init_decoder *
+ * ~~~~~~~~~~~~ *
+ * ->Initialization of variables for the decoder section. *
+ *-----------------------------------------------------------------*/
+
+void Init_decoder(void **spd_state)
+{
+ /* Decoder states */
+ Decoder_State *st;
+
+ *spd_state = NULL;
+
+ /*-------------------------------------------------------------------------*
+ * Memory allocation for coder state. *
+ *-------------------------------------------------------------------------*/
+
+ test();
+ if ((st = (Decoder_State *) malloc(sizeof(Decoder_State))) == NULL)
+ {
+ printf("Can not malloc Decoder_State structure!\n");
+ return;
+ }
+ st->dtx_decSt = NULL;
+ dtx_dec_init(&st->dtx_decSt, isf_init);
+
+ Reset_decoder((void *) st, 1);
+
+ *spd_state = (void *) st;
+
+ return;
+}
+
+void Reset_decoder(void *st, Word16 reset_all)
+{
+ Word16 i;
+
+ Decoder_State *dec_state;
+
+ dec_state = (Decoder_State *) st;
+
+ Set_zero(dec_state->old_exc, PIT_MAX + L_INTERPOL);
+ Set_zero(dec_state->past_isfq, M);
+
+ dec_state->old_T0_frac = 0; move16(); /* old pitch value = 64.0 */
+ dec_state->old_T0 = 64; move16();
+ dec_state->first_frame = 1; move16();
+ dec_state->L_gc_thres = 0; move16();
+ dec_state->tilt_code = 0; move16();
+
+ Init_Phase_dispersion(dec_state->disp_mem);
+
+ /* scaling memories for excitation */
+ dec_state->Q_old = Q_MAX; move16();
+ dec_state->Qsubfr[3] = Q_MAX; move16();
+ dec_state->Qsubfr[2] = Q_MAX; move16();
+ dec_state->Qsubfr[1] = Q_MAX; move16();
+ dec_state->Qsubfr[0] = Q_MAX; move16();
+
+ if (reset_all != 0)
+ {
+ /* routines initialization */
+
+ Init_D_gain2(dec_state->dec_gain);
+ Init_Oversamp_16k(dec_state->mem_oversamp);
+ Init_HP50_12k8(dec_state->mem_sig_out);
+ Init_Filt_6k_7k(dec_state->mem_hf);
+ Init_Filt_7k(dec_state->mem_hf3);
+ Init_HP400_12k8(dec_state->mem_hp400);
+ Init_Lagconc(dec_state->lag_hist);
+
+ /* isp initialization */
+
+ Copy(isp_init, dec_state->ispold, M);
+ Copy(isf_init, dec_state->isfold, M);
+ for (i = 0; i < L_MEANBUF; i++)
+ Copy(isf_init, &dec_state->isf_buf[i * M], M);
+ /* variable initialization */
+
+ dec_state->mem_deemph = 0; move16();
+
+ dec_state->seed = 21845; move16(); /* init random with 21845 */
+ dec_state->seed2 = 21845; move16();
+ dec_state->seed3 = 21845; move16();
+
+ dec_state->state = 0; move16();
+ dec_state->prev_bfi = 0; move16();
+
+ /* Static vectors to zero */
+
+ Set_zero(dec_state->mem_syn_hf, M16k);
+ Set_zero(dec_state->mem_syn_hi, M);
+ Set_zero(dec_state->mem_syn_lo, M);
+
+ dtx_dec_reset(dec_state->dtx_decSt, isf_init);
+ dec_state->vad_hist = 0; move16();
+
+ }
+ return;
+}
+
+void Close_decoder(void *spd_state)
+{
+ dtx_dec_exit(&(((Decoder_State *) spd_state)->dtx_decSt));
+ free(spd_state);
+ return;
+}
+
+/*-----------------------------------------------------------------*
+ * Funtion decoder *
+ * ~~~~~~~ *
+ * ->Main decoder routine. *
+ * *
+ *-----------------------------------------------------------------*/
+
+void decoder(
+ Word16 mode, /* input : used mode */
+ Word16 prms[], /* input : parameter vector */
+ Word16 synth16k[], /* output: synthesis speech */
+ Word16 * frame_length, /* output: lenght of the frame */
+ void *spd_state, /* i/o : State structure */
+ Word16 frame_type /* input : received frame type */
+)
+{
+
+ /* Decoder states */
+ Decoder_State *st;
+
+ /* Excitation vector */
+ Word16 old_exc[(L_FRAME + 1) + PIT_MAX + L_INTERPOL];
+ Word16 *exc;
+
+ /* LPC coefficients */
+
+ Word16 *p_Aq; /* ptr to A(z) for the 4 subframes */
+ Word16 Aq[NB_SUBFR * (M + 1)]; /* A(z) quantized for the 4 subframes */
+ Word16 ispnew[M]; /* immittance spectral pairs at 4nd sfr */
+ Word16 isf[M]; /* ISF (frequency domain) at 4nd sfr */
+ Word16 code[L_SUBFR]; /* algebraic codevector */
+ Word16 code2[L_SUBFR]; /* algebraic codevector */
+ Word16 exc2[L_FRAME]; /* excitation vector */
+
+ Word16 fac, stab_fac, voice_fac, Q_new = 0;
+ Word32 L_tmp, L_gain_code;
+
+ /* Scalars */
+
+ Word16 i, j, i_subfr, index, ind[8], max, tmp;
+ Word16 T0, T0_frac, pit_flag, T0_max, select, T0_min = 0;
+ Word16 gain_pit, gain_code, gain_code_lo;
+ Word16 newDTXState, bfi, unusable_frame, nb_bits;
+ Word16 vad_flag;
+ Word16 pit_sharp;
+ Word16 excp[L_SUBFR];
+ Word16 isf_tmp[M];
+ Word16 HfIsf[M16k];
+
+ Word16 corr_gain = 0;
+
+ st = (Decoder_State *) spd_state;
+
+ /* mode verification */
+
+ nb_bits = nb_of_bits[mode]; move16();
+
+ *frame_length = L_FRAME16k; move16();
+
+ /* find the new DTX state SPEECH OR DTX */
+ newDTXState = rx_dtx_handler(st->dtx_decSt, frame_type);
+
+ test();
+ if (sub(newDTXState, SPEECH) != 0)
+ {
+ dtx_dec(st->dtx_decSt, exc2, newDTXState, isf, &prms);
+ }
+ /* SPEECH action state machine */
+ test();test();
+ if ((sub(frame_type, RX_SPEECH_BAD) == 0) ||
+ (sub(frame_type, RX_SPEECH_PROBABLY_DEGRADED) == 0))
+ {
+ /* bfi only for lsf, gains and pitch period */
+ bfi = 1; move16();
+ unusable_frame = 0; move16();
+ } else if ((sub(frame_type, RX_NO_DATA) == 0) ||
+ (sub(frame_type, RX_SPEECH_LOST) == 0))
+ {
+ /* bfi for all index, bits are not usable */
+ bfi = 1; move16();
+ unusable_frame = 1; move16();
+ } else
+ {
+ bfi = 0; move16();
+ unusable_frame = 0; move16();
+ }
+ test();
+ if (bfi != 0)
+ {
+ st->state = add(st->state, 1); move16();
+ test();
+ if (sub(st->state, 6) > 0)
+ {
+ st->state = 6; move16();
+ }
+ } else
+ {
+ st->state = shr(st->state, 1); move16();
+ }
+
+ /* If this frame is the first speech frame after CNI period, */
+ /* set the BFH state machine to an appropriate state depending */
+ /* on whether there was DTX muting before start of speech or not */
+ /* If there was DTX muting, the first speech frame is muted. */
+ /* If there was no DTX muting, the first speech frame is not */
+ /* muted. The BFH state machine starts from state 5, however, to */
+ /* keep the audible noise resulting from a SID frame which is */
+ /* erroneously interpreted as a good speech frame as small as */
+ /* possible (the decoder output in this case is quickly muted) */
+ test();test();
+ if (sub(st->dtx_decSt->dtxGlobalState, DTX) == 0)
+ {
+ st->state = 5; move16();
+ st->prev_bfi = 0; move16();
+ } else if (sub(st->dtx_decSt->dtxGlobalState, DTX_MUTE) == 0)
+ {
+ st->state = 5; move16();
+ st->prev_bfi = 1; move16();
+ }
+ test();
+ if (sub(newDTXState, SPEECH) == 0)
+ {
+ vad_flag = Serial_parm(1, &prms);
+ test();
+ if (bfi == 0)
+ {
+ test();
+ if (vad_flag == 0)
+ {
+ st->vad_hist = add(st->vad_hist, 1); move16();
+ } else
+ {
+ st->vad_hist = 0; move16();
+ }
+ }
+ }
+ /*----------------------------------------------------------------------*
+ * DTX-CNG *
+ *----------------------------------------------------------------------*/
+ test();
+ if (sub(newDTXState, SPEECH) != 0) /* CNG mode */
+ {
+ /* increase slightly energy of noise below 200 Hz */
+
+ /* Convert ISFs to the cosine domain */
+ Isf_isp(isf, ispnew, M);
+
+ Isp_Az(ispnew, Aq, M, 1);
+
+ Copy(st->isfold, isf_tmp, M);
+
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ j = shr(i_subfr, 6);
+ for (i = 0; i < M; i++)
+ {
+ L_tmp = L_mult(isf_tmp[i], sub(32767, interpol_frac[j]));
+ L_tmp = L_mac(L_tmp, isf[i], interpol_frac[j]);
+ HfIsf[i] = round(L_tmp); move16();
+ }
+ synthesis(Aq, &exc2[i_subfr], 0, &synth16k[i_subfr * 5 / 4], (short) 1, HfIsf, nb_bits, newDTXState, st, bfi);
+ }
+
+ /* reset speech coder memories */
+ Reset_decoder(st, 0);
+
+ Copy(isf, st->isfold, M);
+
+ st->prev_bfi = bfi; move16();
+ st->dtx_decSt->dtxGlobalState = newDTXState; move16();
+
+ return;
+ }
+ /*----------------------------------------------------------------------*
+ * ACELP *
+ *----------------------------------------------------------------------*/
+
+ /* copy coder memory state into working space (internal memory for DSP) */
+
+ Copy(st->old_exc, old_exc, PIT_MAX + L_INTERPOL);
+ exc = old_exc + PIT_MAX + L_INTERPOL; move16();
+
+ /* Decode the ISFs */
+ test();
+ if (sub(nb_bits, NBBITS_7k) <= 0)
+ {
+ ind[0] = Serial_parm(8, &prms); move16();
+ ind[1] = Serial_parm(8, &prms); move16();
+ ind[2] = Serial_parm(7, &prms); move16();
+ ind[3] = Serial_parm(7, &prms); move16();
+ ind[4] = Serial_parm(6, &prms); move16();
+
+ Dpisf_2s_36b(ind, isf, st->past_isfq, st->isfold, st->isf_buf, bfi, 1);
+ } else
+ {
+ ind[0] = Serial_parm(8, &prms); move16();
+ ind[1] = Serial_parm(8, &prms); move16();
+ ind[2] = Serial_parm(6, &prms); move16();
+ ind[3] = Serial_parm(7, &prms); move16();
+ ind[4] = Serial_parm(7, &prms); move16();
+ ind[5] = Serial_parm(5, &prms); move16();
+ ind[6] = Serial_parm(5, &prms); move16();
+
+ Dpisf_2s_46b(ind, isf, st->past_isfq, st->isfold, st->isf_buf, bfi, 1);
+ }
+
+ /* Convert ISFs to the cosine domain */
+
+ Isf_isp(isf, ispnew, M);
+ test();
+ if (st->first_frame != 0)
+ {
+ st->first_frame = 0; move16();
+ Copy(ispnew, st->ispold, M);
+ }
+ /* Find the interpolated ISPs and convert to a[] for all subframes */
+ Int_isp(st->ispold, ispnew, interpol_frac, Aq);
+
+ /* update ispold[] for the next frame */
+ Copy(ispnew, st->ispold, M);
+
+ /* Check stability on isf : distance between old isf and current isf */
+
+ L_tmp = 0; move32();
+ for (i = 0; i < M - 1; i++)
+ {
+ tmp = sub(isf[i], st->isfold[i]);
+ L_tmp = L_mac(L_tmp, tmp, tmp);
+ }
+ tmp = extract_h(L_shl(L_tmp, 8));
+ tmp = mult(tmp, 26214); /* tmp = L_tmp*0.8/256 */
+
+ tmp = sub(20480, tmp); /* 1.25 - tmp */
+ stab_fac = shl(tmp, 1); /* Q14 -> Q15 with saturation */
+ test();
+ if (stab_fac < 0)
+ {
+ stab_fac = 0; move16();
+ }
+ Copy(st->isfold, isf_tmp, M);
+ Copy(isf, st->isfold, M);
+
+ /*------------------------------------------------------------------------*
+ * Loop for every subframe in the analysis frame *
+ *------------------------------------------------------------------------*
+ * The subframe size is L_SUBFR and the loop is repeated L_FRAME/L_SUBFR *
+ * times *
+ * - decode the pitch delay and filter mode *
+ * - decode algebraic code *
+ * - decode pitch and codebook gains *
+ * - find voicing factor and tilt of code for next subframe. *
+ * - find the excitation and compute synthesis speech *
+ *------------------------------------------------------------------------*/
+
+ p_Aq = Aq; move16(); /* pointer to interpolated LPC parameters */
+
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ pit_flag = i_subfr; move16();
+
+ test();test();
+ if ((sub(i_subfr, 2 * L_SUBFR) == 0) && (sub(nb_bits, NBBITS_7k) > 0))
+ {
+ pit_flag = 0; move16();
+ }
+ /*-------------------------------------------------*
+ * - Decode pitch lag *
+ * Lag indeces received also in case of BFI, *
+ * so that the parameter pointer stays in sync. *
+ *-------------------------------------------------*/
+ test();
+ if (pit_flag == 0)
+ {
+ test();
+ if (sub(nb_bits, NBBITS_9k) <= 0)
+ {
+ index = Serial_parm(8, &prms);
+ test();
+ if (sub(index, (PIT_FR1_8b - PIT_MIN) * 2) < 0)
+ {
+ T0 = add(PIT_MIN, shr(index, 1));
+ T0_frac = sub(index, shl(sub(T0, PIT_MIN), 1));
+ T0_frac = shl(T0_frac, 1);
+ } else
+ {
+ T0 = add(index, PIT_FR1_8b - ((PIT_FR1_8b - PIT_MIN) * 2));
+ T0_frac = 0; move16();
+ }
+ } else
+ {
+ index = Serial_parm(9, &prms);
+ test();test();
+ if (sub(index, (PIT_FR2 - PIT_MIN) * 4) < 0)
+ {
+ T0 = add(PIT_MIN, shr(index, 2));
+ T0_frac = sub(index, shl(sub(T0, PIT_MIN), 2));
+ } else if (sub(index, (((PIT_FR2 - PIT_MIN) * 4) + ((PIT_FR1_9b - PIT_FR2) * 2))) < 0)
+ {
+ index = sub(index, (PIT_FR2 - PIT_MIN) * 4);
+ T0 = add(PIT_FR2, shr(index, 1));
+ T0_frac = sub(index, shl(sub(T0, PIT_FR2), 1));
+ T0_frac = shl(T0_frac, 1);
+ } else
+ {
+ T0 = add(index, (PIT_FR1_9b - ((PIT_FR2 - PIT_MIN) * 4) - ((PIT_FR1_9b - PIT_FR2) * 2)));
+ T0_frac = 0; move16();
+ }
+ }
+
+ /* find T0_min and T0_max for subframe 2 and 4 */
+
+ T0_min = sub(T0, 8);
+ test();
+ if (sub(T0_min, PIT_MIN) < 0)
+ {
+ T0_min = PIT_MIN; move16();
+ }
+ T0_max = add(T0_min, 15);
+ test();
+ if (sub(T0_max, PIT_MAX) > 0)
+ {
+ T0_max = PIT_MAX; move16();
+ T0_min = sub(T0_max, 15);
+ }
+ } else
+ { /* if subframe 2 or 4 */
+ test();
+ if (sub(nb_bits, NBBITS_9k) <= 0)
+ {
+ index = Serial_parm(5, &prms);
+
+ T0 = add(T0_min, shr(index, 1));
+ T0_frac = sub(index, shl(sub(T0, T0_min), 1));
+ T0_frac = shl(T0_frac, 1);
+ } else
+ {
+ index = Serial_parm(6, &prms);
+
+ T0 = add(T0_min, shr(index, 2));
+ T0_frac = sub(index, shl(sub(T0, T0_min), 2));
+ }
+ }
+
+ /* check BFI after pitch lag decoding */
+ test();
+ if (bfi != 0) /* if frame erasure */
+ {
+ lagconc(&(st->dec_gain[17]), st->lag_hist, &T0, &(st->old_T0), &(st->seed3), unusable_frame);
+ T0_frac = 0; move16();
+ }
+ /*-------------------------------------------------*
+ * - Find the pitch gain, the interpolation filter *
+ * and the adaptive codebook vector. *
+ *-------------------------------------------------*/
+
+ Pred_lt4(&exc[i_subfr], T0, T0_frac, L_SUBFR + 1);
+
+ test();
+ if (unusable_frame)
+ {
+ select = 1; move16();
+ } else
+ {
+ test();
+ if (sub(nb_bits, NBBITS_9k) <= 0)
+ {
+ select = 0; move16();
+ } else
+ {
+ select = Serial_parm(1, &prms);
+ }
+ }
+
+ test();
+ if (select == 0)
+ {
+ /* find pitch excitation with lp filter */
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ L_tmp = L_mult(5898, exc[i - 1 + i_subfr]);
+ L_tmp = L_mac(L_tmp, 20972, exc[i + i_subfr]);
+ L_tmp = L_mac(L_tmp, 5898, exc[i + 1 + i_subfr]);
+ code[i] = round(L_tmp); move16();
+ }
+ Copy(code, &exc[i_subfr], L_SUBFR);
+ }
+ /*-------------------------------------------------------*
+ * - Decode innovative codebook. *
+ * - Add the fixed-gain pitch contribution to code[]. *
+ *-------------------------------------------------------*/
+ test();test();test();test();test();test();test();test();
+ if (unusable_frame != 0)
+ {
+ /* the innovative code doesn't need to be scaled (see Q_gain2) */
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ code[i] = shr(Random(&(st->seed)), 3); move16();
+ }
+ } else if (sub(nb_bits, NBBITS_7k) <= 0)
+ {
+ ind[0] = Serial_parm(12, &prms); move16();
+ DEC_ACELP_2t64_fx(ind[0], code);
+ } else if (sub(nb_bits, NBBITS_9k) <= 0)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ ind[i] = Serial_parm(5, &prms); move16();
+ }
+ DEC_ACELP_4t64_fx(ind, 20, code);
+ } else if (sub(nb_bits, NBBITS_12k) <= 0)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ ind[i] = Serial_parm(9, &prms); move16();
+ }
+ DEC_ACELP_4t64_fx(ind, 36, code);
+ } else if (sub(nb_bits, NBBITS_14k) <= 0)
+ {
+ ind[0] = Serial_parm(13, &prms); move16();
+ ind[1] = Serial_parm(13, &prms); move16();
+ ind[2] = Serial_parm(9, &prms);move16();
+ ind[3] = Serial_parm(9, &prms);move16();
+ DEC_ACELP_4t64_fx(ind, 44, code);
+ } else if (sub(nb_bits, NBBITS_16k) <= 0)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ ind[i] = Serial_parm(13, &prms); move16();
+ }
+ DEC_ACELP_4t64_fx(ind, 52, code);
+ } else if (sub(nb_bits, NBBITS_18k) <= 0)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ ind[i] = Serial_parm(2, &prms); move16();
+ }
+ for (i = 4; i < 8; i++)
+ {
+ ind[i] = Serial_parm(14, &prms); move16();
+ }
+ DEC_ACELP_4t64_fx(ind, 64, code);
+ } else if (sub(nb_bits, NBBITS_20k) <= 0)
+ {
+ ind[0] = Serial_parm(10, &prms); move16();
+ ind[1] = Serial_parm(10, &prms); move16();
+ ind[2] = Serial_parm(2, &prms);move16();
+ ind[3] = Serial_parm(2, &prms);move16();
+ ind[4] = Serial_parm(10, &prms); move16();
+ ind[5] = Serial_parm(10, &prms); move16();
+ ind[6] = Serial_parm(14, &prms); move16();
+ ind[7] = Serial_parm(14, &prms); move16();
+ DEC_ACELP_4t64_fx(ind, 72, code);
+ } else
+ {
+ for (i = 0; i < 4; i++)
+ {
+ ind[i] = Serial_parm(11, &prms); move16();
+ }
+ for (i = 4; i < 8; i++)
+ {
+ ind[i] = Serial_parm(11, &prms); move16();
+ }
+ DEC_ACELP_4t64_fx(ind, 88, code);
+ }
+
+ tmp = 0; move16();
+ Preemph(code, st->tilt_code, L_SUBFR, &tmp);
+
+ tmp = T0; move16();
+ test();
+ if (sub(T0_frac, 2) > 0)
+ {
+ tmp = add(tmp, 1);
+ }
+ Pit_shrp(code, tmp, PIT_SHARP, L_SUBFR);
+
+ /*-------------------------------------------------*
+ * - Decode codebooks gains. *
+ *-------------------------------------------------*/
+ test();
+ if (sub(nb_bits, NBBITS_9k) <= 0)
+ {
+ index = Serial_parm(6, &prms); /* codebook gain index */
+
+ D_gain2(index, 6, code, L_SUBFR, &gain_pit, &L_gain_code, bfi, st->prev_bfi, st->state, unusable_frame, st->vad_hist, st->dec_gain);
+ } else
+ {
+ index = Serial_parm(7, &prms); /* codebook gain index */
+
+ D_gain2(index, 7, code, L_SUBFR, &gain_pit, &L_gain_code, bfi, st->prev_bfi, st->state, unusable_frame, st->vad_hist, st->dec_gain);
+ }
+
+ /* find best scaling to perform on excitation (Q_new) */
+
+ tmp = st->Qsubfr[0];
+ for (i = 1; i < 4; i++)
+ {
+ test();move16();
+ if (sub(st->Qsubfr[i], tmp) < 0)
+ {
+ tmp = st->Qsubfr[i]; move16();
+ }
+ }
+
+ /* limit scaling (Q_new) to Q_MAX: see cnst.h and syn_filt_32() */
+ test();
+ if (sub(tmp, Q_MAX) > 0)
+ {
+ tmp = Q_MAX; move16();
+ }
+ Q_new = 0; move16();
+ L_tmp = L_gain_code; move32(); /* L_gain_code in Q16 */
+
+ test();test();
+ while ((L_sub(L_tmp, 0x08000000L) < 0) && (sub(Q_new, tmp) < 0))
+ {
+ L_tmp = L_shl(L_tmp, 1);
+ Q_new = add(Q_new, 1);
+ test();test();
+ }
+ gain_code = round(L_tmp); /* scaled gain_code with Qnew */
+
+ Scale_sig(exc + i_subfr - (PIT_MAX + L_INTERPOL),
+ PIT_MAX + L_INTERPOL + L_SUBFR, sub(Q_new, st->Q_old));
+ st->Q_old = Q_new; move16();
+
+
+ /*----------------------------------------------------------*
+ * Update parameters for the next subframe. *
+ * - tilt of code: 0.0 (unvoiced) to 0.5 (voiced) *
+ *----------------------------------------------------------*/
+
+ test();
+ if (bfi == 0)
+ {
+ /* LTP-Lag history update */
+ for (i = 4; i > 0; i--)
+ {
+ st->lag_hist[i] = st->lag_hist[i - 1]; move16();
+ }
+ st->lag_hist[0] = T0; move16();
+
+ st->old_T0 = T0; move16();
+ st->old_T0_frac = 0; move16(); /* Remove fraction in case of BFI */
+ }
+ /* find voice factor in Q15 (1=voiced, -1=unvoiced) */
+
+ Copy(&exc[i_subfr], exc2, L_SUBFR);
+ Scale_sig(exc2, L_SUBFR, -3);
+
+ /* post processing of excitation elements */
+ test();
+ if (sub(nb_bits, NBBITS_9k) <= 0)
+ {
+ pit_sharp = shl(gain_pit, 1);
+ test();
+ if (sub(pit_sharp, 16384) > 0)
+ {
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ tmp = mult(exc2[i], pit_sharp);
+ L_tmp = L_mult(tmp, gain_pit);
+ L_tmp = L_shr(L_tmp, 1);
+ excp[i] = round(L_tmp);
+ move16();
+ }
+ }
+ } else
+ {
+ pit_sharp = 0; move16();
+ }
+
+ voice_fac = voice_factor(exc2, -3, gain_pit, code, gain_code, L_SUBFR);
+
+ /* tilt of code for next subframe: 0.5=voiced, 0=unvoiced */
+
+ st->tilt_code = add(shr(voice_fac, 2), 8192); move16();
+
+ /*-------------------------------------------------------*
+ * - Find the total excitation. *
+ * - Find synthesis speech corresponding to exc[]. *
+ *-------------------------------------------------------*/
+
+ Copy(&exc[i_subfr], exc2, L_SUBFR);
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ L_tmp = L_mult(code[i], gain_code);
+ L_tmp = L_shl(L_tmp, 5);
+ L_tmp = L_mac(L_tmp, exc[i + i_subfr], gain_pit);
+ L_tmp = L_shl(L_tmp, 1);
+ exc[i + i_subfr] = round(L_tmp); move16();
+ }
+
+ /* find maximum value of excitation for next scaling */
+
+ max = 1; move16();
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ tmp = abs_s(exc[i + i_subfr]);
+ test();
+ if (sub(tmp, max) > 0)
+ {
+ max = tmp; move16();
+ }
+ }
+
+ /* tmp = scaling possible according to max value of excitation */
+ tmp = sub(add(norm_s(max), Q_new), 1);
+
+ st->Qsubfr[3] = st->Qsubfr[2]; move16();
+ st->Qsubfr[2] = st->Qsubfr[1]; move16();
+ st->Qsubfr[1] = st->Qsubfr[0]; move16();
+ st->Qsubfr[0] = tmp; move16();
+
+ /*------------------------------------------------------------*
+ * phase dispersion to enhance noise in low bit rate *
+ *------------------------------------------------------------*/
+
+ /* L_gain_code in Q16 */
+ L_Extract(L_gain_code, &gain_code, &gain_code_lo);
+ test();test();move16();
+ if (sub(nb_bits, NBBITS_7k) <= 0)
+ j = 0; /* high dispersion for rate <= 7.5 kbit/s */
+ else if (sub(nb_bits, NBBITS_9k) <= 0)
+ j = 1; /* low dispersion for rate <= 9.6 kbit/s */
+ else
+ j = 2; /* no dispersion for rate > 9.6 kbit/s */
+
+ Phase_dispersion(gain_code, gain_pit, code, j, st->disp_mem);
+
+ /*------------------------------------------------------------*
+ * noise enhancer *
+ * ~~~~~~~~~~~~~~ *
+ * - Enhance excitation on noise. (modify gain of code) *
+ * If signal is noisy and LPC filter is stable, move gain *
+ * of code 1.5 dB toward gain of code threshold. *
+ * This decrease by 3 dB noise energy variation. *
+ *------------------------------------------------------------*/
+
+ tmp = sub(16384, shr(voice_fac, 1)); /* 1=unvoiced, 0=voiced */
+ fac = mult(stab_fac, tmp);
+
+ L_tmp = L_gain_code; move32();
+ test();
+ if (L_sub(L_tmp, st->L_gc_thres) < 0)
+ {
+ L_tmp = L_add(L_tmp, Mpy_32_16(gain_code, gain_code_lo, 6226));
+ test();
+ if (L_sub(L_tmp, st->L_gc_thres) > 0)
+ {
+ L_tmp = st->L_gc_thres; move32();
+ }
+ } else
+ {
+ L_tmp = Mpy_32_16(gain_code, gain_code_lo, 27536);
+ test();
+ if (L_sub(L_tmp, st->L_gc_thres) < 0)
+ {
+ L_tmp = st->L_gc_thres; move32();
+ }
+ }
+ st->L_gc_thres = L_tmp; move32();
+
+ L_gain_code = Mpy_32_16(gain_code, gain_code_lo, sub(32767, fac));
+ L_Extract(L_tmp, &gain_code, &gain_code_lo);
+ L_gain_code = L_add(L_gain_code, Mpy_32_16(gain_code, gain_code_lo, fac));
+
+ /*------------------------------------------------------------*
+ * pitch enhancer *
+ * ~~~~~~~~~~~~~~ *
+ * - Enhance excitation on voice. (HP filtering of code) *
+ * On voiced signal, filtering of code by a smooth fir HP *
+ * filter to decrease energy of code in low frequency. *
+ *------------------------------------------------------------*/
+
+ tmp = add(shr(voice_fac, 3), 4096);/* 0.25=voiced, 0=unvoiced */
+
+ L_tmp = L_deposit_h(code[0]);
+ L_tmp = L_msu(L_tmp, code[1], tmp);
+ code2[0] = round(L_tmp);
+ move16();
+
+ for (i = 1; i < L_SUBFR - 1; i++)
+ {
+ L_tmp = L_deposit_h(code[i]);
+ L_tmp = L_msu(L_tmp, code[i + 1], tmp);
+ L_tmp = L_msu(L_tmp, code[i - 1], tmp);
+ code2[i] = round(L_tmp);
+ move16();
+ }
+
+ L_tmp = L_deposit_h(code[L_SUBFR - 1]);
+ L_tmp = L_msu(L_tmp, code[L_SUBFR - 2], tmp);
+ code2[L_SUBFR - 1] = round(L_tmp);
+ move16();
+
+ /* build excitation */
+
+ gain_code = round(L_shl(L_gain_code, Q_new));
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ L_tmp = L_mult(code2[i], gain_code);
+ L_tmp = L_shl(L_tmp, 5);
+ L_tmp = L_mac(L_tmp, exc2[i], gain_pit);
+ L_tmp = L_shl(L_tmp, 1); /* saturation can occur here */
+ exc2[i] = round(L_tmp);
+ move16();
+ }
+
+ if (sub(nb_bits, NBBITS_9k) <= 0)
+ {
+ if (sub(pit_sharp, 16384) > 0)
+ {
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ excp[i] = add(excp[i], exc2[i]);
+ move16();
+ }
+ agc2(exc2, excp, L_SUBFR);
+ Copy(excp, exc2, L_SUBFR);
+ }
+ }
+ if (sub(nb_bits, NBBITS_7k) <= 0)
+ {
+ j = shr(i_subfr, 6);
+ for (i = 0; i < M; i++)
+ {
+ L_tmp = L_mult(isf_tmp[i], sub(32767, interpol_frac[j]));
+ L_tmp = L_mac(L_tmp, isf[i], interpol_frac[j]);
+ HfIsf[i] = round(L_tmp);
+ }
+ } else
+ {
+ Set_zero(st->mem_syn_hf, M16k - M);
+ }
+
+ if (sub(nb_bits, NBBITS_24k) >= 0)
+ {
+ corr_gain = Serial_parm(4, &prms);
+ synthesis(p_Aq, exc2, Q_new, &synth16k[i_subfr * 5 / 4], corr_gain, HfIsf, nb_bits, newDTXState, st, bfi);
+ } else
+ synthesis(p_Aq, exc2, Q_new, &synth16k[i_subfr * 5 / 4], 0, HfIsf, nb_bits, newDTXState, st, bfi);
+
+ p_Aq += (M + 1); /* interpolated LPC parameters for next subframe */
+ }
+
+ /*--------------------------------------------------*
+ * Update signal for next frame. *
+ * -> save past of exc[]. *
+ * -> save pitch parameters. *
+ *--------------------------------------------------*/
+
+ Copy(&old_exc[L_FRAME], st->old_exc, PIT_MAX + L_INTERPOL);
+
+ Scale_sig(exc, L_FRAME, sub(0, Q_new));
+ dtx_dec_activity_update(st->dtx_decSt, isf, exc);
+
+ st->dtx_decSt->dtxGlobalState = newDTXState; move16();
+
+ st->prev_bfi = bfi; move16();
+
+ return;
+}
+
+
+
+/*-----------------------------------------------------*
+ * Function synthesis() *
+ * *
+ * Synthesis of signal at 16kHz with HF extension. *
+ * *
+ *-----------------------------------------------------*/
+
+static void synthesis(
+ Word16 Aq[], /* A(z) : quantized Az */
+ Word16 exc[], /* (i) : excitation at 12kHz */
+ Word16 Q_new, /* (i) : scaling performed on exc */
+ Word16 synth16k[], /* (o) : 16kHz synthesis signal */
+ Word16 prms, /* (i) : parameter */
+ Word16 HfIsf[],
+ Word16 nb_bits,
+ Word16 newDTXState,
+ Decoder_State * st, /* (i/o) : State structure */
+ Word16 bfi /* (i) : bad frame indicator */
+)
+{
+ Word16 i, fac, tmp, exp;
+ Word16 ener, exp_ener;
+ Word32 L_tmp;
+
+ Word16 synth_hi[M + L_SUBFR], synth_lo[M + L_SUBFR];
+ Word16 synth[L_SUBFR];
+ Word16 HF[L_SUBFR16k]; /* High Frequency vector */
+ Word16 Ap[M16k + 1];
+ Word16 HfA[M16k + 1];
+ Word16 HF_corr_gain;
+ Word16 HF_gain_ind;
+ Word16 gain1, gain2;
+ Word16 weight1, weight2;
+
+ /*------------------------------------------------------------*
+ * speech synthesis *
+ * ~~~~~~~~~~~~~~~~ *
+ * - Find synthesis speech corresponding to exc2[]. *
+ * - Perform fixed deemphasis and hp 50hz filtering. *
+ * - Oversampling from 12.8kHz to 16kHz. *
+ *------------------------------------------------------------*/
+
+ Copy(st->mem_syn_hi, synth_hi, M);
+ Copy(st->mem_syn_lo, synth_lo, M);
+
+ Syn_filt_32(Aq, M, exc, Q_new, synth_hi + M, synth_lo + M, L_SUBFR);
+
+ Copy(synth_hi + L_SUBFR, st->mem_syn_hi, M);
+ Copy(synth_lo + L_SUBFR, st->mem_syn_lo, M);
+
+ Deemph_32(synth_hi + M, synth_lo + M, synth, PREEMPH_FAC, L_SUBFR, &(st->mem_deemph));
+
+ HP50_12k8(synth, L_SUBFR, st->mem_sig_out);
+
+ Oversamp_16k(synth, L_SUBFR, synth16k, st->mem_oversamp);
+
+ /*------------------------------------------------------*
+ * HF noise synthesis *
+ * ~~~~~~~~~~~~~~~~~~ *
+ * - Generate HF noise between 5.5 and 7.5 kHz. *
+ * - Set energy of noise according to synthesis tilt. *
+ * tilt > 0.8 ==> - 14 dB (voiced) *
+ * tilt 0.5 ==> - 6 dB (voiced or noise) *
+ * tilt < 0.0 ==> 0 dB (noise) *
+ *------------------------------------------------------*/
+
+ /* generate white noise vector */
+ for (i = 0; i < L_SUBFR16k; i++)
+ {
+ HF[i] = shr(Random(&(st->seed2)), 3); move16();
+ }
+ /* energy of excitation */
+
+ Scale_sig(exc, L_SUBFR, -3);
+ Q_new = sub(Q_new, 3);
+
+ ener = extract_h(Dot_product12(exc, exc, L_SUBFR, &exp_ener));
+ exp_ener = sub(exp_ener, add(Q_new, Q_new));
+
+ /* set energy of white noise to energy of excitation */
+
+ tmp = extract_h(Dot_product12(HF, HF, L_SUBFR16k, &exp));
+ test();
+ if (sub(tmp, ener) > 0)
+ {
+ tmp = shr(tmp, 1); /* Be sure tmp < ener */
+ exp = add(exp, 1);
+ }
+ L_tmp = L_deposit_h(div_s(tmp, ener)); /* result is normalized */
+ exp = sub(exp, exp_ener);
+ Isqrt_n(&L_tmp, &exp);
+ L_tmp = L_shl(L_tmp, add(exp, 1)); /* L_tmp x 2, L_tmp in Q31 */
+ tmp = extract_h(L_tmp); /* tmp = 2 x sqrt(ener_exc/ener_hf) */
+ for (i = 0; i < L_SUBFR16k; i++)
+ {
+ HF[i] = mult(HF[i], tmp); move16();
+ }
+ /* find tilt of synthesis speech (tilt: 1=voiced, -1=unvoiced) */
+
+ HP400_12k8(synth, L_SUBFR, st->mem_hp400);
+
+ L_tmp = 1L; move32();
+ for (i = 0; i < L_SUBFR; i++)
+ L_tmp = L_mac(L_tmp, synth[i], synth[i]);
+
+ exp = norm_l(L_tmp);
+ ener = extract_h(L_shl(L_tmp, exp)); /* ener = r[0] */
+
+ L_tmp = 1L; move32();
+ for (i = 1; i < L_SUBFR; i++)
+ L_tmp = L_mac(L_tmp, synth[i], synth[i - 1]);
+
+ tmp = extract_h(L_shl(L_tmp, exp)); /* tmp = r[1] */
+ test();
+ if (tmp > 0)
+ {
+ fac = div_s(tmp, ener);
+ } else
+ {
+ fac = 0; move16();
+ }
+
+ /* modify energy of white noise according to synthesis tilt */
+ gain1 = sub(32767, fac);
+ gain2 = mult(sub(32767, fac), 20480);
+ gain2 = shl(gain2, 1);
+
+ test();
+ if (st->vad_hist > 0)
+ {
+ weight1 = 0; move16();
+ weight2 = 32767; move16();
+ } else
+ {
+ weight1 = 32767; move16();
+ weight2 = 0; move16();
+ }
+ tmp = mult(weight1, gain1);
+ tmp = add(tmp, mult(weight2, gain2));
+
+ test();
+ if (tmp != 0)
+ {
+ tmp = add(tmp, 1);
+ }
+ test();
+ if (sub(tmp, 3277) < 0)
+ {
+ tmp = 3277; /* 0.1 in Q15 */
+ move16();
+ }
+ test(); test();
+ if ((sub(nb_bits, NBBITS_24k) >= 0 ) && (bfi == 0))
+ {
+ /* HF correction gain */
+ HF_gain_ind = prms;
+ HF_corr_gain = HP_gain[HF_gain_ind];
+
+ /* HF gain */
+ for (i = 0; i < L_SUBFR16k; i++)
+ {
+ HF[i] = shl(mult(HF[i], HF_corr_gain), 1); move16();
+ }
+ } else
+ {
+ for (i = 0; i < L_SUBFR16k; i++)
+ {
+ HF[i] = mult(HF[i], tmp); move16();
+ }
+ }
+
+ test();test();
+ if ((sub(nb_bits, NBBITS_7k) <= 0) && (sub(newDTXState, SPEECH) == 0))
+ {
+ Isf_Extrapolation(HfIsf);
+ Isp_Az(HfIsf, HfA, M16k, 0);
+
+ Weight_a(HfA, Ap, 29491, M16k); /* fac=0.9 */
+ Syn_filt(Ap, M16k, HF, HF, L_SUBFR16k, st->mem_syn_hf, 1);
+ } else
+ {
+ /* synthesis of noise: 4.8kHz..5.6kHz --> 6kHz..7kHz */
+ Weight_a(Aq, Ap, 19661, M); /* fac=0.6 */
+ Syn_filt(Ap, M, HF, HF, L_SUBFR16k, st->mem_syn_hf + (M16k - M), 1);
+ }
+
+ /* noise High Pass filtering (1ms of delay) */
+ Filt_6k_7k(HF, L_SUBFR16k, st->mem_hf);
+
+ test();
+ if (sub(nb_bits, NBBITS_24k) >= 0)
+ {
+ /* Low Pass filtering (7 kHz) */
+ Filt_7k(HF, L_SUBFR16k, st->mem_hf3);
+ }
+ /* add filtered HF noise to speech synthesis */
+ for (i = 0; i < L_SUBFR16k; i++)
+ {
+ synth16k[i] = add(synth16k[i], HF[i]); move16();
+ }
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/dec_main.h
@@ -1,0 +1,46 @@
+/*--------------------------------------------------------------------------*
+ * DEC_MAIN.H *
+ *--------------------------------------------------------------------------*
+ * Static memory in the decoder *
+ *--------------------------------------------------------------------------*/
+
+#include "cnst.h" /* coder constant parameters */
+#include "dtx.h"
+
+typedef struct
+{
+ Word16 old_exc[PIT_MAX + L_INTERPOL]; /* old excitation vector */
+ Word16 ispold[M]; /* old isp (immittance spectral pairs) */
+ Word16 isfold[M]; /* old isf (frequency domain) */
+ Word16 isf_buf[L_MEANBUF * M]; /* isf buffer(frequency domain) */
+ Word16 past_isfq[M]; /* past isf quantizer */
+ Word16 tilt_code; /* tilt of code */
+ Word16 Q_old; /* old scaling factor */
+ Word16 Qsubfr[4]; /* old maximum scaling factor */
+ Word32 L_gc_thres; /* threshold for noise enhancer */
+ Word16 mem_syn_hi[M]; /* modified synthesis memory (MSB) */
+ Word16 mem_syn_lo[M]; /* modified synthesis memory (LSB) */
+ Word16 mem_deemph; /* speech deemph filter memory */
+ Word16 mem_sig_out[6]; /* hp50 filter memory for synthesis */
+ Word16 mem_oversamp[2 * L_FILT]; /* synthesis oversampled filter memory */
+ Word16 mem_syn_hf[M16k]; /* HF synthesis memory */
+ Word16 mem_hf[2 * L_FILT16k]; /* HF band-pass filter memory */
+ Word16 mem_hf2[2 * L_FILT16k]; /* HF band-pass filter memory */
+ Word16 mem_hf3[2 * L_FILT16k]; /* HF band-pass filter memory */
+ Word16 seed; /* random memory for frame erasure */
+ Word16 seed2; /* random memory for HF generation */
+ Word16 old_T0; /* old pitch lag */
+ Word16 old_T0_frac; /* old pitch fraction lag */
+ Word16 lag_hist[5];
+ Word16 dec_gain[23]; /* gain decoder memory */
+ Word16 seed3; /* random memory for lag concealment */
+ Word16 disp_mem[8]; /* phase dispersion memory */
+ Word16 mem_hp400[6]; /* hp400 filter memory for synthesis */
+
+ Word16 prev_bfi;
+ Word16 state;
+ Word16 first_frame;
+ dtx_decState *dtx_decSt;
+ Word16 vad_hist;
+
+} Decoder_State;
--- /dev/null
+++ b/amr-wb/decim54.c
@@ -1,0 +1,243 @@
+/*-------------------------------------------------------------------*
+ * DECIM54.C *
+ *-------------------------------------------------------------------*
+ * Decim_12k8 : decimation of 16kHz signal to 12.8kHz. *
+ * Oversamp_16k : oversampling from 12.8kHz to 16kHz. *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "acelp.h"
+#include "count.h"
+#include "cnst.h"
+
+#define FAC4 4
+#define FAC5 5
+#define INV_FAC5 6554 /* 1/5 in Q15 */
+#define DOWN_FAC 26215 /* 4/5 in Q15 */
+#define UP_FAC 20480 /* 5/4 in Q14 */
+
+#define NB_COEF_DOWN 15
+#define NB_COEF_UP 12
+
+/* Local functions */
+static void Down_samp(
+ Word16 * sig, /* input: signal to downsampling */
+ Word16 * sig_d, /* output: downsampled signal */
+ Word16 L_frame_d /* input: length of output */
+);
+static void Up_samp(
+ Word16 * sig_d, /* input: signal to oversampling */
+ Word16 * sig_u, /* output: oversampled signal */
+ Word16 L_frame /* input: length of output */
+);
+static Word16 Interpol( /* return result of interpolation */
+ Word16 * x, /* input vector */
+ Word16 * fir, /* filter coefficient */
+ Word16 frac, /* fraction (0..resol) */
+ Word16 resol, /* resolution */
+ Word16 nb_coef /* number of coefficients */
+);
+
+
+/* 1/5 resolution interpolation filter (in Q14) */
+/* -1.5dB @ 6kHz, -6dB @ 6.4kHz, -10dB @ 6.6kHz, -20dB @ 6.9kHz, -25dB @ 7kHz, -55dB @ 8kHz */
+
+static Word16 fir_up[120] =
+{
+ -1, -4, -7, -6, 0,
+ 12, 24, 30, 23, 0,
+ -33, -62, -73, -52, 0,
+ 68, 124, 139, 96, 0,
+ -119, -213, -235, -160, 0,
+ 191, 338, 368, 247, 0,
+ -291, -510, -552, -369, 0,
+ 430, 752, 812, 542, 0,
+ -634, -1111, -1204, -809, 0,
+ 963, 1708, 1881, 1288, 0,
+ -1616, -2974, -3432, -2496, 0,
+ 3792, 8219, 12368, 15317, 16384,
+ 15317, 12368, 8219, 3792, 0,
+ -2496, -3432, -2974, -1616, 0,
+ 1288, 1881, 1708, 963, 0,
+ -809, -1204, -1111, -634, 0,
+ 542, 812, 752, 430, 0,
+ -369, -552, -510, -291, 0,
+ 247, 368, 338, 191, 0,
+ -160, -235, -213, -119, 0,
+ 96, 139, 124, 68, 0,
+ -52, -73, -62, -33, 0,
+ 23, 30, 24, 12, 0,
+ -6, -7, -4, -1, 0
+};
+
+static Word16 fir_down[120] =
+{ /* table x4/5 */
+ -1, -3, -6, -5,
+ 0, 9, 19, 24,
+ 18, 0, -26, -50,
+ -58, -41, 0, 54,
+ 99, 111, 77, 0,
+ -95, -170, -188, -128,
+ 0, 153, 270, 294,
+ 198, 0, -233, -408,
+ -441, -295, 0, 344,
+ 601, 649, 434, 0,
+ -507, -888, -964, -647,
+ 0, 770, 1366, 1505,
+ 1030, 0, -1293, -2379,
+ -2746, -1997, 0, 3034,
+ 6575, 9894, 12254, 13107,
+ 12254, 9894, 6575, 3034,
+ 0, -1997, -2746, -2379,
+ -1293, 0, 1030, 1505,
+ 1366, 770, 0, -647,
+ -964, -888, -507, 0,
+ 434, 649, 601, 344,
+ 0, -295, -441, -408,
+ -233, 0, 198, 294,
+ 270, 153, 0, -128,
+ -188, -170, -95, 0,
+ 77, 111, 99, 54,
+ 0, -41, -58, -50,
+ -26, 0, 18, 24,
+ 19, 9, 0, -5,
+ -6, -3, -1, 0
+};
+
+
+
+void Init_Decim_12k8(
+ Word16 mem[] /* output: memory (2*NB_COEF_DOWN) set to zeros */
+)
+{
+ Set_zero(mem, 2 * NB_COEF_DOWN);
+ return;
+}
+
+void Decim_12k8(
+ Word16 sig16k[], /* input: signal to downsampling */
+ Word16 lg, /* input: length of input */
+ Word16 sig12k8[], /* output: decimated signal */
+ Word16 mem[] /* in/out: memory (2*NB_COEF_DOWN) */
+)
+{
+ Word16 lg_down;
+ Word16 signal[L_FRAME16k + (2 * NB_COEF_DOWN)];
+
+ Copy(mem, signal, 2 * NB_COEF_DOWN);
+
+ Copy(sig16k, signal + (2 * NB_COEF_DOWN), lg);
+
+ lg_down = mult(lg, DOWN_FAC);
+
+ Down_samp(signal + NB_COEF_DOWN, sig12k8, lg_down);
+
+ Copy(signal + lg, mem, 2 * NB_COEF_DOWN);
+
+ return;
+}
+
+
+void Init_Oversamp_16k(
+ Word16 mem[] /* output: memory (2*NB_COEF_UP) set to zeros */
+)
+{
+ Set_zero(mem, 2 * NB_COEF_UP);
+ return;
+}
+
+void Oversamp_16k(
+ Word16 sig12k8[], /* input: signal to oversampling */
+ Word16 lg, /* input: length of input */
+ Word16 sig16k[], /* output: oversampled signal */
+ Word16 mem[] /* in/out: memory (2*NB_COEF_UP) */
+)
+{
+ Word16 lg_up;
+ Word16 signal[L_SUBFR + (2 * NB_COEF_UP)];
+
+ Copy(mem, signal, 2 * NB_COEF_UP);
+
+ Copy(sig12k8, signal + (2 * NB_COEF_UP), lg);
+
+ lg_up = shl(mult(lg, UP_FAC), 1);
+
+ Up_samp(signal + NB_COEF_UP, sig16k, lg_up);
+
+ Copy(signal + lg, mem, 2 * NB_COEF_UP);
+
+ return;
+}
+
+
+static void Down_samp(
+ Word16 * sig, /* input: signal to downsampling */
+ Word16 * sig_d, /* output: downsampled signal */
+ Word16 L_frame_d /* input: length of output */
+)
+{
+ Word16 i, j, frac, pos;
+
+ pos = 0; move16(); /* position is in Q2 -> 1/4 resolution */
+ for (j = 0; j < L_frame_d; j++)
+ {
+ i = shr(pos, 2); /* integer part */
+ frac = (Word16) (pos & 3); logic16(); /* fractional part */
+
+ sig_d[j] = Interpol(&sig[i], fir_down, frac, FAC4, NB_COEF_DOWN); move16();
+
+ pos = add(pos, FAC5); /* pos + 5/4 */
+ }
+
+ return;
+}
+
+
+static void Up_samp(
+ Word16 * sig_d, /* input: signal to oversampling */
+ Word16 * sig_u, /* output: oversampled signal */
+ Word16 L_frame /* input: length of output */
+)
+{
+ Word16 i, j, pos, frac;
+
+ pos = 0; move16(); /* position with 1/5 resolution */
+
+ for (j = 0; j < L_frame; j++)
+ {
+ i = mult(pos, INV_FAC5); /* integer part = pos * 1/5 */
+ frac = sub(pos, add(shl(i, 2), i));/* frac = pos - (pos/5)*5 */
+
+ sig_u[j] = Interpol(&sig_d[i], fir_up, frac, FAC5, NB_COEF_UP); move16();
+
+ pos = add(pos, FAC4); /* position + 4/5 */
+ }
+
+ return;
+}
+
+/* Fractional interpolation of signal at position (frac/resol) */
+
+static Word16 Interpol( /* return result of interpolation */
+ Word16 * x, /* input vector */
+ Word16 * fir, /* filter coefficient */
+ Word16 frac, /* fraction (0..resol) */
+ Word16 resol, /* resolution */
+ Word16 nb_coef /* number of coefficients */
+)
+{
+ Word16 i, k;
+ Word32 L_sum;
+
+ x = x - nb_coef + 1; move16();
+
+ L_sum = 0L; move32();
+ for (i = 0, k = sub(sub(resol, 1), frac); i < 2 * nb_coef; i++, k = (Word16) (k + resol))
+ {
+ L_sum = L_mac(L_sum, x[i], fir[k]);
+ }
+ L_sum = L_shl(L_sum, 1); /* saturation can occur here */
+
+ return (round(L_sum));
+}
--- /dev/null
+++ b/amr-wb/deemph.c
@@ -1,0 +1,108 @@
+/*-------------------------------------------------------------------*
+ * DEEMPH.C *
+ *-------------------------------------------------------------------*
+ * Deemphasis: filtering through 1/(1-mu z^-1) *
+ * *
+ * Deemph2 --> signal is divided by 2. *
+ * Deemph_32 --> for 32 bits signal. *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "math_op.h"
+#include "count.h"
+
+
+void Deemph(
+ Word16 x[], /* (i/o) : input signal overwritten by the output */
+ Word16 mu, /* (i) Q15 : deemphasis factor */
+ Word16 L, /* (i) : vector size */
+ Word16 * mem /* (i/o) : memory (y[-1]) */
+)
+{
+ Word16 i;
+ Word32 L_tmp;
+
+ L_tmp = L_deposit_h(x[0]);
+ L_tmp = L_mac(L_tmp, *mem, mu);
+ x[0] = round(L_tmp); move16();
+
+ for (i = 1; i < L; i++)
+ {
+ L_tmp = L_deposit_h(x[i]);
+ L_tmp = L_mac(L_tmp, x[i - 1], mu);
+ x[i] = round(L_tmp); move16();
+ }
+
+ *mem = x[L - 1]; move16();
+
+ return;
+}
+
+
+void Deemph2(
+ Word16 x[], /* (i/o) : input signal overwritten by the output */
+ Word16 mu, /* (i) Q15 : deemphasis factor */
+ Word16 L, /* (i) : vector size */
+ Word16 * mem /* (i/o) : memory (y[-1]) */
+)
+{
+ Word16 i;
+ Word32 L_tmp;
+
+ /* saturation can occur in L_mac() */
+
+ L_tmp = L_mult(x[0], 16384);
+ L_tmp = L_mac(L_tmp, *mem, mu);
+ x[0] = round(L_tmp); move16();
+
+ for (i = 1; i < L; i++)
+ {
+ L_tmp = L_mult(x[i], 16384);
+ L_tmp = L_mac(L_tmp, x[i - 1], mu);
+ x[i] = round(L_tmp); move16();
+ }
+
+ *mem = x[L - 1]; move16();
+
+ return;
+}
+
+
+void Deemph_32(
+ Word16 x_hi[], /* (i) : input signal (bit31..16) */
+ Word16 x_lo[], /* (i) : input signal (bit15..4) */
+ Word16 y[], /* (o) : output signal (x16) */
+ Word16 mu, /* (i) Q15 : deemphasis factor */
+ Word16 L, /* (i) : vector size */
+ Word16 * mem /* (i/o) : memory (y[-1]) */
+)
+{
+ Word16 i, fac;
+ Word32 L_tmp;
+
+ fac = shr(mu, 1); /* Q15 --> Q14 */
+
+ /* L_tmp = hi<<16 + lo<<4 */
+
+ L_tmp = L_deposit_h(x_hi[0]);
+ L_tmp = L_mac(L_tmp, x_lo[0], 8);
+ L_tmp = L_shl(L_tmp, 3);
+ L_tmp = L_mac(L_tmp, *mem, fac);
+ L_tmp = L_shl(L_tmp, 1); /* saturation can occur here */
+ y[0] = round(L_tmp); move16();
+
+ for (i = 1; i < L; i++)
+ {
+ L_tmp = L_deposit_h(x_hi[i]);
+ L_tmp = L_mac(L_tmp, x_lo[i], 8);
+ L_tmp = L_shl(L_tmp, 3);
+ L_tmp = L_mac(L_tmp, y[i - 1], fac);
+ L_tmp = L_shl(L_tmp, 1); /* saturation can occur here */
+ y[i] = round(L_tmp); move16();
+ }
+
+ *mem = y[L - 1]; move16();
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/dtx.c
@@ -1,0 +1,1276 @@
+/*-------------------------------------------------------------------*
+ * DTX.C *
+ *-------------------------------------------------------------------*
+ * DTX functions *
+ *-------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "math_op.h"
+#include "cnst.h"
+#include "acelp.h" /* prototype of functions */
+#include "bits.h"
+#include "dtx.h"
+#include "count.h"
+#include "log2.h"
+
+static void aver_isf_history(
+ Word16 isf_old[],
+ Word16 indices[],
+ Word32 isf_aver[]
+);
+static void find_frame_indices(
+ Word16 isf_old_tx[],
+ Word16 indices[],
+ dtx_encState * st
+);
+
+static Word16 dithering_control(
+ dtx_encState * st
+);
+static void CN_dithering(
+ Word16 isf[M],
+ Word32 * L_log_en_int,
+ Word16 * dither_seed
+);
+
+/* excitation energy adjustment depending on speech coder mode used, Q7 */
+static Word16 en_adjust[9] =
+{
+ 230, /* mode0 = 7k : -5.4dB */
+ 179, /* mode1 = 9k : -4.2dB */
+ 141, /* mode2 = 12k : -3.3dB */
+ 128, /* mode3 = 14k : -3.0dB */
+ 122, /* mode4 = 16k : -2.85dB */
+ 115, /* mode5 = 18k : -2.7dB */
+ 115, /* mode6 = 20k : -2.7dB */
+ 115, /* mode7 = 23k : -2.7dB */
+ 115 /* mode8 = 24k : -2.7dB */
+};
+
+/**************************************************************************
+ *
+ *
+ * Function : dtx_enc_init
+ *
+ *
+ **************************************************************************/
+Word16 dtx_enc_init(dtx_encState ** st, Word16 isf_init[])
+{
+ dtx_encState *s;
+
+ test();
+ if (st == (dtx_encState **) NULL)
+ {
+ fprintf(stderr, "dtx_enc_init: invalid parameter\n");
+ return -1;
+ }
+ *st = NULL;
+
+ /* allocate memory */
+ test();
+ if ((s = (dtx_encState *) malloc(sizeof(dtx_encState))) == NULL)
+ {
+ fprintf(stderr, "dtx_enc_init: can not malloc state structure\n");
+ return -1;
+ }
+ dtx_enc_reset(s, isf_init);
+ *st = s;
+
+ return 0;
+}
+
+/**************************************************************************
+ *
+ *
+ * Function : dtx_enc_reset
+ *
+ *
+ **************************************************************************/
+Word16 dtx_enc_reset(dtx_encState * st, Word16 isf_init[])
+{
+ Word16 i;
+
+ test();
+ if (st == (dtx_encState *) NULL)
+ {
+ fprintf(stderr, "dtx_enc_reset: invalid parameter\n");
+ return -1;
+ }
+ st->hist_ptr = 0; move16();
+ st->log_en_index = 0; move16();
+
+ /* Init isf_hist[] */
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ Copy(isf_init, &st->isf_hist[i * M], M);
+ }
+ st->cng_seed = RANDOM_INITSEED; move16();
+
+ /* Reset energy history */
+ Set_zero(st->log_en_hist, DTX_HIST_SIZE);
+
+ st->dtxHangoverCount = DTX_HANG_CONST; move16();
+ st->decAnaElapsedCount = 32767; move16();
+
+ for (i = 0; i < 28; i++)
+ {
+ st->D[i] = 0; move16();
+ }
+
+ for (i = 0; i < DTX_HIST_SIZE - 1; i++)
+ {
+ st->sumD[i] = 0; move32();
+ }
+
+ return 1;
+}
+
+/**************************************************************************
+ *
+ *
+ * Function : dtx_enc_exit
+ *
+ *
+ **************************************************************************/
+void dtx_enc_exit(dtx_encState ** st)
+{
+ test();
+ if (st == NULL || *st == NULL)
+ return;
+
+ /* deallocate memory */
+ free(*st);
+ *st = NULL;
+
+ return;
+}
+
+
+/**************************************************************************
+ *
+ *
+ * Function : dtx_enc
+ *
+ *
+ **************************************************************************/
+Word16 dtx_enc(
+ dtx_encState * st, /* i/o : State struct */
+ Word16 isf[M], /* o : CN ISF vector */
+ Word16 * exc2, /* o : CN excitation */
+ Word16 ** prms
+)
+{
+ Word16 i, j;
+ Word16 indice[7];
+ Word16 log_en, gain, level, exp, exp0, tmp;
+ Word16 log_en_int_e, log_en_int_m;
+ Word32 L_isf[M], ener32, level32;
+ Word16 isf_order[3];
+ Word16 CN_dith;
+
+ /* VOX mode computation of SID parameters */
+ log_en = 0;
+ move16();
+ for (i = 0; i < M; i++)
+ {
+ L_isf[i] = 0;
+ move32();
+ }
+ /* average energy and isf */
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ /* Division by DTX_HIST_SIZE = 8 has been done in dtx_buffer. log_en is in Q10 */
+ log_en = add(log_en, st->log_en_hist[i]);
+
+ }
+ find_frame_indices(st->isf_hist, isf_order, st);
+ aver_isf_history(st->isf_hist, isf_order, L_isf);
+
+ for (j = 0; j < M; j++)
+ {
+ isf[j] = extract_l(L_shr(L_isf[j], 3)); move16(); /* divide by 8 */
+ }
+
+ /* quantize logarithmic energy to 6 bits (-6 : 66 dB) which corresponds to -2:22 in log2(E). */
+ /* st->log_en_index = (short)( (log_en + 2.0) * 2.625 ); */
+
+ /* increase dynamics to 7 bits (Q8) */
+ log_en = shr(log_en, 2);
+
+ /* Add 2 in Q8 = 512 to get log2(E) between 0:24 */
+ log_en = add(log_en, 512);
+
+ /* Multiply by 2.625 to get full 6 bit range. 2.625 = 21504 in Q13. The result is in Q6 */
+ log_en = mult(log_en, 21504);
+
+ /* Quantize Energy */
+ st->log_en_index = shr(log_en, 6);
+
+ test();
+ if (sub(st->log_en_index, 63) > 0)
+ {
+ st->log_en_index = 63;
+ move16();
+ }
+ test();
+ if (st->log_en_index < 0)
+ {
+ st->log_en_index = 0;
+ move16();
+ }
+ /* Quantize ISFs */
+ Qisf_ns(isf, isf, indice);
+
+
+ Parm_serial(indice[0], 6, prms);
+ Parm_serial(indice[1], 6, prms);
+ Parm_serial(indice[2], 6, prms);
+ Parm_serial(indice[3], 5, prms);
+ Parm_serial(indice[4], 5, prms);
+
+ Parm_serial((st->log_en_index), 6, prms);
+
+ CN_dith = dithering_control(st);
+ Parm_serial(CN_dith, 1, prms);
+
+ /* level = (float)( pow( 2.0f, (float)st->log_en_index / 2.625 - 2.0 ) ); */
+ /* log2(E) in Q9 (log2(E) lies in between -2:22) */
+ log_en = shl(st->log_en_index, 15 - 6);
+
+ /* Divide by 2.625; log_en will be between 0:24 */
+ log_en = mult(log_en, 12483);
+ /* the result corresponds to log2(gain) in Q10 */
+
+ /* Find integer part */
+ log_en_int_e = shr(log_en, 10);
+
+ /* Find fractional part */
+ log_en_int_m = (Word16) (log_en & 0x3ff); logic16();
+ log_en_int_m = shl(log_en_int_m, 5);
+
+ /* Subtract 2 from log_en in Q9, i.e divide the gain by 2 (energy by 4) */
+ /* Add 16 in order to have the result of pow2 in Q16 */
+ log_en_int_e = add(log_en_int_e, 16 - 1);
+
+ level32 = Pow2(log_en_int_e, log_en_int_m); /* Q16 */
+ exp0 = norm_l(level32);
+ level32 = L_shl(level32, exp0); /* level in Q31 */
+ exp0 = sub(15, exp0);
+ level = extract_h(level32); /* level in Q15 */
+
+ /* generate white noise vector */
+ for (i = 0; i < L_FRAME; i++)
+ {
+ exc2[i] = shr(Random(&(st->cng_seed)), 4); move16();
+ }
+
+ /* gain = level / sqrt(ener) * sqrt(L_FRAME) */
+
+ /* energy of generated excitation */
+ ener32 = Dot_product12(exc2, exc2, L_FRAME, &exp);
+
+ Isqrt_n(&ener32, &exp);
+
+ gain = extract_h(ener32);
+
+ gain = mult(level, gain); /* gain in Q15 */
+
+ exp = add(exp0, exp);
+
+ /* Multiply by sqrt(L_FRAME)=16, i.e. shift left by 4 */
+ exp = add(exp, 4);
+
+ for (i = 0; i < L_FRAME; i++)
+ {
+ tmp = mult(exc2[i], gain); /* Q0 * Q15 */
+ exc2[i] = shl(tmp, exp); move16();
+ }
+
+ return 0;
+}
+
+/**************************************************************************
+ *
+ *
+ * Function : dtx_buffer Purpose : handles the DTX buffer
+ *
+ *
+ **************************************************************************/
+Word16 dtx_buffer(
+ dtx_encState * st, /* i/o : State struct */
+ Word16 isf_new[], /* i : isf vector */
+ Word32 enr, /* i : residual energy (in L_FRAME) */
+ Word16 codec_mode
+)
+{
+ Word16 log_en;
+
+ Word16 log_en_e;
+ Word16 log_en_m;
+
+ st->hist_ptr = add(st->hist_ptr, 1); move16();
+ test();
+ if (sub(st->hist_ptr, DTX_HIST_SIZE) == 0)
+ {
+ st->hist_ptr = 0;
+ move16();
+ }
+ /* copy lsp vector into buffer */
+ Copy(isf_new, &st->isf_hist[st->hist_ptr * M], M);
+
+ /* log_en = (float)log10(enr*0.0059322)/(float)log10(2.0f); */
+ Log2(enr, &log_en_e, &log_en_m);
+
+ /* convert exponent and mantissa to Word16 Q7. Q7 is used to simplify averaging in dtx_enc */
+ log_en = shl(log_en_e, 7); /* Q7 */
+ log_en = add(log_en, shr(log_en_m, 15 - 7));
+
+ /* Find energy per sample by multiplying with 0.0059322, i.e subtract log2(1/0.0059322) = 7.39722 The
+ * constant 0.0059322 takes into account windowings and analysis length from autocorrelation
+ * computations; 7.39722 in Q7 = 947 */
+ /* Subtract 3 dB = 0.99658 in log2(E) = 127 in Q7. */
+ /* log_en = sub( log_en, 947 + en_adjust[codec_mode] ); */
+
+ /* Find energy per sample (divide by L_FRAME=256), i.e subtract log2(256) = 8.0 (1024 in Q7) */
+ /* Subtract 3 dB = 0.99658 in log2(E) = 127 in Q7. */
+
+ log_en = sub(log_en, add(1024, en_adjust[codec_mode]));
+
+ /* Insert into the buffer */
+ st->log_en_hist[st->hist_ptr] = log_en;move16();
+ return 0;
+}
+
+/**************************************************************************
+ *
+ *
+ * Function : tx_dtx_handler Purpose : adds extra speech hangover
+ * to analyze speech on
+ * the decoding side.
+ *
+ **************************************************************************/
+void tx_dtx_handler(dtx_encState * st, /* i/o : State struct */
+ Word16 vad_flag, /* i : vad decision */
+ Word16 * usedMode /* i/o : mode changed or not */
+)
+{
+
+ /* this state machine is in synch with the GSMEFR txDtx machine */
+ st->decAnaElapsedCount = add(st->decAnaElapsedCount, 1); move16();
+
+ test();
+ if (vad_flag != 0)
+ {
+ st->dtxHangoverCount = DTX_HANG_CONST; move16();
+ } else
+ { /* non-speech */
+ test();
+ if (st->dtxHangoverCount == 0)
+ { /* out of decoder analysis hangover */
+ st->decAnaElapsedCount = 0; move16();
+ *usedMode = MRDTX; move16();
+ } else
+ { /* in possible analysis hangover */
+ st->dtxHangoverCount = sub(st->dtxHangoverCount, 1); move16();
+
+ /* decAnaElapsedCount + dtxHangoverCount < DTX_ELAPSED_FRAMES_THRESH */
+ test();
+ if (sub(add(st->decAnaElapsedCount, st->dtxHangoverCount),
+ DTX_ELAPSED_FRAMES_THRESH) < 0)
+ {
+ *usedMode = MRDTX; move16();
+ /* if short time since decoder update, do not add extra HO */
+ }
+ /* else override VAD and stay in speech mode *usedMode and add extra hangover */
+ }
+ }
+
+ return;
+}
+
+/**************************************************************************
+ *
+ *
+ * Function : dtx_dec_init
+ *
+ *
+ **************************************************************************/
+Word16 dtx_dec_init(dtx_decState ** st, Word16 isf_init[])
+{
+ dtx_decState *s;
+
+ test();
+ if (st == (dtx_decState **) NULL)
+ {
+ fprintf(stderr, "dtx_dec_init: invalid parameter\n");
+ return -1;
+ }
+ *st = NULL;
+
+ /* allocate memory */
+ test();
+ if ((s = (dtx_decState *) malloc(sizeof(dtx_decState))) == NULL)
+ {
+ fprintf(stderr, "dtx_dec_init: can not malloc state structure\n");
+ return -1;
+ }
+ dtx_dec_reset(s, isf_init);
+ *st = s;
+
+ return 0;
+}
+
+/**************************************************************************
+ *
+ *
+ * Function : dtx_dec_reset
+ *
+ *
+ **************************************************************************/
+Word16 dtx_dec_reset(dtx_decState * st, Word16 isf_init[])
+{
+ Word16 i;
+
+ test();
+ if (st == (dtx_decState *) NULL)
+ {
+ fprintf(stderr, "dtx_dec_reset: invalid parameter\n");
+ return -1;
+ }
+ st->since_last_sid = 0; move16();
+ st->true_sid_period_inv = (1 << 13); move16(); /* 0.25 in Q15 */
+
+ st->log_en = 3500; move16();
+ st->old_log_en = 3500; move16();
+ /* low level noise for better performance in DTX handover cases */
+
+ st->cng_seed = RANDOM_INITSEED; move16();
+
+ st->hist_ptr = 0; move16();
+
+ /* Init isf_hist[] and decoder log frame energy */
+ Copy(isf_init, st->isf, M);
+ Copy(isf_init, st->isf_old, M);
+
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ Copy(isf_init, &st->isf_hist[i * M], M);
+ st->log_en_hist[i] = st->log_en; move16();
+ }
+
+ st->dtxHangoverCount = DTX_HANG_CONST; move16();
+ st->decAnaElapsedCount = 32767; move16();
+
+ st->sid_frame = 0; move16();
+ st->valid_data = 0; move16();
+ st->dtxHangoverAdded = 0; move16();
+
+ st->dtxGlobalState = SPEECH; move16();
+ st->data_updated = 0; move16();
+
+ st->dither_seed = RANDOM_INITSEED; move16();
+ st->CN_dith = 0;
+
+ return 0;
+}
+
+/**************************************************************************
+ *
+ *
+ * Function : dtx_dec_exit
+ *
+ *
+ **************************************************************************/
+void dtx_dec_exit(dtx_decState ** st)
+{
+ test();
+ if (st == NULL || *st == NULL)
+ return;
+
+ /* deallocate memory */
+ free(*st);
+ *st = NULL;
+
+ 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 : dtx_dec
+ *
+ *
+ **************************************************************************/
+Word16 dtx_dec(
+ dtx_decState * st, /* i/o : State struct */
+ Word16 * exc2, /* o : CN excitation */
+ Word16 new_state, /* i : New DTX state */
+ Word16 isf[], /* o : CN ISF vector */
+ Word16 ** prms
+)
+{
+ Word16 log_en_index;
+ Word16 ind[7];
+ Word16 i, j;
+ Word16 int_fac;
+ Word16 gain;
+
+ Word32 L_isf[M], L_log_en_int, level32, ener32;
+ Word16 ptr;
+ Word16 tmp_int_length;
+ Word16 tmp, exp, exp0, log_en_int_e, log_en_int_m, level;
+
+ /* This function is called if synthesis state is not SPEECH the globally passed inputs to this function
+ * are st->sid_frame st->valid_data st->dtxHangoverAdded new_state (SPEECH, DTX, DTX_MUTE) */
+ test();test();
+ if ((st->dtxHangoverAdded != 0) &&
+ (st->sid_frame != 0))
+ {
+ /* sid_first after dtx hangover period */
+ /* or sid_upd after dtxhangover */
+
+ /* consider twice the last frame */
+ ptr = add(st->hist_ptr, 1);
+ test();
+ if (sub(ptr, DTX_HIST_SIZE) == 0)
+ ptr = 0; move16();
+
+ Copy(&st->isf_hist[st->hist_ptr * M], &st->isf_hist[ptr * M], M);
+
+ st->log_en_hist[ptr] = st->log_en_hist[st->hist_ptr]; move16();
+
+ /* compute mean log energy and isf from decoded signal (SID_FIRST) */
+ st->log_en = 0; move16();
+ for (i = 0; i < M; i++)
+ {
+ L_isf[i] = 0; move32();
+ }
+
+ /* average energy and isf */
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ /* Division by DTX_HIST_SIZE = 8 has been done in dtx_buffer log_en is in Q10 */
+ st->log_en = add(st->log_en, st->log_en_hist[i]); move16();
+
+ for (j = 0; j < M; j++)
+ {
+ L_isf[j] = L_add(L_isf[j], L_deposit_l(st->isf_hist[i * M + j])); move32();
+ }
+ }
+
+ /* st->log_en in Q9 */
+ st->log_en = shr(st->log_en, 1); move16();
+
+ /* Add 2 in Q9, in order to have only positive values for Pow2 */
+ /* this value is subtracted back after Pow2 function */
+ st->log_en = add(st->log_en, 1024);move16();
+ test();
+ if (st->log_en < 0)
+ st->log_en = 0; move16();
+
+ for (j = 0; j < M; j++)
+ {
+ st->isf[j] = extract_l(L_shr(L_isf[j], 3)); move32(); /* divide by 8 */
+ }
+
+ }
+ test();
+ if (st->sid_frame != 0)
+ {
+ /* Set old SID parameters, always shift */
+ /* even if there is no new valid_data */
+
+ Copy(st->isf, st->isf_old, M);
+ st->old_log_en = st->log_en; move16();
+ test();
+ if (st->valid_data != 0) /* new data available (no CRC) */
+ {
+ /* st->true_sid_period_inv = 1.0f/st->since_last_sid; */
+ /* Compute interpolation factor, since the division only works * for values of since_last_sid <
+ * 32 we have to limit the * interpolation to 32 frames */
+ tmp_int_length = st->since_last_sid; move16();
+
+ test();
+ if (sub(tmp_int_length, 32) > 0)
+ {
+ tmp_int_length = 32; move16();
+ }
+ test();
+ if (sub(tmp_int_length, 2) >= 0)
+ {
+ move16();
+ st->true_sid_period_inv = div_s(1 << 10, shl(tmp_int_length, 10));
+ } else
+ {
+ st->true_sid_period_inv = 1 << 14; /* 0.5 it Q15 */move16();
+ }
+
+ ind[0] = Serial_parm(6, prms); move16();
+ ind[1] = Serial_parm(6, prms); move16();
+ ind[2] = Serial_parm(6, prms); move16();
+ ind[3] = Serial_parm(5, prms); move16();
+ ind[4] = Serial_parm(5, prms); move16();
+
+ Disf_ns(ind, st->isf);
+
+ log_en_index = Serial_parm(6, prms);
+
+ /* read background noise stationarity information */
+ st->CN_dith = Serial_parm(1, prms); move16();
+
+ /* st->log_en = (float)log_en_index / 2.625 - 2.0; */
+ /* log2(E) in Q9 (log2(E) lies in between -2:22) */
+ st->log_en = shl(log_en_index, 15 - 6); move16();
+
+ /* Divide by 2.625 */
+ st->log_en = mult(st->log_en, 12483); move16();
+ /* Subtract 2 in Q9 is done later, after Pow2 function */
+
+ /* no interpolation at startup after coder reset */
+ /* or when SID_UPD has been received right after SPEECH */
+ test();test();
+ if ((st->data_updated == 0) ||
+ (sub(st->dtxGlobalState, SPEECH) == 0))
+ {
+ Copy(st->isf, st->isf_old, M);
+ st->old_log_en = st->log_en; move16();
+ }
+ } /* endif valid_data */
+ } /* endif sid_frame */
+ test();
+ test();
+ if ((st->sid_frame != 0) && (st->valid_data != 0))
+ {
+ st->since_last_sid = 0; move16();
+ }
+ /* Interpolate SID info */
+ int_fac = shl(st->since_last_sid, 10); /* Q10 */move16();
+ int_fac = mult(int_fac, st->true_sid_period_inv); /* Q10 * Q15 -> Q10 */
+
+ /* Maximize to 1.0 in Q10 */
+ test();
+ if (sub(int_fac, 1024) > 0)
+ {
+ int_fac = 1024; move16();
+ }
+ int_fac = shl(int_fac, 4); /* Q10 -> Q14 */
+
+ L_log_en_int = L_mult(int_fac, st->log_en); /* Q14 * Q9 -> Q24 */
+
+ for (i = 0; i < M; i++)
+ {
+ isf[i] = mult(int_fac, st->isf[i]);/* Q14 * Q15 -> Q14 */move16();
+ }
+
+ int_fac = sub(16384, int_fac); /* 1-k in Q14 */move16();
+
+ /* ( Q14 * Q9 -> Q24 ) + Q24 -> Q24 */
+ L_log_en_int = L_mac(L_log_en_int, int_fac, st->old_log_en);
+
+ for (i = 0; i < M; i++)
+ {
+ /* Q14 + (Q14 * Q15 -> Q14) -> Q14 */
+ isf[i] = add(isf[i], mult(int_fac, st->isf_old[i])); move16();
+ isf[i] = shl(isf[i], 1); /* Q14 -> Q15 */move16();
+ }
+
+ /* If background noise is non-stationary, insert comfort noise dithering */
+ if (st->CN_dith != 0)
+ {
+ CN_dithering(isf, &L_log_en_int, &st->dither_seed);
+ }
+ /* L_log_en_int corresponds to log2(E)+2 in Q24, i.e log2(gain)+1 in Q25 */
+ /* Q25 -> Q16 */
+ L_log_en_int = L_shr(L_log_en_int, 9);
+
+ /* Find integer part */
+ log_en_int_e = extract_h(L_log_en_int);
+
+ /* Find fractional part */
+ log_en_int_m = extract_l(L_shr(L_sub(L_log_en_int, L_deposit_h(log_en_int_e)), 1));
+
+ /* Subtract 2 from L_log_en_int in Q9, i.e divide the gain by 2 (energy by 4) */
+ /* Add 16 in order to have the result of pow2 in Q16 */
+ log_en_int_e = add(log_en_int_e, 16 - 1);
+
+ /* level = (float)( pow( 2.0f, log_en ) ); */
+ level32 = Pow2(log_en_int_e, log_en_int_m); /* Q16 */
+ exp0 = norm_l(level32);
+ level32 = L_shl(level32, exp0); /* level in Q31 */
+ exp0 = sub(15, exp0);
+ level = extract_h(level32); /* level in Q15 */
+
+ /* generate white noise vector */
+ for (i = 0; i < L_FRAME; i++)
+ {
+ exc2[i] = shr(Random(&(st->cng_seed)), 4); move16();
+ }
+
+ /* gain = level / sqrt(ener) * sqrt(L_FRAME) */
+
+ /* energy of generated excitation */
+ ener32 = Dot_product12(exc2, exc2, L_FRAME, &exp);
+
+ Isqrt_n(&ener32, &exp);
+
+ gain = extract_h(ener32);
+
+ gain = mult(level, gain); /* gain in Q15 */
+
+ exp = add(exp0, exp);
+
+ /* Multiply by sqrt(L_FRAME)=16, i.e. shift left by 4 */
+ exp = add(exp, 4);
+
+ for (i = 0; i < L_FRAME; i++)
+ {
+ tmp = mult(exc2[i], gain); /* Q0 * Q15 */
+ exc2[i] = shl(tmp, exp); move16();
+ }
+
+ test();
+ if (sub(new_state, DTX_MUTE) == 0)
+ {
+ /* mute comfort noise as it has been quite a long time since last SID update was performed */
+
+ tmp_int_length = st->since_last_sid; move16();
+ test();
+ if (sub(tmp_int_length, 32) > 0)
+ {
+ tmp_int_length = 32; move16();
+ }
+ move16();
+ st->true_sid_period_inv = div_s(1 << 10, shl(tmp_int_length, 10));
+
+ st->since_last_sid = 0; move16();
+ st->old_log_en = st->log_en; move16();
+ /* subtract 1/8 in Q9 (energy), i.e -3/8 dB */
+ st->log_en = sub(st->log_en, 64); move16();
+ }
+ /* reset interpolation length timer if data has been updated. */
+ test();test();test();test();
+ if ((st->sid_frame != 0) &&
+ ((st->valid_data != 0) ||
+ ((st->valid_data == 0) && (st->dtxHangoverAdded) != 0)))
+ {
+ st->since_last_sid = 0; move16();
+ st->data_updated = 1; move16();
+ }
+ return 0;
+}
+
+
+void dtx_dec_activity_update(
+ dtx_decState * st,
+ Word16 isf[],
+ Word16 exc[])
+{
+ Word16 i;
+
+ Word32 L_frame_en;
+ Word16 log_en_e, log_en_m, log_en;
+
+
+ st->hist_ptr = add(st->hist_ptr, 1); move16();
+ test();
+ if (sub(st->hist_ptr, DTX_HIST_SIZE) == 0)
+ {
+ st->hist_ptr = 0; move16();
+ }
+ Copy(isf, &st->isf_hist[st->hist_ptr * M], M);
+
+ /* compute log energy based on excitation frame energy in Q0 */
+ L_frame_en = 0; move32();
+ for (i = 0; i < L_FRAME; i++)
+ {
+ L_frame_en = L_mac(L_frame_en, exc[i], exc[i]);
+ }
+ L_frame_en = L_shr(L_frame_en, 1);
+
+ /* log_en = (float)log10(L_frame_en/(float)L_FRAME)/(float)log10(2.0f); */
+ Log2(L_frame_en, &log_en_e, &log_en_m);
+
+ /* convert exponent and mantissa to Word16 Q7. Q7 is used to simplify averaging in dtx_enc */
+ log_en = shl(log_en_e, 7); /* Q7 */
+ log_en = add(log_en, shr(log_en_m, 15 - 7));
+
+ /* Divide by L_FRAME = 256, i.e subtract 8 in Q7 = 1024 */
+ log_en = sub(log_en, 1024);
+
+ /* insert into log energy buffer */
+ st->log_en_hist[st->hist_ptr] = log_en;move16();
+
+ 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.)| |
+ ----------------------------------------------------------------
+*/
+
+Word16 rx_dtx_handler(
+ dtx_decState * st, /* i/o : State struct */
+ Word16 frame_type /* i : Frame type */
+)
+{
+ Word16 newState;
+ Word16 encState;
+
+ /* DTX if SID frame or previously in DTX{_MUTE} and (NO_RX OR BAD_SPEECH) */
+ test();test();test();
+ test();test();test();
+ test();test();
+ if ((sub(frame_type, RX_SID_FIRST) == 0) ||
+ (sub(frame_type, RX_SID_UPDATE) == 0) ||
+ (sub(frame_type, RX_SID_BAD) == 0) ||
+ (((sub(st->dtxGlobalState, DTX) == 0) ||
+ (sub(st->dtxGlobalState, DTX_MUTE) == 0)) &&
+ ((sub(frame_type, RX_NO_DATA) == 0) ||
+ (sub(frame_type, RX_SPEECH_BAD) == 0) ||
+ (sub(frame_type, RX_SPEECH_LOST) == 0))))
+ {
+ newState = DTX; move16();
+
+ /* stay in mute for these input types */
+ test();test();test();test();test();
+ if ((sub(st->dtxGlobalState, DTX_MUTE) == 0) &&
+ ((sub(frame_type, RX_SID_BAD) == 0) ||
+ (sub(frame_type, RX_SID_FIRST) == 0) ||
+ (sub(frame_type, RX_SPEECH_LOST) == 0) ||
+ (sub(frame_type, RX_NO_DATA) == 0)))
+ {
+ newState = DTX_MUTE; move16();
+ }
+ /* evaluate if noise parameters are too old */
+ /* since_last_sid is reset when CN parameters have been updated */
+ st->since_last_sid = add(st->since_last_sid, 1); move16();
+
+ /* no update of sid parameters in DTX for a long while */
+ test();
+ if (sub(st->since_last_sid, DTX_MAX_EMPTY_THRESH) > 0)
+ {
+ newState = DTX_MUTE; move16();
+ }
+ } else
+ {
+ newState = SPEECH; move16();
+ st->since_last_sid = 0; move16();
+ }
+
+ /* 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. */
+ test();test();
+ if ((st->data_updated == 0) &&
+ (sub(frame_type, RX_SID_UPDATE) == 0))
+ {
+ st->decAnaElapsedCount = 0; move16();
+ }
+ /* update the SPE-SPD DTX hangover synchronization */
+ /* to know when SPE has added dtx hangover */
+ st->decAnaElapsedCount = add(st->decAnaElapsedCount, 1); move16();
+ st->dtxHangoverAdded = 0; move16();
+
+ test();test();test();test();
+ if ((sub(frame_type, RX_SID_FIRST) == 0) ||
+ (sub(frame_type, RX_SID_UPDATE) == 0) ||
+ (sub(frame_type, RX_SID_BAD) == 0) ||
+ (sub(frame_type, RX_NO_DATA) == 0))
+ {
+ encState = DTX; move16();
+ } else
+ {
+ encState = SPEECH; move16();
+ }
+
+ test();
+ if (sub(encState, SPEECH) == 0)
+ {
+ st->dtxHangoverCount = DTX_HANG_CONST; move16();
+ } else
+ {
+ test();test();
+ if (sub(st->decAnaElapsedCount, DTX_ELAPSED_FRAMES_THRESH) > 0)
+ {
+ st->dtxHangoverAdded = 1; move16();
+ st->decAnaElapsedCount = 0; move16();
+ st->dtxHangoverCount = 0; move16();
+ } else if (test(), st->dtxHangoverCount == 0)
+ {
+ st->decAnaElapsedCount = 0; move16();
+ } else
+ {
+ st->dtxHangoverCount = sub(st->dtxHangoverCount, 1); move16();
+ }
+ }
+ test();
+ if (sub(newState, SPEECH) != 0)
+ {
+ /* 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; move16();
+ st->valid_data = 0; move16();
+
+ test();test();test();
+ if (sub(frame_type, RX_SID_FIRST) == 0)
+ {
+ st->sid_frame = 1; move16();
+ } else if (test(), sub(frame_type, RX_SID_UPDATE) == 0)
+ {
+ st->sid_frame = 1; move16();
+ st->valid_data = 1; move16();
+ } else if (test(), sub(frame_type, RX_SID_BAD) == 0)
+ {
+ st->sid_frame = 1; move16();
+ st->dtxHangoverAdded = 0; /* use old data */move16();
+ }
+ }
+ return newState;
+ /* newState is used by both SPEECH AND DTX synthesis routines */
+}
+
+static void aver_isf_history(
+ Word16 isf_old[],
+ Word16 indices[],
+ Word32 isf_aver[]
+)
+{
+ Word16 i, j, k;
+ Word16 isf_tmp[2 * M];
+ Word32 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++)
+ {
+ test();
+ if (add(indices[k], 1) != 0)
+ {
+ for (i = 0; i < M; i++)
+ {
+ isf_tmp[k * M + i] = isf_old[indices[k] * M + i]; move16();
+ isf_old[indices[k] * M + i] = isf_old[indices[2] * M + i]; move16();
+ }
+ }
+ }
+
+ /* Perform the ISF averaging */
+ for (j = 0; j < M; j++)
+ {
+ L_tmp = 0; move32();
+
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ L_tmp = L_add(L_tmp, L_deposit_l(isf_old[i * M + j]));
+ }
+ isf_aver[j] = L_tmp; move32();
+ }
+
+ /* Retrieve from isf_tmp[][] the ISF vectors saved prior to averaging */
+ for (k = 0; k < 2; k++)
+ {
+ test();
+ if (add(indices[k], 1) != 0)
+ {
+ for (i = 0; i < M; i++)
+ {
+ isf_old[indices[k] * M + i] = isf_tmp[k * M + i]; move16();
+ }
+ }
+ }
+
+ return;
+}
+
+static void find_frame_indices(
+ Word16 isf_old_tx[],
+ Word16 indices[],
+ dtx_encState * st
+)
+{
+ Word32 L_tmp, summin, summax, summax2nd;
+ Word16 i, j, tmp;
+ Word16 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; move16();
+ j = -1; move16();
+ for (i = 0; i < DTX_HIST_SIZE_MIN_ONE; i++)
+ {
+ j = add(j, tmp);
+ st->sumD[i] = L_sub(st->sumD[i], st->D[j]); move16();
+ tmp = sub(tmp, 1);
+ }
+
+ /* 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]; move32();
+ }
+ st->sumD[0] = 0; move32();
+
+ /* 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; move16();
+ for (i = 27; i >= 12; i = (Word16) (i - tmp))
+ {
+ tmp = add(tmp, 1);
+ for (j = tmp; j > 0; j--)
+ {
+ st->D[i - j + 1] = st->D[i - j - tmp]; move32();
+ }
+ }
+
+ /* Compute the first column of the distance matrix D */
+ /* (squared Euclidean distances from isf1[] to isf_old_tx[][]). */
+
+ ptr = st->hist_ptr; move16();
+ for (i = 1; i < DTX_HIST_SIZE; i++)
+ {
+ /* Compute the distance between the latest isf and the other isfs. */
+ ptr = sub(ptr, 1);
+ test();
+ if (ptr < 0)
+ {
+ ptr = DTX_HIST_SIZE_MIN_ONE; move16();
+ }
+ L_tmp = 0; move32();
+ for (j = 0; j < M; j++)
+ {
+ tmp = sub(isf_old_tx[st->hist_ptr * M + j], isf_old_tx[ptr * M + j]);
+ L_tmp = L_mac(L_tmp, tmp, tmp);
+ }
+ st->D[i - 1] = L_tmp; move32();
+
+ /* Update also the column sums. */
+ st->sumD[0] = L_add(st->sumD[0], st->D[i - 1]); move32();
+ st->sumD[i] = L_add(st->sumD[i], st->D[i - 1]); move32();
+ }
+
+ /* Find the minimum and maximum distances */
+ summax = st->sumD[0]; move32();
+ summin = st->sumD[0]; move32();
+ indices[0] = 0; move16();
+ indices[2] = 0; move16();
+ for (i = 1; i < DTX_HIST_SIZE; i++)
+ {
+ test();
+ if (L_sub(st->sumD[i], summax) > 0)
+ {
+ indices[0] = i; move16();
+ summax = st->sumD[i]; move32();
+ }
+ test();
+ if (L_sub(st->sumD[i], summin) < 0)
+ {
+ indices[2] = i; move16();
+ summin = st->sumD[i]; move32();
+ }
+ }
+
+ /* Find the second largest distance */
+ summax2nd = -2147483647L; move32();
+ indices[1] = -1; move16();
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ test();
+ if ((L_sub(st->sumD[i], summax2nd) > 0) && (sub(i, indices[0]) != 0))
+ {
+ indices[1] = i; move16();
+ summax2nd = st->sumD[i]; move32();
+ }
+ }
+
+ for (i = 0; i < 3; i++)
+ {
+ indices[i] = sub(st->hist_ptr, indices[i]); move16();
+ test();
+ if (indices[i] < 0)
+ {
+ indices[i] = add(indices[i], DTX_HIST_SIZE); move16();
+ }
+ }
+
+ /* If maximum distance/MED_THRESH is smaller than minimum distance */
+ /* then the median ISF vector replacement is not performed */
+ tmp = norm_l(summax);
+ summax = L_shl(summax, tmp);
+ summin = L_shl(summin, tmp);
+ L_tmp = L_mult(round(summax), INV_MED_THRESH);
+ test();
+ if (L_sub(L_tmp, summin) <= 0)
+ {
+ indices[0] = -1; move16();
+ }
+ /* If second largest distance/MED_THRESH is smaller than */
+ /* minimum distance then the median ISF vector replacement is */
+ /* not performed */
+ summax2nd = L_shl(summax2nd, tmp);
+ L_tmp = L_mult(round(summax2nd), INV_MED_THRESH);
+ test();
+ if (L_sub(L_tmp, summin) <= 0)
+ {
+ indices[1] = -1; move16();
+ }
+ return;
+}
+
+static Word16 dithering_control(
+ dtx_encState * st
+)
+{
+ Word16 i, tmp, mean, CN_dith, gain_diff;
+ Word32 ISF_diff;
+
+ /* determine how stationary the spectrum of background noise is */
+ ISF_diff = 0;
+ for (i = 0; i < 8; i++)
+ {
+ ISF_diff = L_add(ISF_diff, st->sumD[i]);
+ }
+ if (L_shr(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(mean, st->log_en_hist[i]);
+ }
+ mean = shr(mean, 3);
+ gain_diff = 0;
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ tmp = abs_s(sub(st->log_en_hist[i], mean));
+ gain_diff = add(gain_diff, tmp);
+ }
+ if (sub(gain_diff, GAIN_THR) > 0)
+ {
+ CN_dith = 1;
+ }
+ return CN_dith;
+}
+
+static void CN_dithering(
+ Word16 isf[M],
+ Word32 * L_log_en_int,
+ Word16 * dither_seed
+)
+{
+ Word16 temp, temp1, i, dither_fac, rand_dith;
+ Word16 rand_dith2;
+
+ /* Insert comfort noise dithering for energy parameter */
+ rand_dith = shr(Random(dither_seed), 1);
+ rand_dith2 = shr(Random(dither_seed), 1);
+ rand_dith = add(rand_dith, rand_dith2);
+ *L_log_en_int = L_add(*L_log_en_int, L_mult(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 = shr(Random(dither_seed), 1);
+ rand_dith2 = shr(Random(dither_seed), 1);
+ rand_dith = add(rand_dith, rand_dith2);
+ temp = add(isf[0], mult_r(rand_dith, dither_fac));
+
+ /* Make sure that isf[0] will not get negative values */
+ if (sub(temp, ISF_GAP) < 0)
+ {
+ isf[0] = ISF_GAP;
+ } else
+ {
+ isf[0] = temp;
+ }
+
+ for (i = 1; i < M - 1; i++)
+ {
+ dither_fac = add(dither_fac, ISF_FACTOR_STEP);
+
+ rand_dith = shr(Random(dither_seed), 1);
+ rand_dith2 = shr(Random(dither_seed), 1);
+ rand_dith = add(rand_dith, rand_dith2);
+ temp = add(isf[i], mult_r(rand_dith, dither_fac));
+ temp1 = sub(temp, isf[i - 1]);
+
+ /* Make sure that isf spacing remains at least ISF_DITH_GAP Hz */
+ if (sub(temp1, ISF_DITH_GAP) < 0)
+ {
+ isf[i] = add(isf[i - 1], ISF_DITH_GAP);
+ } else
+ {
+ isf[i] = temp;
+ }
+ }
+
+ /* Make sure that isf[M-2] will not get values above 16384 */
+ if (sub(isf[M - 2], 16384) > 0)
+ {
+ isf[M - 2] = 16384;
+ }
+ return;
+}
--- /dev/null
+++ b/amr-wb/dtx.h
@@ -1,0 +1,156 @@
+/*--------------------------------------------------------------------------*
+ * DTX.H *
+ *--------------------------------------------------------------------------*
+ * Static memory, constants and frametypes for the DTX *
+ *--------------------------------------------------------------------------*/
+
+
+#ifndef dtx_h
+#define dtx_h
+
+#define DTX_MAX_EMPTY_THRESH 50
+#define DTX_HIST_SIZE 8
+#define DTX_HIST_SIZE_MIN_ONE 7
+#define DTX_ELAPSED_FRAMES_THRESH (24 + 7 -1)
+#define DTX_HANG_CONST 7 /* yields eight frames of SP HANGOVER */
+#define INV_MED_THRESH 14564
+#define ISF_GAP 128 /* 50 */
+#define ONE_MINUS_ISF_GAP 16384 - ISF_GAP
+
+#define ISF_GAP 128
+#define ISF_DITH_GAP 448
+#define ISF_FACTOR_LOW 256
+#define ISF_FACTOR_STEP 2
+
+#define GAIN_THR 180
+#define GAIN_FACTOR 75
+
+typedef struct
+{
+ Word16 isf_hist[M * DTX_HIST_SIZE];
+ Word16 log_en_hist[DTX_HIST_SIZE];
+ Word16 hist_ptr;
+ Word16 log_en_index;
+ Word16 cng_seed;
+
+ /* DTX handler stuff */
+ Word16 dtxHangoverCount;
+ Word16 decAnaElapsedCount;
+ Word32 D[28];
+ Word32 sumD[DTX_HIST_SIZE];
+} dtx_encState;
+
+#define SPEECH 0
+#define DTX 1
+#define DTX_MUTE 2
+
+#define TX_SPEECH 0
+#define TX_SID_FIRST 1
+#define TX_SID_UPDATE 2
+#define TX_NO_DATA 3
+
+#define RX_SPEECH_GOOD 0
+#define RX_SPEECH_PROBABLY_DEGRADED 1
+#define RX_SPEECH_LOST 2
+#define RX_SPEECH_BAD 3
+#define RX_SID_FIRST 4
+#define RX_SID_UPDATE 5
+#define RX_SID_BAD 6
+#define RX_NO_DATA 7
+
+/*****************************************************************************
+ *
+ * DEFINITION OF DATA TYPES
+ *****************************************************************************/
+
+typedef struct
+{
+ Word16 since_last_sid;
+ Word16 true_sid_period_inv;
+ Word16 log_en;
+ Word16 old_log_en;
+ Word16 level;
+ Word16 isf[M];
+ Word16 isf_old[M];
+ Word16 cng_seed;
+
+ Word16 isf_hist[M * DTX_HIST_SIZE];
+ Word16 log_en_hist[DTX_HIST_SIZE];
+ Word16 hist_ptr;
+
+ Word16 dtxHangoverCount;
+ Word16 decAnaElapsedCount;
+
+ Word16 sid_frame;
+ Word16 valid_data;
+ Word16 dtxHangoverAdded;
+
+ Word16 dtxGlobalState; /* contains previous state */
+ /* updated in main decoder */
+
+ Word16 data_updated; /* marker to know if CNI data is ever renewed */
+
+ Word16 dither_seed;
+ Word16 CN_dith;
+
+} dtx_decState;
+
+Word16 dtx_enc_init(dtx_encState ** st, Word16 isf_init[]);
+Word16 dtx_enc_reset(dtx_encState * st, Word16 isf_init[]);
+void dtx_enc_exit(dtx_encState ** st);
+
+Word16 dtx_enc(
+ dtx_encState * st, /* i/o : State struct */
+ Word16 isf[M], /* o : CN ISF vector */
+ Word16 * exc2, /* o : CN excitation */
+ Word16 ** prms
+);
+
+Word16 dtx_buffer(
+ dtx_encState * st, /* i/o : State struct */
+ Word16 isf_new[], /* i : isf vector */
+ Word32 enr, /* i : residual energy (in L_FRAME) */
+ Word16 codec_mode
+);
+
+void tx_dtx_handler(dtx_encState * st, /* i/o : State struct */
+ Word16 vad_flag, /* i : vad decision */
+ Word16 * usedMode /* i/o : mode changed or not */
+);
+
+void Qisf_ns(
+ Word16 * isf1, /* input : ISF in the frequency domain (0..0.5) */
+ Word16 * isf_q, /* output: quantized ISF */
+ Word16 * indice /* output: quantization indices */
+);
+
+
+Word16 dtx_dec_init(dtx_decState ** st, Word16 isf_init[]);
+Word16 dtx_dec_reset(dtx_decState * st, Word16 isf_init[]);
+void dtx_dec_exit(dtx_decState ** st);
+
+Word16 dtx_dec(
+ dtx_decState * st, /* i/o : State struct */
+ Word16 * exc2, /* o : CN excitation */
+ Word16 new_state, /* i : New DTX state */
+ Word16 isf[], /* o : CN ISF vector */
+ Word16 ** prms
+);
+
+void dtx_dec_activity_update(
+ dtx_decState * st,
+ Word16 isf[],
+ Word16 exc[]);
+
+
+Word16 rx_dtx_handler(
+ dtx_decState * st, /* i/o : State struct */
+ Word16 frame_type /* i : Frame type */
+);
+
+void Disf_ns(
+ Word16 * indice, /* input: quantization indices */
+ Word16 * isf_q /* input : ISF in the frequency domain (0..0.5) */
+);
+
+#endif
--- /dev/null
+++ b/amr-wb/g_pitch.c
@@ -1,0 +1,60 @@
+/*-------------------------------------------------------------------*
+ * G_PITCH.C *
+ *-------------------------------------------------------------------*
+ * Compute the gain of pitch. Result in Q12 *
+ * if (gain < 0) gain =0 *
+ * if (gain > 1.2) gain =1.2 *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "math_op.h"
+#include "count.h"
+
+
+Word16 G_pitch( /* (o) Q14 : Gain of pitch lag saturated to 1.2 */
+ Word16 xn[], /* (i) : Pitch target. */
+ Word16 y1[], /* (i) : filtered adaptive codebook. */
+ Word16 g_coeff[], /* : Correlations need for gain quantization. */
+ Word16 L_subfr /* : Length of subframe. */
+)
+{
+ Word16 i;
+ Word16 xy, yy, exp_xy, exp_yy, gain;
+
+ /* Compute scalar product <y1[],y1[]> */
+
+ yy = extract_h(Dot_product12(y1, y1, L_subfr, &exp_yy));
+
+ /* Compute scalar product <xn[],y1[]> */
+
+ xy = extract_h(Dot_product12(xn, y1, L_subfr, &exp_xy));
+
+ g_coeff[0] = yy; move16();
+ g_coeff[1] = exp_yy; move16();
+ g_coeff[2] = xy; move16();
+ g_coeff[3] = exp_xy; move16();
+
+ /* If (xy < 0) gain = 0 */
+ test();
+ if (xy < 0)
+ return ((Word16) 0);
+
+ /* compute gain = xy/yy */
+
+ xy = shr(xy, 1); /* Be sure xy < yy */
+ gain = div_s(xy, yy);
+
+ i = add(exp_xy, 1 - 1); /* -1 -> gain in Q14 */
+ i = sub(i, exp_yy);
+
+ gain = shl(gain, i); /* saturation can occur here */
+
+ /* if (gain > 1.2) gain = 1.2 in Q14 */
+ test();
+ if (sub(gain, 19661) > 0)
+ {
+ gain = 19661; move16();
+ }
+ return (gain);
+}
--- /dev/null
+++ b/amr-wb/gpclip.c
@@ -1,0 +1,97 @@
+/*-----------------------------------------------------------------*
+ * GPCLIP.C *
+ *-----------------------------------------------------------------*
+ * To avoid unstable synthesis on frame erasure, the gain need to *
+ * be limited (gain pitch < 1.0) when the following case occurs: *
+ * - a resonance on LPC filter (lp_disp < 60 Hz) *
+ * - a good pitch prediction (lp_gp > 0.95) *
+ *-----------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+#define DIST_ISF_MAX 307 /* 120 Hz (6400Hz=16384) */
+#define DIST_ISF_THRES 154 /* 60 (6400Hz=16384) */
+#define GAIN_PIT_THRES 14746 /* 0.9 in Q14 */
+#define GAIN_PIT_MIN 9830 /* 0.6 in Q14 */
+#define M 16
+
+
+void Init_gp_clip(
+ Word16 mem[] /* (o) : memory of gain of pitch clipping algorithm */
+)
+{
+ mem[0] = DIST_ISF_MAX; move16();
+ mem[1] = GAIN_PIT_MIN; move16();
+}
+
+
+Word16 Gp_clip(
+ Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */
+)
+{
+ Word16 clip;
+
+ clip = 0; move16(); /* move16 */
+ test();
+ if ((sub(mem[0], DIST_ISF_THRES) < 0) && (sub(mem[1], GAIN_PIT_THRES) > 0))
+ clip = 1; move16();
+
+ return (clip);
+}
+
+
+void Gp_clip_test_isf(
+ Word16 isf[], /* (i) : isf values (in frequency domain) */
+ Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */
+)
+{
+ Word16 i, dist, dist_min;
+
+ dist_min = sub(isf[1], isf[0]);
+
+ for (i = 2; i < M - 1; i++)
+ {
+ dist = sub(isf[i], isf[i - 1]);
+ test();
+ if (sub(dist, dist_min) < 0)
+ {
+ dist_min = dist; move16();
+ }
+ }
+
+ dist = extract_h(L_mac(L_mult(26214, mem[0]), 6554, dist_min));
+
+ test();
+ if (sub(dist, DIST_ISF_MAX) > 0)
+ {
+ dist = DIST_ISF_MAX; move16();
+ }
+ mem[0] = dist; move16();
+
+ return;
+}
+
+
+void Gp_clip_test_gain_pit(
+ Word16 gain_pit, /* (i) Q14 : gain of quantized pitch */
+ Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */
+)
+{
+ Word16 gain;
+ Word32 L_tmp;
+
+ L_tmp = L_mult(29491, mem[1]);
+ L_tmp = L_mac(L_tmp, 3277, gain_pit);
+ gain = extract_h(L_tmp);
+
+ test();
+ if (sub(gain, GAIN_PIT_MIN) < 0)
+ {
+ gain = GAIN_PIT_MIN; move16();
+ }
+ mem[1] = gain; move16();
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/grid100.tab
@@ -1,0 +1,35 @@
+/*-------------------------------------------------------------*
+ * Table for az_isp() *
+ * *
+ * Vector grid[] is in Q15 *
+ * *
+ * grid[0] = 1.0; *
+ * grid[grid_points+1] = -1.0; *
+ * for (i = 1; i < grid_points; i++) *
+ * grid[i] = cos((6.283185307*i)/(2.0*grid_points)); *
+ * *
+ *-------------------------------------------------------------*/
+
+/* Version 101 points */
+
+#define GRID_POINTS 100
+
+Word16 grid[GRID_POINTS+1] ={
+ 32767, 32751, 32703, 32622, 32509, 32364,
+ 32187, 31978, 31738, 31466, 31164, 30830,
+ 30466, 30072, 29649, 29196, 28714, 28204,
+ 27666, 27101, 26509, 25891, 25248, 24579,
+ 23886, 23170, 22431, 21669, 20887, 20083,
+ 19260, 18418, 17557, 16680, 15786, 14876,
+ 13951, 13013, 12062, 11099, 10125, 9141,
+ 8149, 7148, 6140, 5126, 4106, 3083,
+ 2057, 1029, 0, -1029, -2057, -3083,
+ -4106, -5126, -6140, -7148, -8149, -9141,
+ -10125, -11099, -12062, -13013, -13951, -14876,
+ -15786, -16680, -17557, -18418, -19260, -20083,
+ -20887, -21669, -22431, -23170, -23886, -24579,
+ -25248, -25891, -26509, -27101, -27666, -28204,
+ -28714, -29196, -29649, -30072, -30466, -30830,
+ -31164, -31466, -31738, -31978, -32187, -32364,
+ -32509, -32622, -32703, -32751, -32760};
+
--- /dev/null
+++ b/amr-wb/ham_wind.tab
@@ -1,0 +1,56 @@
+/* Hamming_cos window for LPC analysis. */
+/* Create with function hamm_cos(window,384-128,128) */
+
+#define L_WINDOW 384
+
+Word16 window[L_WINDOW] = {
+ 2621, 2622, 2626, 2632, 2640, 2650, 2662, 2677,
+ 2694, 2714, 2735, 2759, 2785, 2814, 2844, 2877,
+ 2912, 2949, 2989, 3031, 3075, 3121, 3169, 3220,
+ 3273, 3328, 3385, 3444, 3506, 3569, 3635, 3703,
+ 3773, 3845, 3919, 3996, 4074, 4155, 4237, 4321,
+ 4408, 4496, 4587, 4680, 4774, 4870, 4969, 5069,
+ 5171, 5275, 5381, 5489, 5599, 5710, 5824, 5939,
+ 6056, 6174, 6295, 6417, 6541, 6666, 6793, 6922,
+ 7052, 7185, 7318, 7453, 7590, 7728, 7868, 8009,
+ 8152, 8296, 8442, 8589, 8737, 8887, 9038, 9191,
+ 9344, 9499, 9655, 9813, 9971, 10131, 10292, 10454,
+ 10617, 10781, 10946, 11113, 11280, 11448, 11617, 11787,
+ 11958, 12130, 12303, 12476, 12650, 12825, 13001, 13178,
+ 13355, 13533, 13711, 13890, 14070, 14250, 14431, 14612,
+ 14793, 14975, 15158, 15341, 15524, 15708, 15891, 16076,
+ 16260, 16445, 16629, 16814, 16999, 17185, 17370, 17555,
+ 17740, 17926, 18111, 18296, 18481, 18666, 18851, 19036,
+ 19221, 19405, 19589, 19773, 19956, 20139, 20322, 20504,
+ 20686, 20867, 21048, 21229, 21408, 21588, 21767, 21945,
+ 22122, 22299, 22475, 22651, 22825, 22999, 23172, 23344,
+ 23516, 23686, 23856, 24025, 24192, 24359, 24525, 24689,
+ 24853, 25016, 25177, 25337, 25496, 25654, 25811, 25967,
+ 26121, 26274, 26426, 26576, 26725, 26873, 27019, 27164,
+ 27308, 27450, 27590, 27729, 27867, 28003, 28137, 28270,
+ 28401, 28531, 28659, 28785, 28910, 29033, 29154, 29274,
+ 29391, 29507, 29622, 29734, 29845, 29953, 30060, 30165,
+ 30268, 30370, 30469, 30566, 30662, 30755, 30847, 30936,
+ 31024, 31109, 31193, 31274, 31354, 31431, 31506, 31579,
+ 31651, 31719, 31786, 31851, 31914, 31974, 32032, 32088,
+ 32142, 32194, 32243, 32291, 32336, 32379, 32419, 32458,
+ 32494, 32528, 32560, 32589, 32617, 32642, 32664, 32685,
+ 32703, 32719, 32733, 32744, 32753, 32760, 32764, 32767,
+ 32767, 32765, 32757, 32745, 32727, 32705, 32678, 32646,
+ 32609, 32567, 32520, 32468, 32411, 32349, 32283, 32211,
+ 32135, 32054, 31968, 31877, 31781, 31681, 31575, 31465,
+ 31351, 31231, 31107, 30978, 30844, 30706, 30563, 30415,
+ 30263, 30106, 29945, 29779, 29609, 29434, 29255, 29071,
+ 28883, 28691, 28494, 28293, 28087, 27878, 27664, 27446,
+ 27224, 26997, 26767, 26533, 26294, 26052, 25806, 25555,
+ 25301, 25043, 24782, 24516, 24247, 23974, 23698, 23418,
+ 23134, 22847, 22557, 22263, 21965, 21665, 21361, 21054,
+ 20743, 20430, 20113, 19794, 19471, 19146, 18817, 18486,
+ 18152, 17815, 17476, 17134, 16789, 16442, 16092, 15740,
+ 15385, 15028, 14669, 14308, 13944, 13579, 13211, 12841,
+ 12470, 12096, 11721, 11344, 10965, 10584, 10202, 9819,
+ 9433, 9047, 8659, 8270, 7879, 7488, 7095, 6701,
+ 6306, 5910, 5514, 5116, 4718, 4319, 3919, 3519,
+ 3118, 2716, 2315, 1913, 1510, 1108, 705, 302};
+
+
--- /dev/null
+++ b/amr-wb/homing.c
@@ -1,0 +1,121 @@
+/*------------------------------------------------------------------------*
+ * HOMING.C *
+ *------------------------------------------------------------------------*
+ * Performs the homing routines *
+ *------------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "cnst.h"
+#include "basic_op.h"
+#include "bits.h"
+
+#include "homing.tab"
+
+Word16 encoder_homing_frame_test(Word16 input_frame[])
+{
+ Word16 i, j = 0;
+
+ /* check 320 input samples for matching EHF_MASK: defined in e_homing.h */
+ for (i = 0; i < L_FRAME16k; i++)
+ {
+ j = (Word16) (input_frame[i] ^ EHF_MASK);
+
+ if (j)
+ break;
+ }
+
+ return (Word16) (!j);
+}
+
+static Word16 dhf_test(Word16 input_frame[], Word16 mode, Word16 nparms)
+{
+ Word16 i, j, tmp, shift;
+ Word16 param[DHF_PARMS_MAX];
+ Word16 *prms;
+
+ prms = input_frame;
+ j = 0;
+ i = 0;
+
+ if (sub(mode, MRDTX) != 0)
+ {
+ if (sub(mode, MODE_24k) != 0)
+ {
+ /* convert the received serial bits */
+ tmp = sub(nparms, 15);
+ while (sub(tmp, j) > 0)
+ {
+ param[i] = Serial_parm(15, &prms);
+ j = add(j, 15);
+ i = add(i, 1);
+ }
+ tmp = sub(nparms, j);
+ param[i] = Serial_parm(tmp, &prms);
+ shift = sub(15, tmp);
+ param[i] = shl(param[i], shift);
+ }
+ else
+ {
+ /*If mode is 23.85Kbit/s, remove high band energy bits */
+ for (i = 0; i < 10; i++)
+ {
+ param[i] = Serial_parm(15, &prms);
+ }
+ param[10] = Serial_parm(15, &prms) & 0x61FF;
+ for (i = 11; i < 17; i++)
+ {
+ param[i] = Serial_parm(15, &prms);
+ }
+ param[17] = Serial_parm(15, &prms) & 0xE0FF;
+ for (i = 18; i < 24; i++)
+ {
+ param[i] = Serial_parm(15, &prms);
+ }
+ param[24] = Serial_parm(15, &prms) & 0x7F0F;
+ for (i = 25; i < 31; i++)
+ {
+ param[i] = Serial_parm(15, &prms);
+ }
+ tmp = Serial_parm(8, &prms);
+ param[31] = shl(tmp,7);
+ shift=0;
+ }
+
+ /* check if the parameters matches the parameters of the corresponding decoder homing frame */
+ tmp = i;
+ j = 0;
+ for (i = 0; i < tmp; i++)
+ {
+ j = (Word16) (param[i] ^ dhf[mode][i]);
+ if (j)
+ break;
+ }
+ tmp = 0x7fff;
+ tmp = shr(tmp, shift);
+ tmp = shl(tmp, shift);
+ tmp = (Word16) (dhf[mode][i] & tmp);
+ tmp = (Word16) (param[i] ^ tmp);
+ j = (Word16) (j | tmp);
+
+ }
+ else
+ {
+ j = 1;
+ }
+
+ return (Word16) (!j);
+}
+
+
+Word16 decoder_homing_frame_test(Word16 input_frame[], Word16 mode)
+{
+ /* perform test for COMPLETE parameter frame */
+ return dhf_test(input_frame, mode, nb_of_bits[mode]);
+}
+
+
+Word16 decoder_homing_frame_test_first(Word16 input_frame[], Word16 mode)
+{
+ /* perform test for FIRST SUBFRAME of parameter frame ONLY */
+ return dhf_test(input_frame, mode, prmnofsf[mode]);
+}
--- /dev/null
+++ b/amr-wb/homing.tab
@@ -1,0 +1,132 @@
+/*-----------------------------------------------------*
+ | Tables for homing |
+ *-----------------------------------------------------*/
+
+
+#define DHF_PARMS_MAX 32 /* homing frame pattern */
+#define NUM_OF_SPMODES 9
+
+#define PRML 15
+#define PRMN_7k NBBITS_7k/PRML + 1
+#define PRMN_9k NBBITS_9k/PRML + 1
+#define PRMN_12k NBBITS_12k/PRML + 1
+#define PRMN_14k NBBITS_14k/PRML + 1
+#define PRMN_16k NBBITS_16k/PRML + 1
+#define PRMN_18k NBBITS_18k/PRML + 1
+#define PRMN_20k NBBITS_20k/PRML + 1
+#define PRMN_23k NBBITS_23k/PRML + 1
+#define PRMN_24k NBBITS_24k/PRML + 1
+
+Word16 prmnofsf[NUM_OF_SPMODES]=
+{
+ 63, 81, 100,
+ 108, 116, 128,
+ 136, 152, 156
+};
+
+
+static const Word16 dfh_M7k[PRMN_7k] =
+{
+ 3168, 29954, 29213, 16121,
+ 64, 13440, 30624, 16430,
+ 19008
+};
+
+static const Word16 dfh_M9k[PRMN_9k] =
+{
+ 3168, 31665, 9943, 9123,
+ 15599, 4358, 20248, 2048,
+ 17040, 27787, 16816, 13888
+};
+
+static const Word16 dfh_M12k[PRMN_12k] =
+{
+ 3168, 31665, 9943, 9128,
+ 3647, 8129, 30930, 27926,
+ 18880, 12319, 496, 1042,
+ 4061, 20446, 25629, 28069,
+ 13948
+};
+
+static const Word16 dfh_M14k[PRMN_14k] =
+{
+ 3168, 31665, 9943, 9131,
+ 24815, 655, 26616, 26764,
+ 7238, 19136, 6144, 88,
+ 4158, 25733, 30567, 30494,
+ 221, 20321, 17823
+};
+
+static const Word16 dfh_M16k[PRMN_16k] =
+{
+ 3168, 31665, 9943, 9131,
+ 24815, 700, 3824, 7271,
+ 26400, 9528, 6594, 26112,
+ 108, 2068, 12867, 16317,
+ 23035, 24632, 7528, 1752,
+ 6759, 24576
+};
+
+static const Word16 dfh_M18k[PRMN_18k] =
+{
+ 3168, 31665, 9943, 9135,
+ 14787, 14423, 30477, 24927,
+ 25345, 30154, 916, 5728,
+ 18978, 2048, 528, 16449,
+ 2436, 3581, 23527, 29479,
+ 8237, 16810, 27091, 19052,
+ 0
+};
+
+static const Word16 dfh_M20k[PRMN_20k] =
+{
+ 3168, 31665, 9943, 9129,
+ 8637, 31807, 24646, 736,
+ 28643, 2977, 2566, 25564,
+ 12930, 13960, 2048, 834,
+ 3270, 4100, 26920, 16237,
+ 31227, 17667, 15059, 20589,
+ 30249, 29123, 0
+};
+
+static const Word16 dfh_M23k[PRMN_23k] =
+{
+ 3168, 31665, 9943, 9132,
+ 16748, 3202, 28179, 16317,
+ 30590, 15857, 19960, 8818,
+ 21711, 21538, 4260, 16690,
+ 20224, 3666, 4194, 9497,
+ 16320, 15388, 5755, 31551,
+ 14080, 3574, 15932, 50,
+ 23392, 26053, 31216
+};
+
+static const Word16 dfh_M24k[PRMN_24k] =
+{
+ 3168, 31665, 9943, 9134,
+ 24776, 5857, 18475, 28535,
+ 29662, 14321, 16725, 4396,
+ 29353, 10003, 17068, 20504,
+ 720, 0, 8465, 12581,
+ 28863, 24774, 9709, 26043,
+ 7941, 27649, 13965, 15236,
+ 18026, 22047, 16681, 3968
+};
+
+
+/* overall table with the parameters of the
+ decoder homing frames for all modes */
+
+static const Word16 *dhf[] =
+{
+ dfh_M7k,
+ dfh_M9k,
+ dfh_M12k,
+ dfh_M14k,
+ dfh_M16k,
+ dfh_M18k,
+ dfh_M20k,
+ dfh_M23k,
+ dfh_M24k,
+ dfh_M24k
+};
--- /dev/null
+++ b/amr-wb/hp400.c
@@ -1,0 +1,98 @@
+/*-----------------------------------------------------------------------*
+ * HP400.C *
+ *-----------------------------------------------------------------------*
+ * 2nd order high pass filter with cut off frequency at 400 Hz. *
+ * Designed with cheby2 function in MATLAB. *
+ * Optimized for fixed-point to get the following frequency response: *
+ * *
+ * frequency: 0Hz 100Hz 200Hz 300Hz 400Hz 630Hz 1.5kHz 3kHz *
+ * dB loss: -infdB -30dB -20dB -10dB -3dB +6dB +1dB 0dB *
+ * *
+ * Algorithm: *
+ * *
+ * y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] *
+ * + a[1]*y[i-1] + a[2]*y[i-2]; *
+ * *
+ * Word16 b[3] = {3660, -7320, 3660}; in Q12 *
+ * Word16 a[3] = {4096, 7320, -3540}; in Q12 *
+ * *
+ * float --> b[3] = {0.893554687, -1.787109375, 0.893554687}; *
+ * a[3] = {1.000000000, 1.787109375, -0.864257812}; *
+ *-----------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "acelp.h"
+#include "count.h"
+
+/* filter coefficients */
+
+static Word16 b[3] = {915, -1830, 915}; /* Q12 (/4) */
+static Word16 a[3] = {16384, 29280, -14160}; /* Q12 (x4) */
+
+
+/* Initialization of static values */
+
+void Init_HP400_12k8(Word16 mem[])
+{
+ Set_zero(mem, 6);
+}
+
+
+void HP400_12k8(
+ Word16 signal[], /* input signal / output is divided by 16 */
+ Word16 lg, /* lenght of signal */
+ Word16 mem[] /* filter memory [6] */
+)
+{
+ Word16 i, x2;
+ Word16 y2_hi, y2_lo, y1_hi, y1_lo, x0, x1;
+ Word32 L_tmp;
+
+ y2_hi = mem[0]; move16();
+ y2_lo = mem[1]; move16();
+ y1_hi = mem[2]; move16();
+ y1_lo = mem[3]; move16();
+ x0 = mem[4]; move16();
+ x1 = mem[5]; move16();
+
+ for (i = 0; i < lg; i++)
+ {
+ x2 = x1; move16();
+ x1 = x0; move16();
+ x0 = signal[i]; move16();
+
+ /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b140[2]*x[i-2] */
+ /* + a[1]*y[i-1] + a[2] * y[i-2]; */
+
+ move32();
+ L_tmp = 16384L; /* rounding to maximise precision */
+ L_tmp = L_mac(L_tmp, y1_lo, a[1]);
+ L_tmp = L_mac(L_tmp, y2_lo, a[2]);
+ L_tmp = L_shr(L_tmp, 15);
+ L_tmp = L_mac(L_tmp, y1_hi, a[1]);
+ L_tmp = L_mac(L_tmp, y2_hi, a[2]);
+ L_tmp = L_mac(L_tmp, x0, b[0]);
+ L_tmp = L_mac(L_tmp, x1, b[1]);
+ L_tmp = L_mac(L_tmp, x2, b[2]);
+
+ L_tmp = L_shl(L_tmp, 1); /* coeff Q12 --> Q13 */
+
+ y2_hi = y1_hi; move16();
+ y2_lo = y1_lo; move16();
+ L_Extract(L_tmp, &y1_hi, &y1_lo);
+
+ /* signal is divided by 16 to avoid overflow in energy computation */
+ signal[i] = round(L_tmp); move16();
+ }
+
+ mem[0] = y2_hi; move16();
+ mem[1] = y2_lo; move16();
+ mem[2] = y1_hi; move16();
+ mem[3] = y1_lo; move16();
+ mem[4] = x0; move16();
+ mem[5] = x1; move16();
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/hp50.c
@@ -1,0 +1,97 @@
+/*-----------------------------------------------------------------------*
+ * HP50.C *
+ *-----------------------------------------------------------------------*
+ * 2nd order high pass filter with cut off frequency at 31 Hz. *
+ * Designed with cheby2 function in MATLAB. *
+ * Optimized for fixed-point to get the following frequency response: *
+ * *
+ * frequency: 0Hz 14Hz 24Hz 31Hz 37Hz 41Hz 47Hz *
+ * dB loss: -infdB -15dB -6dB -3dB -1.5dB -1dB -0.5dB *
+ * *
+ * Algorithm: *
+ * *
+ * y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] *
+ * + a[1]*y[i-1] + a[2]*y[i-2]; *
+ * *
+ * Word16 b[3] = {4053, -8106, 4053}; in Q12 *
+ * Word16 a[3] = {8192, 16211, -8021}; in Q12 *
+ * *
+ * float --> b[3] = {0.989501953, -1.979003906, 0.989501953}; *
+ * a[3] = {1.000000000, 1.978881836, -0.979125977}; *
+ *-----------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "cnst.h"
+#include "acelp.h"
+#include "count.h"
+
+/* filter coefficients */
+static Word16 b[3] = {4053, -8106, 4053}; /* Q12 */
+static Word16 a[3] = {8192, 16211, -8021}; /* Q12 (x2) */
+
+/* Initialization of static values */
+
+void Init_HP50_12k8(Word16 mem[])
+{
+ Set_zero(mem, 6);
+}
+
+
+void HP50_12k8(
+ Word16 signal[], /* input/output signal */
+ Word16 lg, /* lenght of signal */
+ Word16 mem[] /* filter memory [6] */
+)
+{
+ Word16 i, x2;
+ Word16 y2_hi, y2_lo, y1_hi, y1_lo, x0, x1;
+ Word32 L_tmp;
+
+ y2_hi = mem[0]; move16();
+ y2_lo = mem[1]; move16();
+ y1_hi = mem[2]; move16();
+ y1_lo = mem[3]; move16();
+ x0 = mem[4]; move16();
+ x1 = mem[5]; move16();
+
+ for (i = 0; i < lg; i++)
+ {
+ x2 = x1; move16();
+ x1 = x0; move16();
+ x0 = signal[i]; move16();
+
+ /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b140[2]*x[i-2] */
+ /* + a[1]*y[i-1] + a[2] * y[i-2]; */
+
+ move32();
+ L_tmp = 16384L; /* rounding to maximise precision */
+ L_tmp = L_mac(L_tmp, y1_lo, a[1]);
+ L_tmp = L_mac(L_tmp, y2_lo, a[2]);
+ L_tmp = L_shr(L_tmp, 15);
+ L_tmp = L_mac(L_tmp, y1_hi, a[1]);
+ L_tmp = L_mac(L_tmp, y2_hi, a[2]);
+ L_tmp = L_mac(L_tmp, x0, b[0]);
+ L_tmp = L_mac(L_tmp, x1, b[1]);
+ L_tmp = L_mac(L_tmp, x2, b[2]);
+
+ L_tmp = L_shl(L_tmp, 2); /* coeff Q12 --> Q14 */
+
+ y2_hi = y1_hi; move16();
+ y2_lo = y1_lo; move16();
+ L_Extract(L_tmp, &y1_hi, &y1_lo);
+
+ L_tmp = L_shl(L_tmp, 1); /* coeff Q14 --> Q15 with saturation */
+ signal[i] = round(L_tmp); move16();
+ }
+
+ mem[0] = y2_hi; move16();
+ mem[1] = y2_lo; move16();
+ mem[2] = y1_hi; move16();
+ mem[3] = y1_lo; move16();
+ mem[4] = x0; move16();
+ mem[5] = x1; move16();
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/hp6k.c
@@ -1,0 +1,66 @@
+/*-------------------------------------------------------------------*
+ * HP6K.C *
+ *-------------------------------------------------------------------*
+ * 15th order band pass 6kHz to 7kHz FIR filter. *
+ * *
+ * frequency: 4kHz 5kHz 5.5kHz 6kHz 6.5kHz 7kHz 7.5kHz 8kHz *
+ * dB loss: -60dB -45dB -13dB -3dB 0dB -3dB -13dB -45dB *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "acelp.h"
+#include "count.h"
+#include "cnst.h"
+
+#define L_FIR 31
+
+/* filter coefficients (gain=4.0) */
+
+static Word16 fir_6k_7k[L_FIR] =
+{
+ -32, 47, 32, -27, -369,
+ 1122, -1421, 0, 3798, -8880,
+ 12349, -10984, 3548, 7766, -18001,
+ 22118, -18001, 7766, 3548, -10984,
+ 12349, -8880, 3798, 0, -1421,
+ 1122, -369, -27, 32, 47,
+ -32
+};
+
+
+void Init_Filt_6k_7k(Word16 mem[]) /* mem[30] */
+{
+ Set_zero(mem, L_FIR - 1);
+
+ return;
+}
+
+void Filt_6k_7k(
+ Word16 signal[], /* input: signal */
+ Word16 lg, /* input: length of input */
+ Word16 mem[] /* in/out: memory (size=30) */
+)
+{
+ Word16 i, j, x[L_SUBFR16k + (L_FIR - 1)];
+ Word32 L_tmp;
+
+ Copy(mem, x, L_FIR - 1);
+
+ for (i = 0; i < lg; i++)
+ {
+ x[i + L_FIR - 1] = shr(signal[i], 2); move16(); /* gain of filter = 4 */
+ }
+
+ for (i = 0; i < lg; i++)
+ {
+ L_tmp = 0; move32();
+ for (j = 0; j < L_FIR; j++)
+ L_tmp = L_mac(L_tmp, x[i + j], fir_6k_7k[j]);
+ signal[i] = round(L_tmp); move16();
+ }
+
+ Copy(x + lg, mem, L_FIR - 1);
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/hp7k.c
@@ -1,0 +1,63 @@
+/*-------------------------------------------------------------------*
+ * HP6K.C *
+ *-------------------------------------------------------------------*
+ * 15th order high pass 7kHz FIR filter. *
+ * *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+#include "acelp.h"
+#include "count.h"
+
+
+#define L_FIR 31
+
+static Word16 fir_7k[L_FIR] =
+{
+ -21, 47, -89, 146, -203,
+ 229, -177, 0, 335, -839,
+ 1485, -2211, 2931, -3542, 3953,
+ 28682, 3953, -3542, 2931, -2211,
+ 1485, -839, 335, 0, -177,
+ 229, -203, 146, -89, 47,
+ -21
+};
+
+void Init_Filt_7k(Word16 mem[]) /* mem[30] */
+{
+ Set_zero(mem, L_FIR - 1);
+
+ return;
+}
+
+
+void Filt_7k(
+ Word16 signal[], /* input: signal */
+ Word16 lg, /* input: length of input */
+ Word16 mem[] /* in/out: memory (size=30) */
+)
+{
+ Word16 i, j, x[L_SUBFR16k + (L_FIR - 1)];
+ Word32 L_tmp;
+
+ Copy(mem, x, L_FIR - 1);
+
+ for (i = 0; i < lg; i++)
+ {
+ x[i + L_FIR - 1] = signal[i]; move16();
+ }
+
+ for (i = 0; i < lg; i++)
+ {
+ L_tmp = 0; move32();
+ for (j = 0; j < L_FIR; j++)
+ L_tmp = L_mac(L_tmp, x[i + j], fir_7k[j]);
+ signal[i] = round(L_tmp); move16();
+ }
+
+ Copy(x + lg, mem, L_FIR - 1);
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/hp_wsp.c
@@ -1,0 +1,139 @@
+/*-----------------------------------------------------------------------*
+ * HP_WSP.C *
+ *-----------------------------------------------------------------------*
+ * *
+ * 3nd order high pass filter with cut off frequency at 180 Hz *
+ * *
+ * Algorithm: *
+ * *
+ * y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] + b[3]*x[i-3] *
+ * + a[1]*y[i-1] + a[2]*y[i-2] + a[3]*y[i-3]; *
+ * *
+ * float a_coef[HP_ORDER]= { *
+ * -2.64436711600664f, *
+ * 2.35087386625360f, *
+ * -0.70001156927424f}; *
+ * *
+ * float b_coef[HP_ORDER+1]= { *
+ * -0.83787057505665f, *
+ * 2.50975570071058f, *
+ * -2.50975570071058f, *
+ * 0.83787057505665f}; *
+ * *
+ *-----------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "acelp.h"
+#include "count.h"
+
+
+/* filter coefficients in Q12 */
+
+static Word16 a[4] = {8192, 21663, -19258, 5734};
+static Word16 b[4] = {-3432, +10280, -10280, +3432};
+
+
+/* Initialization of static values */
+
+void Init_Hp_wsp(Word16 mem[])
+{
+ Set_zero(mem, 9);
+
+ return;
+}
+
+void scale_mem_Hp_wsp(Word16 mem[], Word16 exp)
+{
+ Word16 i;
+ Word32 L_tmp;
+
+ for (i = 0; i < 6; i += 2)
+ {
+ L_tmp = L_Comp(mem[i], mem[i + 1]);/* y_hi, y_lo */
+ L_tmp = L_shl(L_tmp, exp);
+ L_Extract(L_tmp, &mem[i], &mem[i + 1]);
+ }
+
+ for (i = 6; i < 9; i++)
+ {
+ L_tmp = L_deposit_h(mem[i]); /* x[i] */
+ L_tmp = L_shl(L_tmp, exp);
+ mem[i] = round(L_tmp); move16();
+ }
+
+ return;
+}
+
+
+void Hp_wsp(
+ Word16 wsp[], /* i : wsp[] signal */
+ Word16 hp_wsp[], /* o : hypass wsp[] */
+ Word16 lg, /* i : lenght of signal */
+ Word16 mem[] /* i/o : filter memory [9] */
+)
+{
+ Word16 i;
+ Word16 x0, x1, x2, x3;
+ Word16 y3_hi, y3_lo, y2_hi, y2_lo, y1_hi, y1_lo;
+ Word32 L_tmp;
+
+ y3_hi = mem[0]; move16();
+ y3_lo = mem[1]; move16();
+ y2_hi = mem[2]; move16();
+ y2_lo = mem[3]; move16();
+ y1_hi = mem[4]; move16();
+ y1_lo = mem[5]; move16();
+ x0 = mem[6]; move16();
+ x1 = mem[7]; move16();
+ x2 = mem[8]; move16();
+
+ for (i = 0; i < lg; i++)
+ {
+ x3 = x2; move16();
+ x2 = x1; move16();
+ x1 = x0; move16();
+ x0 = wsp[i]; move16();
+
+ /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b140[2]*x[i-2] + b[3]*x[i-3] */
+ /* + a[1]*y[i-1] + a[2] * y[i-2] + a[3]*y[i-3] */
+
+ move32();
+ L_tmp = 16384L; /* rounding to maximise precision */
+ L_tmp = L_mac(L_tmp, y1_lo, a[1]);
+ L_tmp = L_mac(L_tmp, y2_lo, a[2]);
+ L_tmp = L_mac(L_tmp, y3_lo, a[3]);
+ L_tmp = L_shr(L_tmp, 15);
+ L_tmp = L_mac(L_tmp, y1_hi, a[1]);
+ L_tmp = L_mac(L_tmp, y2_hi, a[2]);
+ L_tmp = L_mac(L_tmp, y3_hi, a[3]);
+ L_tmp = L_mac(L_tmp, x0, b[0]);
+ L_tmp = L_mac(L_tmp, x1, b[1]);
+ L_tmp = L_mac(L_tmp, x2, b[2]);
+ L_tmp = L_mac(L_tmp, x3, b[3]);
+
+ L_tmp = L_shl(L_tmp, 2); /* coeff Q12 --> Q15 */
+
+ y3_hi = y2_hi; move16();
+ y3_lo = y2_lo; move16();
+ y2_hi = y1_hi; move16();
+ y2_lo = y1_lo; move16();
+ L_Extract(L_tmp, &y1_hi, &y1_lo);
+
+ L_tmp = L_shl(L_tmp, 1); /* coeff Q14 --> Q15 */
+ hp_wsp[i] = round(L_tmp); move16();
+ }
+
+ mem[0] = y3_hi; move16();
+ mem[1] = y3_lo; move16();
+ mem[2] = y2_hi; move16();
+ mem[3] = y2_lo; move16();
+ mem[4] = y1_hi; move16();
+ mem[5] = y1_lo; move16();
+ mem[6] = x0; move16();
+ mem[7] = x1; move16();
+ mem[8] = x2; move16();
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/int_lpc.c
@@ -1,0 +1,47 @@
+/*-----------------------------------------------------------------------*
+ * HP400.C *
+ *-----------------------------------------------------------------------*
+ * Interpolation of the LP parameters in 4 subframes. *
+ *-----------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+#include "acelp.h"
+#include "count.h"
+
+#define MP1 (M+1)
+
+
+void Int_isp(
+ Word16 isp_old[], /* input : isps from past frame */
+ Word16 isp_new[], /* input : isps from present frame */
+ Word16 frac[], /* input : fraction for 3 first subfr (Q15) */
+ Word16 Az[] /* output: LP coefficients in 4 subframes */
+)
+{
+ Word16 i, k, fac_old, fac_new;
+ Word16 isp[M];
+ Word32 L_tmp;
+
+ for (k = 0; k < 3; k++)
+ {
+ fac_new = frac[k]; move16();
+ fac_old = add(sub(32767, fac_new), 1); /* 1.0 - fac_new */
+
+ for (i = 0; i < M; i++)
+ {
+ L_tmp = L_mult(isp_old[i], fac_old);
+ L_tmp = L_mac(L_tmp, isp_new[i], fac_new);
+ isp[i] = round(L_tmp); move16();
+ }
+ Isp_Az(isp, Az, M, 0);
+ Az += MP1;
+ }
+
+ /* 4th subframe: isp_new (frac=1.0) */
+
+ Isp_Az(isp_new, Az, M, 0);
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/isfextrp.c
@@ -1,0 +1,167 @@
+/*-----------------------------------------------------------------------*
+ * ISFEXTRP.C *
+ *-----------------------------------------------------------------------*
+ * Conversion of 16th-order 12.8kHz ISF vector *
+ * into 20th-order 16kHz ISF vector *
+ *-----------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "cnst.h"
+#include "acelp.h"
+#include "count.h"
+
+#define INV_LENGTH 2731 /* 1/12 */
+
+void Isf_Extrapolation(Word16 HfIsf[])
+{
+ Word16 IsfDiff[M - 2];
+ Word32 IsfCorr[3];
+ Word32 L_tmp;
+ Word16 coeff, mean, tmp, tmp2, tmp3;
+ Word16 exp, exp2, hi, lo;
+ Word16 i, MaxCorr;
+
+ HfIsf[M16k - 1] = HfIsf[M - 1]; move16();
+
+ /* Difference vector */
+ for (i = 1; i < (M - 1); i++)
+ {
+ IsfDiff[i - 1] = sub(HfIsf[i], HfIsf[i - 1]); move16();
+ }
+ L_tmp = 0; move32();
+
+ /* Mean of difference vector */
+ for (i = 3; i < (M - 1); i++)
+ L_tmp = L_mac(L_tmp, IsfDiff[i - 1], INV_LENGTH);
+ mean = round(L_tmp);
+
+ IsfCorr[0] = 0; move32();
+ IsfCorr[1] = 0; move32();
+ IsfCorr[2] = 0; move32();
+
+ tmp = 0; move16();
+ for (i = 0; i < (M - 2); i++)
+ {
+ test();
+ if (sub(IsfDiff[i], tmp) > 0)
+ {
+ tmp = IsfDiff[i]; move16();
+ }
+ }
+ exp = norm_s(tmp);
+ for (i = 0; i < (M - 2); i++)
+ {
+ IsfDiff[i] = shl(IsfDiff[i], exp); move16();
+ }
+ mean = shl(mean, exp);
+ for (i = 7; i < (M - 2); i++)
+ {
+ tmp2 = sub(IsfDiff[i], mean);
+ tmp3 = sub(IsfDiff[i - 2], mean);
+ L_tmp = L_mult(tmp2, tmp3);
+ L_Extract(L_tmp, &hi, &lo);
+ L_tmp = Mpy_32(hi, lo, hi, lo);
+ IsfCorr[0] = L_add(IsfCorr[0], L_tmp); move32();
+ }
+ for (i = 7; i < (M - 2); i++)
+ {
+ tmp2 = sub(IsfDiff[i], mean);
+ tmp3 = sub(IsfDiff[i - 3], mean);
+ L_tmp = L_mult(tmp2, tmp3);
+ L_Extract(L_tmp, &hi, &lo);
+ L_tmp = Mpy_32(hi, lo, hi, lo);
+ IsfCorr[1] = L_add(IsfCorr[1], L_tmp); move32();
+ }
+ for (i = 7; i < (M - 2); i++)
+ {
+ tmp2 = sub(IsfDiff[i], mean);
+ tmp3 = sub(IsfDiff[i - 4], mean);
+ L_tmp = L_mult(tmp2, tmp3);
+ L_Extract(L_tmp, &hi, &lo);
+ L_tmp = Mpy_32(hi, lo, hi, lo);
+ IsfCorr[2] = L_add(IsfCorr[2], L_tmp); move32();
+ }
+ test();
+ if (L_sub(IsfCorr[0], IsfCorr[1]) > 0)
+ {
+ MaxCorr = 0; move16();
+ } else
+ {
+ MaxCorr = 1; move16();
+ }
+
+ test();
+ if (L_sub(IsfCorr[2], IsfCorr[MaxCorr]) > 0)
+ MaxCorr = 2; move16();
+
+ MaxCorr = add(MaxCorr, 1); /* Maximum correlation of difference vector */
+
+ for (i = M - 1; i < (M16k - 1); i++)
+ {
+ tmp = sub(HfIsf[i - 1 - MaxCorr], HfIsf[i - 2 - MaxCorr]);
+ HfIsf[i] = add(HfIsf[i - 1], tmp); move16();
+ }
+
+ /* tmp=7965+(HfIsf[2]-HfIsf[3]-HfIsf[4])/6; */
+ tmp = add(HfIsf[4], HfIsf[3]);
+ tmp = sub(HfIsf[2], tmp);
+ tmp = mult(tmp, 5461);
+ tmp = add(tmp, 20390);
+
+ test();
+ if (sub(tmp, 19456) > 0)
+ { /* Maximum value of ISF should be at most 7600 Hz */
+ tmp = 19456; move16();
+ }
+ tmp = sub(tmp, HfIsf[M - 2]);
+ tmp2 = sub(HfIsf[M16k - 2], HfIsf[M - 2]);
+
+ exp2 = norm_s(tmp2);
+ exp = norm_s(tmp);
+ exp = sub(exp, 1);
+ tmp = shl(tmp, exp);
+ tmp2 = shl(tmp2, exp2);
+ coeff = div_s(tmp, tmp2); /* Coefficient for stretching the ISF vector */
+ exp = sub(exp2, exp);
+
+ for (i = M - 1; i < (M16k - 1); i++)
+ {
+ tmp = mult(sub(HfIsf[i], HfIsf[i - 1]), coeff);
+ IsfDiff[i - (M - 1)] = shl(tmp, exp); move16();
+ }
+
+ for (i = M; i < (M16k - 1); i++)
+ {
+ /* The difference between ISF(n) and ISF(n-2) should be at least 500 Hz */
+ tmp = sub(add(IsfDiff[i - (M - 1)], IsfDiff[i - M]), 1280);
+ test();
+ if (tmp < 0)
+ {
+ test();
+ if (sub(IsfDiff[i - (M - 1)], IsfDiff[i - M]) > 0)
+ {
+ IsfDiff[i - M] = sub(1280, IsfDiff[i - (M - 1)]); move16();
+ } else
+ {
+ IsfDiff[i - (M - 1)] = sub(1280, IsfDiff[i - M]); move16();
+ }
+ }
+ }
+
+ for (i = M - 1; i < (M16k - 1); i++)
+ {
+ HfIsf[i] = add(HfIsf[i - 1], IsfDiff[i - (M - 1)]); move16();
+ }
+
+ for (i = 0; i < (M16k - 1); i++)
+ {
+ move16();
+ HfIsf[i] = mult(HfIsf[i], 26214); /* Scale the ISF vector correctly for 16000 kHz */
+ }
+
+ Isf_isp(HfIsf, HfIsf, M16k);
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/isp_az.c
@@ -1,0 +1,246 @@
+/*-----------------------------------------------------------------------*
+ * ISP_AZ.C *
+ *-----------------------------------------------------------------------*
+ * Compute the LPC coefficients from isp (order=M) *
+ *-----------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "count.h"
+#include "cnst.h"
+
+#define NC (M/2)
+#define NC16k (M16k/2)
+
+/* local function */
+
+static void Get_isp_pol(Word16 * isp, Word32 * f, Word16 n);
+static void Get_isp_pol_16kHz(Word16 * isp, Word32 * f, Word16 n);
+
+void Isp_Az(
+ Word16 isp[], /* (i) Q15 : Immittance spectral pairs */
+ Word16 a[], /* (o) Q12 : predictor coefficients (order = M) */
+ Word16 m,
+ Word16 adaptive_scaling /* (i) 0 : adaptive scaling disabled */
+ /* 1 : adaptive scaling enabled */
+)
+{
+ Word16 i, j, hi, lo;
+ Word32 f1[NC16k + 1], f2[NC16k];
+ Word16 nc;
+ Word32 t0;
+ Word16 q, q_sug;
+ Word32 tmax;
+
+ nc = shr(m, 1);
+ test();
+ if (sub(nc, 8) > 0)
+ {
+ Get_isp_pol_16kHz(&isp[0], f1, nc);
+ for (i = 0; i <= nc; i++)
+ {
+ f1[i] = L_shl(f1[i], 2); move32();
+ }
+ } else
+ Get_isp_pol(&isp[0], f1, nc);
+
+ test();
+ if (sub(nc, 8) > 0)
+ {
+ Get_isp_pol_16kHz(&isp[1], f2, sub(nc, 1));
+ for (i = 0; i <= nc - 1; i++)
+ {
+ f2[i] = L_shl(f2[i], 2); move32();
+ }
+ } else
+ Get_isp_pol(&isp[1], f2, sub(nc, 1));
+
+ /*-----------------------------------------------------*
+ * Multiply F2(z) by (1 - z^-2) *
+ *-----------------------------------------------------*/
+
+ for (i = sub(nc, 1); i > 1; i--)
+ {
+ f2[i] = L_sub(f2[i], f2[i - 2]); move32(); /* f2[i] -= f2[i-2]; */
+ }
+
+ /*----------------------------------------------------------*
+ * Scale F1(z) by (1+isp[m-1]) and F2(z) by (1-isp[m-1]) *
+ *----------------------------------------------------------*/
+
+ for (i = 0; i < nc; i++)
+ {
+ /* f1[i] *= (1.0 + isp[M-1]); */
+
+ L_Extract(f1[i], &hi, &lo);
+ t0 = Mpy_32_16(hi, lo, isp[m - 1]);
+ f1[i] = L_add(f1[i], t0); move32();
+
+ /* f2[i] *= (1.0 - isp[M-1]); */
+
+ L_Extract(f2[i], &hi, &lo);
+ t0 = Mpy_32_16(hi, lo, isp[m - 1]);
+ f2[i] = L_sub(f2[i], t0); move32();
+ }
+
+ /*-----------------------------------------------------*
+ * A(z) = (F1(z)+F2(z))/2 *
+ * F1(z) is symmetric and F2(z) is antisymmetric *
+ *-----------------------------------------------------*/
+
+ /* a[0] = 1.0; */
+ a[0] = 4096; move16();
+ tmax = 1; move32();
+ for (i = 1, j = sub(m, 1); i < nc; i++, j--)
+ {
+ /* a[i] = 0.5*(f1[i] + f2[i]); */
+
+ t0 = L_add(f1[i], f2[i]); /* f1[i] + f2[i] */
+ tmax |= L_abs(t0); logic32();
+ a[i] = extract_l(L_shr_r(t0, 12)); /* from Q23 to Q12 and * 0.5 */
+ move16();
+
+ /* a[j] = 0.5*(f1[i] - f2[i]); */
+
+ t0 = L_sub(f1[i], f2[i]); /* f1[i] - f2[i] */
+ tmax |= L_abs(t0); logic32();
+ a[j] = extract_l(L_shr_r(t0, 12)); /* from Q23 to Q12 and * 0.5 */
+ move16();
+ }
+
+ /* rescale data if overflow has occured and reprocess the loop */
+
+ test();
+ if ( sub(adaptive_scaling, 1) == 0 )
+ q = sub(4, norm_l(tmax)); /* adaptive scaling enabled */
+ else
+ q = 0; move16(); /* adaptive scaling disabled */
+
+ test();
+ if (q > 0)
+ {
+ q_sug = add(12, q);
+ for (i = 1, j = sub(m, 1); i < nc; i++, j--)
+ {
+ /* a[i] = 0.5*(f1[i] + f2[i]); */
+
+ t0 = L_add(f1[i], f2[i]); /* f1[i] + f2[i] */
+ a[i] = extract_l(L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */
+ move16();
+
+ /* a[j] = 0.5*(f1[i] - f2[i]); */
+
+ t0 = L_sub(f1[i], f2[i]); /* f1[i] - f2[i] */
+ a[j] = extract_l(L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */
+ move16();
+ }
+ a[0] = shr(a[0], q); move16();
+ }
+ else
+ {
+ q_sug = 12; move16();
+ q = 0; move16();
+ }
+
+
+ /* a[NC] = 0.5*f1[NC]*(1.0 + isp[M-1]); */
+
+ L_Extract(f1[nc], &hi, &lo);
+ t0 = Mpy_32_16(hi, lo, isp[m - 1]);
+ t0 = L_add(f1[nc], t0);
+ a[nc] = extract_l(L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */
+ move16();
+ /* a[m] = isp[m-1]; */
+
+ a[m] = shr_r(isp[m - 1], add(3,q)); /* from Q15 to Q12 */
+ move16();
+
+ return;
+}
+
+/*-----------------------------------------------------------*
+ * procedure Get_isp_pol: *
+ * ~~~~~~~~~~~ *
+ * Find the polynomial F1(z) or F2(z) from the ISPs. *
+ * This is performed by expanding the product polynomials: *
+ * *
+ * F1(z) = product ( 1 - 2 isp_i z^-1 + z^-2 ) *
+ * i=0,2,4,6,8 *
+ * F2(z) = product ( 1 - 2 isp_i z^-1 + z^-2 ) *
+ * i=1,3,5,7 *
+ * *
+ * where isp_i are the ISPs in the cosine domain. *
+ *-----------------------------------------------------------*
+ * *
+ * Parameters: *
+ * isp[] : isp vector (cosine domaine) in Q15 *
+ * f[] : the coefficients of F1 or F2 in Q23 *
+ * n : == NC for F1(z); == NC-1 for F2(z) *
+ *-----------------------------------------------------------*/
+
+static void Get_isp_pol(Word16 * isp, Word32 * f, Word16 n)
+{
+ Word16 i, j, hi, lo;
+ Word32 t0;
+
+
+ /* All computation in Q23 */
+
+ f[0] = L_mult(4096, 1024); move32(); /* f[0] = 1.0; in Q23 */
+ f[1] = L_mult(isp[0], -256); move32(); /* f[1] = -2.0*isp[0] in Q23 */
+
+ f += 2; move32(); /* Advance f pointer */
+ isp += 2; move16(); /* Advance isp pointer */
+
+ for (i = 2; i <= n; i++)
+ {
+
+ *f = f[-2]; move32();
+
+ for (j = 1; j < i; j++, f--)
+ {
+ L_Extract(f[-1], &hi, &lo);
+ t0 = Mpy_32_16(hi, lo, *isp); /* t0 = f[-1] * isp */
+ t0 = L_shl(t0, 1);
+ *f = L_sub(*f, t0); move32(); /* *f -= t0 */
+ *f = L_add(*f, f[-2]); move32(); /* *f += f[-2] */
+ }
+ *f = L_msu(*f, *isp, 256); move32(); /* *f -= isp<<8 */
+ f += i; /* Advance f pointer */
+ isp += 2; /* Advance isp pointer */
+ }
+ return;
+}
+
+static void Get_isp_pol_16kHz(Word16 * isp, Word32 * f, Word16 n)
+{
+ Word16 i, j, hi, lo;
+ Word32 t0;
+
+ /* All computation in Q23 */
+
+ f[0] = L_mult(4096, 256); move32(); /* f[0] = 1.0; in Q23 */
+ f[1] = L_mult(isp[0], -64); move32(); /* f[1] = -2.0*isp[0] in Q23 */
+
+ f += 2; move32(); /* Advance f pointer */
+ isp += 2; move16(); /* Advance isp pointer */
+
+ for (i = 2; i <= n; i++)
+ {
+ *f = f[-2]; move32();
+
+ for (j = 1; j < i; j++, f--)
+ {
+ L_Extract(f[-1], &hi, &lo);
+ t0 = Mpy_32_16(hi, lo, *isp); /* t0 = f[-1] * isp */
+ t0 = L_shl(t0, 1);
+ *f = L_sub(*f, t0); move32(); /* *f -= t0 */
+ *f = L_add(*f, f[-2]); move32(); /* *f += f[-2] */
+ }
+ *f = L_msu(*f, *isp, 64); move32(); /* *f -= isp<<8 */
+ f += i; /* Advance f pointer */
+ isp += 2; /* Advance isp pointer */
+ }
+ return;
+}
--- /dev/null
+++ b/amr-wb/isp_isf.c
@@ -1,0 +1,81 @@
+/*-------------------------------------------------------------------*
+ * ISP_ISF.C *
+ *-------------------------------------------------------------------*
+ * Isp_isf Transformation isp to isf *
+ * Isf_isp Transformation isf to isp *
+ * *
+ * The transformation from isp[i] to isf[i] and isf[i] to isp[i] are *
+ * approximated by a look-up table and interpolation. *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+#include "isp_isf.tab" /* Look-up table for transformations */
+
+void Isp_isf(
+ Word16 isp[], /* (i) Q15 : isp[m] (range: -1<=val<1) */
+ Word16 isf[], /* (o) Q15 : isf[m] normalized (range: 0.0<=val<=0.5) */
+ Word16 m /* (i) : LPC order */
+)
+{
+ Word16 i, ind;
+ Word32 L_tmp;
+
+ ind = 127; move16(); /* beging at end of table -1 */
+
+ for (i = (Word16) (m - 1); i >= 0; i--)
+ {
+ test();
+ if (sub(i, sub(m, 2)) >= 0)
+ { /* m-2 is a constant */
+ ind = 127; move16(); /* beging at end of table -1 */
+ }
+ /* find value in table that is just greater than isp[i] */
+ test();
+ while (sub(table[ind], isp[i]) < 0)
+ ind--;
+
+ /* acos(isp[i])= ind*128 + ( ( isp[i]-table[ind] ) * slope[ind] )/2048 */
+
+ L_tmp = L_mult(sub(isp[i], table[ind]), slope[ind]);
+ isf[i] = round(L_shl(L_tmp, 4)); /* (isp[i]-table[ind])*slope[ind])>>11 */
+ move16();
+ isf[i] = add(isf[i], shl(ind, 7)); move16();
+ }
+
+ isf[m - 1] = shr(isf[m - 1], 1); move16();
+
+ return;
+}
+
+
+void Isf_isp(
+ Word16 isf[], /* (i) Q15 : isf[m] normalized (range: 0.0<=val<=0.5) */
+ Word16 isp[], /* (o) Q15 : isp[m] (range: -1<=val<1) */
+ Word16 m /* (i) : LPC order */
+)
+{
+ Word16 i, ind, offset;
+ Word32 L_tmp;
+
+ for (i = 0; i < m - 1; i++)
+ {
+ isp[i] = isf[i]; move16();
+ }
+ isp[m - 1] = shl(isf[m - 1], 1);
+
+ for (i = 0; i < m; i++)
+ {
+ ind = shr(isp[i], 7); /* ind = b7-b15 of isf[i] */
+ offset = (Word16) (isp[i] & 0x007f); logic16(); /* offset = b0-b6 of isf[i] */
+
+ /* isp[i] = table[ind]+ ((table[ind+1]-table[ind])*offset) / 128 */
+
+ L_tmp = L_mult(sub(table[ind + 1], table[ind]), offset);
+ isp[i] = add(table[ind], extract_l(L_shr(L_tmp, 8))); move16();
+ }
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/isp_isf.tab
@@ -1,0 +1,45 @@
+/*-----------------------------------------------------*
+ | Tables for function Isf_isp() and Isp_isf() |
+ *-----------------------------------------------------*/
+
+/* table of cos(x) in Q15 */
+
+static Word16 table[129] = {
+ 32767,
+ 32758, 32729, 32679, 32610, 32522, 32413, 32286, 32138,
+ 31972, 31786, 31581, 31357, 31114, 30853, 30572, 30274,
+ 29957, 29622, 29269, 28899, 28511, 28106, 27684, 27246,
+ 26791, 26320, 25833, 25330, 24812, 24279, 23732, 23170,
+ 22595, 22006, 21403, 20788, 20160, 19520, 18868, 18205,
+ 17531, 16846, 16151, 15447, 14733, 14010, 13279, 12540,
+ 11793, 11039, 10279, 9512, 8740, 7962, 7180, 6393,
+ 5602, 4808, 4011, 3212, 2411, 1608, 804, 0,
+ -804, -1608, -2411, -3212, -4011, -4808, -5602, -6393,
+ -7180, -7962, -8740, -9512, -10279, -11039, -11793, -12540,
+ -13279, -14010, -14733, -15447, -16151, -16846, -17531, -18205,
+ -18868, -19520, -20160, -20788, -21403, -22006, -22595, -23170,
+ -23732, -24279, -24812, -25330, -25833, -26320, -26791, -27246,
+ -27684, -28106, -28511, -28899, -29269, -29622, -29957, -30274,
+ -30572, -30853, -31114, -31357, -31581, -31786, -31972, -32138,
+ -32286, -32413, -32522, -32610, -32679, -32729, -32758, -32768};
+
+/* slope in Q11 used to compute y = acos(x) */
+
+static Word16 slope[128] = {
+ -26214, -9039, -5243, -3799, -2979, -2405, -2064, -1771,
+ -1579, -1409, -1279, -1170, -1079, -1004, -933, -880,
+ -827, -783, -743, -708, -676, -647, -621, -599,
+ -576, -557, -538, -521, -506, -492, -479, -466,
+ -456, -445, -435, -426, -417, -410, -402, -395,
+ -389, -383, -377, -372, -367, -363, -359, -355,
+ -351, -348, -345, -342, -340, -337, -335, -333,
+ -331, -330, -329, -328, -327, -326, -326, -326,
+ -326, -326, -326, -327, -328, -329, -330, -331,
+ -333, -335, -337, -340, -342, -345, -348, -351,
+ -355, -359, -363, -367, -372, -377, -383, -389,
+ -395, -402, -410, -417, -426, -435, -445, -456,
+ -466, -479, -492, -506, -521, -538, -557, -576,
+ -599, -621, -647, -676, -708, -743, -783, -827,
+ -880, -933, -1004, -1079, -1170, -1279, -1409, -1579,
+ -1771, -2064, -2405, -2979, -3799, -5243, -9039, -26214};
+
--- /dev/null
+++ b/amr-wb/lag_wind.c
@@ -1,0 +1,33 @@
+/*---------------------------------------------------------*
+ * LAG_WIND.C *
+ *---------------------------------------------------------*
+ * Lag_window on autocorrelations. *
+ * *
+ * r[i] *= lag_wind[i] *
+ * *
+ * r[i] and lag_wind[i] are in special double precision. *
+ * See "oper_32b.c" for the format *
+ *---------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+
+#include "lag_wind.tab"
+
+
+void Lag_window(
+ Word16 r_h[], /* (i/o) : Autocorrelations (msb) */
+ Word16 r_l[] /* (i/o) : Autocorrelations (lsb) */
+)
+{
+ Word16 i;
+ Word32 x;
+
+ for (i = 1; i <= M; i++)
+ {
+ x = Mpy_32(r_h[i], r_l[i], lag_h[i - 1], lag_l[i - 1]);
+ L_Extract(x, &r_h[i], &r_l[i]);
+ }
+ return;
+}
--- /dev/null
+++ b/amr-wb/lag_wind.tab
@@ -1,0 +1,64 @@
+/*-----------------------------------------------------*
+ | Table of lag_window for autocorrelation. |
+ | noise floor = 1.0001 = (0.9999 on r[1] ..r[16]) |
+ | Bandwidth expansion = 60 Hz |
+ | Sampling frequency = 12800 Hz |
+ | |
+ | Special double precision format. See "math_op.c" |
+ | |
+ | lag_wind[0] = 1.00000000 (not stored) |
+ | lag_wind[1] = 0.99946642 |
+ | lag_wind[2] = 0.99816680 |
+ | lag_wind[3] = 0.99600452 |
+ | lag_wind[4] = 0.99298513 |
+ | lag_wind[5] = 0.98911655 |
+ | lag_wind[6] = 0.98440880 |
+ | lag_wind[7] = 0.97887397 |
+ | lag_wind[8] = 0.97252619 |
+ | lag_wind[9] = 0.96538186 |
+ | lag_wind[10]= 0.95745903 |
+ | lag_wind[11]= 0.94877797 |
+ | lag_wind[12]= 0.93936038 |
+ | lag_wind[13]= 0.92922986 |
+ | lag_wind[14]= 0.91841155 |
+ | lag_wind[15]= 0.90693212 |
+ | lag_wind[16]= 0.89481968 |
+ ------------------------------------------------------*/
+
+#define M 16
+
+Word16 lag_h[M] = {
+ 32750,
+ 32707,
+ 32637,
+ 32538,
+ 32411,
+ 32257,
+ 32075,
+ 31867,
+ 31633,
+ 31374,
+ 31089,
+ 30780,
+ 30449,
+ 30094,
+ 29718,
+ 29321};
+
+Word16 lag_l[M] = {
+ 16896,
+ 30464,
+ 2496,
+ 4480,
+ 12160,
+ 3520,
+ 24320,
+ 24192,
+ 20736,
+ 576,
+ 18240,
+ 31488,
+ 128,
+ 16704,
+ 11520,
+ 14784};
--- /dev/null
+++ b/amr-wb/lagconc.c
@@ -1,0 +1,244 @@
+/*---------------------------------------------------------*
+ * LAGCONC.C *
+ *---------------------------------------------------------*
+ * Concealment of LTP lags during bad frames *
+ *---------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+#include "cnst.h"
+#include "acelp.h"
+
+#define L_LTPHIST 5
+#define ONE_PER_3 10923
+#define ONE_PER_LTPHIST 6554
+
+void insertion_sort(Word16 array[], Word16 n);
+void insert(Word16 array[], Word16 num, Word16 x);
+
+void Init_Lagconc(Word16 lag_hist[])
+{
+ Word16 i;
+
+ for (i = 0; i < L_LTPHIST; i++)
+ {
+ lag_hist[i] = 64;
+ }
+}
+
+void lagconc(
+ Word16 gain_hist[], /* (i) : Gain history */
+ Word16 lag_hist[], /* (i) : Subframe size */
+ Word16 * T0,
+ Word16 * old_T0,
+ Word16 * seed,
+ Word16 unusable_frame
+)
+{
+ Word16 maxLag, minLag, lastLag, lagDif, meanLag = 0;
+ Word16 lag_hist2[L_LTPHIST] = {0};
+ Word16 i, tmp, tmp2;
+ Word16 minGain, lastGain, secLastGain;
+ Word16 D, D2;
+
+ /* Is lag index such that it can be aplied directly or does it has to be subtituted */
+
+ lastGain = gain_hist[4]; move16();
+ secLastGain = gain_hist[3]; move16();
+
+ lastLag = lag_hist[0]; move16();
+
+ /***********SMALLEST history lag***********/
+ minLag = lag_hist[0]; move16();
+ for (i = 1; i < L_LTPHIST; i++)
+ {
+ test();
+ if (sub(lag_hist[i], minLag) < 0)
+ {
+ minLag = lag_hist[i]; move16();
+ }
+ }
+ /*******BIGGEST history lag*******/
+ maxLag = lag_hist[0]; move16();
+ for (i = 1; i < L_LTPHIST; i++)
+ {
+ test();
+ if (sub(lag_hist[i], maxLag) > 0)
+ {
+ maxLag = lag_hist[i]; move16();
+ }
+ }
+ /***********SMALLEST history gain***********/
+ minGain = gain_hist[0]; move16();
+ for (i = 1; i < L_LTPHIST; i++)
+ {
+ test();
+ if (sub(gain_hist[i], minGain) < 0)
+ {
+ minGain = gain_hist[i]; move16();
+ }
+ }
+ /***Difference between MAX and MIN lag**/
+ lagDif = sub(maxLag, minLag);
+
+ test();
+ if (unusable_frame != 0)
+ {
+ /* LTP-lag for RX_SPEECH_LOST */
+ /**********Recognition of the LTP-history*********/
+ test();test();test();test();
+ if ((sub(minGain, 8192) > 0) && (sub(lagDif, 10) < 0))
+ {
+ *T0 = *old_T0; move16();
+ } else if (sub(lastGain, 8192) > 0 && sub(secLastGain, 8192) > 0)
+ {
+ *T0 = lag_hist[0]; move16();
+ } else
+ {
+ /********SORT************/
+ /* The sorting of the lag history */
+ for (i = 0; i < L_LTPHIST; i++)
+ {
+ lag_hist2[i] = lag_hist[i];move16();
+ }
+ insertion_sort(lag_hist2, 5);
+
+ /* Lag is weighted towards bigger lags */
+ /* and random variation is added */
+ lagDif = sub(lag_hist2[4], lag_hist2[2]);
+
+ test();
+ if (sub(lagDif, 40) > 0)
+ lagDif = 40; move16();
+
+ D = Random(seed); /* D={-1, ...,1} */
+ /* D2={-lagDif/2..lagDif/2} */
+ tmp = shr(lagDif, 1);
+ D2 = mult(tmp, D);
+ tmp = add(add(lag_hist2[2], lag_hist2[3]), lag_hist2[4]);
+ *T0 = add(mult(tmp, ONE_PER_3), D2); move16();
+ }
+ /* New lag is not allowed to be bigger or smaller than last lag values */
+ test();
+ if (sub(*T0, maxLag) > 0)
+ {
+ *T0 = maxLag; move16();
+ }
+ test();
+ if (sub(*T0, minLag) < 0)
+ {
+ *T0 = minLag; move16();
+ }
+ } else
+ {
+ /* LTP-lag for RX_BAD_FRAME */
+
+ /***********MEAN lag**************/
+ meanLag = 0; move16();
+ for (i = 0; i < L_LTPHIST; i++)
+ {
+ meanLag = add(meanLag, lag_hist[i]);
+ }
+ meanLag = mult(meanLag, ONE_PER_LTPHIST);
+
+ tmp = sub(*T0, maxLag);
+ tmp2 = sub(*T0, lastLag);
+
+ test();test();test();
+ test();test();test();test();
+ test();test();test();test();
+ test();test();test();
+ test();
+ if (sub(lagDif, 10) < 0 && (sub(*T0, sub(minLag, 5)) > 0) && (sub(tmp, 5) < 0))
+ {
+ *T0 = *T0; move16();
+ } else if (sub(lastGain, 8192) > 0 && sub(secLastGain, 8192) > 0 && (add(tmp2, 10) > 0 && sub(tmp2, 10) < 0))
+ {
+ *T0 = *T0; move16();
+ } else if (sub(minGain, 6554) < 0 && sub(lastGain, minGain) == 0 && (sub(*T0, minLag) > 0 && sub(*T0, maxLag) < 0))
+ {
+ *T0 = *T0; move16();
+ } else if (sub(lagDif, 70) < 0 && sub(*T0, minLag) > 0 && sub(*T0, maxLag) < 0)
+ {
+ *T0 = *T0; move16();
+ } else if (sub(*T0, meanLag) > 0 && sub(*T0, maxLag) < 0)
+ {
+ *T0 = *T0; move16();
+ } else
+ {
+ test();test();
+ test();test();
+ if ((sub(minGain, 8192) > 0) & (sub(lagDif, 10) < 0))
+ {
+ *T0 = lag_hist[0]; move16();
+ } else if (sub(lastGain, 8192) > 0 && sub(secLastGain, 8192) > 0)
+ {
+ *T0 = lag_hist[0]; move16();
+ } else
+ {
+ /********SORT************/
+ /* The sorting of the lag history */
+ for (i = 0; i < L_LTPHIST; i++)
+ {
+ lag_hist2[i] = lag_hist[i]; move16();
+ }
+ insertion_sort(lag_hist2, 5);
+
+ /* Lag is weighted towards bigger lags */
+ /* and random variation is added */
+ lagDif = sub(lag_hist2[4], lag_hist2[2]);
+ test();
+ if (sub(lagDif, 40) > 0)
+ lagDif = 40; move16();
+
+ D = Random(seed); /* D={-1,.., 1} */
+ /* D2={-lagDif/2..lagDif/2} */
+ tmp = shr(lagDif, 1);
+ D2 = mult(tmp, D);
+ tmp = add(add(lag_hist2[2], lag_hist2[3]), lag_hist2[4]);
+ *T0 = add(mult(tmp, ONE_PER_3), D2); move16();
+ }
+ /* New lag is not allowed to be bigger or smaller than last lag values */
+ test();
+ if (sub(*T0, maxLag) > 0)
+ {
+ *T0 = maxLag; move16();
+ }
+ test();
+ if (sub(*T0, minLag) < 0)
+ {
+ *T0 = minLag; move16();
+ }
+ }
+ }
+}
+void insertion_sort(Word16 array[], Word16 n)
+{
+ Word16 i;
+
+ for (i = 0; i < n; i++)
+ {
+ insert(array, i, array[i]);
+ }
+}
+
+
+void insert(Word16 array[], Word16 n, Word16 x)
+{
+ Word16 i;
+
+ for (i = (Word16) (n - 1); i >= 0; i--)
+ {
+ test();
+ if (sub(x, array[i]) < 0)
+ {
+ array[i + 1] = array[i]; move16();
+ } else
+ break;
+ }
+ array[i + 1] = x; move16();
+}
--- /dev/null
+++ b/amr-wb/levinson.c
@@ -1,0 +1,232 @@
+/*---------------------------------------------------------------------------*
+ * LEVINSON.C *
+ *---------------------------------------------------------------------------*
+ * *
+ * LEVINSON-DURBIN algorithm in double precision *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * *
+ * Algorithm *
+ * *
+ * R[i] autocorrelations. *
+ * A[i] filter coefficients. *
+ * K reflection coefficients. *
+ * Alpha prediction gain. *
+ * *
+ * Initialization: *
+ * A[0] = 1 *
+ * K = -R[1]/R[0] *
+ * A[1] = K *
+ * Alpha = R[0] * (1-K**2] *
+ * *
+ * Do for i = 2 to M *
+ * *
+ * S = SUM ( R[j]*A[i-j] ,j=1,i-1 ) + R[i] *
+ * *
+ * K = -S / Alpha *
+ * *
+ * An[j] = A[j] + K*A[i-j] for j=1 to i-1 *
+ * where An[i] = new A[i] *
+ * An[i]=K *
+ * *
+ * Alpha=Alpha * (1-K**2) *
+ * *
+ * END *
+ * *
+ * Remarks on the dynamics of the calculations. *
+ * *
+ * The numbers used are in double precision in the following format : *
+ * A = AH <<16 + AL<<1. AH and AL are 16 bit signed integers. *
+ * Since the LSB's also contain a sign bit, this format does not *
+ * correspond to standard 32 bit integers. We use this format since *
+ * it allows fast execution of multiplications and divisions. *
+ * *
+ * "DPF" will refer to this special format in the following text. *
+ * See oper_32b.c *
+ * *
+ * The R[i] were normalized in routine AUTO (hence, R[i] < 1.0). *
+ * The K[i] and Alpha are theoretically < 1.0. *
+ * The A[i], for a sampling frequency of 8 kHz, are in practice *
+ * always inferior to 16.0. *
+ * *
+ * These characteristics allow straigthforward fixed-point *
+ * implementation. We choose to represent the parameters as *
+ * follows : *
+ * *
+ * R[i] Q31 +- .99.. *
+ * K[i] Q31 +- .99.. *
+ * Alpha Normalized -> mantissa in Q31 plus exponent *
+ * A[i] Q27 +- 15.999.. *
+ * *
+ * The additions are performed in 32 bit. For the summation used *
+ * to calculate the K[i], we multiply numbers in Q31 by numbers *
+ * in Q27, with the result of the multiplications in Q27, *
+ * resulting in a dynamic of +- 16. This is sufficient to avoid *
+ * overflow, since the final result of the summation is *
+ * necessarily < 1.0 as both the K[i] and Alpha are *
+ * theoretically < 1.0. *
+ *___________________________________________________________________________*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "acelp.h"
+#include "count.h"
+
+#define M 16
+#define NC (M/2)
+
+void Init_Levinson(
+ Word16 * mem /* output :static memory (18 words) */
+)
+{
+ Set_zero(mem, 18); /* old_A[0..M-1] = 0, old_rc[0..1] = 0 */
+ return;
+}
+
+
+void Levinson(
+ Word16 Rh[], /* (i) : Rh[M+1] Vector of autocorrelations (msb) */
+ Word16 Rl[], /* (i) : Rl[M+1] Vector of autocorrelations (lsb) */
+ Word16 A[], /* (o) Q12 : A[M] LPC coefficients (m = 16) */
+ Word16 rc[], /* (o) Q15 : rc[M] Reflection coefficients. */
+ Word16 * mem /* (i/o) :static memory (18 words) */
+)
+{
+ Word16 i, j;
+ Word16 hi, lo;
+ Word16 Kh, Kl; /* reflection coefficient; hi and lo */
+ Word16 alp_h, alp_l, alp_exp; /* Prediction gain; hi lo and exponent */
+ Word16 Ah[M + 1], Al[M + 1]; /* LPC coef. in double prec. */
+ Word16 Anh[M + 1], Anl[M + 1]; /* LPC coef.for next iteration in double prec. */
+ Word32 t0, t1, t2; /* temporary variable */
+ Word16 *old_A, *old_rc;
+
+ /* Last A(z) for case of unstable filter */
+
+ old_A = mem; move16();
+ old_rc = mem + M; move16();
+
+ /* K = A[1] = -R[1] / R[0] */
+
+ t1 = L_Comp(Rh[1], Rl[1]); /* R[1] in Q31 */
+ t2 = L_abs(t1); /* abs R[1] */
+ t0 = Div_32(t2, Rh[0], Rl[0]); /* R[1]/R[0] in Q31 */
+ test();
+ if (t1 > 0)
+ t0 = L_negate(t0); /* -R[1]/R[0] */
+ L_Extract(t0, &Kh, &Kl); /* K in DPF */
+ rc[0] = Kh; move16();
+ t0 = L_shr(t0, 4); /* A[1] in Q27 */
+ L_Extract(t0, &Ah[1], &Al[1]); /* A[1] in DPF */
+
+ /* Alpha = R[0] * (1-K**2) */
+
+ t0 = Mpy_32(Kh, Kl, Kh, Kl); /* K*K in Q31 */
+ t0 = L_abs(t0); /* Some case <0 !! */
+ t0 = L_sub((Word32) 0x7fffffffL, t0); /* 1 - K*K in Q31 */
+ L_Extract(t0, &hi, &lo); /* DPF format */
+ t0 = Mpy_32(Rh[0], Rl[0], hi, lo); /* Alpha in Q31 */
+
+ /* Normalize Alpha */
+
+ alp_exp = norm_l(t0);
+ t0 = L_shl(t0, alp_exp);
+ L_Extract(t0, &alp_h, &alp_l);
+ /* DPF format */
+
+ /*--------------------------------------*
+ * ITERATIONS I=2 to M *
+ *--------------------------------------*/
+
+ for (i = 2; i <= M; i++)
+ {
+
+ /* t0 = SUM ( R[j]*A[i-j] ,j=1,i-1 ) + R[i] */
+
+ t0 = 0; move32();
+ for (j = 1; j < i; j++)
+ t0 = L_add(t0, Mpy_32(Rh[j], Rl[j], Ah[i - j], Al[i - j]));
+
+ t0 = L_shl(t0, 4); /* result in Q27 -> convert to Q31 */
+ /* No overflow possible */
+ t1 = L_Comp(Rh[i], Rl[i]);
+ t0 = L_add(t0, t1); /* add R[i] in Q31 */
+
+ /* K = -t0 / Alpha */
+
+ t1 = L_abs(t0);
+ t2 = Div_32(t1, alp_h, alp_l); /* abs(t0)/Alpha */
+ test();
+ if (t0 > 0)
+ t2 = L_negate(t2); /* K =-t0/Alpha */
+ t2 = L_shl(t2, alp_exp); /* denormalize; compare to Alpha */
+ L_Extract(t2, &Kh, &Kl); /* K in DPF */
+ rc[i - 1] = Kh; move16();
+
+ /* Test for unstable filter. If unstable keep old A(z) */
+
+ test();
+ if (sub(abs_s(Kh), 32750) > 0)
+ {
+ A[0] = 4096; move16(); /* Ai[0] not stored (always 1.0) */
+ for (j = 0; j < M; j++)
+ {
+ A[j + 1] = old_A[j]; move16();
+ }
+ rc[0] = old_rc[0]; /* only two rc coefficients are needed */
+ rc[1] = old_rc[1];
+ move16();move16();
+ return;
+ }
+ /*------------------------------------------*
+ * Compute new LPC coeff. -> An[i] *
+ * An[j]= A[j] + K*A[i-j] , j=1 to i-1 *
+ * An[i]= K *
+ *------------------------------------------*/
+
+ for (j = 1; j < i; j++)
+ {
+ t0 = Mpy_32(Kh, Kl, Ah[i - j], Al[i - j]);
+ t0 = L_add(t0, L_Comp(Ah[j], Al[j]));
+ L_Extract(t0, &Anh[j], &Anl[j]);
+ }
+ t2 = L_shr(t2, 4); /* t2 = K in Q31 ->convert to Q27 */
+ L_Extract(t2, &Anh[i], &Anl[i]); /* An[i] in Q27 */
+
+ /* Alpha = Alpha * (1-K**2) */
+
+ t0 = Mpy_32(Kh, Kl, Kh, Kl); /* K*K in Q31 */
+ t0 = L_abs(t0); /* Some case <0 !! */
+ t0 = L_sub((Word32) 0x7fffffffL, t0); /* 1 - K*K in Q31 */
+ L_Extract(t0, &hi, &lo); /* DPF format */
+ t0 = Mpy_32(alp_h, alp_l, hi, lo); /* Alpha in Q31 */
+
+ /* Normalize Alpha */
+
+ j = norm_l(t0);
+ t0 = L_shl(t0, j);
+ L_Extract(t0, &alp_h, &alp_l); /* DPF format */
+ alp_exp = add(alp_exp, j); /* Add normalization to alp_exp */
+
+ /* A[j] = An[j] */
+
+ for (j = 1; j <= i; j++)
+ {
+ Ah[j] = Anh[j]; move16();
+ Al[j] = Anl[j]; move16();
+ }
+ }
+
+ /* Truncate A[i] in Q27 to Q12 with rounding */
+
+ A[0] = 4096; move16();
+ for (i = 1; i <= M; i++)
+ {
+ t0 = L_Comp(Ah[i], Al[i]);
+ old_A[i - 1] = A[i] = round(L_shl(t0, 1)); move16();move16();
+ }
+ old_rc[0] = rc[0]; move16();
+ old_rc[1] = rc[1]; move16();
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/log2.c
@@ -1,0 +1,115 @@
+/********************************************************************************
+*
+* File : log2.c
+* Purpose : Computes log2(L_x)
+*
+********************************************************************************
+*/
+/*
+********************************************************************************
+* MODULE INCLUDE FILE AND VERSION ID
+********************************************************************************
+*/
+#include "log2.h"
+const char log2_id[] = "@(#)$Id $" log2_h;
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+/*
+********************************************************************************
+* LOCAL VARIABLES AND TABLES
+********************************************************************************
+*/
+#include "log2_tab.h" /* Table for Log2() */
+
+/*
+********************************************************************************
+* PUBLIC PROGRAM CODE
+********************************************************************************
+*/
+
+/*************************************************************************
+ *
+ * FUNCTION: Log2_norm()
+ *
+ * PURPOSE: Computes log2(L_x, exp), where L_x is positive and
+ * normalized, and exp is the normalisation exponent
+ * If L_x is negative or zero, the result is 0.
+ *
+ * DESCRIPTION:
+ * The function Log2(L_x) is approximated by a table and linear
+ * interpolation. The following steps are used to compute Log2(L_x)
+ *
+ * 1- exponent = 30-norm_exponent
+ * 2- i = bit25-b31 of L_x; 32<=i<=63 (because of normalization).
+ * 3- a = bit10-b24
+ * 4- i -=32
+ * 5- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2
+ *
+ *************************************************************************/
+void Log2_norm (
+ Word32 L_x, /* (i) : input value (normalized) */
+ Word16 exp, /* (i) : norm_l (L_x) */
+ Word16 *exponent, /* (o) : Integer part of Log2. (range: 0<=val<=30) */
+ Word16 *fraction /* (o) : Fractional part of Log2. (range: 0<=val<1) */
+)
+{
+ Word16 i, a, tmp;
+ Word32 L_y;
+
+ test ();
+ if (L_x <= (Word32) 0)
+ {
+ *exponent = 0; move16 ();
+ *fraction = 0; move16 ();
+ return;
+ }
+
+ *exponent = sub (30, exp); move16 ();
+
+ L_x = L_shr (L_x, 9);
+ i = extract_h (L_x); /* Extract b25-b31 */
+ L_x = L_shr (L_x, 1);
+ a = extract_l (L_x); /* Extract b10-b24 of fraction */
+ a = (Word16)(a & (Word16)0x7fff); logic16 ();
+
+ i = sub (i, 32);
+
+ L_y = L_deposit_h (table[i]); /* table[i] << 16 */
+ tmp = sub (table[i], table[i + 1]); /* table[i] - table[i+1] */
+ L_y = L_msu (L_y, tmp, a); /* L_y -= tmp*a*2 */
+
+ *fraction = extract_h (L_y);move16 ();
+
+ return;
+}
+
+/*************************************************************************
+ *
+ * FUNCTION: Log2()
+ *
+ * PURPOSE: Computes log2(L_x), where L_x is positive.
+ * If L_x is negative or zero, the result is 0.
+ *
+ * DESCRIPTION:
+ * normalizes L_x and then calls Log2_norm().
+ *
+ *************************************************************************/
+void Log2 (
+ Word32 L_x, /* (i) : input value */
+ Word16 *exponent, /* (o) : Integer part of Log2. (range: 0<=val<=30) */
+ Word16 *fraction /* (o) : Fractional part of Log2. (range: 0<=val<1) */
+)
+{
+ Word16 exp;
+
+ exp = norm_l (L_x);
+ Log2_norm (L_shl (L_x, exp), exp, exponent, fraction);
+}
--- /dev/null
+++ b/amr-wb/log2.h
@@ -1,0 +1,42 @@
+/********************************************************************************
+*
+* File : log2.h
+* Purpose : Computes log2(L_x)
+*
+********************************************************************************
+*/
+#ifndef log2_h
+#define log2_h "$Id $"
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include "typedef.h"
+
+/*
+********************************************************************************
+* DEFINITION OF DATA TYPES
+********************************************************************************
+*/
+
+/*
+********************************************************************************
+* DECLARATION OF PROTOTYPES
+********************************************************************************
+*/
+void Log2 (
+ Word32 L_x, /* (i) : input value */
+ Word16 *exponent, /* (o) : Integer part of Log2. (range: 0<=val<=30) */
+ Word16 *fraction /* (o) : Fractional part of Log2. (range: 0<=val<1)*/
+);
+
+void Log2_norm (
+ Word32 L_x, /* (i) : input value (normalized) */
+ Word16 exp, /* (i) : norm_l (L_x) */
+ Word16 *exponent, /* (o) : Integer part of Log2. (range: 0<=val<=30) */
+ Word16 *fraction /* (o) : Fractional part of Log2. (range: 0<=val<1) */
+);
+
+#endif
--- /dev/null
+++ b/amr-wb/log2_tab.h
@@ -1,0 +1,16 @@
+
+/*******************************************************************************
+*
+* File : log2.tab
+* Purpose : Table for routine Log2().
+* $Id $
+*
+********************************************************************************
+*/
+static const Word16 table[33] =
+{
+ 0, 1455, 2866, 4236, 5568, 6863, 8124, 9352, 10549, 11716,
+ 12855, 13967, 15054, 16117, 17156, 18172, 19167, 20142, 21097, 22033,
+ 22951, 23852, 24735, 25603, 26455, 27291, 28113, 28922, 29716, 30497,
+ 31266, 32023, 32767
+};
--- /dev/null
+++ b/amr-wb/lp_dec2.c
@@ -1,0 +1,58 @@
+/*-------------------------------------------------------------------*
+ * LP_DEC2.C *
+ *-------------------------------------------------------------------*
+ * Decimate a vector by 2 with 2nd order fir filter. *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+#include "cnst.h"
+
+#define L_FIR 5
+#define L_MEM (L_FIR-2)
+
+/* static float h_fir[L_FIR] = {0.13, 0.23, 0.28, 0.23, 0.13}; */
+/* fixed-point: sum of coef = 32767 to avoid overflow on DC */
+static Word16 h_fir[L_FIR] = {4260, 7536, 9175, 7536, 4260};
+
+
+void LP_Decim2(
+ Word16 x[], /* in/out: signal to process */
+ Word16 l, /* input : size of filtering */
+ Word16 mem[] /* in/out: memory (size=3) */
+)
+{
+ Word16 *p_x, x_buf[L_FRAME + L_MEM];
+ Word16 i, j, k;
+ Word32 L_tmp;
+
+ /* copy initial filter states into buffer */
+
+ p_x = x_buf; move16();
+ for (i = 0; i < L_MEM; i++)
+ {
+ *p_x++ = mem[i]; move16();
+ }
+ for (i = 0; i < l; i++)
+ {
+ *p_x++ = x[i]; move16();
+ }
+ for (i = 0; i < L_MEM; i++)
+ {
+ mem[i] = x[l - L_MEM + i]; move16();
+ }
+
+ for (i = 0, j = 0; i < l; i += 2, j++)
+ {
+ p_x = &x_buf[i]; move16();
+
+ L_tmp = 0L; move32();
+ for (k = 0; k < L_FIR; k++)
+ L_tmp = L_mac(L_tmp, *p_x++, h_fir[k]);
+
+ x[j] = round(L_tmp); move16();
+ }
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/main.h
@@ -1,0 +1,39 @@
+/*--------------------------------------------------------------------------*
+ * MAIN.H *
+ *--------------------------------------------------------------------------*
+ * Main functions *
+ *--------------------------------------------------------------------------*/
+
+void Init_coder(void **spe_state);
+void Close_coder(void *spe_state);
+
+void coder(
+ Word16 * mode, /* input : used mode */
+ Word16 speech16k[], /* input : 320 new speech samples (at 16 kHz) */
+ Word16 prms[], /* output: output parameters */
+ Word16 * ser_size, /* output: bit rate of the used mode */
+ void *spe_state, /* i/o : State structure */
+ Word16 allow_dtx /* input : DTX ON/OFF */
+);
+
+void Init_decoder(void **spd_state);
+void Close_decoder(void *spd_state);
+
+void decoder(
+ Word16 mode, /* input : used mode */
+ Word16 prms[], /* input : parameter vector */
+ Word16 synth16k[], /* output: synthesis speech */
+ Word16 * frame_length, /* output: lenght of the frame */
+ void *spd_state, /* i/o : State structure */
+ Word16 frame_type /* input : received frame type */
+);
+
+void Reset_encoder(void *st, Word16 reset_all);
+
+void Reset_decoder(void *st, Word16 reset_all);
+
+Word16 encoder_homing_frame_test(Word16 input_frame[]);
+
+Word16 decoder_homing_frame_test(Word16 input_frame[], Word16 mode);
+
+Word16 decoder_homing_frame_test_first(Word16 input_frame[], Word16 mode);
--- /dev/null
+++ b/amr-wb/math_op.c
@@ -1,0 +1,212 @@
+/*___________________________________________________________________________
+ | |
+ | This file contains mathematic operations in fixed point. |
+ | |
+ | Isqrt() : inverse square root (16 bits precision). |
+ | Pow2() : 2^x (16 bits precision). |
+ | Log2() : log2 (16 bits precision). |
+ | Dot_product() : scalar product of <x[],y[]> |
+ | |
+ | These operations are not standard double precision operations. |
+ | They are used where low complexity is important and the full 32 bits |
+ | precision is not necessary. For example, the function Div_32() has a |
+ | 24 bits precision which is enough for our purposes. |
+ | |
+ | In this file, the values use theses representations: |
+ | |
+ | Word32 L_32 : standard signed 32 bits format |
+ | Word16 hi, lo : L_32 = hi<<16 + lo<<1 (DPF - Double Precision Format) |
+ | Word32 frac, Word16 exp : L_32 = frac << exp-31 (normalised format) |
+ | Word16 int, frac : L_32 = int.frac (fractional format) |
+ |___________________________________________________________________________|
+*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "math_op.h"
+#include "count.h"
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : Isqrt |
+ | |
+ | Compute 1/sqrt(L_x). |
+ | if L_x is negative or zero, result is 1 (7fffffff). |
+ |---------------------------------------------------------------------------|
+ | Algorithm: |
+ | |
+ | 1- Normalization of L_x. |
+ | 2- call Isqrt_n(L_x, exponant) |
+ | 3- L_y = L_x << exponant |
+ |___________________________________________________________________________|
+*/
+Word32 Isqrt( /* (o) Q31 : output value (range: 0<=val<1) */
+ Word32 L_x /* (i) Q0 : input value (range: 0<=val<=7fffffff) */
+)
+{
+ Word16 exp;
+ Word32 L_y;
+
+ exp = norm_l(L_x);
+ L_x = L_shl(L_x, exp); /* L_x is normalized */
+ exp = sub(31, exp);
+
+ Isqrt_n(&L_x, &exp);
+
+ L_y = L_shl(L_x, exp); /* denormalization */
+
+ return (L_y);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : Isqrt_n |
+ | |
+ | Compute 1/sqrt(value). |
+ | if value is negative or zero, result is 1 (frac=7fffffff, exp=0). |
+ |---------------------------------------------------------------------------|
+ | Algorithm: |
+ | |
+ | The function 1/sqrt(value) is approximated by a table and linear |
+ | interpolation. |
+ | |
+ | 1- If exponant is odd then shift fraction right once. |
+ | 2- exponant = -((exponant-1)>>1) |
+ | 3- i = bit25-b30 of fraction, 16 <= i <= 63 ->because of normalization. |
+ | 4- a = bit10-b24 |
+ | 5- i -=16 |
+ | 6- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2 |
+ |___________________________________________________________________________|
+*/
+static Word16 table_isqrt[49] =
+{
+ 32767, 31790, 30894, 30070, 29309, 28602, 27945, 27330, 26755, 26214,
+ 25705, 25225, 24770, 24339, 23930, 23541, 23170, 22817, 22479, 22155,
+ 21845, 21548, 21263, 20988, 20724, 20470, 20225, 19988, 19760, 19539,
+ 19326, 19119, 18919, 18725, 18536, 18354, 18176, 18004, 17837, 17674,
+ 17515, 17361, 17211, 17064, 16921, 16782, 16646, 16514, 16384
+};
+
+void Isqrt_n(
+ Word32 * frac, /* (i/o) Q31: normalized value (1.0 < frac <= 0.5) */
+ Word16 * exp /* (i/o) : exponent (value = frac x 2^exponent) */
+)
+{
+ Word16 i, a, tmp;
+
+ test();
+ if (*frac <= (Word32) 0)
+ {
+ *exp = 0; move16();
+ *frac = 0x7fffffffL; move32();
+ return;
+ }
+ test();logic16();
+ if (sub((Word16) (*exp & 1), 1) == 0) /* If exponant odd -> shift right */
+ *frac = L_shr(*frac, 1);
+
+ *exp = negate(shr(sub(*exp, 1), 1)); move16();
+
+ *frac = L_shr(*frac, 9); move32();
+ i = extract_h(*frac); /* Extract b25-b31 */
+ *frac = L_shr(*frac, 1); move32();
+ a = extract_l(*frac); /* Extract b10-b24 */
+ a = (Word16) (a & (Word16) 0x7fff); logic16();
+
+ i = sub(i, 16);
+ move32();
+ *frac = L_deposit_h(table_isqrt[i]); /* table[i] << 16 */
+ tmp = sub(table_isqrt[i], table_isqrt[i + 1]); /* table[i] - table[i+1]) */
+ move32();
+ *frac = L_msu(*frac, tmp, a); /* frac -= tmp*a*2 */
+
+ return;
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : Pow2() |
+ | |
+ | L_x = pow(2.0, exponant.fraction) (exponant = interger part) |
+ | = pow(2.0, 0.fraction) << exponant |
+ |---------------------------------------------------------------------------|
+ | Algorithm: |
+ | |
+ | The function Pow2(L_x) is approximated by a table and linear |
+ | interpolation. |
+ | |
+ | 1- i = bit10-b15 of fraction, 0 <= i <= 31 |
+ | 2- a = bit0-b9 of fraction |
+ | 3- L_x = table[i]<<16 - (table[i] - table[i+1]) * a * 2 |
+ | 4- L_x = L_x >> (30-exponant) (with rounding) |
+ |___________________________________________________________________________|
+*/
+static Word16 table_pow2[33] =
+{
+ 16384, 16743, 17109, 17484, 17867, 18258, 18658, 19066, 19484, 19911,
+ 20347, 20792, 21247, 21713, 22188, 22674, 23170, 23678, 24196, 24726,
+ 25268, 25821, 26386, 26964, 27554, 28158, 28774, 29405, 30048, 30706,
+ 31379, 32066, 32767
+};
+
+Word32 Pow2( /* (o) Q0 : result (range: 0<=val<=0x7fffffff) */
+ Word16 exponant, /* (i) Q0 : Integer part. (range: 0<=val<=30) */
+ Word16 fraction /* (i) Q15 : Fractionnal part. (range: 0.0<=val<1.0) */
+)
+{
+ Word16 exp, i, a, tmp;
+ Word32 L_x;
+
+ L_x = L_mult(fraction, 32); /* L_x = fraction<<6 */
+ i = extract_h(L_x); /* Extract b10-b16 of fraction */
+ L_x = L_shr(L_x, 1);
+ a = extract_l(L_x); /* Extract b0-b9 of fraction */
+ a = (Word16) (a & (Word16) 0x7fff); logic16();
+
+ L_x = L_deposit_h(table_pow2[i]); /* table[i] << 16 */
+ tmp = sub(table_pow2[i], table_pow2[i + 1]); /* table[i] - table[i+1] */
+ L_x = L_msu(L_x, tmp, a); /* L_x -= tmp*a*2 */
+
+ exp = sub(30, exponant);
+ L_x = L_shr_r(L_x, exp);
+
+ return (L_x);
+}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : Dot_product12() |
+ | |
+ | Compute scalar product of <x[],y[]> using accumulator. |
+ | |
+ | The result is normalized (in Q31) with exponent (0..30). |
+ |---------------------------------------------------------------------------|
+ | Algorithm: |
+ | |
+ | dot_product = sum(x[i]*y[i]) i=0..N-1 |
+ |___________________________________________________________________________|
+*/
+
+Word32 Dot_product12( /* (o) Q31: normalized result (1 < val <= -1) */
+ Word16 x[], /* (i) 12bits: x vector */
+ Word16 y[], /* (i) 12bits: y vector */
+ Word16 lg, /* (i) : vector length */
+ Word16 * exp /* (o) : exponent of result (0..+30) */
+)
+{
+ Word16 i, sft;
+ Word32 L_sum;
+
+ L_sum = 1L; move32();
+ for (i = 0; i < lg; i++)
+ L_sum = L_mac(L_sum, x[i], y[i]);
+
+ /* Normalize acc in Q31 */
+
+ sft = norm_l(L_sum);
+ L_sum = L_shl(L_sum, sft);
+
+ *exp = sub(30, sft); move16(); /* exponent = 0..30 */
+
+ return (L_sum);
+}
--- /dev/null
+++ b/amr-wb/math_op.h
@@ -1,0 +1,23 @@
+/*--------------------------------------------------------------------------*
+ * MATH_OP.H *
+ *--------------------------------------------------------------------------*
+ * Mathematical operations *
+ *--------------------------------------------------------------------------*/
+
+Word32 Isqrt( /* (o) Q31 : output value (range: 0<=val<1) */
+ Word32 L_x /* (i) Q0 : input value (range: 0<=val<=7fffffff) */
+);
+void Isqrt_n(
+ Word32 * frac, /* (i/o) Q31: normalized value (1.0 < frac <= 0.5) */
+ Word16 * exp /* (i/o) : exponent (value = frac x 2^exponent) */
+);
+Word32 Pow2( /* (o) Q0 : result (range: 0<=val<=0x7fffffff) */
+ Word16 exponant, /* (i) Q0 : Integer part. (range: 0<=val<=30) */
+ Word16 fraction /* (i) Q15 : Fractionnal part. (range: 0.0<=val<1.0) */
+);
+Word32 Dot_product12( /* (o) Q31: normalized result (1 < val <= -1) */
+ Word16 x[], /* (i) 12bits: x vector */
+ Word16 y[], /* (i) 12bits: y vector */
+ Word16 lg, /* (i) : vector length */
+ Word16 * exp /* (o) : exponent of result (0..+30) */
+);
--- /dev/null
+++ b/amr-wb/mime_io.tab
@@ -1,0 +1,347 @@
+#include <stdio.h>
+#include "typedef.h"
+
+static UWord8 toc_byte[16] = {0x04, 0x0C, 0x14, 0x1C, 0x24, 0x2C, 0x34, 0x3C,
+ 0x44, 0x4C, 0x54, 0x5C, 0x64, 0x6C, 0x74, 0x7C};
+
+/* number of speech bits for all modes */
+static Word16 unpacked_size[16] = {132, 177, 253, 285, 317, 365, 397, 461,
+ 477, 35, 0, 0, 0, 0, 0, 0};
+
+/* size of packed frame for each mode, excluding TOC byte */
+static Word16 packed_size[16] = {17, 23, 32, 36, 40, 46, 50, 58,
+ 60, 5, 0, 0, 0, 0, 0, 0};
+
+/* number of unused speech bits in packed format for each mode */
+static Word16 unused_size[16] = {4, 7, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0};
+
+/* sorting tables for all modes */
+
+static Word16 sort_660[132] = {
+ 0, 5, 6, 7, 61, 84, 107, 130, 62, 85,
+ 8, 4, 37, 38, 39, 40, 58, 81, 104, 127,
+ 60, 83, 106, 129, 108, 131, 128, 41, 42, 80,
+ 126, 1, 3, 57, 103, 82, 105, 59, 2, 63,
+ 109, 110, 86, 19, 22, 23, 64, 87, 18, 20,
+ 21, 17, 13, 88, 43, 89, 65, 111, 14, 24,
+ 25, 26, 27, 28, 15, 16, 44, 90, 66, 112,
+ 9, 11, 10, 12, 67, 113, 29, 30, 31, 32,
+ 34, 33, 35, 36, 45, 51, 68, 74, 91, 97,
+ 114, 120, 46, 69, 92, 115, 52, 75, 98, 121,
+ 47, 70, 93, 116, 53, 76, 99, 122, 48, 71,
+ 94, 117, 54, 77, 100, 123, 49, 72, 95, 118,
+ 55, 78, 101, 124, 50, 73, 96, 119, 56, 79,
+ 102, 125
+};
+
+static Word16 sort_885[177] = {
+ 0, 4, 6, 7, 5, 3, 47, 48, 49, 112,
+ 113, 114, 75, 106, 140, 171, 80, 111, 145, 176,
+ 77, 108, 142, 173, 78, 109, 143, 174, 79, 110,
+ 144, 175, 76, 107, 141, 172, 50, 115, 51, 2,
+ 1, 81, 116, 146, 19, 21, 12, 17, 18, 20,
+ 16, 25, 13, 10, 14, 24, 23, 22, 26, 8,
+ 15, 52, 117, 31, 82, 147, 9, 33, 11, 83,
+ 148, 53, 118, 28, 27, 84, 149, 34, 35, 29,
+ 46, 32, 30, 54, 119, 37, 36, 39, 38, 40,
+ 85, 150, 41, 42, 43, 44, 45, 55, 60, 65,
+ 70, 86, 91, 96, 101, 120, 125, 130, 135, 151,
+ 156, 161, 166, 56, 87, 121, 152, 61, 92, 126,
+ 157, 66, 97, 131, 162, 71, 102, 136, 167, 57,
+ 88, 122, 153, 62, 93, 127, 158, 67, 98, 132,
+ 163, 72, 103, 137, 168, 58, 89, 123, 154, 63,
+ 94, 128, 159, 68, 99, 133, 164, 73, 104, 138,
+ 169, 59, 90, 124, 155, 64, 95, 129, 160, 69,
+ 100, 134, 165, 74, 105, 139, 170
+};
+
+static Word16 sort_1265[253] = {
+ 0, 4, 6, 93, 143, 196, 246, 7, 5, 3,
+ 47, 48, 49, 50, 51, 150, 151, 152, 153, 154,
+ 94, 144, 197, 247, 99, 149, 202, 252, 96, 146,
+ 199, 249, 97, 147, 200, 250, 100, 203, 98, 148,
+ 201, 251, 95, 145, 198, 248, 52, 2, 1, 101,
+ 204, 155, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 156, 31, 102, 205, 9, 33, 11, 103, 206, 54,
+ 157, 28, 27, 104, 207, 34, 35, 29, 46, 32,
+ 30, 55, 158, 37, 36, 39, 38, 40, 105, 208,
+ 41, 42, 43, 44, 45, 56, 106, 159, 209, 57,
+ 66, 75, 84, 107, 116, 125, 134, 160, 169, 178,
+ 187, 210, 219, 228, 237, 58, 108, 161, 211, 62,
+ 112, 165, 215, 67, 117, 170, 220, 71, 121, 174,
+ 224, 76, 126, 179, 229, 80, 130, 183, 233, 85,
+ 135, 188, 238, 89, 139, 192, 242, 59, 109, 162,
+ 212, 63, 113, 166, 216, 68, 118, 171, 221, 72,
+ 122, 175, 225, 77, 127, 180, 230, 81, 131, 184,
+ 234, 86, 136, 189, 239, 90, 140, 193, 243, 60,
+ 110, 163, 213, 64, 114, 167, 217, 69, 119, 172,
+ 222, 73, 123, 176, 226, 78, 128, 181, 231, 82,
+ 132, 185, 235, 87, 137, 190, 240, 91, 141, 194,
+ 244, 61, 111, 164, 214, 65, 115, 168, 218, 70,
+ 120, 173, 223, 74, 124, 177, 227, 79, 129, 182,
+ 232, 83, 133, 186, 236, 88, 138, 191, 241, 92,
+ 142, 195, 245
+};
+
+static Word16 sort_1425[285] = {
+ 0, 4, 6, 101, 159, 220, 278, 7, 5, 3,
+ 47, 48, 49, 50, 51, 166, 167, 168, 169, 170,
+ 102, 160, 221, 279, 107, 165, 226, 284, 104, 162,
+ 223, 281, 105, 163, 224, 282, 108, 227, 106, 164,
+ 225, 283, 103, 161, 222, 280, 52, 2, 1, 109,
+ 228, 171, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 172, 31, 110, 229, 9, 33, 11, 111, 230, 54,
+ 173, 28, 27, 112, 231, 34, 35, 29, 46, 32,
+ 30, 55, 174, 37, 36, 39, 38, 40, 113, 232,
+ 41, 42, 43, 44, 45, 56, 114, 175, 233, 62,
+ 120, 181, 239, 75, 133, 194, 252, 57, 115, 176,
+ 234, 63, 121, 182, 240, 70, 128, 189, 247, 76,
+ 134, 195, 253, 83, 141, 202, 260, 92, 150, 211,
+ 269, 84, 142, 203, 261, 93, 151, 212, 270, 85,
+ 143, 204, 262, 94, 152, 213, 271, 86, 144, 205,
+ 263, 95, 153, 214, 272, 64, 122, 183, 241, 77,
+ 135, 196, 254, 65, 123, 184, 242, 78, 136, 197,
+ 255, 87, 145, 206, 264, 96, 154, 215, 273, 58,
+ 116, 177, 235, 66, 124, 185, 243, 71, 129, 190,
+ 248, 79, 137, 198, 256, 88, 146, 207, 265, 97,
+ 155, 216, 274, 59, 117, 178, 236, 67, 125, 186,
+ 244, 72, 130, 191, 249, 80, 138, 199, 257, 89,
+ 147, 208, 266, 98, 156, 217, 275, 60, 118, 179,
+ 237, 68, 126, 187, 245, 73, 131, 192, 250, 81,
+ 139, 200, 258, 90, 148, 209, 267, 99, 157, 218,
+ 276, 61, 119, 180, 238, 69, 127, 188, 246, 74,
+ 132, 193, 251, 82, 140, 201, 259, 91, 149, 210,
+ 268, 100, 158, 219, 277
+};
+
+static Word16 sort_1585[317] = {
+ 0, 4, 6, 109, 175, 244, 310, 7, 5, 3,
+ 47, 48, 49, 50, 51, 182, 183, 184, 185, 186,
+ 110, 176, 245, 311, 115, 181, 250, 316, 112, 178,
+ 247, 313, 113, 179, 248, 314, 116, 251, 114, 180,
+ 249, 315, 111, 177, 246, 312, 52, 2, 1, 117,
+ 252, 187, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 188, 31, 118, 253, 9, 33, 11, 119, 254, 54,
+ 189, 28, 27, 120, 255, 34, 35, 29, 46, 32,
+ 30, 55, 190, 37, 36, 39, 38, 40, 121, 256,
+ 41, 42, 43, 44, 45, 56, 122, 191, 257, 63,
+ 129, 198, 264, 76, 142, 211, 277, 89, 155, 224,
+ 290, 102, 168, 237, 303, 57, 123, 192, 258, 70,
+ 136, 205, 271, 83, 149, 218, 284, 96, 162, 231,
+ 297, 62, 128, 197, 263, 75, 141, 210, 276, 88,
+ 154, 223, 289, 101, 167, 236, 302, 58, 124, 193,
+ 259, 71, 137, 206, 272, 84, 150, 219, 285, 97,
+ 163, 232, 298, 59, 125, 194, 260, 64, 130, 199,
+ 265, 67, 133, 202, 268, 72, 138, 207, 273, 77,
+ 143, 212, 278, 80, 146, 215, 281, 85, 151, 220,
+ 286, 90, 156, 225, 291, 93, 159, 228, 294, 98,
+ 164, 233, 299, 103, 169, 238, 304, 106, 172, 241,
+ 307, 60, 126, 195, 261, 65, 131, 200, 266, 68,
+ 134, 203, 269, 73, 139, 208, 274, 78, 144, 213,
+ 279, 81, 147, 216, 282, 86, 152, 221, 287, 91,
+ 157, 226, 292, 94, 160, 229, 295, 99, 165, 234,
+ 300, 104, 170, 239, 305, 107, 173, 242, 308, 61,
+ 127, 196, 262, 66, 132, 201, 267, 69, 135, 204,
+ 270, 74, 140, 209, 275, 79, 145, 214, 280, 82,
+ 148, 217, 283, 87, 153, 222, 288, 92, 158, 227,
+ 293, 95, 161, 230, 296, 100, 166, 235, 301, 105,
+ 171, 240, 306, 108, 174, 243, 309
+};
+
+static Word16 sort_1825[365] = {
+ 0, 4, 6, 121, 199, 280, 358, 7, 5, 3,
+ 47, 48, 49, 50, 51, 206, 207, 208, 209, 210,
+ 122, 200, 281, 359, 127, 205, 286, 364, 124, 202,
+ 283, 361, 125, 203, 284, 362, 128, 287, 126, 204,
+ 285, 363, 123, 201, 282, 360, 52, 2, 1, 129,
+ 288, 211, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 212, 31, 130, 289, 9, 33, 11, 131, 290, 54,
+ 213, 28, 27, 132, 291, 34, 35, 29, 46, 32,
+ 30, 55, 214, 37, 36, 39, 38, 40, 133, 292,
+ 41, 42, 43, 44, 45, 56, 134, 215, 293, 198,
+ 299, 136, 120, 138, 60, 279, 58, 62, 357, 139,
+ 140, 295, 156, 57, 219, 297, 63, 217, 137, 170,
+ 300, 222, 64, 106, 61, 78, 294, 92, 142, 141,
+ 135, 221, 296, 301, 343, 59, 298, 184, 329, 315,
+ 220, 216, 265, 251, 218, 237, 352, 223, 157, 86,
+ 171, 87, 164, 351, 111, 302, 65, 178, 115, 323,
+ 72, 192, 101, 179, 93, 73, 193, 151, 337, 309,
+ 143, 274, 69, 324, 165, 150, 97, 338, 110, 310,
+ 330, 273, 68, 107, 175, 245, 114, 79, 113, 189,
+ 246, 259, 174, 71, 185, 96, 344, 100, 322, 83,
+ 334, 316, 333, 252, 161, 348, 147, 82, 269, 232,
+ 260, 308, 353, 347, 163, 231, 306, 320, 188, 270,
+ 146, 177, 266, 350, 256, 85, 149, 116, 191, 160,
+ 238, 258, 336, 305, 255, 88, 224, 99, 339, 230,
+ 228, 227, 272, 242, 241, 319, 233, 311, 102, 74,
+ 180, 275, 66, 194, 152, 325, 172, 247, 244, 261,
+ 117, 158, 166, 354, 75, 144, 108, 312, 94, 186,
+ 303, 80, 234, 89, 195, 112, 340, 181, 345, 317,
+ 326, 276, 239, 167, 118, 313, 70, 355, 327, 253,
+ 190, 176, 271, 104, 98, 153, 103, 90, 76, 267,
+ 277, 248, 225, 262, 182, 84, 154, 235, 335, 168,
+ 331, 196, 341, 249, 162, 307, 148, 349, 263, 321,
+ 257, 243, 229, 356, 159, 119, 67, 187, 173, 145,
+ 240, 77, 304, 332, 314, 342, 109, 254, 81, 278,
+ 105, 91, 346, 318, 183, 250, 197, 328, 95, 155,
+ 169, 268, 226, 236, 264
+};
+
+static Word16 sort_1985[397] = {
+ 0, 4, 6, 129, 215, 304, 390, 7, 5, 3,
+ 47, 48, 49, 50, 51, 222, 223, 224, 225, 226,
+ 130, 216, 305, 391, 135, 221, 310, 396, 132, 218,
+ 307, 393, 133, 219, 308, 394, 136, 311, 134, 220,
+ 309, 395, 131, 217, 306, 392, 52, 2, 1, 137,
+ 312, 227, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 228, 31, 138, 313, 9, 33, 11, 139, 314, 54,
+ 229, 28, 27, 140, 315, 34, 35, 29, 46, 32,
+ 30, 55, 230, 37, 36, 39, 38, 40, 141, 316,
+ 41, 42, 43, 44, 45, 56, 142, 231, 317, 63,
+ 73, 92, 340, 82, 324, 149, 353, 159, 334, 165,
+ 338, 178, 163, 254, 77, 168, 257, 153, 343, 57,
+ 248, 238, 79, 252, 166, 67, 80, 201, 101, 267,
+ 143, 164, 341, 255, 339, 187, 376, 318, 78, 328,
+ 362, 115, 232, 242, 253, 290, 276, 62, 58, 158,
+ 68, 93, 179, 319, 148, 169, 154, 72, 385, 329,
+ 333, 344, 102, 83, 144, 233, 323, 124, 243, 192,
+ 354, 237, 64, 247, 202, 209, 150, 116, 335, 268,
+ 239, 299, 188, 196, 298, 94, 195, 258, 123, 363,
+ 384, 109, 325, 371, 170, 370, 84, 110, 295, 180,
+ 74, 210, 191, 106, 291, 205, 367, 381, 377, 206,
+ 355, 122, 119, 120, 383, 160, 105, 108, 277, 380,
+ 294, 284, 285, 345, 208, 269, 249, 366, 386, 300,
+ 297, 259, 125, 369, 197, 97, 194, 286, 211, 281,
+ 280, 183, 372, 87, 155, 283, 59, 348, 327, 184,
+ 76, 111, 330, 203, 349, 69, 98, 152, 145, 189,
+ 66, 320, 337, 173, 358, 251, 198, 174, 263, 262,
+ 126, 241, 193, 88, 388, 117, 95, 387, 112, 359,
+ 287, 244, 103, 272, 301, 171, 162, 234, 273, 127,
+ 373, 181, 292, 85, 378, 302, 121, 107, 364, 346,
+ 356, 212, 278, 213, 65, 382, 288, 207, 113, 175,
+ 99, 296, 374, 368, 199, 260, 185, 336, 331, 161,
+ 270, 264, 250, 240, 75, 350, 151, 60, 89, 321,
+ 156, 274, 360, 326, 70, 282, 167, 146, 352, 81,
+ 91, 389, 266, 245, 177, 235, 190, 256, 204, 342,
+ 128, 118, 303, 104, 379, 182, 114, 375, 200, 96,
+ 293, 172, 214, 365, 279, 86, 289, 351, 347, 357,
+ 261, 186, 176, 271, 90, 100, 147, 322, 275, 361,
+ 71, 332, 61, 265, 157, 246, 236
+};
+
+static Word16 sort_2305[461] = {
+ 0, 4, 6, 145, 247, 352, 454, 7, 5, 3,
+ 47, 48, 49, 50, 51, 254, 255, 256, 257, 258,
+ 146, 248, 353, 455, 151, 253, 358, 460, 148, 250,
+ 355, 457, 149, 251, 356, 458, 152, 359, 150, 252,
+ 357, 459, 147, 249, 354, 456, 52, 2, 1, 153,
+ 360, 259, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 260, 31, 154, 361, 9, 33, 11, 155, 362, 54,
+ 261, 28, 27, 156, 363, 34, 35, 29, 46, 32,
+ 30, 55, 262, 37, 36, 39, 38, 40, 157, 364,
+ 41, 42, 43, 44, 45, 56, 158, 263, 365, 181,
+ 192, 170, 79, 57, 399, 90, 159, 297, 377, 366,
+ 275, 68, 183, 388, 286, 194, 299, 92 , 70, 182,
+ 401, 172, 59, 91, 58, 400, 368, 161, 81, 160,
+ 264, 171, 80, 389, 390, 378, 379, 193, 298, 69,
+ 266, 265, 367, 277, 288, 276, 287, 184, 60, 195,
+ 82, 93, 71, 369, 402, 173, 162, 444, 300, 391,
+ 98, 76, 278, 61, 267, 374, 135, 411, 167, 102,
+ 380, 200, 87, 178, 65, 94, 204, 124, 72, 342,
+ 189, 305, 381, 396, 433, 301, 226, 407, 289, 237,
+ 113, 215, 185, 128, 309, 403, 116, 320, 196, 331,
+ 370, 422, 174, 64, 392, 83, 425, 219, 134, 188,
+ 432, 112, 427, 139, 279, 163, 436, 208, 447, 218,
+ 236, 229, 97, 294, 385, 230, 166, 268, 177, 443,
+ 225, 426, 101, 272, 138, 127, 290, 117, 347, 199,
+ 414, 95, 140, 240, 410, 395, 209, 129, 283, 346,
+ 105, 241, 437, 86, 308, 448, 203, 345, 186, 107,
+ 220, 415, 334, 319, 106, 313, 118, 123, 73, 207,
+ 421, 214, 384, 373, 438, 62, 371, 341, 75, 449,
+ 168, 323, 164, 242, 416, 324, 304, 197, 335, 404,
+ 271, 63, 191, 325, 96, 169, 231, 280, 312, 187,
+ 406, 84, 201, 100, 67, 382, 175, 336, 202, 330,
+ 269, 393, 376, 383, 293, 307, 409, 179, 285, 314,
+ 302, 372, 398, 190, 180, 89, 99, 103, 232, 78,
+ 88, 77, 136, 387, 165, 198, 394, 125, 176, 428,
+ 74, 375, 238, 227, 66, 273, 282, 141, 306, 412,
+ 114, 85, 130, 348, 119, 291, 296, 386, 233, 397,
+ 303, 405, 284, 445, 423, 221, 210, 205, 450, 108,
+ 274, 434, 216, 343, 337, 142, 243, 321, 408, 451,
+ 310, 292, 120, 109, 281, 439, 270, 429, 332, 295,
+ 418, 211, 315, 222, 326, 131, 430, 244, 327, 349,
+ 417, 316, 143, 338, 440, 234, 110, 212, 452, 245,
+ 121, 419, 350, 223, 132, 441, 328, 413, 317, 339,
+ 126, 104, 137, 446, 344, 239, 435, 115, 333, 206,
+ 322, 217, 228, 424, 453, 311, 351, 111, 442, 224,
+ 213, 122, 431, 340, 235, 246, 133, 144, 420, 329,
+ 318
+};
+
+static Word16 sort_2385[477] = {
+ 0, 4, 6, 145, 251, 360, 466, 7, 5, 3,
+ 47, 48, 49, 50, 51, 262, 263, 264, 265, 266,
+ 146, 252, 361, 467, 151, 257, 366, 472, 148, 254,
+ 363, 469, 149, 255, 364, 470, 156, 371, 150, 256,
+ 365, 471, 147, 253, 362, 468, 52, 2, 1, 157,
+ 372, 267, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 268, 31, 152, 153, 154, 155, 258, 259, 260, 261,
+ 367, 368, 369, 370, 473, 474, 475, 476, 158, 373,
+ 9, 33, 11, 159, 374, 54, 269, 28, 27, 160,
+ 375, 34, 35, 29, 46, 32, 30, 55, 270, 37,
+ 36, 39, 38, 40, 161, 376, 41, 42, 43, 44,
+ 45, 56, 162, 271, 377, 185, 196, 174, 79, 57,
+ 411, 90, 163, 305, 389, 378, 283, 68, 187, 400,
+ 294, 198, 307, 92, 70, 186, 413, 176, 59, 91,
+ 58, 412, 380, 165, 81, 164, 272, 175, 80, 401,
+ 402, 390, 391, 197, 306, 69, 274, 273, 379, 285,
+ 296, 284, 295, 188, 60, 199, 82, 93, 71, 381,
+ 414, 177, 166, 456, 308, 403, 98, 76, 286, 61,
+ 275, 386, 135, 423, 171, 102, 392, 204, 87, 182,
+ 65, 94, 208, 124, 72, 350, 193, 313, 393, 408,
+ 445, 309, 230, 419, 297, 241, 113, 219, 189, 128,
+ 317, 415, 116, 328, 200, 339, 382, 434, 178, 64,
+ 404, 83, 437, 223, 134, 192, 444, 112, 439, 139,
+ 287, 167, 448, 212, 459, 222, 240, 233, 97, 302,
+ 397, 234, 170, 276, 181, 455, 229, 438, 101, 280,
+ 138, 127, 298, 117, 355, 203, 426, 95, 140, 244,
+ 422, 407, 213, 129, 291, 354, 105, 245, 449, 86,
+ 316, 460, 207, 353, 190, 107, 224, 427, 342, 327,
+ 106, 321, 118, 123, 73, 211, 433, 218, 396, 385,
+ 450, 62, 383, 349, 75, 461, 172, 331, 168, 246,
+ 428, 332, 312, 201, 343, 416, 279, 63, 195, 333,
+ 96, 173, 235, 288, 320, 191, 418, 84, 205, 100,
+ 67, 394, 179, 344, 206, 338, 277, 405, 388, 395,
+ 301, 315, 421, 183, 293, 322, 310, 384, 410, 194,
+ 184, 89, 99, 103, 236, 78, 88, 77, 136, 399,
+ 169, 202, 406, 125, 180, 440, 74, 387, 242, 231,
+ 66, 281, 290, 141, 314, 424, 114, 85, 130, 356,
+ 119, 299, 304, 398, 237, 409, 311, 417, 292, 457,
+ 435, 225, 214, 209, 462, 108, 282, 446, 220, 351,
+ 345, 142, 247, 329, 420, 463, 318, 300, 120, 109,
+ 289, 451, 278, 441, 340, 303, 430, 215, 323, 226,
+ 334, 131, 442, 248, 335, 357, 429, 324, 143, 346,
+ 452, 238, 110, 216, 464, 249, 121, 431, 358, 227,
+ 132, 453, 336, 425, 325, 347, 126, 104, 137, 458,
+ 352, 243, 447, 115, 341, 210, 330, 221, 232, 436,
+ 465, 319, 359, 111, 454, 228, 217, 122, 443, 348,
+ 239, 250, 133, 144, 432, 337, 326
+};
+
+static Word16 sort_SID[35] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34
+};
+
+/* pointer table for bit sorting tables */
+static Word16 *sort_ptr[16] = { sort_660, sort_885, sort_1265, sort_1425, sort_1585, sort_1825, sort_1985, sort_2305,
+ sort_2385, sort_SID, NULL, NULL, NULL, NULL, NULL, NULL};
--- /dev/null
+++ b/amr-wb/oper_32b.c
@@ -1,0 +1,210 @@
+/*****************************************************************************
+ * $Id: oper_32b.c,v 1.1 2007/02/15 23:22:35 robs Exp $
+ *
+ * This file contains operations in double precision. *
+ * These operations are not standard double precision operations. *
+ * They are used where single precision is not enough but the full 32 bits *
+ * precision is not necessary. For example, the function Div_32() has a *
+ * 24 bits precision which is enough for our purposes. *
+ * *
+ * The double precision numbers use a special representation: *
+ * *
+ * L_32 = hi<<16 + lo<<1 *
+ * *
+ * L_32 is a 32 bit integer. *
+ * hi and lo are 16 bit signed integers. *
+ * As the low part also contains the sign, this allows fast multiplication. *
+ * *
+ * 0x8000 0000 <= L_32 <= 0x7fff fffe. *
+ * *
+ * We will use DPF (Double Precision Format )in this file to specify *
+ * this special format. *
+ *****************************************************************************
+*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "count.h"
+
+/*****************************************************************************
+ * *
+ * Function L_Extract() *
+ * *
+ * Extract from a 32 bit integer two 16 bit DPF. *
+ * *
+ * Arguments: *
+ * *
+ * L_32 : 32 bit integer. *
+ * 0x8000 0000 <= L_32 <= 0x7fff ffff. *
+ * hi : b16 to b31 of L_32 *
+ * lo : (L_32 - hi<<16)>>1 *
+ *****************************************************************************
+*/
+
+void L_Extract (Word32 L_32, Word16 *hi, Word16 *lo)
+{
+ *hi = extract_h (L_32);
+ *lo = extract_l (L_msu (L_shr (L_32, 1), *hi, 16384));
+ return;
+}
+
+/*****************************************************************************
+ * *
+ * Function L_Comp() *
+ * *
+ * Compose from two 16 bit DPF a 32 bit integer. *
+ * *
+ * L_32 = hi<<16 + lo<<1 *
+ * *
+ * Arguments: *
+ * *
+ * hi msb *
+ * lo lsf (with sign) *
+ * *
+ * Return Value : *
+ * *
+ * 32 bit long signed integer (Word32) whose value falls in the *
+ * range : 0x8000 0000 <= L_32 <= 0x7fff fff0. *
+ * *
+ *****************************************************************************
+*/
+
+Word32 L_Comp (Word16 hi, Word16 lo)
+{
+ Word32 L_32;
+
+ L_32 = L_deposit_h (hi);
+ return (L_mac (L_32, lo, 1)); /* = hi<<16 + lo<<1 */
+}
+
+/*****************************************************************************
+ * Function Mpy_32() *
+ * *
+ * Multiply two 32 bit integers (DPF). The result is divided by 2**31 *
+ * *
+ * L_32 = (hi1*hi2)<<1 + ( (hi1*lo2)>>15 + (lo1*hi2)>>15 )<<1 *
+ * *
+ * This operation can also be viewed as the multiplication of two Q31 *
+ * number and the result is also in Q31. *
+ * *
+ * Arguments: *
+ * *
+ * hi1 hi part of first number *
+ * lo1 lo part of first number *
+ * hi2 hi part of second number *
+ * lo2 lo part of second number *
+ * *
+ *****************************************************************************
+*/
+
+Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2)
+{
+ Word32 L_32;
+
+ L_32 = L_mult (hi1, hi2);
+ L_32 = L_mac (L_32, mult (hi1, lo2), 1);
+ L_32 = L_mac (L_32, mult (lo1, hi2), 1);
+
+ return (L_32);
+}
+
+/*****************************************************************************
+ * Function Mpy_32_16() *
+ * *
+ * Multiply a 16 bit integer by a 32 bit (DPF). The result is divided *
+ * by 2**15 *
+ * *
+ * *
+ * L_32 = (hi1*lo2)<<1 + ((lo1*lo2)>>15)<<1 *
+ * *
+ * Arguments: *
+ * *
+ * hi hi part of 32 bit number. *
+ * lo lo part of 32 bit number. *
+ * n 16 bit number. *
+ * *
+ *****************************************************************************
+*/
+
+Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n)
+{
+ Word32 L_32;
+
+ L_32 = L_mult (hi, n);
+ L_32 = L_mac (L_32, mult (lo, n), 1);
+
+ return (L_32);
+}
+
+/*****************************************************************************
+ * *
+ * Function Name : Div_32 *
+ * *
+ * Purpose : *
+ * Fractional integer division of two 32 bit numbers. *
+ * L_num / L_denom. *
+ * L_num and L_denom must be positive and L_num < L_denom. *
+ * L_denom = denom_hi<<16 + denom_lo<<1 *
+ * denom_hi is a normalize number. *
+ * *
+ * Inputs : *
+ * *
+ * L_num *
+ * 32 bit long signed integer (Word32) whose value falls in the *
+ * range : 0x0000 0000 < L_num < L_denom *
+ * *
+ * L_denom = denom_hi<<16 + denom_lo<<1 (DPF) *
+ * *
+ * denom_hi *
+ * 16 bit positive normalized integer whose value falls in the *
+ * range : 0x4000 < hi < 0x7fff *
+ * denom_lo *
+ * 16 bit positive integer whose value falls in the *
+ * range : 0 < lo < 0x7fff *
+ * *
+ * Return Value : *
+ * *
+ * L_div *
+ * 32 bit long signed integer (Word32) whose value falls in the *
+ * range : 0x0000 0000 <= L_div <= 0x7fff ffff. *
+ * *
+ * Algorithm: *
+ * *
+ * - find = 1/L_denom. *
+ * First approximation: approx = 1 / denom_hi *
+ * 1/L_denom = approx * (2.0 - L_denom * approx ) *
+ * *
+ * - result = L_num * (1/L_denom) *
+ *****************************************************************************
+*/
+
+Word32 Div_32 (Word32 L_num, Word16 denom_hi, Word16 denom_lo)
+{
+ Word16 approx, hi, lo, n_hi, n_lo;
+ Word32 L_32;
+
+ /* First approximation: 1 / L_denom = 1/denom_hi */
+
+ approx = div_s ((Word16) 0x3fff, denom_hi);
+
+ /* 1/L_denom = approx * (2.0 - L_denom * approx) */
+
+ L_32 = Mpy_32_16 (denom_hi, denom_lo, approx);
+
+ L_32 = L_sub ((Word32) 0x7fffffffL, L_32);
+
+ L_Extract (L_32, &hi, &lo);
+
+ L_32 = Mpy_32_16 (hi, lo, approx);
+
+ /* L_num * (1/L_denom) */
+
+ L_Extract (L_32, &hi, &lo);
+ L_Extract (L_num, &n_hi, &n_lo);
+ L_32 = Mpy_32 (n_hi, n_lo, hi, lo);
+ L_32 = L_shl (L_32, 2);
+
+ return (L_32);
+}
+
--- /dev/null
+++ b/amr-wb/oper_32b.h
@@ -1,0 +1,9 @@
+/* Double precision operations */
+/* $Id: oper_32b.h,v 1.1 2007/02/15 23:22:35 robs Exp $ */
+
+void L_Extract (Word32 L_32, Word16 *hi, Word16 *lo);
+Word32 L_Comp (Word16 hi, Word16 lo);
+Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2);
+Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n);
+Word32 Div_32 (Word32 L_num, Word16 denom_hi, Word16 denom_lo);
+
--- /dev/null
+++ b/amr-wb/p_med_o.h
@@ -1,0 +1,28 @@
+/*--------------------------------------------------------------------------*
+ * P_MED_O.H *
+ *--------------------------------------------------------------------------*
+ * Median open-loop lag search *
+ *--------------------------------------------------------------------------*/
+
+Word16 Pitch_med_ol( /* output: open loop pitch lag */
+ Word16 wsp[], /* input : signal used to compute the open loop pitch */
+ /* wsp[-pit_max] to wsp[-1] should be known */
+ Word16 L_min, /* input : minimum pitch lag */
+ Word16 L_max, /* input : maximum pitch lag */
+ Word16 L_frame, /* input : length of frame to compute pitch */
+ Word16 L_0, /* input : old_ open-loop pitch */
+ Word16 * gain, /* output: normalize correlation of hp_wsp for the Lag */
+ Word16 * hp_wsp_mem, /* i:o : memory of the hypass filter for hp_wsp[] (lg=9) */
+ Word16 * old_hp_wsp, /* i:o : hypass wsp[] */
+ Word16 wght_flg /* input : is weighting function used */
+);
+Word16 Med_olag( /* output : median of 5 previous open-loop lags */
+ Word16 prev_ol_lag, /* input : previous open-loop lag */
+ Word16 old_ol_lag[5]
+);
+void Hp_wsp(
+ Word16 wsp[], /* i : wsp[] signal */
+ Word16 hp_wsp[], /* o : hypass wsp[] */
+ Word16 lg, /* i : lenght of signal */
+ Word16 mem[] /* i/o : filter memory [9] */
+);
--- /dev/null
+++ b/amr-wb/p_med_ol.c
@@ -1,0 +1,243 @@
+/*------------------------------------------------------------------------*
+ * P_MED_OL.C *
+ *------------------------------------------------------------------------*
+ * Compute the open loop pitch lag. *
+ *------------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "acelp.h"
+#include "oper_32b.h"
+#include "count.h"
+#include "math_op.h"
+
+#include "p_med_ol.tab"
+
+
+Word16 Pitch_med_ol( /* output: open loop pitch lag */
+ Word16 wsp[], /* input : signal used to compute the open loop pitch */
+ /* wsp[-pit_max] to wsp[-1] should be known */
+ Word16 L_min, /* input : minimum pitch lag */
+ Word16 L_max, /* input : maximum pitch lag */
+ Word16 L_frame, /* input : length of frame to compute pitch */
+ Word16 L_0, /* input : old_ open-loop pitch */
+ Word16 * gain, /* output: normalize correlation of hp_wsp for the Lag */
+ Word16 * hp_wsp_mem, /* i:o : memory of the hypass filter for hp_wsp[] (lg=9) */
+ Word16 * old_hp_wsp, /* i:o : hypass wsp[] */
+ Word16 wght_flg /* input : is weighting function used */
+)
+{
+ Word16 i, j, Tm;
+ Word16 hi, lo;
+ Word16 *ww, *we, *hp_wsp;
+ Word16 exp_R0, exp_R1, exp_R2;
+ Word32 max, R0, R1, R2;
+
+ ww = &corrweight[198];
+ move16();
+ we = &corrweight[98 + L_max - L_0];
+ move16();
+
+ max = MIN_32; move32();
+ Tm = 0; move16();
+ for (i = L_max; i > L_min; i--)
+ {
+ /* Compute the correlation */
+
+ R0 = 0; move32();
+ for (j = 0; j < L_frame; j++)
+ R0 = L_mac(R0, wsp[j], wsp[j - i]);
+
+ /* Weighting of the correlation function. */
+
+ L_Extract(R0, &hi, &lo);
+ R0 = Mpy_32_16(hi, lo, *ww);
+ ww--;
+
+ test();
+ test();
+ if ((L_0 > 0) && (wght_flg > 0))
+ {
+ /* Weight the neighbourhood of the old lag. */
+ L_Extract(R0, &hi, &lo);
+ R0 = Mpy_32_16(hi, lo, *we);
+ we--;
+ move16();
+ }
+ test();
+ if (L_sub(R0, max) >= 0)
+ {
+ max = R0;
+ move32();
+ Tm = i;
+ move16();
+ }
+ }
+
+ /* Hypass the wsp[] vector */
+
+ hp_wsp = old_hp_wsp + L_max; move16();
+ Hp_wsp(wsp, hp_wsp, L_frame, hp_wsp_mem);
+
+ /* Compute normalize correlation at delay Tm */
+
+ R0 = 0; move32();
+ R1 = 1L; move32();
+ R2 = 1L; move32();
+ for (j = 0; j < L_frame; j++)
+ {
+ R0 = L_mac(R0, hp_wsp[j], hp_wsp[j - Tm]);
+ R1 = L_mac(R1, hp_wsp[j - Tm], hp_wsp[j - Tm]);
+ R2 = L_mac(R2, hp_wsp[j], hp_wsp[j]);
+ }
+
+ /* gain = R0/ sqrt(R1*R2) */
+
+ exp_R0 = norm_l(R0);
+ R0 = L_shl(R0, exp_R0);
+
+ exp_R1 = norm_l(R1);
+ R1 = L_shl(R1, exp_R1);
+
+ exp_R2 = norm_l(R2);
+ R2 = L_shl(R2, exp_R2);
+
+
+ R1 = L_mult(round(R1), round(R2));
+
+ i = norm_l(R1);
+ R1 = L_shl(R1, i);
+
+ exp_R1 = add(exp_R1, exp_R2);
+ exp_R1 = add(exp_R1, i);
+ exp_R1 = sub(62, exp_R1);
+
+ Isqrt_n(&R1, &exp_R1);
+
+ R0 = L_mult(round(R0), round(R1));
+ exp_R0 = sub(31, exp_R0);
+ exp_R0 = add(exp_R0, exp_R1);
+
+ *gain = round(L_shl(R0, exp_R0));
+ move16();
+
+ /* Shitf hp_wsp[] for next frame */
+
+ for (i = 0; i < L_max; i++)
+ {
+ old_hp_wsp[i] = old_hp_wsp[i + L_frame];
+ move16();
+ }
+
+ return (Tm);
+}
+
+/*____________________________________________________________________
+ |
+ |
+ | FUNCTION NAME median5
+ |
+ | Returns the median of the set {X[-2], X[-1],..., X[2]},
+ | whose elements are 16-bit integers.
+ |
+ | INPUT
+ | X[-2:2] 16-bit integers.
+ |
+ | RETURN VALUE
+ | The median of {X[-2], X[-1],..., X[2]}.
+ |_____________________________________________________________________
+ */
+
+Word16 median5(Word16 x[])
+{
+ Word16 x1, x2, x3, x4, x5;
+ Word16 tmp;
+
+ x1 = x[-2]; move16();
+ x2 = x[-1]; move16();
+ x3 = x[0]; move16();
+ x4 = x[1]; move16();
+ x5 = x[2]; move16();
+
+ test();test();test();test();test();test();test();test();test();
+
+ if (sub(x2, x1) < 0)
+ {
+ tmp = x1;
+ x1 = x2;
+ x2 = tmp; move16();move16();move16();
+ }
+ if (sub(x3, x1) < 0)
+ {
+ tmp = x1;
+ x1 = x3;
+ x3 = tmp; move16();move16();move16();
+ }
+ if (sub(x4, x1) < 0)
+ {
+ tmp = x1;
+ x1 = x4;
+ x4 = tmp; move16();move16();move16();
+ }
+ if (sub(x5, x1) < 0)
+ {
+ x5 = x1; move16();
+ }
+ if (sub(x3, x2) < 0)
+ {
+ tmp = x2;
+ x2 = x3;
+ x3 = tmp; move16();move16();move16();
+ }
+ if (sub(x4, x2) < 0)
+ {
+ tmp = x2;
+ x2 = x4;
+ x4 = tmp; move16();move16();move16();
+ }
+ if (sub(x5, x2) < 0)
+ {
+ x5 = x2; move16();
+ }
+ if (sub(x4, x3) < 0)
+ {
+ x3 = x4; move16();
+ }
+ if (sub(x5, x3) < 0)
+ {
+ x3 = x5; move16();
+ }
+ return (x3);
+}
+
+/*____________________________________________________________________
+ |
+ |
+ | FUNCTION NAME med_olag
+ |
+ |
+ |_____________________________________________________________________
+ */
+
+
+Word16 Med_olag( /* output : median of 5 previous open-loop lags */
+ Word16 prev_ol_lag, /* input : previous open-loop lag */
+ Word16 old_ol_lag[5]
+)
+{
+ Word16 i;
+
+ /* Use median of 5 previous open-loop lags as old lag */
+
+ for (i = 4; i > 0; i--)
+ {
+ old_ol_lag[i] = old_ol_lag[i - 1]; move16();
+ }
+
+ old_ol_lag[0] = prev_ol_lag; move16();
+
+ i = median5(&old_ol_lag[2]);
+
+ return i;
+
+}
--- /dev/null
+++ b/amr-wb/p_med_ol.tab
@@ -1,0 +1,26 @@
+/*-----------------------------------------------------*
+ | Table for function Pitch_med_ol() |
+ *-----------------------------------------------------*/
+
+ static Word16 corrweight[199]= {
+
+ 10772, 10794, 10816, 10839, 10862, 10885, 10908, 10932, 10955, 10980,
+ 11004, 11029, 11054, 11079, 11105, 11131, 11157, 11183, 11210, 11238,
+ 11265, 11293, 11322, 11350, 11379, 11409, 11439, 11469, 11500, 11531,
+ 11563, 11595, 11628, 11661, 11694, 11728, 11763, 11798, 11834, 11870,
+ 11907, 11945, 11983, 12022, 12061, 12101, 12142, 12184, 12226, 12270,
+ 12314, 12358, 12404, 12451, 12498, 12547, 12596, 12647, 12699, 12751,
+ 12805, 12861, 12917, 12975, 13034, 13095, 13157, 13221, 13286, 13353,
+ 13422, 13493, 13566, 13641, 13719, 13798, 13880, 13965, 14053, 14143,
+ 14237, 14334, 14435, 14539, 14648, 14761, 14879, 15002, 15130, 15265,
+ 15406, 15554, 15710, 15874, 16056, 16384, 16384, 16384, 16384, 16384,
+ 16384, 16384, 16056, 15874, 15710, 15554, 15406, 15265, 15130, 15002,
+ 14879, 14761, 14648, 14539, 14435, 14334, 14237, 14143, 14053, 13965,
+ 13880, 13798, 13719, 13641, 13566, 13493, 13422, 13353, 13286, 13221,
+ 13157, 13095, 13034, 12975, 12917, 12861, 12805, 12751, 12699, 12647,
+ 12596, 12547, 12498, 12451, 12404, 12358, 12314, 12270, 12226, 12184,
+ 12142, 12101, 12061, 12022, 11983, 11945, 11907, 11870, 11834, 11798,
+ 11763, 11728, 11694, 11661, 11628, 11595, 11563, 11531, 11500, 11469,
+ 11439, 11409, 11379, 11350, 11322, 11293, 11265, 11238, 11210, 11183,
+ 11157, 11131, 11105, 11079, 11054, 11029, 11004, 10980, 10955, 10932,
+ 10908, 10885, 10862, 10839, 10816, 10794, 10772, 10750, 10728};
--- /dev/null
+++ b/amr-wb/ph_disp.c
@@ -1,0 +1,160 @@
+/*-----------------------------------------------------------------------*
+ * PH_DISP.C *
+ *-----------------------------------------------------------------------*
+ * post-processing to enhance noise in low bit rate. *
+ *-----------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+#include "acelp.h"
+#include "count.h"
+
+#define pitch_0_9 14746 /* 0.9 in Q14 */
+#define pitch_0_6 9830 /* 0.6 in Q14 */
+
+
+#define L_SUBFR 64
+
+/* impulse response with phase dispersion */
+
+/* 2.0 - 6.4 kHz phase dispersion */
+static Word16 ph_imp_low[L_SUBFR] =
+{
+ 20182, 9693, 3270, -3437, 2864, -5240, 1589, -1357,
+ 600, 3893, -1497, -698, 1203, -5249, 1199, 5371,
+ -1488, -705, -2887, 1976, 898, 721, -3876, 4227,
+ -5112, 6400, -1032, -4725, 4093, -4352, 3205, 2130,
+ -1996, -1835, 2648, -1786, -406, 573, 2484, -3608,
+ 3139, -1363, -2566, 3808, -639, -2051, -541, 2376,
+ 3932, -6262, 1432, -3601, 4889, 370, 567, -1163,
+ -2854, 1914, 39, -2418, 3454, 2975, -4021, 3431
+};
+
+/* 3.2 - 6.4 kHz phase dispersion */
+static Word16 ph_imp_mid[L_SUBFR] =
+{
+ 24098, 10460, -5263, -763, 2048, -927, 1753, -3323,
+ 2212, 652, -2146, 2487, -3539, 4109, -2107, -374,
+ -626, 4270, -5485, 2235, 1858, -2769, 744, 1140,
+ -763, -1615, 4060, -4574, 2982, -1163, 731, -1098,
+ 803, 167, -714, 606, -560, 639, 43, -1766,
+ 3228, -2782, 665, 763, 233, -2002, 1291, 1871,
+ -3470, 1032, 2710, -4040, 3624, -4214, 5292, -4270,
+ 1563, 108, -580, 1642, -2458, 957, 544, 2540
+};
+
+
+
+void Init_Phase_dispersion(
+ Word16 disp_mem[] /* (i/o): static memory (size = 8) */
+)
+{
+ Set_zero(disp_mem, 8);
+
+ return;
+}
+
+
+void Phase_dispersion(
+ Word16 gain_code, /* (i) Q0 : gain of code */
+ Word16 gain_pit, /* (i) Q14 : gain of pitch */
+ Word16 code[], /* (i/o) : code vector */
+ Word16 mode, /* (i) : level, 0=hi, 1=lo, 2=off */
+ Word16 disp_mem[] /* (i/o) : static memory (size = 8) */
+)
+{
+ Word16 i, j, state;
+ Word16 *prev_gain_pit, *prev_gain_code, *prev_state;
+ Word16 code2[2 * L_SUBFR];
+
+ prev_state = disp_mem;
+ prev_gain_code = disp_mem + 1;
+ prev_gain_pit = disp_mem + 2;
+
+ Set_zero(code2, 2 * L_SUBFR);
+
+ test();test();move16();
+ if (sub(gain_pit, pitch_0_6) < 0)
+ state = 0;
+ else if (sub(gain_pit, pitch_0_9) < 0)
+ state = 1;
+ else
+ state = 2;
+
+ for (i = 5; i > 0; i--)
+ {
+ prev_gain_pit[i] = prev_gain_pit[i - 1]; move16();
+ }
+ prev_gain_pit[0] = gain_pit; move16();
+
+ if (sub(sub(gain_code, *prev_gain_code), shl(*prev_gain_code, 1)) > 0)
+ {
+ /* onset */
+ test();
+ if (sub(state, 2) < 0)
+ state = add(state, 1);
+ } else
+ {
+ j = 0;
+ for (i = 0; i < 6; i++)
+ {
+ test();
+ if (sub(prev_gain_pit[i], pitch_0_6) < 0)
+ j = add(j, 1);
+ }
+ test();
+ if (sub(j, 2) > 0)
+ {
+ state = 0; move16();
+ }
+ if (sub(sub(state, *prev_state), 1) > 0)
+ state = sub(state, 1);
+ }
+
+ *prev_gain_code = gain_code; move16();
+ *prev_state = state; move16();
+
+ /* circular convolution */
+
+ state = add(state, mode); /* level of dispersion */
+
+ if (state == 0)
+ {
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ test();
+ if (code[i] != 0)
+ {
+ for (j = 0; j < L_SUBFR; j++)
+ {
+ move16();
+ code2[i + j] = add(code2[i + j], mult_r(code[i], ph_imp_low[j]));
+ }
+ }
+ }
+ } else if (sub(state, 1) == 0)
+ {
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ test();
+ if (code[i] != 0)
+ {
+ for (j = 0; j < L_SUBFR; j++)
+ {
+ move16();
+ code2[i + j] = add(code2[i + j], mult_r(code[i], ph_imp_mid[j]));
+ }
+ }
+ }
+ }
+ if (sub(state, 2) < 0)
+ {
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ move16();
+ code[i] = add(code2[i], code2[i + L_SUBFR]);
+ }
+ }
+ return;
+}
--- /dev/null
+++ b/amr-wb/pit_shrp.c
@@ -1,0 +1,30 @@
+/*-----------------------------------------------------------------------*
+ * PIT_SHRP.C *
+ *-----------------------------------------------------------------------*
+ * Performs Pitch sharpening routine *
+ *-----------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+void Pit_shrp(
+ Word16 * x, /* in/out: impulse response (or algebraic code) */
+ Word16 pit_lag, /* input : pitch lag */
+ Word16 sharp, /* input : pitch sharpening factor (Q15) */
+ Word16 L_subfr /* input : subframe size */
+)
+{
+ Word16 i;
+ Word32 L_tmp;
+
+ for (i = pit_lag; i < L_subfr; i++)
+ {
+ L_tmp = L_deposit_h(x[i]);
+ L_tmp = L_mac(L_tmp, x[i - pit_lag], sharp);
+ x[i] = round(L_tmp);
+ move16();
+ }
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/pitch_f4.c
@@ -1,0 +1,295 @@
+/*-----------------------------------------------------------------------*
+ * PITCH_F4.C *
+ *-----------------------------------------------------------------------*
+ * Find the closed loop pitch period with 1/4 subsample resolution. *
+ *-----------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "math_op.h"
+#include "acelp.h"
+#include "cnst.h"
+#include "count.h"
+
+#define UP_SAMP 4
+#define L_INTERPOL1 4
+
+/* Local functions */
+
+static void Norm_Corr(
+ Word16 exc[], /* (i) : excitation buffer */
+ Word16 xn[], /* (i) : target vector */
+ Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */
+ Word16 L_subfr, /* (i) : Length of subframe */
+ Word16 t_min, /* (i) : minimum value of pitch lag. */
+ Word16 t_max, /* (i) : maximum value of pitch lag. */
+ Word16 corr_norm[] /* (o) Q15 : normalized correlation */
+);
+static Word16 Interpol_4( /* (o) : interpolated value */
+ Word16 * x, /* (i) : input vector */
+ Word16 frac /* (i) : fraction (-4..+3) */
+);
+
+
+Word16 Pitch_fr4( /* (o) : pitch period. */
+ Word16 exc[], /* (i) : excitation buffer */
+ Word16 xn[], /* (i) : target vector */
+ Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */
+ Word16 t0_min, /* (i) : minimum value in the searched range. */
+ Word16 t0_max, /* (i) : maximum value in the searched range. */
+ Word16 * pit_frac, /* (o) : chosen fraction (0, 1, 2 or 3). */
+ Word16 i_subfr, /* (i) : indicator for first subframe. */
+ Word16 t0_fr2, /* (i) : minimum value for resolution 1/2 */
+ Word16 t0_fr1, /* (i) : minimum value for resolution 1 */
+ Word16 L_subfr /* (i) : Length of subframe */
+)
+{
+ Word16 i;
+ Word16 t_min, t_max;
+ Word16 max, t0, fraction, step, temp;
+ Word16 *corr;
+ Word16 corr_v[40]; /* Total length = t0_max-t0_min+1+2*L_inter */
+
+ /* Find interval to compute normalized correlation */
+
+ t_min = sub(t0_min, L_INTERPOL1);
+ t_max = add(t0_max, L_INTERPOL1);
+
+ 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();
+ t0 = t0_min;
+ move16();
+
+ for (i = add(t0_min, 1); i <= t0_max; i++)
+ {
+ test();
+ if (sub(corr[i], max) >= 0)
+ {
+ max = corr[i]; move16();
+ t0 = i; move16();
+ }
+ }
+
+ /* If first subframe and t0 >= t0_fr1, do not search fractionnal pitch */
+ test();test();
+ if ((i_subfr == 0) && (sub(t0, t0_fr1) >= 0))
+ {
+ *pit_frac = 0;
+ move16();
+ return (t0);
+ }
+ /*------------------------------------------------------------------*
+ * Search fractionnal pitch with 1/4 subsample resolution. *
+ * Test the fractions around t0 and choose the one which maximizes *
+ * the interpolated normalized correlation. *
+ *------------------------------------------------------------------*/
+
+ step = 1;
+ move16(); /* 1/4 subsample resolution */
+ fraction = -3;
+ move16();
+ test();test();test();
+ if (((i_subfr == 0) && (sub(t0, t0_fr2) >= 0)) || (sub(t0_fr2, PIT_MIN) == 0))
+ {
+ step = 2;
+ move16(); /* 1/2 subsample resolution */
+ fraction = -2;
+ move16();
+ }
+ test();
+ if (sub(t0, t0_min) == 0)
+ {
+ fraction = 0;
+ move16();
+ }
+ max = Interpol_4(&corr[t0], fraction);
+
+ for (i = add(fraction, step); i <= 3; i = (Word16) (i + step))
+ {
+ temp = Interpol_4(&corr[t0], i);
+
+ test();
+ if (sub(temp, max) > 0)
+ {
+ max = temp;
+ move16();
+ fraction = i;
+ move16();
+ }
+ }
+
+ /* limit the fraction value in the interval [0,1,2,3] */
+ test();
+ if (fraction < 0)
+ {
+ fraction = add(fraction, UP_SAMP);
+ t0 = sub(t0, 1);
+ }
+ *pit_frac = fraction;
+ move16();
+
+ return (t0);
+}
+
+
+/*--------------------------------------------------------------------------*
+ * Function Norm_Corr() *
+ * ~~~~~~~~~~~~~~~~~~~~ *
+ * Find the normalized correlation between the target vector and the *
+ * filtered past excitation. *
+ * (correlation between target and filtered excitation divided by the *
+ * square root of energy of target and filtered excitation). *
+ *--------------------------------------------------------------------------*/
+
+static void Norm_Corr(
+ Word16 exc[], /* (i) : excitation buffer */
+ Word16 xn[], /* (i) : target vector */
+ Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */
+ Word16 L_subfr, /* (i) : Length of subframe */
+ Word16 t_min, /* (i) : minimum value of pitch lag. */
+ Word16 t_max, /* (i) : maximum value of pitch lag. */
+ Word16 corr_norm[]) /* (o) Q15 : normalized correlation */
+{
+ Word16 i, k, t;
+ Word16 corr, exp_corr, norm, exp_norm, exp, scale;
+ Word16 excf[L_SUBFR];
+ Word32 L_tmp;
+
+ /* compute the filtered excitation for the first delay t_min */
+
+ k = negate(t_min);
+ Convolve(&exc[k], h, excf, L_subfr);
+
+ /* Compute rounded down 1/sqrt(energy of xn[]) */
+
+ L_tmp = 1L; move32();
+ for (i = 0; i < L_subfr; i++)
+ L_tmp = L_mac(L_tmp, xn[i], xn[i]);
+
+ exp = norm_l(L_tmp);
+ exp = sub(30, exp);
+
+ exp = add(exp, 2); /* energy of xn[] x 2 + rounded up */
+ scale = negate(shr(exp, 1)); /* (1<<scale) < 1/sqrt(energy rounded) */
+
+ /* loop for every possible period */
+
+ for (t = t_min; t <= t_max; t++)
+ {
+ /* Compute correlation between xn[] and excf[] */
+
+ L_tmp = 1L; move32();
+ for (i = 0; i < L_subfr; i++)
+ L_tmp = L_mac(L_tmp, xn[i], excf[i]);
+
+ exp = norm_l(L_tmp);
+ L_tmp = L_shl(L_tmp, exp);
+ exp_corr = sub(30, exp);
+
+ corr = extract_h(L_tmp);
+
+ /* Compute 1/sqrt(energy of excf[]) */
+
+ L_tmp = 1L; move32();
+ for (i = 0; i < L_subfr; i++)
+ L_tmp = L_mac(L_tmp, excf[i], excf[i]);
+
+ exp = norm_l(L_tmp);
+ L_tmp = L_shl(L_tmp, exp);
+ exp_norm = sub(30, exp);
+
+ Isqrt_n(&L_tmp, &exp_norm);
+ norm = extract_h(L_tmp);
+
+ /* Normalize correlation = correlation * (1/sqrt(energy)) */
+
+ L_tmp = L_mult(corr, norm);
+ L_tmp = L_shl(L_tmp, add(add(exp_corr, exp_norm), scale));
+
+ corr_norm[t] = round(L_tmp); move16();
+
+ /* modify the filtered excitation excf[] for the next iteration */
+
+ test();
+ if (sub(t, t_max) != 0)
+ {
+ k--; move16();
+ for (i = (Word16) (L_subfr - 1); i > 0; i--)
+ {
+ /* saturation can occur in add() */
+ excf[i] = add(mult(exc[k], h[i]), excf[i - 1]); move16();
+ }
+ excf[0] = mult(exc[k], h[0]); move16();
+ }
+ }
+
+ return;
+}
+
+
+/*--------------------------------------------------------------------------*
+ * Procedure Interpol_4() *
+ * ~~~~~~~~~~~~~~~~~~~~~~ *
+ * For interpolating the normalized correlation with 1/4 resolution. *
+ *--------------------------------------------------------------------------*/
+
+/* 1/4 resolution interpolation filter (-3 dB at 0.791*fs/2) in Q14 */
+
+static Word16 inter4_1[UP_SAMP * 2 * L_INTERPOL1] =
+{
+ -12, -26, 32, 206,
+ 420, 455, 73, -766,
+ -1732, -2142, -1242, 1376,
+ 5429, 9910, 13418, 14746,
+ 13418, 9910, 5429, 1376,
+ -1242, -2142, -1732, -766,
+ 73, 455, 420, 206,
+ 32, -26, -12, 0
+};
+
+/*** Coefficients in floating point
+static float inter4_1[UP_SAMP*L_INTERPOL1+1] = {
+ 0.900000,
+ 0.818959, 0.604850, 0.331379, 0.083958,
+ -0.075795, -0.130717, -0.105685, -0.046774,
+ 0.004467, 0.027789, 0.025642, 0.012571,
+ 0.001927, -0.001571, -0.000753, 0.000000};
+***/
+
+static Word16 Interpol_4( /* (o) : interpolated value */
+ Word16 * x, /* (i) : input vector */
+ Word16 frac /* (i) : fraction (-4..+3) */
+)
+{
+ Word16 i, k, sum;
+ Word32 L_sum;
+
+ test();
+ if (frac < 0)
+ {
+ frac = add(frac, UP_SAMP);
+ x--;
+ move16();
+ }
+ x = x - L_INTERPOL1 + 1;
+ move16();
+
+ L_sum = 0L; move32();
+ for (i = 0, k = sub(sub(UP_SAMP, 1), frac); i < 2 * L_INTERPOL1; i++, k += UP_SAMP)
+ {
+ L_sum = L_mac(L_sum, x[i], inter4_1[k]);
+ }
+
+ sum = round(L_shl(L_sum, 1));
+
+ return (sum);
+}
--- /dev/null
+++ b/amr-wb/pred_lt4.c
@@ -1,0 +1,116 @@
+/*-------------------------------------------------------------------*
+ * PRED_LT4.C *
+ *-------------------------------------------------------------------*
+ * Compute the result of long term prediction with fractionnal *
+ * interpolation of resolution 1/4. *
+ * *
+ * On return exc[0..L_subfr-1] contains the interpolated signal *
+ * (adaptive codebook excitation) *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+#define UP_SAMP 4
+#define L_INTERPOL2 16
+
+/* 1/4 resolution interpolation filter (-3 dB at 0.856*fs/2) in Q14 */
+
+static Word16 inter4_2[UP_SAMP * 2 * L_INTERPOL2] =
+{
+ 0, 1, 2, 1,
+ -2, -7, -10, -7,
+ 4, 19, 28, 22,
+ -2, -33, -55, -49,
+ -10, 47, 91, 92,
+ 38, -52, -133, -153,
+ -88, 43, 175, 231,
+ 165, -9, -209, -325,
+ -275, -60, 226, 431,
+ 424, 175, -213, -544,
+ -619, -355, 153, 656,
+ 871, 626, -16, -762,
+ -1207, -1044, -249, 853,
+ 1699, 1749, 780, -923,
+ -2598, -3267, -2147, 968,
+ 5531, 10359, 14031, 15401,
+ 14031, 10359, 5531, 968,
+ -2147, -3267, -2598, -923,
+ 780, 1749, 1699, 853,
+ -249, -1044, -1207, -762,
+ -16, 626, 871, 656,
+ 153, -355, -619, -544,
+ -213, 175, 424, 431,
+ 226, -60, -275, -325,
+ -209, -9, 165, 231,
+ 175, 43, -88, -153,
+ -133, -52, 38, 92,
+ 91, 47, -10, -49,
+ -55, -33, -2, 22,
+ 28, 19, 4, -7,
+ -10, -7, -2, 1,
+ 2, 1, 0, 0
+};
+
+/*** Coefficients in floating point
+static float inter4_2[UP_SAMP*L_INTERPOL2+1] = {
+ 0.940000,
+ 0.856390, 0.632268, 0.337560, 0.059072,
+ -0.131059, -0.199393, -0.158569, -0.056359,
+ 0.047606, 0.106749, 0.103705, 0.052062,
+ -0.015182, -0.063705, -0.073660, -0.046497,
+ -0.000983, 0.038227, 0.053143, 0.040059,
+ 0.009308, -0.021674, -0.037767, -0.033186,
+ -0.013028, 0.010702, 0.025901, 0.026318,
+ 0.013821, -0.003645, -0.016813, -0.019855,
+ -0.012766, -0.000530, 0.010080, 0.014122,
+ 0.010657, 0.002594, -0.005363, -0.009344,
+ -0.008101, -0.003182, 0.002330, 0.005635,
+ 0.005562, 0.002844, -0.000627, -0.002993,
+ -0.003362, -0.002044, -0.000116, 0.001315,
+ 0.001692, 0.001151, 0.000259, -0.000417,
+ -0.000618, -0.000434, -0.000133, 0.000063,
+ 0.000098, 0.000048, 0.000007, 0.000000};
+***/
+
+void Pred_lt4(
+ Word16 exc[], /* in/out: excitation buffer */
+ Word16 T0, /* input : integer pitch lag */
+ Word16 frac, /* input : fraction of lag */
+ Word16 L_subfr /* input : subframe size */
+)
+{
+ Word16 i, j, k, *x;
+ Word32 L_sum;
+
+ x = &exc[-T0];
+ move16();
+
+ frac = negate(frac);
+ test();
+ if (frac < 0)
+ {
+ frac = add(frac, UP_SAMP);
+ x--;
+ move16();
+ }
+ x = x - L_INTERPOL2 + 1;
+ move16();
+
+ for (j = 0; j < L_subfr; j++)
+ {
+ L_sum = 0L; move32();
+ for (i = 0, k = sub(sub(UP_SAMP, 1), frac); i < 2 * L_INTERPOL2; i++, k += UP_SAMP)
+ {
+ L_sum = L_mac(L_sum, x[i], inter4_2[k]);
+ }
+ L_sum = L_shl(L_sum, 1);
+
+ exc[j] = round(L_sum);
+ move16();
+ x++;
+ }
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/preemph.c
@@ -1,0 +1,71 @@
+/*-------------------------------------------------------------------*
+ * PREEMPH.C *
+ *-------------------------------------------------------------------*
+ * Preemphasis: filtering through 1 - g z^-1 *
+ * *
+ * Preemph2 --> signal is multiplied by 2. *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+
+void Preemph(
+ Word16 x[], /* (i/o) : input signal overwritten by the output */
+ Word16 mu, /* (i) Q15 : preemphasis coefficient */
+ Word16 lg, /* (i) : lenght of filtering */
+ Word16 * mem /* (i/o) : memory (x[-1]) */
+)
+{
+ Word16 i, temp;
+ Word32 L_tmp;
+
+ temp = x[lg - 1]; move16();
+
+ for (i = (Word16) (lg - 1); i > 0; i--)
+ {
+ L_tmp = L_deposit_h(x[i]);
+ L_tmp = L_msu(L_tmp, x[i - 1], mu);
+ x[i] = round(L_tmp); move16();
+ }
+
+ L_tmp = L_deposit_h(x[0]);
+ L_tmp = L_msu(L_tmp, *mem, mu);
+ x[0] = round(L_tmp); move16();
+
+ *mem = temp; move16();
+
+ return;
+}
+
+
+void Preemph2(
+ Word16 x[], /* (i/o) : input signal overwritten by the output */
+ Word16 mu, /* (i) Q15 : preemphasis coefficient */
+ Word16 lg, /* (i) : lenght of filtering */
+ Word16 * mem /* (i/o) : memory (x[-1]) */
+)
+{
+ Word16 i, temp;
+ Word32 L_tmp;
+
+ temp = x[lg - 1]; move16();
+
+ for (i = (Word16) (lg - 1); i > 0; i--)
+ {
+ L_tmp = L_deposit_h(x[i]);
+ L_tmp = L_msu(L_tmp, x[i - 1], mu);
+ L_tmp = L_shl(L_tmp, 1);
+ x[i] = round(L_tmp); move16();
+ }
+
+ L_tmp = L_deposit_h(x[0]);
+ L_tmp = L_msu(L_tmp, *mem, mu);
+ L_tmp = L_shl(L_tmp, 1);
+ x[0] = round(L_tmp); move16();
+
+ *mem = temp; move16();
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/q_gain2.c
@@ -1,0 +1,326 @@
+/*--------------------------------------------------------------------------*
+ * Q_GAIN2.C *
+ *--------------------------------------------------------------------------*
+ * Quantization of pitch and codebook gains. *
+ * MA prediction is performed on the innovation energy (in dB with mean *
+ * removed). *
+ * An initial predicted gain, g_0, is first determined and the correction *
+ * factor alpha = gain / g_0 is quantized. *
+ * The pitch gain and the correction factor are vector quantized and the *
+ * mean-squared weighted error criterion is used in the quantizer search. *
+ *--------------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "math_op.h"
+#include "count.h"
+#include "log2.h"
+
+#include "acelp.h"
+
+#include "q_gain2.tab"
+
+#define MEAN_ENER 30
+#define RANGE 64
+#define PRED_ORDER 4
+
+
+/* MA prediction coeff ={0.5, 0.4, 0.3, 0.2} in Q13 */
+static Word16 pred[PRED_ORDER] = {4096, 3277, 2458, 1638};
+
+
+void Init_Q_gain2(
+ Word16 * mem /* output :static memory (2 words) */
+)
+{
+ Word16 i;
+
+ /* 4nd order quantizer energy predictor (init to -14.0 in Q10) */
+ for (i = 0; i < PRED_ORDER; i++)
+ {
+ mem[i] = -14336; move16(); /* past_qua_en[i] */
+ }
+
+ return;
+}
+
+
+Word16 Q_gain2( /* Return index of quantization. */
+ Word16 xn[], /* (i) Q_xn: Target vector. */
+ Word16 y1[], /* (i) Q_xn: Adaptive codebook. */
+ Word16 Q_xn, /* (i) : xn and y1 format */
+ Word16 y2[], /* (i) Q9 : Filtered innovative vector. */
+ Word16 code[], /* (i) Q9 : Innovative vector. */
+ Word16 g_coeff[], /* (i) : Correlations <xn y1> <y1 y1> */
+ /* Compute in G_pitch(). */
+ Word16 L_subfr, /* (i) : Subframe lenght. */
+ Word16 nbits, /* (i) : number of bits (6 or 7) */
+ Word16 * gain_pit, /* (i/o)Q14: Pitch gain. */
+ Word32 * gain_cod, /* (o) Q16 : Code gain. */
+ Word16 gp_clip, /* (i) : Gp Clipping flag */
+ Word16 * mem /* (i/o) : static memory (2 words) */
+)
+{
+ Word16 i, j, index, *p, min_ind, size;
+ Word16 exp, frac, gcode0, exp_gcode0, e_max, exp_code, qua_ener;
+ Word16 g_pitch, g2_pitch, g_code, g_pit_cod, g2_code, g2_code_lo;
+ Word16 coeff[5], coeff_lo[5], exp_coeff[5];
+ Word16 exp_max[5];
+ Word32 L_tmp, dist_min;
+ Word16 *past_qua_en, *t_qua_gain;
+
+ past_qua_en = mem; move16();
+
+ /*-----------------------------------------------------------------*
+ * - Find the initial quantization pitch index *
+ * - Set gains search range *
+ *-----------------------------------------------------------------*/
+ test();
+ if (sub(nbits, 6) == 0)
+ {
+ t_qua_gain = t_qua_gain6b; move16();
+ min_ind = 0; move16();
+ size = RANGE; move16();
+
+ test();
+ if (sub(gp_clip, 1) == 0)
+ {
+ size = sub(size, 16); /* limit gain pitch to 1.0 */
+ }
+ } else
+ {
+ t_qua_gain = t_qua_gain7b; move16();
+
+ p = t_qua_gain7b + RANGE; move16(); /* pt at 1/4th of table */
+
+ j = nb_qua_gain7b - RANGE; move16();
+ test();
+ if (sub(gp_clip, 1) == 0)
+ {
+ j = sub(j, 27); /* limit gain pitch to 1.0 */
+ }
+ min_ind = 0; move16();
+ g_pitch = *gain_pit; move16();
+
+ for (i = 0; i < j; i++, p += 2)
+ {
+ test();
+ if (sub(g_pitch, *p) > 0)
+ {
+ min_ind = add(min_ind, 1);
+ }
+ }
+ size = RANGE; move16();
+ }
+
+ /*------------------------------------------------------------------*
+ * Compute coefficient need for the quantization. *
+ * *
+ * coeff[0] = y1 y1 *
+ * coeff[1] = -2 xn y1 *
+ * coeff[2] = y2 y2 *
+ * coeff[3] = -2 xn y2 *
+ * coeff[4] = 2 y1 y2 *
+ * *
+ * Product <y1 y1> and <xn y1> have been compute in G_pitch() and *
+ * are in vector g_coeff[]. *
+ *------------------------------------------------------------------*/
+
+ coeff[0] = g_coeff[0]; move16();
+ exp_coeff[0] = g_coeff[1]; move16();
+ coeff[1] = negate(g_coeff[2]); move16(); /* coeff[1] = -2 xn y1 */
+ exp_coeff[1] = add(g_coeff[3], 1); move16();
+
+ /* Compute scalar product <y2[],y2[]> */
+ move16();move16();
+ coeff[2] = extract_h(Dot_product12(y2, y2, L_subfr, &exp));
+ exp_coeff[2] = add(sub(exp, 18), shl(Q_xn, 1)); /* -18 (y2 Q9) */
+
+ /* Compute scalar product -2*<xn[],y2[]> */
+ move16();move16();
+ coeff[3] = extract_h(L_negate(Dot_product12(xn, y2, L_subfr, &exp)));
+ exp_coeff[3] = add(sub(exp, 9 - 1), Q_xn); /* -9 (y2 Q9), +1 (2 xn y2) */
+
+ /* Compute scalar product 2*<y1[],y2[]> */
+ move16();move16();
+ coeff[4] = extract_h(Dot_product12(y1, y2, L_subfr, &exp));
+ exp_coeff[4] = add(sub(exp, 9 - 1), Q_xn); /* -9 (y2 Q9), +1 (2 y1 y2) */
+
+ /*-----------------------------------------------------------------*
+ * Find energy of code and compute: *
+ * *
+ * L_tmp = MEAN_ENER - 10log10(energy of code/ L_subfr) *
+ * = MEAN_ENER - 3.0103*log2(energy of code/ L_subfr) *
+ *-----------------------------------------------------------------*/
+
+ L_tmp = Dot_product12(code, code, L_subfr, &exp_code);
+ /* exp_code: -18 (code in Q9), -6 (/L_subfr), -31 (L_tmp Q31->Q0) */
+ exp_code = sub(exp_code, 18 + 6 + 31);
+
+ Log2(L_tmp, &exp, &frac);
+ exp = add(exp, exp_code);
+ L_tmp = Mpy_32_16(exp, frac, -24660); /* x -3.0103(Q13) -> Q14 */
+
+ L_tmp = L_mac(L_tmp, MEAN_ENER, 8192); /* + MEAN_ENER in Q14 */
+
+ /*-----------------------------------------------------------------*
+ * Compute gcode0. *
+ * = Sum(i=0,1) pred[i]*past_qua_en[i] + mean_ener - ener_code *
+ *-----------------------------------------------------------------*/
+
+ L_tmp = L_shl(L_tmp, 10); /* From Q14 to Q24 */
+ L_tmp = L_mac(L_tmp, pred[0], past_qua_en[0]); /* Q13*Q10 -> Q24 */
+ L_tmp = L_mac(L_tmp, pred[1], past_qua_en[1]); /* Q13*Q10 -> Q24 */
+ L_tmp = L_mac(L_tmp, pred[2], past_qua_en[2]); /* Q13*Q10 -> Q24 */
+ L_tmp = L_mac(L_tmp, pred[3], past_qua_en[3]); /* Q13*Q10 -> Q24 */
+
+ gcode0 = extract_h(L_tmp); /* From Q24 to Q8 */
+
+ /*-----------------------------------------------------------------*
+ * gcode0 = pow(10.0, gcode0/20) *
+ * = pow(2, 3.321928*gcode0/20) *
+ * = pow(2, 0.166096*gcode0) *
+ *-----------------------------------------------------------------*/
+
+ L_tmp = L_mult(gcode0, 5443); /* *0.166096 in Q15 -> Q24 */
+ L_tmp = L_shr(L_tmp, 8); /* From Q24 to Q16 */
+ L_Extract(L_tmp, &exp_gcode0, &frac); /* Extract exponent of gcode0 */
+
+ gcode0 = extract_l(Pow2(14, frac)); /* Put 14 as exponent so that */
+ /* output of Pow2() will be: */
+ /* 16384 < Pow2() <= 32767 */
+ exp_gcode0 = sub(exp_gcode0, 14);
+
+ /*-------------------------------------------------------------------------*
+ * Find the best quantizer *
+ * ~~~~~~~~~~~~~~~~~~~~~~~ *
+ * Before doing the computation we need to aling exponents of coeff[] *
+ * to be sure to have the maximum precision. *
+ * *
+ * In the table the pitch gains are in Q14, the code gains are in Q11 and *
+ * are multiply by gcode0 which have been multiply by 2^exp_gcode0. *
+ * Also when we compute g_pitch*g_pitch, g_code*g_code and g_pitch*g_code *
+ * we divide by 2^15. *
+ * Considering all the scaling above we have: *
+ * *
+ * exp_code = exp_gcode0-11+15 = exp_gcode0+4 *
+ * *
+ * g_pitch*g_pitch = -14-14+15 *
+ * g_pitch = -14 *
+ * g_code*g_code = (2*exp_code)+15 *
+ * g_code = exp_code *
+ * g_pitch*g_code = -14 + exp_code +15 *
+ * *
+ * g_pitch*g_pitch * coeff[0] ;exp_max0 = exp_coeff[0] - 13 *
+ * g_pitch * coeff[1] ;exp_max1 = exp_coeff[1] - 14 *
+ * g_code*g_code * coeff[2] ;exp_max2 = exp_coeff[2] +15+(2*exp_code) *
+ * g_code * coeff[3] ;exp_max3 = exp_coeff[3] + exp_code *
+ * g_pitch*g_code * coeff[4] ;exp_max4 = exp_coeff[4] + 1 + exp_code *
+ *-------------------------------------------------------------------------*/
+
+ exp_code = add(exp_gcode0, 4);
+
+ exp_max[0] = sub(exp_coeff[0], 13); move16();
+ exp_max[1] = sub(exp_coeff[1], 14); move16();
+ exp_max[2] = add(exp_coeff[2], add(15, shl(exp_code, 1))); move16();
+ exp_max[3] = add(exp_coeff[3], exp_code); move16();
+ exp_max[4] = add(exp_coeff[4], add(1, exp_code)); move16();
+
+ /* Find maximum exponant */
+
+ e_max = exp_max[0]; move16();
+ for (i = 1; i < 5; i++)
+ {
+ test();
+ if (sub(exp_max[i], e_max) > 0)
+ {
+ e_max = exp_max[i]; move16();
+ }
+ }
+
+ /* align coeff[] and save in special 32 bit double precision */
+
+ for (i = 0; i < 5; i++)
+ {
+ j = add(sub(e_max, exp_max[i]), 2);/* /4 to avoid overflow */
+ L_tmp = L_deposit_h(coeff[i]);
+ L_tmp = L_shr(L_tmp, j);
+ L_Extract(L_tmp, &coeff[i], &coeff_lo[i]);
+ coeff_lo[i] = shr(coeff_lo[i], 3); move16(); /* lo >> 3 */
+ }
+
+ /* Codebook search */
+
+ dist_min = MAX_32; move32();
+ p = &t_qua_gain[shl(min_ind, 1)]; move16();
+
+ index = 0; move16();
+ for (i = 0; i < size; i++)
+ {
+ g_pitch = *p++; move16();
+ g_code = *p++; move16();
+
+ g_code = mult_r(g_code, gcode0);
+ g2_pitch = mult_r(g_pitch, g_pitch);
+ g_pit_cod = mult_r(g_code, g_pitch);
+ L_tmp = L_mult(g_code, g_code);
+ L_Extract(L_tmp, &g2_code, &g2_code_lo);
+
+ L_tmp = L_mult(coeff[2], g2_code_lo);
+ L_tmp = L_shr(L_tmp, 3);
+ L_tmp = L_mac(L_tmp, coeff_lo[0], g2_pitch);
+ L_tmp = L_mac(L_tmp, coeff_lo[1], g_pitch);
+ L_tmp = L_mac(L_tmp, coeff_lo[2], g2_code);
+ L_tmp = L_mac(L_tmp, coeff_lo[3], g_code);
+ L_tmp = L_mac(L_tmp, coeff_lo[4], g_pit_cod);
+ L_tmp = L_shr(L_tmp, 12);
+ L_tmp = L_mac(L_tmp, coeff[0], g2_pitch);
+ L_tmp = L_mac(L_tmp, coeff[1], g_pitch);
+ L_tmp = L_mac(L_tmp, coeff[2], g2_code);
+ L_tmp = L_mac(L_tmp, coeff[3], g_code);
+ L_tmp = L_mac(L_tmp, coeff[4], g_pit_cod);
+
+ test();
+ if (L_sub(L_tmp, dist_min) < (Word32) 0)
+ {
+ dist_min = L_tmp; move32();
+ index = i; move16();
+ }
+ }
+
+ /* Read the quantized gains */
+
+ index = add(index, min_ind);
+
+ p = &t_qua_gain[add(index, index)]; move16();
+ *gain_pit = *p++; move16(); /* selected pitch gain in Q14 */
+ g_code = *p++; move16(); /* selected code gain in Q11 */
+
+ L_tmp = L_mult(g_code, gcode0); /* Q11*Q0 -> Q12 */
+ L_tmp = L_shl(L_tmp, add(exp_gcode0, 4)); /* Q12 -> Q16 */
+
+ *gain_cod = L_tmp; move16(); /* gain of code in Q16 */
+
+ /*---------------------------------------------------*
+ * qua_ener = 20*log10(g_code) *
+ * = 6.0206*log2(g_code) *
+ * = 6.0206*(log2(g_codeQ11) - 11) *
+ *---------------------------------------------------*/
+
+ L_tmp = L_deposit_l(g_code);
+ Log2(L_tmp, &exp, &frac);
+ exp = sub(exp, 11);
+ L_tmp = Mpy_32_16(exp, frac, 24660); /* x 6.0206 in Q12 */
+
+ qua_ener = extract_l(L_shr(L_tmp, 3)); /* result in Q10 */
+
+ /* update table of past quantized energies */
+
+ past_qua_en[3] = past_qua_en[2]; move16();
+ past_qua_en[2] = past_qua_en[1]; move16();
+ past_qua_en[1] = past_qua_en[0]; move16();
+ past_qua_en[0] = qua_ener; move16();
+
+ return (index);
+}
--- /dev/null
+++ b/amr-wb/q_gain2.tab
@@ -1,0 +1,210 @@
+/*------------------------------------------------------*
+ * Tables for function q_gain2() *
+ * *
+ * g_pitch(Q14), g_code(Q11) *
+ * *
+ * pitch gain are ordered in table to reduce complexity *
+ * during quantization of gains. *
+ *------------------------------------------------------*/
+
+#define nb_qua_gain6b 64 /* Number of quantization level */
+#define nb_qua_gain7b 128 /* Number of quantization level */
+
+
+static Word16 t_qua_gain6b[64*2] = {
+ 1566, 1332,
+ 1577, 3557,
+ 3071, 6490,
+ 4193, 10163,
+ 4496, 2534,
+ 5019, 4488,
+ 5586, 15614,
+ 5725, 1422,
+ 6453, 580,
+ 6724, 6831,
+ 7657, 3527,
+ 8072, 2099,
+ 8232, 5319,
+ 8827, 8775,
+ 9740, 2868,
+ 9856, 1465,
+ 10087, 12488,
+ 10241, 4453,
+ 10859, 6618,
+ 11321, 3587,
+ 11417, 1800,
+ 11643, 2428,
+ 11718, 988,
+ 12312, 5093,
+ 12523, 8413,
+ 12574, 26214,
+ 12601, 3396,
+ 13172, 1623,
+ 13285, 2423,
+ 13418, 6087,
+ 13459, 12810,
+ 13656, 3607,
+ 14111, 4521,
+ 14144, 1229,
+ 14425, 1871,
+ 14431, 7234,
+ 14445, 2834,
+ 14628, 10036,
+ 14860, 17496,
+ 15161, 3629,
+ 15209, 5819,
+ 15299, 2256,
+ 15518, 4722,
+ 15663, 1060,
+ 15759, 7972,
+ 15939, 11964,
+ 16020, 2996,
+ 16086, 1707,
+ 16521, 4254,
+ 16576, 6224,
+ 16894, 2380,
+ 16906, 681,
+ 17213, 8406,
+ 17610, 3418,
+ 17895, 5269,
+ 18168, 11748,
+ 18230, 1575,
+ 18607, 32767,
+ 18728, 21684,
+ 19137, 2543,
+ 19422, 6577,
+ 19446, 4097,
+ 19450, 9056,
+ 20371, 14885};
+
+static Word16 t_qua_gain7b[128*2] = {
+ 204, 441,
+ 464, 1977,
+ 869, 1077,
+ 1072, 3062,
+ 1281, 4759,
+ 1647, 1539,
+ 1845, 7020,
+ 1853, 634,
+ 1995, 2336,
+ 2351, 15400,
+ 2661, 1165,
+ 2702, 3900,
+ 2710, 10133,
+ 3195, 1752,
+ 3498, 2624,
+ 3663, 849,
+ 3984, 5697,
+ 4214, 3399,
+ 4415, 1304,
+ 4695, 2056,
+ 5376, 4558,
+ 5386, 676,
+ 5518, 23554,
+ 5567, 7794,
+ 5644, 3061,
+ 5672, 1513,
+ 5957, 2338,
+ 6533, 1060,
+ 6804, 5998,
+ 6820, 1767,
+ 6937, 3837,
+ 7277, 414,
+ 7305, 2665,
+ 7466, 11304,
+ 7942, 794,
+ 8007, 1982,
+ 8007, 1366,
+ 8326, 3105,
+ 8336, 4810,
+ 8708, 7954,
+ 8989, 2279,
+ 9031, 1055,
+ 9247, 3568,
+ 9283, 1631,
+ 9654, 6311,
+ 9811, 2605,
+ 10120, 683,
+ 10143, 4179,
+ 10245, 1946,
+ 10335, 1218,
+ 10468, 9960,
+ 10651, 3000,
+ 10951, 1530,
+ 10969, 5290,
+ 11203, 2305,
+ 11325, 3562,
+ 11771, 6754,
+ 11839, 1849,
+ 11941, 4495,
+ 11954, 1298,
+ 11975, 15223,
+ 11977, 883,
+ 11986, 2842,
+ 12438, 2141,
+ 12593, 3665,
+ 12636, 8367,
+ 12658, 1594,
+ 12886, 2628,
+ 12984, 4942,
+ 13146, 1115,
+ 13224, 524,
+ 13341, 3163,
+ 13399, 1923,
+ 13549, 5961,
+ 13606, 1401,
+ 13655, 2399,
+ 13782, 3909,
+ 13868, 10923,
+ 14226, 1723,
+ 14232, 2939,
+ 14278, 7528,
+ 14439, 4598,
+ 14451, 984,
+ 14458, 2265,
+ 14792, 1403,
+ 14818, 3445,
+ 14899, 5709,
+ 15017, 15362,
+ 15048, 1946,
+ 15069, 2655,
+ 15405, 9591,
+ 15405, 4079,
+ 15570, 7183,
+ 15687, 2286,
+ 15691, 1624,
+ 15699, 3068,
+ 15772, 5149,
+ 15868, 1205,
+ 15970, 696,
+ 16249, 3584,
+ 16338, 1917,
+ 16424, 2560,
+ 16483, 4438,
+ 16529, 6410,
+ 16620, 11966,
+ 16839, 8780,
+ 17030, 3050,
+ 17033, 18325,
+ 17092, 1568,
+ 17123, 5197,
+ 17351, 2113,
+ 17374, 980,
+ 17566, 26214,
+ 17609, 3912,
+ 17639, 32767,
+ 18151, 7871,
+ 18197, 2516,
+ 18202, 5649,
+ 18679, 3283,
+ 18930, 1370,
+ 19271, 13757,
+ 19317, 4120,
+ 19460, 1973,
+ 19654, 10018,
+ 19764, 6792,
+ 19912, 5135,
+ 20040, 2841,
+ 21234, 19833};
+
+
--- /dev/null
+++ b/amr-wb/q_pulse.c
@@ -1,0 +1,637 @@
+/*--------------------------------------------------------------------------*
+ * Q_PULSE.C *
+ *--------------------------------------------------------------------------*
+ * Coding and decodeing of algebraic codebook *
+ *--------------------------------------------------------------------------*/
+
+#include <stdio.h>
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+#include "q_pulse.h"
+
+
+#define NB_POS 16 /* pos in track, mask for sign bit */
+
+
+Word32 quant_1p_N1( /* (o) return N+1 bits */
+ Word16 pos, /* (i) position of the pulse */
+ Word16 N) /* (i) number of bits for position */
+{
+ Word16 mask;
+ Word32 index;
+
+ mask = sub(shl(1, N), 1); /* mask = ((1<<N)-1); */
+ /*-------------------------------------------------------*
+ * Quantization of 1 pulse with N+1 bits: *
+ *-------------------------------------------------------*/
+ index = L_deposit_l((Word16) (pos & mask));
+ test();
+ if ((pos & NB_POS) != 0)
+ {
+ index = L_add(index, L_deposit_l(shl(1, N))); /* index += 1 << N; */
+ }
+ return (index);
+}
+
+void dec_1p_N1(Word32 index, Word16 N, Word16 offset, Word16 pos[])
+{
+ Word16 pos1;
+ Word32 mask, i;
+
+ mask = L_deposit_l(sub(shl(1, N), 1)); /* mask = ((1<<N)-1); */
+ /*-------------------------------------------------------*
+ * Decode 1 pulse with N+1 bits: *
+ *-------------------------------------------------------*/
+ pos1 = add(extract_l(index & mask), offset); /* pos1 = ((index & mask) + offset); */
+ i = (L_shr(index, N) & 1L); /* i = ((index >> N) & 1); */
+ test();
+ if (L_sub(i, 1) == 0)
+ {
+ pos1 = add(pos1, NB_POS);
+ }
+ pos[0] = pos1; move16();
+
+ return;
+}
+
+
+Word32 quant_2p_2N1( /* (o) return (2*N)+1 bits */
+ Word16 pos1, /* (i) position of the pulse 1 */
+ Word16 pos2, /* (i) position of the pulse 2 */
+ Word16 N) /* (i) number of bits for position */
+{
+ Word16 mask, tmp;
+ Word32 index;
+
+ mask = sub(shl(1, N), 1); /* mask = ((1<<N)-1); */
+ /*-------------------------------------------------------*
+ * Quantization of 2 pulses with 2*N+1 bits: *
+ *-------------------------------------------------------*/
+ test();logic16();logic16();
+ if (((pos2 ^ pos1) & NB_POS) == 0)
+ {
+ /* sign of 1st pulse == sign of 2th pulse */
+ test();
+ if (sub(pos1, pos2) <= 0) /* ((pos1 - pos2) <= 0) */
+ {
+ /* index = ((pos1 & mask) << N) + (pos2 & mask); */
+ index = L_deposit_l(add(shl(((Word16) (pos1 & mask)), N), ((Word16) (pos2 & mask))));
+ } else
+ {
+ /* ((pos2 & mask) << N) + (pos1 & mask); */
+ index = L_deposit_l(add(shl(((Word16) (pos2 & mask)), N), ((Word16) (pos1 & mask))));
+ }
+ test();logic16();
+ if ((pos1 & NB_POS) != 0)
+ {
+ tmp = shl(N, 1);
+ index = L_add(index, L_shl(1L, tmp)); /* index += 1 << (2*N); */
+ }
+ } else
+ {
+ /* sign of 1st pulse != sign of 2th pulse */
+ test();logic16();logic16();
+ if (sub((Word16) (pos1 & mask), (Word16) (pos2 & mask)) <= 0)
+ {
+ /* index = ((pos2 & mask) << N) + (pos1 & mask); */
+ index = L_deposit_l(add(shl(((Word16) (pos2 & mask)), N), ((Word16) (pos1 & mask)))); logic16();logic16();
+ test();logic16();
+ if ((pos2 & NB_POS) != 0)
+ {
+ tmp = shl(N, 1); /* index += 1 << (2*N); */
+ index = L_add(index, L_shl(1L, tmp));
+ }
+ } else
+ {
+ /* index = ((pos1 & mask) << N) + (pos2 & mask); */
+ index = L_deposit_l(add(shl(((Word16) (pos1 & mask)), N), ((Word16) (pos2 & mask)))); logic16();logic16();
+ test();logic16();
+ if ((pos1 & NB_POS) != 0)
+ {
+ tmp = shl(N, 1);
+ index = L_add(index, L_shl(1, tmp)); /* index += 1 << (2*N); */
+ }
+ }
+ }
+ return (index);
+}
+
+void dec_2p_2N1(Word32 index, Word16 N, Word16 offset, Word16 pos[])
+{
+ Word16 pos1, pos2, tmp;
+ Word32 mask, i;
+
+ mask = L_deposit_l(sub(shl(1, N), 1)); /* mask = ((1<<N)-1); */
+ /*-------------------------------------------------------*
+ * Decode 2 pulses with 2*N+1 bits: *
+ *-------------------------------------------------------*/
+ /* pos1 = (((index >> N) & mask) + offset); */
+ pos1 = extract_l(L_add((L_shr(index, N) & mask), L_deposit_l(offset))); logic16();
+ tmp = shl(N, 1);
+ i = (L_shr(index, tmp) & 1L); logic16();/* i = (index >> (2*N)) & 1; */
+ pos2 = add(extract_l(index & mask), offset); logic16();/* pos2 = ((index & mask) + offset); */
+ test();
+ if (sub(pos2, pos1) < 0) /* ((pos2 - pos1) < 0) */
+ {
+ test();
+ if (L_sub(i, 1L) == 0)
+ { /* (i == 1) */
+ pos1 = add(pos1, NB_POS); /* pos1 += NB_POS; */
+ } else
+ {
+ pos2 = add(pos2, NB_POS); /* pos2 += NB_POS; */
+ }
+ } else
+ {
+ test();
+ if (L_sub(i, 1L) == 0)
+ { /* (i == 1) */
+ pos1 = add(pos1, NB_POS); /* pos1 += NB_POS; */
+ pos2 = add(pos2, NB_POS); /* pos2 += NB_POS; */
+ }
+ }
+
+ pos[0] = pos1; move16();
+ pos[1] = pos2; move16();
+
+ return;
+}
+
+
+Word32 quant_3p_3N1( /* (o) return (3*N)+1 bits */
+ Word16 pos1, /* (i) position of the pulse 1 */
+ Word16 pos2, /* (i) position of the pulse 2 */
+ Word16 pos3, /* (i) position of the pulse 3 */
+ Word16 N) /* (i) number of bits for position */
+{
+ Word16 nb_pos;
+ Word32 index;
+
+ nb_pos = shl(1, sub(N, 1)); /* nb_pos = (1<<(N-1)); */
+ /*-------------------------------------------------------*
+ * Quantization of 3 pulses with 3*N+1 bits: *
+ *-------------------------------------------------------*/
+ test();test();logic16();logic16();logic16();logic16();
+ if (((pos1 ^ pos2) & nb_pos) == 0)
+ {
+ index = quant_2p_2N1(pos1, pos2, sub(N, 1)); /* index = quant_2p_2N1(pos1, pos2, (N-1)); */
+ /* index += (pos1 & nb_pos) << N; */
+ index = L_add(index, L_shl(L_deposit_l((Word16) (pos1 & nb_pos)), N)); logic16();
+ /* index += quant_1p_N1(pos3, N) << (2*N); */
+ index = L_add(index, L_shl(quant_1p_N1(pos3, N), shl(N, 1)));
+
+ } else if (((pos1 ^ pos3) & nb_pos) == 0)
+ {
+ index = quant_2p_2N1(pos1, pos3, sub(N, 1)); /* index = quant_2p_2N1(pos1, pos3, (N-1)); */
+ index = L_add(index, L_shl(L_deposit_l((Word16) (pos1 & nb_pos)), N)); logic16();
+ /* index += (pos1 & nb_pos) << N; */
+ index = L_add(index, L_shl(quant_1p_N1(pos2, N), shl(N, 1)));
+ /* index += quant_1p_N1(pos2, N) <<
+ * (2*N); */
+ } else
+ {
+ index = quant_2p_2N1(pos2, pos3, sub(N, 1)); /* index = quant_2p_2N1(pos2, pos3, (N-1)); */
+ /* index += (pos2 & nb_pos) << N; */
+ index = L_add(index, L_shl(L_deposit_l((Word16) (pos2 & nb_pos)), N)); logic16();
+ /* index += quant_1p_N1(pos1, N) << (2*N); */
+ index = L_add(index, L_shl(quant_1p_N1(pos1, N), shl(N, 1)));
+ }
+ return (index);
+}
+
+void dec_3p_3N1(Word32 index, Word16 N, Word16 offset, Word16 pos[])
+{
+ Word16 j, tmp;
+ Word32 mask, idx;
+
+ /*-------------------------------------------------------*
+ * Decode 3 pulses with 3*N+1 bits: *
+ *-------------------------------------------------------*/
+ tmp = sub(shl(N, 1), 1); /* mask = ((1<<((2*N)-1))-1); */
+ mask = L_sub(L_shl(1L, tmp), 1L);
+
+ idx = index & mask; logic16();
+ j = offset;
+ tmp = sub(shl(N, 1), 1);
+
+ test();logic16();
+ if ((L_shr(index, tmp) & 1L) != 0L)
+ { /* if (((index >> ((2*N)-1)) & 1) == 1){ */
+ j = add(j, shl(1, sub(N, 1))); /* j += (1<<(N-1)); */
+ }
+ dec_2p_2N1(idx, (Word16) (N - 1), j, pos);
+
+ mask = sub(shl(1, add(N, 1)), 1); /* mask = ((1<<(N+1))-1); */
+ tmp = shl(N, 1); /* idx = (index >> (2*N)) & mask; */
+ idx = L_shr(index, tmp) & mask; logic16();
+
+ dec_1p_N1(idx, N, offset, pos + 2); move16();
+
+ return;
+}
+
+
+Word32 quant_4p_4N1( /* (o) return (4*N)+1 bits */
+ Word16 pos1, /* (i) position of the pulse 1 */
+ Word16 pos2, /* (i) position of the pulse 2 */
+ Word16 pos3, /* (i) position of the pulse 3 */
+ Word16 pos4, /* (i) position of the pulse 4 */
+ Word16 N) /* (i) number of bits for position */
+{
+ Word16 nb_pos;
+ Word32 index;
+
+ nb_pos = shl(1, sub(N, 1)); /* nb_pos = (1<<(N-1)); */
+ /*-------------------------------------------------------*
+ * Quantization of 4 pulses with 4*N+1 bits: *
+ *-------------------------------------------------------*/
+ test();test();logic16();logic16();logic16();logic16();
+ if (((pos1 ^ pos2) & nb_pos) == 0)
+ {
+ index = quant_2p_2N1(pos1, pos2, sub(N, 1)); /* index = quant_2p_2N1(pos1, pos2, (N-1)); */
+ /* index += (pos1 & nb_pos) << N; */
+ index = L_add(index, L_shl(L_deposit_l((Word16) (pos1 & nb_pos)), N)); logic16();
+ /* index += quant_2p_2N1(pos3, pos4, N) << (2*N); */
+ index = L_add(index, L_shl(quant_2p_2N1(pos3, pos4, N), shl(N, 1)));
+ } else if (((pos1 ^ pos3) & nb_pos) == 0)
+ {
+ index = quant_2p_2N1(pos1, pos3, sub(N, 1));
+ /* index += (pos1 & nb_pos) << N; */
+ index = L_add(index, L_shl(L_deposit_l((Word16) (pos1 & nb_pos)), N)); logic16();
+ /* index += quant_2p_2N1(pos2, pos4, N) << (2*N); */
+ index = L_add(index, L_shl(quant_2p_2N1(pos2, pos4, N), shl(N, 1)));
+ } else
+ {
+ index = quant_2p_2N1(pos2, pos3, sub(N, 1));
+ /* index += (pos2 & nb_pos) << N; */
+ index = L_add(index, L_shl(L_deposit_l((Word16) (pos2 & nb_pos)), N)); logic16();
+ /* index += quant_2p_2N1(pos1, pos4, N) << (2*N); */
+ index = L_add(index, L_shl(quant_2p_2N1(pos1, pos4, N), shl(N, 1)));
+ }
+ return (index);
+}
+
+void dec_4p_4N1(Word32 index, Word16 N, Word16 offset, Word16 pos[])
+{
+ Word16 j, tmp;
+ Word32 mask, idx;
+
+ /*-------------------------------------------------------*
+ * Decode 4 pulses with 4*N+1 bits: *
+ *-------------------------------------------------------*/
+ tmp = sub(shl(N, 1), 1); /* mask = ((1<<((2*N)-1))-1); */
+ mask = L_sub(L_shl(1L, tmp), 1L);
+ idx = index & mask; logic16();
+ j = offset; move16();
+ tmp = sub(shl(N, 1), 1);
+
+ test();logic16();
+ if ((L_shr(index, tmp) & 1L) != 0L)
+ { /* (((index >> ((2*N)-1)) & 1) == 1) */
+ j = add(j, shl(1, sub(N, 1))); /* j += (1<<(N-1)); */
+ }
+ dec_2p_2N1(idx, (Word16) (N - 1), j, pos);
+
+
+ tmp = add(shl(N, 1), 1); /* mask = ((1<<((2*N)+1))-1); */
+ mask = L_sub(L_shl(1L, tmp), 1L);
+ idx = L_shr(index, shl(N, 1)) & mask; logic16();/* idx = (index >> (2*N)) & mask; */
+ dec_2p_2N1(idx, N, offset, pos + 2); move16(); /* dec_2p_2N1(idx, N, offset, pos+2); */
+
+ return;
+}
+
+
+Word32 quant_4p_4N( /* (o) return 4*N bits */
+ Word16 pos[], /* (i) position of the pulse 1..4 */
+ Word16 N) /* (i) number of bits for position */
+{
+ Word16 i, j, k, nb_pos, mask, n_1, tmp;
+ Word16 posA[4], posB[4];
+ Word32 index;
+
+ n_1 = (Word16) (N - 1); move16();
+ nb_pos = shl(1, n_1); /* nb_pos = (1<<n_1); */
+ mask = sub(shl(1, N), 1); /* mask = ((1<<N)-1); */
+
+ i = 0; move16();
+ j = 0; move16();
+ for (k = 0; k < 4; k++)
+ {
+ test();logic16();
+ if ((pos[k] & nb_pos) == 0)
+ {
+ posA[i++] = pos[k]; move16();
+ } else
+ {
+ posB[j++] = pos[k]; move16();
+ }
+ }
+
+ switch (i)
+ {
+ case 0:
+ tmp = sub(shl(N, 2), 3); /* index = 1 << ((4*N)-3); */
+ index = L_shl(1L, tmp);
+ /* index += quant_4p_4N1(posB[0], posB[1], posB[2], posB[3], n_1); */
+ index = L_add(index, quant_4p_4N1(posB[0], posB[1], posB[2], posB[3], n_1));
+ break;
+ case 1:
+ /* index = quant_1p_N1(posA[0], n_1) << ((3*n_1)+1); */
+ tmp = add(extract_l(L_shr(L_mult(3, n_1), 1)), 1);
+ index = L_shl(quant_1p_N1(posA[0], n_1), tmp);
+ /* index += quant_3p_3N1(posB[0], posB[1], posB[2], n_1); */
+ index = L_add(index, quant_3p_3N1(posB[0], posB[1], posB[2], n_1));
+ break;
+ case 2:
+ tmp = add(shl(n_1, 1), 1); /* index = quant_2p_2N1(posA[0], posA[1], n_1) << ((2*n_1)+1); */
+ index = L_shl(quant_2p_2N1(posA[0], posA[1], n_1), tmp);
+ /* index += quant_2p_2N1(posB[0], posB[1], n_1); */
+ index = L_add(index, quant_2p_2N1(posB[0], posB[1], n_1));
+ break;
+ case 3:
+ /* index = quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << N; */
+ index = L_shl(quant_3p_3N1(posA[0], posA[1], posA[2], n_1), N);
+ index = L_add(index, quant_1p_N1(posB[0], n_1)); /* index += quant_1p_N1(posB[0], n_1); */
+ break;
+ case 4:
+ index = quant_4p_4N1(posA[0], posA[1], posA[2], posA[3], n_1);
+ break;
+ default:
+ index = 0;
+ fprintf(stderr, "Error in function quant_4p_4N\n");
+ }
+ tmp = sub(shl(N, 2), 2); /* index += (i & 3) << ((4*N)-2); */
+ index = L_add(index, L_shl((L_deposit_l(i) & (3L)), tmp)); logic16();
+
+ return (index);
+}
+
+void dec_4p_4N(Word32 index, Word16 N, Word16 offset, Word16 pos[])
+{
+ Word16 j, n_1, tmp;
+
+ /*-------------------------------------------------------*
+ * Decode 4 pulses with 4*N bits: *
+ *-------------------------------------------------------*/
+
+ n_1 = (Word16) (N - 1); move16();
+ j = add(offset, shl(1, n_1)); /* j = offset + (1 << n_1); */
+
+ tmp = sub(shl(N, 2), 2);
+ test();logic16();
+ switch (L_shr(index, tmp) & 3)
+ { /* ((index >> ((4*N)-2)) & 3) */
+ case 0:
+ tmp = add(shl(n_1, 2), 1);
+
+ test();logic16();
+ if ((L_shr(index, tmp) & 1) == 0)
+ { /* (((index >> ((4*n_1)+1)) & 1) == 0) */
+ dec_4p_4N1(index, n_1, offset, pos);
+ } else
+ {
+ dec_4p_4N1(index, n_1, j, pos);
+ }
+ break;
+ case 1:
+ tmp = add(extract_l(L_shr(L_mult(3, n_1), 1)), 1); /* dec_1p_N1((index>>((3*n_1)+1)), n_1, offset, pos) */
+ dec_1p_N1(L_shr(index, tmp), n_1, offset, pos);
+ dec_3p_3N1(index, n_1, j, pos + 1);move16();
+ break;
+ case 2:
+ tmp = add(shl(n_1, 1), 1); /* dec_2p_2N1((index>>((2*n_1)+1)), n_1, offset, pos); */
+ dec_2p_2N1(L_shr(index, tmp), n_1, offset, pos);
+ dec_2p_2N1(index, n_1, j, pos + 2);move16();
+ break;
+ case 3:
+ tmp = add(n_1, 1); /* dec_3p_3N1((index>>(n_1+1)), n_1, offset, pos); */
+ dec_3p_3N1(L_shr(index, tmp), n_1, offset, pos);
+ dec_1p_N1(index, n_1, j, pos + 3); move16();
+ break;
+ }
+ return;
+}
+
+
+Word32 quant_5p_5N( /* (o) return 5*N bits */
+ Word16 pos[], /* (i) position of the pulse 1..5 */
+ Word16 N) /* (i) number of bits for position */
+{
+ Word16 i, j, k, nb_pos, n_1, tmp;
+ Word16 posA[5], posB[5];
+ Word32 index, tmp2;
+
+ n_1 = (Word16) (N - 1); move16();
+ nb_pos = shl(1, n_1); /* nb_pos = (1<<n_1); */
+
+ i = 0; move16();
+ j = 0; move16();
+ for (k = 0; k < 5; k++)
+ {
+ test();logic16();
+ if ((pos[k] & nb_pos) == 0)
+ {
+ posA[i++] = pos[k]; move16();
+ } else
+ {
+ posB[j++] = pos[k]; move16();
+ }
+ }
+
+ switch (i)
+ {
+ case 0:
+ tmp = sub(extract_l(L_shr(L_mult(5, N), 1)), 1); /* ((5*N)-1)) */
+ index = L_shl(1L, tmp); /* index = 1 << ((5*N)-1); */
+ tmp = add(shl(N, 1), 1); /* index += quant_3p_3N1(posB[0], posB[1], posB[2], n_1) << ((2*N)+1);*/
+ tmp2 = L_shl(quant_3p_3N1(posB[0], posB[1], posB[2], n_1), tmp);
+ index = L_add(index, tmp2);
+ index = L_add(index, quant_2p_2N1(posB[3], posB[4], N)); /* index += quant_2p_2N1(posB[3], posB[4], N); */
+ break;
+ case 1:
+ tmp = sub(extract_l(L_shr(L_mult(5, N), 1)), 1); /* index = 1 << ((5*N)-1); */
+ index = L_shl(1L, tmp);
+ tmp = add(shl(N, 1), 1); /* index += quant_3p_3N1(posB[0], posB[1], posB[2], n_1) <<((2*N)+1); */
+ tmp2 = L_shl(quant_3p_3N1(posB[0], posB[1], posB[2], n_1), tmp);
+ index = L_add(index, tmp2);
+ index = L_add(index, quant_2p_2N1(posB[3], posA[0], N)); /* index += quant_2p_2N1(posB[3], posA[0], N); */
+ break;
+ case 2:
+ tmp = sub(extract_l(L_shr(L_mult(5, N), 1)), 1); /* ((5*N)-1)) */
+ index = L_shl(1L, tmp); /* index = 1 << ((5*N)-1); */
+ tmp = add(shl(N, 1), 1); /* index += quant_3p_3N1(posB[0], posB[1], posB[2], n_1) << ((2*N)+1); */
+ tmp2 = L_shl(quant_3p_3N1(posB[0], posB[1], posB[2], n_1), tmp);
+ index = L_add(index, tmp2);
+ index = L_add(index, quant_2p_2N1(posA[0], posA[1], N)); /* index += quant_2p_2N1(posA[0], posA[1], N); */
+ break;
+ case 3:
+ tmp = add(shl(N, 1), 1); /* index = quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << ((2*N)+1); */
+ index = L_shl(quant_3p_3N1(posA[0], posA[1], posA[2], n_1), tmp);
+ index = L_add(index, quant_2p_2N1(posB[0], posB[1], N)); /* index += quant_2p_2N1(posB[0], posB[1], N); */
+ break;
+ case 4:
+ tmp = add(shl(N, 1), 1); /* index = quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << ((2*N)+1); */
+ index = L_shl(quant_3p_3N1(posA[0], posA[1], posA[2], n_1), tmp);
+ index = L_add(index, quant_2p_2N1(posA[3], posB[0], N)); /* index += quant_2p_2N1(posA[3], posB[0], N); */
+ break;
+ case 5:
+ tmp = add(shl(N, 1), 1); /* index = quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << ((2*N)+1); */
+ index = L_shl(quant_3p_3N1(posA[0], posA[1], posA[2], n_1), tmp);
+ index = L_add(index, quant_2p_2N1(posA[3], posA[4], N)); /* index += quant_2p_2N1(posA[3], posA[4], N); */
+ break;
+ default:
+ index = 0;
+ fprintf(stderr, "Error in function quant_5p_5N\n");
+ }
+
+ return (index);
+}
+
+void dec_5p_5N(Word32 index, Word16 N, Word16 offset, Word16 pos[])
+{
+ Word16 j, n_1, tmp;
+ Word32 idx;
+
+ /*-------------------------------------------------------*
+ * Decode 5 pulses with 5*N bits: *
+ *-------------------------------------------------------*/
+
+ n_1 = (Word16) (N - 1); move16();
+ j = add(offset, shl(1, n_1)); /* j = offset + (1 << n_1); */
+ tmp = add(shl(N, 1), 1); /* idx = (index >> ((2*N)+1)); */
+ idx = L_shr(index, tmp);
+ tmp = sub(extract_l(L_shr(L_mult(5, N), 1)), 1); /* ((5*N)-1)) */
+
+ test();logic16();
+ if ((L_shr(index, tmp) & 1) == 0) /* ((index >> ((5*N)-1)) & 1) */
+ {
+ dec_3p_3N1(idx, n_1, offset, pos);
+ dec_2p_2N1(index, N, offset, pos + 3); move16();
+ } else
+ {
+ dec_3p_3N1(idx, n_1, j, pos);
+ dec_2p_2N1(index, N, offset, pos + 3); move16();
+ }
+ return;
+}
+
+
+Word32 quant_6p_6N_2( /* (o) return (6*N)-2 bits */
+ Word16 pos[], /* (i) position of the pulse 1..6 */
+ Word16 N) /* (i) number of bits for position */
+{
+ Word16 i, j, k, nb_pos, n_1;
+ Word16 posA[6], posB[6];
+ Word32 index;
+
+ /* !! N and n_1 are constants -> it doesn't need to be operated by Basic Operators */
+
+ n_1 = (Word16) (N - 1); move16();
+ nb_pos = shl(1, n_1); /* nb_pos = (1<<n_1); */
+
+ i = 0; move16();
+ j = 0; move16();
+ for (k = 0; k < 6; k++)
+ {
+ test();logic16();
+ if ((pos[k] & nb_pos) == 0)
+ {
+ posA[i++] = pos[k]; move16();
+ } else
+ {
+ posB[j++] = pos[k]; move16();
+ }
+ }
+
+ switch (i)
+ {
+ case 0:
+ index = L_shl(1L, (Word16) (6 * N - 5)); /* index = 1 << ((6*N)-5); */
+ index = L_add(index, L_shl(quant_5p_5N(posB, n_1), N)); /* index += quant_5p_5N(posB, n_1) << N; */
+ index = L_add(index, quant_1p_N1(posB[5], n_1)); /* index += quant_1p_N1(posB[5], n_1); */
+ break;
+ case 1:
+ index = L_shl(1L, (Word16) (6 * N - 5)); /* index = 1 << ((6*N)-5); */
+ index = L_add(index, L_shl(quant_5p_5N(posB, n_1), N)); /* index += quant_5p_5N(posB, n_1) << N; */
+ index = L_add(index, quant_1p_N1(posA[0], n_1)); /* index += quant_1p_N1(posA[0], n_1); */
+ break;
+ case 2:
+ index = L_shl(1L, (Word16) (6 * N - 5)); /* index = 1 << ((6*N)-5); */
+ /* index += quant_4p_4N(posB, n_1) << ((2*n_1)+1); */
+ index = L_add(index, L_shl(quant_4p_4N(posB, n_1), (Word16) (2 * n_1 + 1)));
+ index = L_add(index, quant_2p_2N1(posA[0], posA[1], n_1)); /* index += quant_2p_2N1(posA[0], posA[1], n_1); */
+ break;
+ case 3:
+ index = L_shl(quant_3p_3N1(posA[0], posA[1], posA[2], n_1), (Word16) (3 * n_1 + 1)); /* index = quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << ((3*n_1)+1); */
+ index = L_add(index, quant_3p_3N1(posB[0], posB[1], posB[2], n_1)); /* index += quant_3p_3N1(posB[0], posB[1], posB[2], n_1); */
+ break;
+ case 4:
+ i = 2; move16();
+ index = L_shl(quant_4p_4N(posA, n_1), (Word16) (2 * n_1 + 1)); /* index = quant_4p_4N(posA, n_1) << ((2*n_1)+1); */
+ index = L_add(index, quant_2p_2N1(posB[0], posB[1], n_1)); /* index += quant_2p_2N1(posB[0], posB[1], n_1); */
+ break;
+ case 5:
+ i = 1; move16();
+ index = L_shl(quant_5p_5N(posA, n_1), N); /* index = quant_5p_5N(posA, n_1) << N; */
+ index = L_add(index, quant_1p_N1(posB[0], n_1)); /* index += quant_1p_N1(posB[0], n_1); */
+ break;
+ case 6:
+ i = 0; move16();
+ index = L_shl(quant_5p_5N(posA, n_1), N); /* index = quant_5p_5N(posA, n_1) << N; */
+ index = L_add(index, quant_1p_N1(posA[5], n_1)); /* index += quant_1p_N1(posA[5], n_1); */
+ break;
+ default:
+ index = 0;
+ fprintf(stderr, "Error in function quant_6p_6N_2\n");
+ }
+ index = L_add(index, L_shl((L_deposit_l(i) & 3L), (Word16) (6 * N - 4))); logic16();/* index += (i & 3) << ((6*N)-4); */
+
+ return (index);
+}
+
+void dec_6p_6N_2(Word32 index, Word16 N, Word16 offset, Word16 pos[])
+{
+ Word16 j, n_1, offsetA, offsetB;
+
+ n_1 = (Word16) (N - 1); move16();
+ j = add(offset, shl(1, n_1)); /* j = offset + (1 << n_1); */
+
+
+ /* !! N and n_1 are constants -> it doesn't need to be operated by Basic Operators */
+
+ offsetA = offsetB = j; move16();move16();
+ test();logic16();
+ if ((L_shr(index, (Word16) (6 * N - 5)) & 1L) == 0)
+ { /* if (((index >> ((6*N)-5)) & 1) == 0) */
+ offsetA = offset; move16();
+ } else
+ {
+ offsetB = offset; move16();
+ }
+
+ test();logic16();
+ switch (L_shr(index, (Word16) (6 * N - 4)) & 3)
+ { /* (index >> ((6*N)-4)) & 3 */
+ case 0:
+ dec_5p_5N(L_shr(index, N), n_1, offsetA, pos); /* dec_5p_5N(index>>N, n_1, offsetA, pos); */
+ dec_1p_N1(index, n_1, offsetA, pos + 5); move16();
+ break;
+ case 1:
+ dec_5p_5N(L_shr(index, N), n_1, offsetA, pos); /* dec_5p_5N(index>>N, n_1, offsetA, pos); */
+ dec_1p_N1(index, n_1, offsetB, pos + 5); move16();
+ break;
+ case 2:
+ dec_4p_4N(L_shr(index, (Word16) (2 * n_1 + 1)), n_1, offsetA, pos); /* dec_4p_4N(index>>((2*n_1)+1 ), n_1, offsetA, pos); */
+ dec_2p_2N1(index, n_1, offsetB, pos + 4); move16();
+ break;
+ case 3:
+ dec_3p_3N1(L_shr(index, (Word16) (3 * n_1 + 1)), n_1, offset, pos); /* dec_3p_3N1(index>>((3*n_1)+ 1), n_1, offset, pos); */
+ dec_3p_3N1(index, n_1, j, pos + 3);move16();
+ break;
+ }
+ return;
+}
--- /dev/null
+++ b/amr-wb/q_pulse.h
@@ -1,0 +1,50 @@
+/*--------------------------------------------------------------------------*
+ * Q_PULSE.H *
+ *--------------------------------------------------------------------------*
+ * Coding and decoding of algebraic codebook *
+ *--------------------------------------------------------------------------*/
+
+#include "typedef.h"
+
+Word32 quant_1p_N1( /* (o) return (N+1) bits */
+ Word16 pos, /* (i) position of the pulse */
+ Word16 N); /* (i) number of bits for position */
+
+Word32 quant_2p_2N1( /* (o) return (2*N)+1 bits */
+ Word16 pos1, /* (i) position of the pulse 1 */
+ Word16 pos2, /* (i) position of the pulse 2 */
+ Word16 N); /* (i) number of bits for position */
+
+Word32 quant_3p_3N1( /* (o) return (3*N)+1 bits */
+ Word16 pos1, /* (i) position of the pulse 1 */
+ Word16 pos2, /* (i) position of the pulse 2 */
+ Word16 pos3, /* (i) position of the pulse 3 */
+ Word16 N); /* (i) number of bits for position */
+
+Word32 quant_4p_4N1( /* (o) return (4*N)+1 bits */
+ Word16 pos1, /* (i) position of the pulse 1 */
+ Word16 pos2, /* (i) position of the pulse 2 */
+ Word16 pos3, /* (i) position of the pulse 3 */
+ Word16 pos4, /* (i) position of the pulse 4 */
+ Word16 N); /* (i) number of bits for position */
+
+Word32 quant_4p_4N( /* (o) return 4*N bits */
+ Word16 pos[], /* (i) position of the pulse 1..4 */
+ Word16 N); /* (i) number of bits for position */
+
+Word32 quant_5p_5N( /* (o) return 5*N bits */
+ Word16 pos[], /* (i) position of the pulse 1..5 */
+ Word16 N); /* (i) number of bits for position */
+
+Word32 quant_6p_6N_2( /* (o) return (6*N)-2 bits */
+ Word16 pos[], /* (i) position of the pulse 1..6 */
+ Word16 N); /* (i) number of bits for position */
+
+
+void dec_1p_N1(Word32 index, Word16 N, Word16 offset, Word16 pos[]);
+void dec_2p_2N1(Word32 index, Word16 N, Word16 offset, Word16 pos[]);
+void dec_3p_3N1(Word32 index, Word16 N, Word16 offset, Word16 pos[]);
+void dec_4p_4N1(Word32 index, Word16 N, Word16 offset, Word16 pos[]);
+void dec_4p_4N(Word32 index, Word16 N, Word16 offset, Word16 pos[]);
+void dec_5p_5N(Word32 index, Word16 N, Word16 offset, Word16 pos[]);
+void dec_6p_6N_2(Word32 index, Word16 N, Word16 offset, Word16 pos[]);
--- /dev/null
+++ b/amr-wb/qisf_ns.c
@@ -1,0 +1,95 @@
+/*-------------------------------------------------------------------*
+ * QISF_NS.C *
+ *-------------------------------------------------------------------*
+ * *
+ * Coding/Decoding of ISF parameters for background noise. *
+ * *
+ * The ISF vector is quantized using VQ with split-by-5 *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "acelp.h"
+#include "count.h"
+
+#include "qisf_ns.tab" /* Codebooks of ISFs */
+
+/*------------------------------------------------------------------*
+ * routine: Qisf_ns() *
+ * ~~~~~~~~~ *
+ *------------------------------------------------------------------*/
+
+void Qisf_ns(
+ Word16 * isf1, /* input : ISF in the frequency domain (0..0.5) */
+ Word16 * isf_q, /* output: quantized ISF */
+ Word16 * indice /* output: quantization indices */
+)
+{
+ Word16 i;
+ Word32 tmp;
+
+ for (i = 0; i < ORDER; i++)
+ {
+ isf_q[i] = sub(isf1[i], mean_isf_noise[i]); move16();
+ }
+
+ indice[0] = Sub_VQ(&isf_q[0], dico1_isf_noise, 2, SIZE_BK_NOISE1, &tmp); move16();
+ indice[1] = Sub_VQ(&isf_q[2], dico2_isf_noise, 3, SIZE_BK_NOISE2, &tmp); move16();
+ indice[2] = Sub_VQ(&isf_q[5], dico3_isf_noise, 3, SIZE_BK_NOISE3, &tmp); move16();
+ indice[3] = Sub_VQ(&isf_q[8], dico4_isf_noise, 4, SIZE_BK_NOISE4, &tmp); move16();
+ indice[4] = Sub_VQ(&isf_q[12], dico5_isf_noise, 4, SIZE_BK_NOISE5, &tmp); move16();
+
+ /* decoding the ISFs */
+
+ Disf_ns(indice, isf_q);
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * routine: Disf_ns() *
+ * ~~~~~~~~~ *
+ * Decoding of ISF parameters *
+ *-------------------------------------------------------------------*
+ * Arguments: *
+ * indice[] : indices of the selected codebook entries *
+ * isf[] : quantized ISFs (in frequency domain) *
+ *-------------------------------------------------------------------*/
+
+void Disf_ns(
+ Word16 * indice, /* input: quantization indices */
+ Word16 * isf_q /* input : ISF in the frequency domain (0..0.5) */
+)
+{
+ Word16 i;
+
+ for (i = 0; i < 2; i++)
+ {
+ isf_q[i] = dico1_isf_noise[indice[0] * 2 + i]; move16();
+ }
+ for (i = 0; i < 3; i++)
+ {
+ isf_q[i + 2] = dico2_isf_noise[indice[1] * 3 + i]; move16();
+ }
+ for (i = 0; i < 3; i++)
+ {
+ isf_q[i + 5] = dico3_isf_noise[indice[2] * 3 + i]; move16();
+ }
+ for (i = 0; i < 4; i++)
+ {
+ isf_q[i + 8] = dico4_isf_noise[indice[3] * 4 + i]; move16();
+ }
+ for (i = 0; i < 4; i++)
+ {
+ isf_q[i + 12] = dico5_isf_noise[indice[4] * 4 + i]; move16();
+ }
+
+ for (i = 0; i < ORDER; i++)
+ {
+ isf_q[i] = add(isf_q[i], mean_isf_noise[i]); move16();
+ }
+
+ Reorder_isf(isf_q, ISF_GAP, ORDER);
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/qisf_ns.tab
@@ -1,0 +1,329 @@
+/*-------------------------------------------------------------------*
+ * qisf_ns.h
+ *-------------------------------------------------------------------*
+ * Quantization tables for split by 5 VQ of ISFs for a background noise database
+ * Version whith no prediction
+ *-------------------------------------------------------------------*/
+
+#define ORDER 16 /* order of linear prediction filter */
+#define ISF_GAP 128
+
+#define SIZE_BK_NOISE1 64
+#define SIZE_BK_NOISE2 64
+#define SIZE_BK_NOISE3 64
+#define SIZE_BK_NOISE4 32
+#define SIZE_BK_NOISE5 32
+
+
+/* means of ISFs */
+ static Word16 mean_isf_noise[ORDER] = {
+
+ 478, 1100, 2213, 3267, 4219, 5222, 6198, 7240,
+ 8229, 9153, 10098, 11108, 12144, 13184, 14165, 3803};
+
+
+/* 28 bits */
+/*-------------------------------------------------------------------*
+ * isf codebooks: split-by-5 VQ *
+ * *
+ * codebook vector dimension number of vectors *
+ * ~~~~~~~~ ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ *
+ * 1 2 64 *
+ * 2 3 64 *
+ * 3 3 64 *
+ * 4 4 32 *
+ * 5 4 32 *
+ *-------------------------------------------------------------------*/
+
+/*------------------------------------------------*
+ * 1st split: isf0 to isf1
+ *------------------------------------------------*/
+
+
+ static Word16 dico1_isf_noise[SIZE_BK_NOISE1*2] = {
+
+ -269, -673,
+ -222, -537,
+ -233, -430,
+ -138, -451,
+ -212, -331,
+ -192, -241,
+ -87, -231,
+ -191, -128,
+ -70, -106,
+ -164, -6,
+ 74, -179,
+ 27, -33,
+ -102, 74,
+ -162, 115,
+ -94, 172,
+ -6, 130,
+ -143, 234,
+ 14, 218,
+ -65, 270,
+ 88, 182,
+ -124, 341,
+ -44, 381,
+ 38, 335,
+ 117, 274,
+ -112, 454,
+ 74, 431,
+ -5, 488,
+ 175, 384,
+ -83, 561,
+ 122, 529,
+ 21, 601,
+ 229, 481,
+ 231, 303,
+ 226, 608,
+ 300, 372,
+ 210, 187,
+ 306, 265,
+ 328, 473,
+ 382, 331,
+ 371, 132,
+ 139, 58,
+ 365, 21,
+ 250, -82,
+ 443, 218,
+ 483, 110,
+ 426, 415,
+ 579, 222,
+ 518, 333,
+ 573, 448,
+ 455, 529,
+ 685, 329,
+ 332, 580,
+ 595, 593,
+ 468, 645,
+ 762, 517,
+ 326, 709,
+ 485, 793,
+ 130, 684,
+ 671, 737,
+ 354, 876,
+ 88, 806,
+ -65, 706,
+ -35, 1016,
+ 266, 1123};
+
+
+/*------------------------------------------------*
+ * 2nd split: isf2 to isf4
+ *------------------------------------------------*/
+
+ static Word16 dico2_isf_noise[SIZE_BK_NOISE2*3] = {
+
+ -824, -884, -949,
+ -805, -456, -418,
+ -442, -438, -541,
+ -217, -578, -793,
+ -168, -444, -582,
+ -287, -492, -274,
+ -552, -297, -300,
+ -163, -333, -358,
+ -370, -232, -232,
+ -175, -358, -159,
+ -381, -21, -357,
+ -184, -159, -162,
+ -53, -191, -280,
+ 18, -267, -215,
+ -138, 61, -283,
+ 71, -95, -294,
+ 13, -156, -546,
+ 0, -83, -79,
+ 44, 97, -316,
+ 178, -52, -213,
+ 222, -261, -422,
+ 237, -118, -44,
+ 141, 145, -132,
+ 363, 81, -287,
+ 213, 65, 34,
+ -107, 94, -5,
+ 91, -29, 126,
+ -355, 51, -41,
+ -219, -76, 145,
+ -63, 100, 244,
+ -719, 44, 27,
+ -572, -124, 155,
+ -423, 133, 315,
+ -917, 71, 224,
+ -268, 318, 131,
+ -93, -190, 420,
+ -97, 122, 491,
+ -79, 317, 355,
+ 130, 100, 325,
+ 86, -293, 210,
+ 133, 258, 161,
+ 176, -73, 465,
+ 195, 300, 384,
+ 348, 22, 221,
+ 376, 183, 409,
+ 377, 286, 202,
+ 242, 213, 659,
+ 257, 565, 248,
+ 344, 408, -76,
+ 405, 440, 509,
+ 612, 385, 379,
+ 536, 607, 216,
+ -56, 582, 192,
+ 100, 517, 567,
+ -365, 448, 445,
+ 728, 347, 10,
+ 505, 357, 759,
+ 636, 582, 658,
+ 335, 517, 852,
+ 378, 809, 572,
+ -195, 878, 829,
+ 529, 707, 987,
+ 918, 726, 392,
+ 1250, 997, 1063};
+
+/*------------------------------------------------*
+ * 3rd split: isf5 to isf7
+ *------------------------------------------------*/
+
+ static Word16 dico3_isf_noise[SIZE_BK_NOISE3*3] = {
+
+ -805, -838, -774,
+ -522, -627, -828,
+ -477, -486, -603,
+ -295, -481, -634,
+ -366, -384, -393,
+ -186, -414, -396,
+ -237, -394, -106,
+ -252, -202, -275,
+ -61, -177, -442,
+ -84, -198, -199,
+ -179, -125, -31,
+ -72, -47, -163,
+ -298, -220, 215,
+ -64, -168, 251,
+ -133, 156, -59,
+ -30, -2, 127,
+ 54, 66, -61,
+ -233, 21, 251,
+ 209, -50, 32,
+ 33, 194, 136,
+ -117, -18, 475,
+ 202, 46, 309,
+ 256, 185, 53,
+ 35, 200, 390,
+ 200, 263, 242,
+ -216, 302, 294,
+ 128, 358, 0,
+ 19, 431, 287,
+ 224, 447, 280,
+ 367, 165, 213,
+ 397, 314, 319,
+ 383, 379, 75,
+ 277, 325, 462,
+ 394, 505, 334,
+ 251, 98, -213,
+ 450, 153, 448,
+ 565, 226, 76,
+ 470, 383, 502,
+ 635, 390, 278,
+ 237, 135, 620,
+ 342, 401, 649,
+ 331, 551, 518,
+ 130, 418, 592,
+ 531, 306, 737,
+ 729, 389, 580,
+ 497, 557, 699,
+ 296, 383, 874,
+ 283, 624, 759,
+ 126, 622, 476,
+ 559, 595, 472,
+ 382, 770, 616,
+ 719, 613, 745,
+ 540, 639, 928,
+ 517, 826, 801,
+ 684, 811, 604,
+ 752, 786, 857,
+ 933, 661, 350,
+ 694, 450, 1061,
+ 562, 911, 1051,
+ 824, 813, 1104,
+ 758, 1047, 882,
+ 1140, 917, 889,
+ 1039, 1246, 1426,
+ 1483, 1666, 1876};
+
+/*------------------------------------------------*
+ * 4th split: isf8 to isf11
+ *------------------------------------------------*/
+
+ static Word16 dico4_isf_noise[SIZE_BK_NOISE4*4] = {
+
+ -776, -854, -891, -920,
+ -552, -610, -663, -741,
+ -321, -370, -476, -565,
+ 274, -160, -456, 201,
+ 265, 67, -160, -306,
+ -8, -210, 79, 272,
+ 163, 236, 307, 308,
+ 578, 317, 64, 298,
+ -9, 197, 342, 620,
+ 343, 232, 314, 622,
+ 173, 149, 548, 527,
+ 356, 370, 481, 376,
+ 135, 444, 488, 556,
+ 391, 471, 487, 653,
+ 228, 424, 576, 835,
+ 422, 372, 722, 682,
+ 295, 673, 693, 635,
+ 539, 596, 590, 449,
+ 475, 618, 659, 818,
+ 735, 517, 491, 673,
+ 602, 346, 257, 877,
+ 625, 635, 849, 720,
+ 727, 818, 698, 595,
+ 653, 481, 690, 1139,
+ 814, 762, 704, 908,
+ 507, 747, 898, 936,
+ 848, 855, 924, 785,
+ 646, 1037, 882, 795,
+ 772, 845, 1024, 1151,
+ 1133, 983, 818, 921,
+ 940, 1068, 1252, 1302,
+ 1588, 1767, 1718, 1513};
+
+/*------------------------------------------------*
+ * 5th split: isf12 to isf15
+ *------------------------------------------------*/
+
+ static Word16 dico5_isf_noise[SIZE_BK_NOISE5*4] = {
+ -810, -879, -945, -254,
+ 248, 184, 671, 128,
+ 288, 703, 918, 99,
+ 658, 558, 662, 219,
+ 552, 585, 910, 208,
+ 559, 804, 759, 119,
+ 606, 774, 921, -139,
+ 782, 761, 748, 208,
+ 756, 708, 983, 56,
+ 544, 864, 1010, 152,
+ 737, 698, 987, 299,
+ 771, 924, 879, 103,
+ 536, 785, 961, 405,
+ 667, 916, 801, 328,
+ 738, 705, 773, 439,
+ 823, 871, 992, 355,
+ 640, 1004, 1052, 369,
+ 724, 822, 949, 597,
+ 415, 655, 729, 482,
+ 1009, 896, 793, 363,
+ 908, 803, 687, -25,
+ 1016, 838, 1011, 189,
+ 947, 1112, 942, 222,
+ 914, 1049, 981, 527,
+ 956, 987, 1011, -120,
+ 781, 1049, 1121, 92,
+ 1178, 1053, 884, 47,
+ 1123, 1059, 1182, 118,
+ 933, 972, 1277, 357,
+ 1109, 918, 1101, 503,
+ 1039, 1286, 1220, 317,
+ 1351, 1207, 1010, 326};
+
--- /dev/null
+++ b/amr-wb/qpisf_2s.c
@@ -1,0 +1,554 @@
+/*-------------------------------------------------------------------*
+ * QPISF_2S.C *
+ *-------------------------------------------------------------------*
+ * Coding/Decoding of ISF parameters with prediction. *
+ * *
+ * The ISF vector is quantized using two-stage VQ with split-by-2 *
+ * in 1st stage and split-by-5 (or 3)in the second stage. *
+ *-------------------------------------------------------------------*/
+
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+#include "acelp.h"
+#include "count.h"
+
+#include "qpisf_2s.tab" /* Codebooks of isfs */
+
+#define MU 10923 /* Prediction factor (1.0/3.0) in Q15 */
+#define N_SURV_MAX 4 /* 4 survivors max */
+#define ALPHA 29491 /* 0. 9 in Q15 */
+#define ONE_ALPHA (32768-ALPHA) /* (1.0 - ALPHA) in Q15 */
+
+/* local functions */
+
+static void VQ_stage1(
+ Word16 * x, /* input : ISF residual vector */
+ Word16 * dico, /* input : quantization codebook */
+ Word16 dim, /* input : dimention of vector */
+ Word16 dico_size, /* input : size of quantization codebook */
+ Word16 * index, /* output: indices of survivors */
+ Word16 surv /* input : number of survivor */
+);
+
+/*-------------------------------------------------------------------*
+ * Function Qpisf_2s_46B() *
+ * ~~~~~~~~~ *
+ * Quantization of isf parameters with prediction. (46 bits) *
+ * *
+ * The isf vector is quantized using two-stage VQ with split-by-2 in *
+ * 1st stage and split-by-5 in the second stage. *
+ *-------------------------------------------------------------------*/
+
+
+void Qpisf_2s_46b(
+ Word16 * isf1, /* (i) Q15 : ISF in the frequency domain (0..0.5) */
+ Word16 * isf_q, /* (o) Q15 : quantized ISF (0..0.5) */
+ Word16 * past_isfq, /* (io)Q15 : past ISF quantizer */
+ Word16 * indice, /* (o) : quantization indices */
+ Word16 nb_surv /* (i) : number of survivor (1, 2, 3 or 4) */
+)
+{
+ Word16 i, k, tmp_ind[5];
+ Word16 surv1[N_SURV_MAX]; /* indices of survivors from 1st stage */
+ Word32 temp, min_err, distance;
+ Word16 isf[ORDER];
+ Word16 isf_stage2[ORDER];
+
+
+ for (i = 0; i < ORDER; i++)
+ {
+ /* isf[i] = isf1[i] - mean_isf[i] - MU*past_isfq[i] */
+ isf[i] = sub(isf1[i], mean_isf[i]);move16();
+ isf[i] = sub(isf[i], mult(MU, past_isfq[i])); move16();
+ }
+
+ VQ_stage1(&isf[0], dico1_isf, 9, SIZE_BK1, surv1, nb_surv);
+
+ distance = MAX_32; move32();
+
+ for (k = 0; k < nb_surv; k++)
+ {
+ for (i = 0; i < 9; i++)
+ {
+ isf_stage2[i] = sub(isf[i], dico1_isf[i + surv1[k] * 9]); move16();
+ }
+
+ tmp_ind[0] = Sub_VQ(&isf_stage2[0], dico21_isf, 3, SIZE_BK21, &min_err); move16();
+ temp = min_err; move32();
+ tmp_ind[1] = Sub_VQ(&isf_stage2[3], dico22_isf, 3, SIZE_BK22, &min_err); move16();
+ temp = L_add(temp, min_err);
+ tmp_ind[2] = Sub_VQ(&isf_stage2[6], dico23_isf, 3, SIZE_BK23, &min_err); move16();
+ temp = L_add(temp, min_err);
+
+ test();
+ if (L_sub(temp, distance) < (Word32) 0)
+ {
+ distance = temp; move32();
+ indice[0] = surv1[k]; move16();
+ for (i = 0; i < 3; i++)
+ {
+ indice[i + 2] = tmp_ind[i];move16();
+ }
+ }
+ }
+
+
+ VQ_stage1(&isf[9], dico2_isf, 7, SIZE_BK2, surv1, nb_surv);
+
+ distance = MAX_32; move32();
+
+ for (k = 0; k < nb_surv; k++)
+ {
+ for (i = 0; i < 7; i++)
+ {
+ isf_stage2[i] = sub(isf[9 + i], dico2_isf[i + surv1[k] * 7]); move16();
+ }
+
+ tmp_ind[0] = Sub_VQ(&isf_stage2[0], dico24_isf, 3, SIZE_BK24, &min_err); move16();
+ temp = min_err; move32();
+ tmp_ind[1] = Sub_VQ(&isf_stage2[3], dico25_isf, 4, SIZE_BK25, &min_err); move16();
+ temp = L_add(temp, min_err);
+
+ test();
+ if (L_sub(temp, distance) < (Word32) 0)
+ {
+ distance = temp; move32();
+ indice[1] = surv1[k]; move16();
+ for (i = 0; i < 2; i++)
+ {
+ indice[i + 5] = tmp_ind[i];move16();
+ }
+ }
+ }
+
+ Dpisf_2s_46b(indice, isf_q, past_isfq, isf_q, isf_q, 0, 0);
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * Function Qpisf_2s_36B() *
+ * ~~~~~~~~~ *
+ * Quantization of isf parameters with prediction. (36 bits) *
+ * *
+ * The isf vector is quantized using two-stage VQ with split-by-2 in *
+ * 1st stage and split-by-3 in the second stage. *
+ *-------------------------------------------------------------------*/
+
+
+void Qpisf_2s_36b(
+ Word16 * isf1, /* (i) Q15 : ISF in the frequency domain (0..0.5) */
+ Word16 * isf_q, /* (o) Q15 : quantized ISF (0..0.5) */
+ Word16 * past_isfq, /* (io)Q15 : past ISF quantizer */
+ Word16 * indice, /* (o) : quantization indices */
+ Word16 nb_surv /* (i) : number of survivor (1, 2, 3 or 4) */
+)
+{
+ Word16 i, k, tmp_ind[5];
+ Word16 surv1[N_SURV_MAX]; /* indices of survivors from 1st stage */
+ Word32 temp, min_err, distance;
+ Word16 isf[ORDER];
+ Word16 isf_stage2[ORDER];
+
+ for (i = 0; i < ORDER; i++)
+ {
+ /* isf[i] = isf1[i] - mean_isf[i] - MU*past_isfq[i] */
+ isf[i] = sub(isf1[i], mean_isf[i]);move16();
+ isf[i] = sub(isf[i], mult(MU, past_isfq[i])); move16();
+ }
+
+ VQ_stage1(&isf[0], dico1_isf, 9, SIZE_BK1, surv1, nb_surv);
+
+ distance = MAX_32; move32();
+
+ for (k = 0; k < nb_surv; k++)
+ {
+ for (i = 0; i < 9; i++)
+ {
+ isf_stage2[i] = sub(isf[i], dico1_isf[i + surv1[k] * 9]); move16();
+ }
+
+ tmp_ind[0] = Sub_VQ(&isf_stage2[0], dico21_isf_36b, 5, SIZE_BK21_36b, &min_err); move16();
+ temp = min_err; move32();
+ tmp_ind[1] = Sub_VQ(&isf_stage2[5], dico22_isf_36b, 4, SIZE_BK22_36b, &min_err); move16();
+ temp = L_add(temp, min_err);
+
+ test();
+ if (L_sub(temp, distance) < (Word32) 0)
+ {
+ distance = temp; move32();
+ indice[0] = surv1[k]; move16();
+ for (i = 0; i < 2; i++)
+ {
+ indice[i + 2] = tmp_ind[i];move16();
+ }
+ }
+ }
+
+
+ VQ_stage1(&isf[9], dico2_isf, 7, SIZE_BK2, surv1, nb_surv);
+
+ distance = MAX_32; move32();
+
+ for (k = 0; k < nb_surv; k++)
+ {
+ for (i = 0; i < 7; i++)
+ {
+ isf_stage2[i] = sub(isf[9 + i], dico2_isf[i + surv1[k] * 7]); move16();
+ }
+
+ tmp_ind[0] = Sub_VQ(&isf_stage2[0], dico23_isf_36b, 7, SIZE_BK23_36b, &min_err); move16();
+ temp = min_err; move32();
+
+ test();
+ if (L_sub(temp, distance) < (Word32) 0)
+ {
+ distance = temp; move32();
+ indice[1] = surv1[k]; move16();
+ indice[4] = tmp_ind[0]; move16();
+ }
+ }
+
+ Dpisf_2s_36b(indice, isf_q, past_isfq, isf_q, isf_q, 0, 0);
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * routine: Disf_2s_46b() *
+ * ~~~~~~~~~ *
+ * Decoding of ISF parameters *
+ *-------------------------------------------------------------------*/
+
+void Dpisf_2s_46b(
+ Word16 * indice, /* input: quantization indices */
+ Word16 * isf_q, /* output: quantized ISF in frequency domain (0..0.5) */
+ Word16 * past_isfq, /* i/0 : past ISF quantizer */
+ Word16 * isfold, /* input : past quantized ISF */
+ Word16 * isf_buf, /* input : isf buffer */
+ Word16 bfi, /* input : Bad frame indicator */
+ Word16 enc_dec
+)
+{
+ Word16 ref_isf[M];
+ Word16 i, j, tmp;
+ Word32 L_tmp;
+
+ test();
+ if (bfi == 0) /* Good frame */
+ {
+ for (i = 0; i < 9; i++)
+ {
+ isf_q[i] = dico1_isf[indice[0] * 9 + i]; move16();
+ }
+ for (i = 0; i < 7; i++)
+ {
+ isf_q[i + 9] = dico2_isf[indice[1] * 7 + i]; move16();
+ }
+
+ for (i = 0; i < 3; i++)
+ {
+ isf_q[i] = add(isf_q[i], dico21_isf[indice[2] * 3 + i]); move16();
+ }
+ for (i = 0; i < 3; i++)
+ {
+ isf_q[i + 3] = add(isf_q[i + 3], dico22_isf[indice[3] * 3 + i]); move16();
+ }
+ for (i = 0; i < 3; i++)
+ {
+ isf_q[i + 6] = add(isf_q[i + 6], dico23_isf[indice[4] * 3 + i]); move16();
+ }
+ for (i = 0; i < 3; i++)
+ {
+ isf_q[i + 9] = add(isf_q[i + 9], dico24_isf[indice[5] * 3 + i]); move16();
+ }
+ for (i = 0; i < 4; i++)
+ {
+ isf_q[i + 12] = add(isf_q[i + 12], dico25_isf[indice[6] * 4 + i]); move16();
+ }
+
+ for (i = 0; i < ORDER; i++)
+ {
+ tmp = isf_q[i]; move16();
+ isf_q[i] = add(tmp, mean_isf[i]); move16();
+ isf_q[i] = add(isf_q[i], mult(MU, past_isfq[i])); move16();
+ past_isfq[i] = tmp; move16();
+ }
+
+ test();
+ if (enc_dec)
+ {
+ for (i = 0; i < M; i++)
+ {
+ for (j = (L_MEANBUF - 1); j > 0; j--)
+ {
+ isf_buf[j * M + i] = isf_buf[(j - 1) * M + i]; move16();
+ }
+ isf_buf[i] = isf_q[i]; move16();
+ }
+ }
+ } else
+ { /* bad frame */
+ for (i = 0; i < M; i++)
+ {
+ L_tmp = L_mult(mean_isf[i], 8192);
+ for (j = 0; j < L_MEANBUF; j++)
+ {
+ L_tmp = L_mac(L_tmp, isf_buf[j * M + i], 8192);
+ }
+ ref_isf[i] = round(L_tmp); move16();
+ }
+
+ /* use the past ISFs slightly shifted towards their mean */
+ for (i = 0; i < ORDER; i++)
+ {
+ isf_q[i] = add(mult(ALPHA, isfold[i]), mult(ONE_ALPHA, ref_isf[i])); move16();
+ }
+
+ /* estimate past quantized residual to be used in next frame */
+
+ for (i = 0; i < ORDER; i++)
+ {
+ tmp = add(ref_isf[i], mult(past_isfq[i], MU)); /* predicted ISF */
+ past_isfq[i] = sub(isf_q[i], tmp); move16();
+ past_isfq[i] = shr(past_isfq[i], 1); move16(); /* past_isfq[i] *= 0.5 */
+ }
+ }
+
+ Reorder_isf(isf_q, ISF_GAP, ORDER);
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * routine: Disf_2s_36b() *
+ * ~~~~~~~~~ *
+ * Decoding of ISF parameters *
+ *-------------------------------------------------------------------*/
+
+void Dpisf_2s_36b(
+ Word16 * indice, /* input: quantization indices */
+ Word16 * isf_q, /* output: quantized ISF in frequency domain (0..0.5) */
+ Word16 * past_isfq, /* i/0 : past ISF quantizer */
+ Word16 * isfold, /* input : past quantized ISF */
+ Word16 * isf_buf, /* input : isf buffer */
+ Word16 bfi, /* input : Bad frame indicator */
+ Word16 enc_dec
+)
+{
+ Word16 ref_isf[M];
+ Word16 i, j, tmp;
+ Word32 L_tmp;
+
+ test();
+ if (bfi == 0) /* Good frame */
+ {
+ for (i = 0; i < 9; i++)
+ {
+ isf_q[i] = dico1_isf[indice[0] * 9 + i]; move16();
+ }
+ for (i = 0; i < 7; i++)
+ {
+ isf_q[i + 9] = dico2_isf[indice[1] * 7 + i]; move16();
+ }
+
+ for (i = 0; i < 5; i++)
+ {
+ isf_q[i] = add(isf_q[i], dico21_isf_36b[indice[2] * 5 + i]); move16();
+ }
+ for (i = 0; i < 4; i++)
+ {
+ isf_q[i + 5] = add(isf_q[i + 5], dico22_isf_36b[indice[3] * 4 + i]); move16();
+ }
+ for (i = 0; i < 7; i++)
+ {
+ isf_q[i + 9] = add(isf_q[i + 9], dico23_isf_36b[indice[4] * 7 + i]); move16();
+ }
+
+ for (i = 0; i < ORDER; i++)
+ {
+ tmp = isf_q[i];
+ isf_q[i] = add(tmp, mean_isf[i]); move16();
+ isf_q[i] = add(isf_q[i], mult(MU, past_isfq[i])); move16();
+ past_isfq[i] = tmp; move16();
+ }
+
+ test();
+ if (enc_dec)
+ {
+ for (i = 0; i < M; i++)
+ {
+ for (j = (L_MEANBUF - 1); j > 0; j--)
+ {
+ isf_buf[j * M + i] = isf_buf[(j - 1) * M + i]; move16();
+ }
+ isf_buf[i] = isf_q[i]; move16();
+ }
+ }
+ } else
+ { /* bad frame */
+ for (i = 0; i < M; i++)
+ {
+ L_tmp = L_mult(mean_isf[i], 8192);
+ for (j = 0; j < L_MEANBUF; j++)
+ {
+ L_tmp = L_mac(L_tmp, isf_buf[j * M + i], 8192);
+ }
+
+ ref_isf[i] = round(L_tmp); move16();
+ }
+
+ /* use the past ISFs slightly shifted towards their mean */
+ for (i = 0; i < ORDER; i++)
+ {
+ isf_q[i] = add(mult(ALPHA, isfold[i]), mult(ONE_ALPHA, ref_isf[i])); move16();
+ }
+
+ /* estimate past quantized residual to be used in next frame */
+
+ for (i = 0; i < ORDER; i++)
+ {
+ tmp = add(ref_isf[i], mult(past_isfq[i], MU)); /* predicted ISF */
+ past_isfq[i] = sub(isf_q[i], tmp); move16();
+ past_isfq[i] = shr(past_isfq[i], 1); move16(); /* past_isfq[i] *= 0.5 */
+ }
+ }
+
+ Reorder_isf(isf_q, ISF_GAP, ORDER);
+
+ return;
+}
+
+
+/*--------------------------------------------------------------------------*
+ * procedure Reorder_isf() *
+ * ~~~~~~~~~~~~~ *
+ * To make sure that the isfs are properly order and to keep a certain *
+ * minimum distance between consecutive isfs. *
+ *--------------------------------------------------------------------------*
+ * Argument description in/out *
+ * ~~~~~~~~ ~~~~~~~~~~~ ~~~~~~ *
+ * isf[] vector of isfs i/o *
+ * min_dist minimum required distance i *
+ * n LPC order i *
+ *--------------------------------------------------------------------------*/
+
+void Reorder_isf(
+ Word16 * isf, /* (i/o) Q15: ISF in the frequency domain (0..0.5) */
+ Word16 min_dist, /* (i) Q15 : minimum distance to keep */
+ Word16 n /* (i) : number of ISF */
+)
+{
+ Word16 i, isf_min;
+
+ isf_min = min_dist; move16();
+
+ for (i = 0; i < n - 1; i++)
+ {
+ test();
+ if (sub(isf[i], isf_min) < 0)
+ {
+ isf[i] = isf_min; move16();
+ }
+ isf_min = add(isf[i], min_dist);
+ }
+
+ return;
+}
+
+
+Word16 Sub_VQ( /* output: return quantization index */
+ Word16 * x, /* input : ISF residual vector */
+ Word16 * dico, /* input : quantization codebook */
+ Word16 dim, /* input : dimention of vector */
+ Word16 dico_size, /* input : size of quantization codebook */
+ Word32 * distance /* output: error of quantization */
+)
+{
+ Word16 i, j, index, temp, *p_dico;
+ Word32 dist_min, dist;
+
+ dist_min = MAX_32; move32();
+ p_dico = dico; move16();
+
+ index = 0; move16();
+ for (i = 0; i < dico_size; i++)
+ {
+ dist = 0; move32();
+ for (j = 0; j < dim; j++)
+ {
+ temp = sub(x[j], *p_dico++);
+ dist = L_mac(dist, temp, temp);
+ }
+
+ test();
+ if (L_sub(dist, dist_min) < (Word32) 0)
+ {
+ dist_min = dist; move32();
+ index = i; move16();
+ }
+ }
+
+ *distance = dist_min; move32();
+
+ /* Reading the selected vector */
+
+ p_dico = &dico[index * dim]; move16();
+ for (j = 0; j < dim; j++)
+ {
+ x[j] = *p_dico++; move16();
+ }
+
+ return index;
+}
+
+
+static void VQ_stage1(
+ Word16 * x, /* input : ISF residual vector */
+ Word16 * dico, /* input : quantization codebook */
+ Word16 dim, /* input : dimention of vector */
+ Word16 dico_size, /* input : size of quantization codebook */
+ Word16 * index, /* output: indices of survivors */
+ Word16 surv /* input : number of survivor */
+)
+{
+ Word16 i, j, k, l, temp, *p_dico;
+ Word32 dist_min[N_SURV_MAX], dist;
+
+ for (i = 0; i < surv; i++)
+ {
+ dist_min[i] = MAX_32; move32();
+ index[i] = i; move16();
+ }
+ p_dico = dico; move16();
+
+ for (i = 0; i < dico_size; i++)
+ {
+ dist = 0; move32();
+ for (j = 0; j < dim; j++)
+ {
+ temp = sub(x[j], *p_dico++);
+ dist = L_mac(dist, temp, temp);
+ }
+
+ for (k = 0; k < surv; k++)
+ {
+ test();
+ if (L_sub(dist, dist_min[k]) < (Word32) 0)
+ {
+ for (l = sub(surv, 1); l > k; l--)
+ {
+ dist_min[l] = dist_min[l - 1]; move32();
+ index[l] = index[l - 1]; move16();
+ }
+ dist_min[k] = dist; move32();
+ index[k] = i; move16();
+ break;
+ }
+ }
+ }
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/qpisf_2s.tab
@@ -1,0 +1,1343 @@
+/*-------------------------------------------------------------------*
+ * qpisf_2s.h
+ *-------------------------------------------------------------------*
+ * Quantization tables for two-stage of ISFs (split by 2 in 1st stage)
+ * Version whith prediction MU = 0.25
+ *-------------------------------------------------------------------*/
+
+#define ORDER 16 /* order of linear prediction filter */
+#define ISF_GAP 128 /* 50 Hz */
+#define N_SURV 4
+
+#define SIZE_BK1 256
+#define SIZE_BK2 256
+#define SIZE_BK21 64
+#define SIZE_BK22 128
+#define SIZE_BK23 128
+#define SIZE_BK24 32
+#define SIZE_BK25 32
+
+#define SIZE_BK21_36b 128
+#define SIZE_BK22_36b 128
+#define SIZE_BK23_36b 64
+
+/* means of ISFs */
+static Word16 mean_isf[ORDER] = {
+
+ 738, 1326, 2336, 3578, 4596, 5662, 6711, 7730,
+ 8750, 9753, 10705, 11728, 12833, 13971, 15043, 4037};
+
+/* 46 bits */
+/*-------------------------------------------------------------------*
+ * isf codebooks: two-stage VQ with split-by-5 in 2nd stage *
+ * *
+ * codebook vector dimension number of vectors *
+ * ~~~~~~~~ ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ *
+ * 1_1 9 256 *
+ * 1_2 7 256 *
+ * 2_1 3 64 *
+ * 2_2 3 128 *
+ * 2_3 3 128 *
+ * 2_4 3 32 *
+ * 2_5 4 32 *
+ *-------------------------------------------------------------------*/
+
+/*------------------------------------------------*
+ * 1st stage codebook; 1st split: isf0 to isf8
+ *------------------------------------------------*/
+
+static Word16 dico1_isf[SIZE_BK1*9] = {
+
+ 579, 1081, 1035, 390, 3, -263, -198, -82, 38,
+ 18, -68, -12, 313, 761, 405, 249, 111, -76,
+ 740, 1263, 1292, 1006, 997, 1019, 1017, 976, 923,
+ -91, 827, 948, 648, 613, 535, 522, 490, 421,
+ 41, -44, -281, -472, 652, 534, 193, 135, -90,
+ 41, -121, -356, -60, 663, 307, 61, -48, -344,
+ 557, 946, 1049, 867, 846, 990, 1112, 1262, 1241,
+ -118, -204, 328, 512, 870, 793, 610, 402, 186,
+ 156, 293, 74, -338, -475, -897, -594, -161, -497,
+ 226, 131, -138, 307, 169, -271, -164, -387, -624,
+ 62, -32, -61, -252, -541, -828, -1027, -523, -662,
+ 102, -61, 141, 112, -270, -251, -541, 25, -150,
+ 6, -132, -356, -686, -96, -322, -522, -31, -326,
+ -36, -209, -521, -229, 307, -132, -5, -99, -384,
+ 60, -51, -237, -668, -973, -407, -708, -75, -172,
+ 26, -138, -266, 111, -302, 43, -278, -356, -359,
+ 570, 822, 496, -154, -312, -92, 137, 279, 371,
+ -146, 368, 409, 68, 6, 77, 167, 202, 162,
+ 633, 898, 996, 756, 662, 683, 783, 909, 996,
+ -103, 294, 607, 415, 483, 462, 480, 431, 408,
+ -120, -338, -612, -524, 584, 331, 92, 433, 276,
+ -178, -293, -154, -41, 269, 100, -9, 213, 160,
+ 830, 736, 278, 820, 1254, 686, 712, 1039, 473,
+ -218, -304, 463, 454, 397, 273, 202, 286, 273,
+ -232, 7, 6, -388, -472, -427, -378, -167, -100,
+ -294, -183, 134, -47, 101, -88, -84, -117, -3,
+ 57, 17, -202, -634, -989, -1119, -533, 176, -36,
+ 120, -28, 23, 111, -319, 318, -22, -77, 266,
+ -271, -464, -434, -658, -640, -385, -385, -99, -69,
+ -198, -259, -266, -44, -39, -139, -137, 171, 66,
+ 9, -145, -377, -846, -1000, -111, -325, 342, 135,
+ -81, -286, -380, 192, -57, 307, 76, -24, -140,
+ 677, 702, 247, 56, 249, 141, -105, -236, -99,
+ 36, -39, -69, 348, 198, -93, 322, 91, -72,
+ 503, 885, 1508, 1307, 1282, 1172, 1119, 1209, 1061,
+ 416, 719, 989, 1227, 1001, 1052, 954, 741, 1044,
+ -127, -376, -657, 139, 623, 223, 501, 306, 220,
+ -113, -384, -796, 504, 438, 85, 213, -83, -194,
+ 585, 1132, 1233, 1091, 1247, 1433, 1512, 1448, 1314,
+ -174, -422, 7, 1155, 1089, 1182, 1003, 945, 806,
+ 8, -126, -317, -103, -351, -695, -98, -268, -537,
+ 33, -103, -290, 167, -39, -407, 44, -208, -375,
+ 104, -23, -64, -291, -637, -851, -1084, -61, -112,
+ -75, -306, -434, 218, -148, -354, -680, -133, -216,
+ -121, -377, -718, -97, -130, -361, -156, -379, -599,
+ -56, -254, -586, 235, 157, -214, 11, -260, -149,
+ -124, -267, -397, -580, -593, -527, -805, -385, 346,
+ -193, -440, -708, -351, -141, -255, -499, -147, -185,
+ 448, 660, 494, 208, 509, 461, 338, 291, 149,
+ -223, 88, 335, 159, 212, 191, 286, 308, 205,
+ -31, 469, 803, 659, 619, 658, 843, 987, 1113,
+ -171, -242, 514, 362, 295, 524, 552, 694, 585,
+ -64, -308, -448, -21, 284, 786, 446, 289, 92,
+ -218, -390, -7, 169, 206, 330, 352, 408, 358,
+ -36, 702, 959, 859, 861, 1115, 1269, 1357, 1305,
+ -133, -341, -65, 678, 417, 440, 486, 518, 780,
+ 33, -44, -191, -344, -461, -755, -201, 217, -31,
+ -353, -547, -44, 123, -61, -68, -79, 29, 60,
+ 73, -57, -406, -766, -1243, -1203, 240, 400, 165,
+ -73, -282, -601, -213, -171, -375, 332, 35, -103,
+ -29, -207, -553, -476, -638, -908, 172, -22, -135,
+ -192, -239, -164, -103, -111, -47, 153, 125, 110,
+ -1, -203, -570, -1030, -1424, -535, 155, 1, 147,
+ -333, -653, -865, -197, -158, -21, -44, 95, 108,
+ 389, 588, 490, 33, -237, -524, -628, -136, -260,
+ 40, -177, -462, 453, 862, 380, 131, -130, -405,
+ 842, 1678, 1841, 1549, 1474, 1256, 1082, 905, 742,
+ 370, 1216, 1768, 1633, 1212, 636, 22, -330, 71,
+ -76, -281, -741, -742, 898, 619, 277, 71, -222,
+ -32, -265, -556, -25, 994, 682, 305, 126, -165,
+ 73, 738, 893, 968, 993, 1768, 2273, 1840, 1391,
+ -69, -349, -585, 234, 1158, 903, 626, 510, 251,
+ -1, -99, -272, -210, -603, -351, -540, -811, -383,
+ -16, -230, -504, 410, 149, -205, -343, -651, -639,
+ 103, -9, -227, -205, -562, -781, -1079, -1208, -156,
+ 143, 63, -135, -67, -317, -602, -784, -1154, -640,
+ -144, -391, -674, -622, -200, -254, -660, -947, -395,
+ -40, -250, -625, 27, 543, 94, -131, -386, -673,
+ -123, -371, -757, -451, -564, -614, -415, -711, -35,
+ -116, -309, -593, -268, 239, -33, -338, -650, -135,
+ 94, 251, 554, 57, -312, -423, -154, -57, 235,
+ -268, -71, 381, 114, -44, -87, 125, 173, 133,
+ 1513, 1714, 1238, 534, 276, 315, 461, 459, 508,
+ -131, -19, 1149, 670, 486, 356, 309, 369, 296,
+ -223, -501, -899, -722, -70, 6, 131, 310, 394,
+ -99, -303, -517, 249, 64, -53, 135, -11, 453,
+ -147, -399, -730, -401, 817, 738, 802, 749, 575,
+ -154, -435, -739, 800, 593, 366, 529, 318, 326,
+ -224, 45, -39, -387, -515, -518, -608, -384, -321,
+ -315, -377, 143, -101, -113, -377, -177, -144, -12,
+ 117, 40, -239, -651, -1051, -581, -737, -990, -328,
+ 26, -50, -157, -23, -453, -283, -531, -546, 192,
+ -252, -501, -743, -589, -627, -499, -328, -118, -72,
+ -324, -494, -244, -306, -144, -177, -262, -135, -78,
+ -36, -234, -519, -961, -1290, -314, -479, -371, -45,
+ -95, -292, -535, -8, -300, 112, -164, -277, 198,
+ -99, -128, 880, 836, 579, 351, 23, -95, -217,
+ -27, -258, 124, 1011, 597, 425, 144, 7, -73,
+ 421, 1293, 1640, 1623, 1742, 1617, 1499, 1284, 1006,
+ -95, 752, 1680, 1569, 1618, 1436, 1200, 980, 712,
+ -69, -300, -683, -435, 1132, 899, 504, 332, 109,
+ -74, -323, -637, 563, 1074, 608, 371, 105, -49,
+ -78, 831, 1194, 1110, 1378, 1481, 1492, 1365, 1217,
+ -259, -121, 1440, 1334, 1628, 1490, 1438, 1223, 933,
+ -82, -306, -613, -222, -378, -675, -545, -671, -845,
+ 53, -124, -347, 422, 52, -125, -270, -529, 9,
+ 79, -89, -320, -662, -999, -1199, -1243, -676, -297,
+ -68, -273, -611, 137, -146, -397, -627, -845, -220,
+ -112, -346, -797, -826, 234, -132, -188, -278, -522,
+ -159, -405, -734, -419, 293, 74, -167, -167, 184,
+ -153, -437, -833, -1080, -336, -472, -561, -340, -253,
+ -169, -423, -820, -904, -131, -19, -346, -604, 31,
+ 33, -31, 312, 62, -148, 49, -59, 564, 486,
+ -306, -333, 194, -44, 67, 72, 147, 205, 243,
+ -207, -49, 1360, 983, 969, 991, 1014, 1110, 973,
+ -211, -172, 883, 627, 711, 674, 705, 798, 746,
+ -88, -325, -763, -974, 687, 908, 514, 382, 172,
+ -292, -612, -805, 63, 131, 270, 259, 352, 348,
+ -235, -84, 955, 818, 1120, 1289, 1559, 1480, 1285,
+ -180, -461, -614, 657, 691, 745, 854, 783, 713,
+ -97, -309, -477, -614, -777, -734, -768, -526, -472,
+ -344, -476, -35, -169, 49, -77, -150, -240, -141,
+ -52, -268, -639, -919, -1278, -1113, -342, -333, -151,
+ -68, -242, -585, -73, -209, -478, -159, -429, 133,
+ -197, -499, -1005, -1268, -272, -224, -105, -67, 17,
+ -363, -618, -414, -116, -62, 20, 10, 116, 108,
+ -195, -475, -906, -1260, -891, -441, -277, -142, -28,
+ -226, -519, -950, -700, -275, -266, -116, -105, 82,
+ 404, 511, 520, 327, 17, -194, -333, -536, -586,
+ -114, -130, 276, 237, 204, 342, 135, -16, -111,
+ 670, 1208, 1168, 860, 742, 601, 528, 403, 309,
+ 397, 621, 966, 752, 579, 398, 400, 329, 252,
+ 191, 180, -137, -467, 272, 106, -95, 17, -192,
+ -80, -290, -626, 194, 598, 196, 21, -281, 77,
+ 510, 864, 1108, 807, 939, 902, 925, 717, 481,
+ 137, 367, 534, 764, 670, 382, 296, 153, 84,
+ 303, 497, 144, -85, -125, -539, -482, -464, -764,
+ 233, 347, 68, -147, 169, -210, -242, -226, -482,
+ 307, 422, 154, -175, -386, -722, -724, -904, -1015,
+ 309, 308, 160, -60, -470, -420, -598, -791, -219,
+ 68, 121, -137, -560, -146, -446, -515, -494, -729,
+ 130, 53, -227, 46, 474, 32, -161, -192, -490,
+ 213, 164, -71, -465, -876, -161, -456, -587, -48,
+ 218, 117, 39, 177, -194, -88, -226, -418, 50,
+ 210, 547, 569, 279, 121, -44, -50, 10, -84,
+ 58, 140, 182, -5, 267, 117, 106, 211, 198,
+ 539, 835, 913, 719, 617, 544, 591, 565, 642,
+ 153, 559, 872, 460, 222, 108, 188, 180, 183,
+ 158, 119, 284, -153, -271, 229, 87, 110, -57,
+ -183, 82, 118, 21, 13, 40, 118, 191, 185,
+ 162, 889, 654, 108, -34, 244, 488, 561, 532,
+ 163, 56, 609, 341, 50, 329, 68, 266, 218,
+ 100, 206, 18, -304, -107, -436, -487, -65, -306,
+ -86, 154, 134, -30, -45, -73, -104, -80, -96,
+ 245, 330, 10, -440, -849, -1082, 79, 40, -265,
+ 196, 372, 272, -181, -493, -389, 275, 80, -59,
+ 2, -12, -246, -505, -100, -436, 21, -187, -431,
+ -221, -48, 36, -271, -186, -147, -109, 26, 71,
+ 213, 140, 72, -351, -620, -84, -363, 69, 46,
+ 91, 167, -3, -95, -99, -105, -48, 114, 147,
+ 259, 249, 172, 607, 406, 52, 59, -189, -320,
+ 115, -85, -54, 574, 128, 226, -59, -253, 130,
+ -62, 1033, 1308, 1035, 1127, 1098, 1029, 961, 823,
+ 39, 364, 757, 940, 728, 660, 659, 583, 770,
+ -115, -338, -760, -471, 394, 37, 441, 178, 6,
+ -57, -305, -525, 796, 453, 188, -4, -114, 248,
+ 71, 444, 797, 731, 1096, 1157, 1222, 1029, 811,
+ 135, 359, 551, 425, 749, 815, 874, 704, 502,
+ 132, 247, 0, -206, -449, -750, -258, -514, -633,
+ 248, 249, 91, 121, -195, -499, -90, -282, -435,
+ 78, 20, -277, -623, -983, -1224, -415, -458, -639,
+ 347, 509, 208, -179, -464, -728, -76, -237, -486,
+ -103, -343, -756, -713, -265, -609, -191, -398, -636,
+ -121, -383, -749, 567, 252, -36, -354, -417, -50,
+ 204, 100, -149, -650, -1081, -47, -7, -263, 111,
+ -46, -180, -267, -324, -562, -394, -692, 398, 292,
+ 482, 670, 683, 624, 442, 165, 116, 36, -149,
+ 108, 247, 291, 247, 355, 122, 109, 224, 296,
+ -14, 945, 990, 801, 755, 815, 847, 913, 892,
+ 292, 349, 725, 482, 388, 329, 429, 620, 667,
+ -34, 197, 213, -127, 84, 494, 620, 575, 375,
+ 126, 207, 172, 167, 362, 202, 296, 395, 455,
+ -6, 250, 539, 467, 636, 801, 1149, 1287, 1118,
+ 27, 240, 369, 280, 440, 411, 634, 892, 953,
+ 159, 170, -58, -395, -797, -690, 77, -211, -334,
+ -5, -28, -13, -74, -335, -603, 300, 88, -205,
+ 82, -33, -364, -698, -1203, -1153, 110, -146, -289,
+ 113, 1, -243, -588, -994, -496, 414, 160, 42,
+ -56, -247, -440, -693, -996, -479, 11, -178, -357,
+ -151, -353, -327, -211, -340, 141, 65, 425, 453,
+ 34, -169, -455, -932, -1215, 138, 499, 256, 324,
+ 68, 139, -15, -547, -478, 17, 306, 502, 481,
+ -32, -134, 445, 129, -143, -244, -503, -507, -599,
+ 61, -140, -345, 496, 458, -2, 20, -227, -514,
+ 394, 1765, 1666, 1339, 1117, 806, 642, 479, 380,
+ 215, 519, 920, 1053, 1090, 791, 528, 290, 155,
+ -54, -233, -647, -602, 639, 294, -2, -167, -442,
+ -78, -315, -791, -113, 820, 403, 158, -116, -356,
+ 529, 1851, 2003, 1228, 622, -41, -416, 344, 819,
+ -105, -379, -236, 1224, 893, 749, 568, 356, 214,
+ -17, -199, -144, 50, -283, -247, -578, -846, -1087,
+ 69, -11, -381, -206, 209, -284, -387, -416, -716,
+ 39, -5, -145, -374, -682, -909, -1074, -1169, -1066,
+ 287, 226, 67, -221, -662, -171, -421, -642, -707,
+ -132, -348, -538, -448, -20, -4, -354, -748, -933,
+ 4, -75, -289, -598, 317, 52, -208, -297, -559,
+ -88, -264, -358, -589, -631, -248, -523, -822, -1071,
+ 70, -8, 54, -314, -515, 92, -146, -274, -493,
+ 199, 62, 391, 158, -141, 71, -219, -203, -207,
+ 152, 40, 329, 162, -29, 48, -149, 108, 127,
+ 635, 1058, 883, 492, 372, 312, 317, 274, 241,
+ 267, 722, 1256, 882, 625, 248, 8, -81, -60,
+ -58, -138, -291, -600, -12, -2, -39, 147, 117,
+ -107, -345, -513, 459, 76, 92, -272, 388, 262,
+ 362, 516, 203, -409, -716, -831, -331, 185, 209,
+ -117, -391, -298, 671, 292, 538, 257, 166, -38,
+ -102, -319, -194, -283, -573, -262, -579, -219, -444,
+ -235, 78, 11, -168, -101, -229, -263, -321, -123,
+ 70, 50, -170, -599, -996, -588, -263, -516, -455,
+ 394, 363, 229, -136, -538, 21, -183, -348, -201,
+ -124, -368, -640, -879, -847, -209, -409, -494, -515,
+ -127, -341, -541, -425, -510, -10, -252, -473, -291,
+ 84, -69, -201, -676, -868, 103, -311, -132, -320,
+ 5, -173, -188, -297, -628, 197, -57, 7, -11,
+ 49, -160, 56, 558, 111, 33, -311, -440, -463,
+ -1, -246, -307, 862, 453, 139, -170, -355, -232,
+ 279, 966, 1642, 1478, 1463, 1123, 795, 525, 339,
+ -197, -38, 1702, 1331, 1252, 950, 692, 504, 426,
+ -108, -344, -861, -1172, 444, 354, 88, -46, -220,
+ -53, -321, -494, 1113, 744, 364, 198, -34, -75,
+ 457, 955, 1177, 1214, 1427, 1457, 1345, 917, 539,
+ -69, 199, 897, 1140, 1343, 1183, 977, 742, 522,
+ 122, 44, -269, 27, -155, -562, -307, -590, -773,
+ 154, 42, -160, 252, -129, -305, -471, -733, -371,
+ 135, 185, -82, -416, -722, -913, -504, -743, -880,
+ 149, 214, -84, -329, -680, -835, -426, -661, -81,
+ -128, -380, -735, -998, -337, 17, -182, -467, -697,
+ -84, -290, -510, -592, 13, 440, 154, -38, -279,
+ 70, -61, -246, -727, -1047, -80, -381, -535, -704,
+ 178, -2, -146, -670, -938, 482, 138, 63, 65,
+ -11, 15, 772, 443, 142, -20, -209, -126, -161,
+ -32, -249, 95, 552, 124, 30, -343, 82, -86,
+ 148, 751, 1515, 1105, 867, 606, 474, 448, 399,
+ -163, -257, 899, 1097, 906, 751, 502, 390, 294,
+ -51, -258, -447, -806, -368, 763, 464, 364, 183,
+ -166, -374, -367, 87, 35, 399, 418, 856, 833,
+ -205, -310, 588, 778, 785, 1065, 1118, 1245, 1157,
+ -173, -312, 107, 345, 400, 790, 870, 1113, 1001,
+ -7, -120, -387, -410, -614, -943, -226, -384, -491,
+ -203, -288, -51, -331, -90, -178, -408, -573, -338,
+ 56, -29, -273, -627, -1041, -798, -247, -467, 148,
+ 66, -2, -205, -205, -575, -349, -57, -352, -58,
+ -45, -225, -471, -924, -497, 77, -32, 44, -135,
+ -277, -491, -497, -502, -424, -202, -137, 77, 96,
+ 26, -179, -469, -1008, -1260, 262, -35, -132, -259,
+ -66, -232, -447, -533, -789, -191, -100, -267, 364};
+
+/*------------------------------------------------*
+ * 1st stage codebook; 2nd split: isf9 to isf15
+ *------------------------------------------------*/
+
+static Word16 dico2_isf[SIZE_BK2*7] = {
+
+ 1357, 1313, 1136, 784, 438, 181, 145,
+ 636, 648, 667, 568, 442, 217, 362,
+ 427, 440, 674, 524, 332, 117, -417,
+ 121, 295, 468, 465, 230, 44, -221,
+ -147, -240, 149, 80, 390, 278, 106,
+ -418, -556, 552, 511, 235, 144, -95,
+ 43, 193, 274, 150, 67, 34, -273,
+ -43, -126, 171, 416, 282, 63, -354,
+ -372, -86, -344, -108, -94, -182, -89,
+ -600, -840, -200, 465, 258, -11, -253,
+ -48, 329, 97, -290, -543, -795, -354,
+ -570, -117, 187, 10, -133, -416, -76,
+ -618, -129, -247, -371, 45, -76, 277,
+ -1022, -1079, 126, 474, 254, 127, 52,
+ -281, 76, -167, -361, -283, -551, -283,
+ -119, -52, -1, 134, -32, -204, -415,
+ 1064, 827, 637, 684, 464, 209, 12,
+ 482, 416, 449, 371, 335, 294, 194,
+ 719, 576, 365, 135, 113, 91, -199,
+ 298, 176, 493, 366, 194, 163, 36,
+ -35, -236, -259, -36, -4, 99, 152,
+ -98, -306, -27, 228, 90, 111, -86,
+ 91, 13, -211, -258, -106, 86, -64,
+ 73, -35, -57, -31, 162, 35, -192,
+ -109, -335, -629, -66, -61, -128, 322,
+ -495, -669, -728, 193, 31, -220, 122,
+ 324, 95, -89, -91, -409, -710, -154,
+ 0, -234, 92, 33, -343, -609, -220,
+ -343, -408, -476, -655, -153, 82, 222,
+ -490, -745, -255, 49, -48, 135, -127,
+ 119, -67, -328, -390, -272, -545, -56,
+ -57, -130, -10, -7, -164, -47, -22,
+ 984, 1064, 961, 568, 210, -27, 16,
+ 811, 691, 754, 514, 224, -35, 166,
+ 662, 704, 618, 386, 57, -211, -257,
+ 510, 359, 418, 393, 91, -144, -18,
+ -193, -31, -27, 223, 89, -143, 24,
+ -112, -98, 471, 319, 185, 3, 175,
+ 252, 146, -47, 272, 48, -211, -234,
+ 146, 69, 203, 364, 68, -52, 51,
+ -259, -478, -697, -349, -758, -501, 63,
+ -501, -769, -289, 79, -311, -497, -106,
+ 251, 53, -235, -469, -895, -884, 145,
+ -416, -551, 140, -133, -523, -775, 44,
+ -326, -423, -713, -497, -86, -431, 99,
+ -757, -772, -160, -76, -46, -32, 379,
+ 85, -35, -200, -401, -663, -1040, -247,
+ -180, -330, -92, -376, 27, -183, -110,
+ 1279, 1086, 781, 502, 324, 164, 157,
+ 682, 466, 449, 277, 146, 28, 409,
+ 635, 472, 390, 107, -232, -538, -139,
+ 196, 396, 332, 213, 209, -29, -81,
+ 150, -95, -312, 76, -77, -320, -50,
+ 46, 9, 47, 175, 139, 30, 384,
+ 218, 206, -24, -250, -96, -276, -183,
+ 26, 119, 38, 14, -4, -133, -52,
+ -477, -614, -987, -715, -631, -813, 200,
+ -744, -1009, -1065, -745, -631, -171, 18,
+ -137, -251, -483, -613, -980, -1203, 12,
+ -605, -767, -562, -686, -1088, -515, 58,
+ -202, -428, -782, -1072, -96, -234, -179,
+ -480, -709, -1070, -897, -131, -92, 321,
+ -145, -193, -512, -729, -572, -765, -210,
+ -331, -585, -525, -631, -281, -208, -303,
+ 1165, 1104, 939, 828, 716, 426, 155,
+ 6, -109, 820, 778, 415, 113, -27,
+ 381, 339, 314, 265, 121, -9, -474,
+ -373, 47, 584, 442, 99, -231, -113,
+ -496, -38, -285, 262, 305, 170, 4,
+ -587, -556, 69, 66, 471, 354, 13,
+ -138, 70, -18, 106, 67, 167, -302,
+ -445, -141, 185, 191, 151, 83, -133,
+ -257, -521, -720, -198, 134, -46, -182,
+ -819, -1168, -777, 512, 359, 95, -113,
+ 137, -2, -74, -138, -401, -114, -371,
+ -242, -466, 204, 223, -31, -212, -192,
+ -532, -637, -466, -686, 256, 277, -139,
+ -1141, -1244, -381, -75, -54, 14, 88,
+ -311, 115, -143, -499, -343, 124, -416,
+ -616, -147, -135, 43, -4, 121, -369,
+ 835, 783, 641, 390, 355, 350, 64,
+ 72, 194, 443, 467, 436, 219, 372,
+ 464, 369, 192, 4, -156, -72, -226,
+ 57, 206, 303, 205, 188, 101, 265,
+ -40, -205, -488, -184, 276, 64, -26,
+ -217, -433, -297, 137, 328, 308, -289,
+ 378, 81, -308, -465, 57, -37, 227,
+ -100, 24, -36, -151, 199, 8, 143,
+ -426, -697, -1059, -133, 388, 161, 321,
+ -644, -1023, -1271, 39, 66, -123, 70,
+ 372, 177, -173, -556, -553, -304, -189,
+ -117, -369, -425, -122, -462, -152, -73,
+ -649, -850, -1189, -767, 497, 360, 222,
+ -798, -1139, -1455, -190, 430, 234, 179,
+ 42, -94, -405, -692, 38, -202, -246,
+ -169, -366, -290, -88, -64, 32, -292,
+ 1010, 923, 938, 710, 465, 230, 342,
+ 217, 300, 1054, 675, 68, -458, -179,
+ 78, 453, 316, 18, -237, -496, -243,
+ 167, 21, 424, 215, -91, -303, -170,
+ -290, -81, -70, -67, 40, 54, -59,
+ -353, -427, -90, 53, 94, 9, 54,
+ -28, 318, 283, 15, -240, -58, 79,
+ -75, -121, 229, 35, 58, 6, -133,
+ -351, -514, -744, -834, -705, -137, 164,
+ -1124, -1388, -1055, -230, -73, 40, 36,
+ -163, -233, -532, -785, -1170, -697, 96,
+ -788, -959, -246, -430, -624, -165, -8,
+ -856, -540, -630, -907, -337, -70, 76,
+ -937, -1042, -659, -733, -208, 199, -26,
+ -523, 78, -98, -501, -869, -890, -81,
+ -624, -703, -45, -348, -25, 87, -186,
+ 1005, 823, 546, 249, 90, -22, 207,
+ 298, 397, 381, 319, 200, 62, 303,
+ 473, 379, 133, -247, -632, -441, 75,
+ 284, 208, 391, 115, -25, 44, 95,
+ -72, 79, -95, -63, -129, -293, 203,
+ -164, -349, 115, 122, 69, -1, 378,
+ 348, 170, 99, 58, -179, -302, 188,
+ -190, -2, 150, 23, -51, -11, 216,
+ -615, -863, -1090, -1427, -802, -48, -6,
+ -961, -1276, -1548, -727, -58, 56, 223,
+ -124, -255, -561, -988, -1277, -148, -82,
+ -480, -660, -891, -1191, -1339, -325, 20,
+ -621, -917, -1296, -1350, 264, 289, 50,
+ -844, -1022, -1345, -1329, -293, 46, 278,
+ -260, -468, -829, -1176, -533, -560, -78,
+ -215, -484, -822, -1233, -791, 15, -138,
+ 1301, 1317, 1262, 1048, 716, 357, -64,
+ 578, 824, 925, 802, 630, 362, 102,
+ 470, 925, 767, 514, 327, 190, -112,
+ 225, 492, 495, 437, 598, 384, -45,
+ 43, 82, -42, 175, 519, 342, -64,
+ -304, -154, 159, 576, 403, 221, 327,
+ 214, 244, 122, -62, 312, 92, -160,
+ 218, 208, 310, 268, 306, 323, -199,
+ -285, -269, -79, -124, -143, -153, 236,
+ -205, -384, -426, 344, 59, -185, -184,
+ -272, 247, 126, -210, -518, -468, 78,
+ -99, -120, 502, 160, -280, -557, 304,
+ -423, -17, -283, -443, 215, 212, -140,
+ -564, -684, -228, 510, 361, 130, 323,
+ -428, 335, 98, -65, 36, -215, -246,
+ -362, 51, 364, -16, -234, 150, -165,
+ 914, 883, 751, 653, 676, 464, -153,
+ 631, 545, 535, 720, 596, 360, -81,
+ 783, 712, 512, 439, 341, 251, -391,
+ 497, 417, 249, 372, 295, 173, -193,
+ 128, -110, -385, 93, 39, 173, -231,
+ 216, -59, -253, 462, 389, 154, 69,
+ 455, 270, -4, -337, -49, 233, -322,
+ 307, 143, 53, 218, 128, 236, -156,
+ -37, -186, -240, -411, -110, 9, 399,
+ -140, -365, -628, 258, 380, 214, 277,
+ 131, 454, 177, -285, -520, 108, -214,
+ 77, -141, 201, -123, -490, -131, 60,
+ -14, -194, -521, -741, 273, 362, -33,
+ -362, -566, -287, -228, 161, 237, 317,
+ -269, 195, -75, -375, -204, 11, 77,
+ -128, -264, -156, -223, -475, 265, 27,
+ 1238, 1147, 916, 689, 432, 210, -280,
+ 800, 664, 879, 726, 411, 160, -164,
+ 454, 686, 536, 275, 147, 46, 111,
+ 303, 486, 512, 355, 241, 181, -69,
+ 79, 92, 29, 147, 233, 52, 17,
+ -171, 289, 131, 439, 271, 3, -10,
+ 413, 241, 144, 174, 155, -2, 14,
+ 58, 217, 247, 219, 149, 175, -18,
+ 228, -8, -240, -206, -513, -191, 202,
+ -96, -272, -454, 33, -300, -575, 46,
+ -10, -108, -246, -347, -770, -535, 9,
+ -326, -430, -61, -321, -704, -299, 201,
+ -1, -280, -603, -419, -185, 18, -36,
+ -516, -522, -379, -291, -181, -97, 27,
+ -159, -313, -525, -224, -510, -831, -197,
+ -292, -459, -59, -310, -562, -143, -351,
+ 1066, 912, 631, 389, 207, 86, -224,
+ 596, 512, 596, 505, 314, 122, -48,
+ 787, 861, 441, -93, -303, 33, -190,
+ 257, 469, 337, 51, 15, 298, -93,
+ 295, 73, -119, 25, 36, 23, 108,
+ -28, -3, -32, 114, 21, 185, 107,
+ 482, 305, 15, -279, -319, 52, 96,
+ 226, 46, 115, 72, -136, 133, -125,
+ 18, -207, -559, -590, -503, -482, 321,
+ -571, -789, -951, -172, -441, -538, 113,
+ 181, 14, -310, -641, -1001, -202, 159,
+ -136, -393, -433, -513, -911, -144, -22,
+ 72, -265, -706, -954, -159, 53, 332,
+ -338, -591, -852, -383, -395, 56, 44,
+ 43, -158, -464, -897, -631, -157, -294,
+ -161, -128, -328, -573, -483, -125, 11,
+ 1017, 906, 1051, 1005, 679, 341, -102,
+ 359, 334, 1567, 1314, 723, 105, 10,
+ -65, 726, 529, 301, 220, 43, -273,
+ -510, 436, 719, 566, 358, 179, 114,
+ -560, 298, 133, -120, 342, 225, 14,
+ -899, -101, 217, 617, 400, 146, -58,
+ -41, 352, 82, -196, 39, 121, -167,
+ -212, 59, 447, 284, 423, 250, -169,
+ -371, -484, -596, 30, -41, 249, 22,
+ -372, -650, -794, 477, 445, 216, -79,
+ -352, 275, 17, -443, -929, 92, 19,
+ -699, -696, 431, 264, -49, -310, 182,
+ -978, -217, -430, -400, 101, 261, 72,
+ -929, -889, -357, -13, 463, 378, 236,
+ -826, 56, 30, -299, -360, -128, -51,
+ -878, -299, -111, 75, 65, 36, 3,
+ 817, 368, -25, 354, 697, 591, -173,
+ 309, 212, 222, 751, 484, 140, -56,
+ 593, 379, 70, -8, 258, 180, 110,
+ 165, -46, 255, 297, 219, 273, 105,
+ 160, -70, -358, -181, 379, 330, 319,
+ -238, -369, -198, 740, 580, 319, -143,
+ 201, 109, -202, -456, 328, 276, -141,
+ 203, 170, 111, 42, 207, 360, 188,
+ -345, -399, -513, -233, 650, 422, 81,
+ -635, -961, -1220, 463, 539, 204, 209,
+ 202, -25, -194, -498, -787, 193, -143,
+ -449, -538, 195, -106, -331, 68, 62,
+ -228, -477, -840, -576, 317, 128, 283,
+ -671, -937, -807, -114, 391, 335, -62,
+ 246, 2, -314, -679, -303, 180, -88,
+ -107, -272, 90, -198, -28, 290, -112,
+ 885, 1149, 1021, 712, 496, 281, -83,
+ 269, 492, 787, 643, 347, 70, 124,
+ 336, 636, 499, 92, -229, -179, 191,
+ 26, 402, 564, 340, 149, -11, 135,
+ -440, 561, 470, 204, -72, -186, 140,
+ -720, 14, 355, 229, 68, -133, 465,
+ 110, 310, 103, 12, 106, 29, 158,
+ -178, 113, 161, 142, 121, 115, 27,
+ -651, -414, -645, -152, -164, -13, -429,
+ -639, -944, -681, -104, -81, 52, -189,
+ -663, -164, -316, -683, -954, -205, -83,
+ -609, -669, -172, -517, -694, 283, -80,
+ -646, -152, -383, -678, -246, -40, -143,
+ -747, -796, -745, -390, -98, 43, 275,
+ -599, -199, -398, -433, -436, -538, 31,
+ -1107, -568, -376, -265, -126, -21, 1,
+ 847, 573, 308, 392, 305, 101, 55,
+ 273, 293, 201, 267, 346, 201, 123,
+ 727, 480, 226, 2, -65, -138, 164,
+ 273, 208, 173, 292, 12, 253, 174,
+ 340, 207, 180, 88, 116, 46, 475,
+ -460, -166, -30, 13, 110, 173, 396,
+ 137, 88, 43, -137, -94, 34, 284,
+ 96, -14, 226, 40, 63, 70, 130,
+ -467, -735, -1012, -1174, -307, 305, -67,
+ -612, -920, -1146, -567, -8, 92, -25,
+ -182, -271, -492, -754, -857, 287, -75,
+ -494, -787, -689, -683, -709, 137, -326,
+ -288, -550, -903, -1105, 334, 321, -62,
+ -354, -653, -834, -445, 1, 377, -152,
+ -162, -306, -608, -937, -297, 247, -192,
+ -234, -477, -244, -488, -266, 342, -332};
+
+/*---------------------------------------------------*
+ * 2nd stage codebook; 1st split: isf2_0 to isf2_2
+ *---------------------------------------------------*/
+
+
+static Word16 dico21_isf[SIZE_BK21*3] = {
+
+ 329, 409, 249,
+ -33, 505, 160,
+ -29, -14, 582,
+ -262, 127, 354,
+ 145, 237, 175,
+ -152, 245, 122,
+ 27, 42, 340,
+ -84, -93, 311,
+ 285, 222, -156,
+ 47, -43, -504,
+ 234, 121, 385,
+ 104, -317, 45,
+ 176, 195, 8,
+ 104, -59, -94,
+ 177, 53, 192,
+ -34, -127, 152,
+ 570, 277, -34,
+ -67, -329, -639,
+ -157, -272, 462,
+ -177, -462, 198,
+ 322, 179, 115,
+ -386, 171, 19,
+ 19, -12, 195,
+ -120, -252, 201,
+ 304, 36, -336,
+ -128, -221, -380,
+ 171, -185, 296,
+ -242, -312, 23,
+ 198, 39, 16,
+ -3, -177, -111,
+ 111, -93, 76,
+ -92, -223, 4,
+ 177, 406, -44,
+ -168, 380, -149,
+ -4, 273, 331,
+ -420, 513, 277,
+ 21, 247, 47,
+ -58, 131, -2,
+ -3, 134, 180,
+ -145, 40, 175,
+ 189, 74, -145,
+ -27, -45, -325,
+ 370, -114, -21,
+ -83, -415, -173,
+ 77, 95, -51,
+ -40, -30, -67,
+ 71, 88, 86,
+ -35, -98, 14,
+ 69, 197, -334,
+ -196, 79, -231,
+ -348, -137, 218,
+ -352, -89, -85,
+ 47, 201, -130,
+ -165, 37, -15,
+ -43, 3, 86,
+ -161, -108, 79,
+ 83, 21, -237,
+ -81, -149, -238,
+ 150, -186, -251,
+ -186, -249, -162,
+ -19, 66, -139,
+ -26, -50, -181,
+ 24, 11, 0,
+ -130, -105, -98};
+
+
+
+/*---------------------------------------------------*
+ * 2nd stage codebook; 2nd split: isf2_3 to isf2_5
+ *---------------------------------------------------*/
+
+
+static Word16 dico22_isf[SIZE_BK22*3] = {
+
+ -127, 310, 42,
+ -242, 197, 5,
+ -151, 84, -17,
+ -214, 127, -149,
+ -247, -131, 159,
+ -268, -267, -95,
+ -217, 1, -79,
+ -271, -80, -185,
+ -45, 436, 159,
+ 165, 199, 391,
+ -33, 81, 187,
+ -66, -42, 355,
+ -298, -57, 343,
+ -108, -537, 226,
+ -144, -23, 193,
+ 176, -402, 87,
+ 53, 296, 25,
+ -84, 253, -104,
+ -58, 105, -126,
+ -169, 174, -314,
+ -48, 44, -294,
+ -164, -417, -242,
+ -139, 3, -194,
+ -155, -207, -211,
+ 119, 322, 213,
+ 333, 50, 380,
+ 237, 247, -2,
+ 466, -16, 201,
+ 238, -255, -107,
+ 67, -440, -149,
+ 122, -88, -139,
+ 88, -247, -73,
+ -41, 231, 167,
+ -62, 155, 16,
+ -65, 16, 77,
+ -68, -2, -63,
+ -151, -300, 160,
+ -18, -333, 54,
+ -56, -94, 5,
+ 2, -190, 14,
+ 92, 148, 209,
+ 108, 9, 272,
+ 108, 35, 110,
+ 142, -85, 145,
+ 47, -157, 279,
+ 3, -320, 246,
+ 43, -72, 68,
+ 86, -217, 135,
+ 36, 140, 79,
+ 56, 175, -49,
+ 26, 45, 3,
+ 73, 55, -101,
+ 109, -183, -242,
+ -4, -283, -242,
+ 48, -68, -48,
+ -6, -153, -122,
+ 161, 196, 96,
+ 232, 80, 190,
+ 165, 97, 11,
+ 258, -31, 71,
+ 267, -77, -91,
+ 311, -209, 87,
+ 152, -14, -22,
+ 150, -149, 9,
+ -324, 557, 187,
+ -384, 307, 46,
+ -251, 27, 77,
+ -365, 77, -52,
+ -482, -84, 160,
+ -424, -515, -64,
+ -294, -120, -4,
+ -476, -116, -109,
+ -97, 318, 365,
+ 106, 627, 445,
+ -190, 120, 287,
+ -146, 65, 619,
+ -427, 242, 363,
+ -361, -371, 432,
+ -347, 102, 168,
+ -629, 195, -14,
+ -65, 476, -47,
+ -297, 320, -168,
+ -55, 356, -264,
+ -391, 82, -286,
+ -51, -31, -556,
+ -178, -399, -586,
+ -205, -49, -360,
+ -343, -238, -337,
+ 220, 457, 58,
+ 561, 467, 259,
+ 340, 270, -168,
+ 450, 77, -280,
+ 60, 167, -413,
+ 133, -252, -492,
+ 216, 157, -290,
+ 282, 0, -495,
+ -226, 293, 183,
+ -157, 135, 122,
+ -158, -59, 39,
+ -133, -118, -97,
+ -332, -309, 113,
+ -160, -425, -6,
+ -149, -211, 24,
+ -80, -277, -90,
+ -11, 125, 338,
+ 130, -71, 465,
+ 5, -45, 184,
+ 237, -95, 253,
+ -139, -197, 297,
+ -19, -300, 511,
+ -63, -152, 139,
+ 250, -289, 336,
+ 124, 339, -150,
+ 34, 176, -208,
+ 171, 166, -116,
+ 94, 38, -229,
+ 75, -65, -339,
+ -78, -205, -385,
+ 0, -30, -163,
+ -56, -110, -242,
+ 321, 244, 194,
+ 505, 238, -1,
+ 317, 116, 65,
+ 309, 88, -74,
+ 452, -51, -50,
+ 334, -217, -290,
+ 211, 41, -152,
+ 238, -55, -260};
+
+
+/*---------------------------------------------------*
+ * 2nd stage codebook; 3rd split: isf2_6 to isf2_8
+ *---------------------------------------------------*/
+
+
+static Word16 dico23_isf[SIZE_BK23*3] = {
+
+ -10, 151, 359,
+ 136, 298, 223,
+ 255, -104, 290,
+ 423, 6, 183,
+ -270, -269, -98,
+ -52, -82, 13,
+ -82, -274, -97,
+ 90, -246, -72,
+ -299, -70, 421,
+ -88, 365, 430,
+ 187, -318, 381,
+ 380, 37, 488,
+ -373, -316, 79,
+ -308, -101, 5,
+ -135, -451, 8,
+ 72, -421, -154,
+ 180, 170, -121,
+ 62, 177, -40,
+ 326, 80, -105,
+ 248, 263, -5,
+ -168, -181, -221,
+ -2, -23, -158,
+ -14, -149, -121,
+ 119, -91, -147,
+ 119, 332, -153,
+ 49, 303, 34,
+ 442, -55, -69,
+ 217, 454, 58,
+ -359, -187, -375,
+ -42, 50, -274,
+ -8, -267, -249,
+ 85, -86, -346,
+ -77, -40, 345,
+ 89, 134, 219,
+ 156, -80, 160,
+ 108, 40, 116,
+ -158, -206, 29,
+ 5, -32, 175,
+ -65, -158, 146,
+ 55, -78, 73,
+ -114, -222, 353,
+ -47, 81, 211,
+ 49, -151, 268,
+ 105, 4, 302,
+ -263, -132, 183,
+ -151, -28, 201,
+ -177, -307, 166,
+ 101, -221, 130,
+ 74, 58, -98,
+ 32, 44, 13,
+ 194, 30, -142,
+ 170, 96, 8,
+ -136, -119, -91,
+ -65, 8, -55,
+ 3, -188, 12,
+ 45, -63, -49,
+ 149, -21, -19,
+ 24, 144, 95,
+ 254, -22, 60,
+ 161, 196, 96,
+ -158, -61, 48,
+ -70, 33, 82,
+ -23, -321, 58,
+ 155, -147, 5,
+ -364, 328, 77,
+ -21, 453, 173,
+ -108, 82, 630,
+ 367, 263, 208,
+ -300, -62, -176,
+ -205, 143, -158,
+ -169, -410, -264,
+ 257, -269, -100,
+ -636, 289, -2,
+ -292, 627, 173,
+ -382, -363, 387,
+ 248, 524, 447,
+ -521, -111, -107,
+ -395, 118, -274,
+ -343, -680, -125,
+ -172, -447, -663,
+ 75, 148, -367,
+ -79, 263, -94,
+ 249, 148, -286,
+ 380, 271, -162,
+ -142, -4, -186,
+ -57, 111, -125,
+ -35, -108, -254,
+ 100, 29, -242,
+ -80, 303, -264,
+ -78, 464, -57,
+ 248, -22, -494,
+ 661, 662, 44,
+ -193, -40, -330,
+ -178, 145, -337,
+ -90, -199, -400,
+ -40, -23, -498,
+ -192, 114, 315,
+ -41, 244, 190,
+ 88, -97, 485,
+ 241, 80, 212,
+ -246, 40, 87,
+ -156, 147, 134,
+ -2, -334, 239,
+ 308, -203, 110,
+ -459, 251, 422,
+ -218, 310, 228,
+ -86, -346, 654,
+ 184, 175, 425,
+ -481, -63, 169,
+ -349, 117, 188,
+ -125, -560, 310,
+ 158, -416, 94,
+ 46, 171, -192,
+ -63, 157, 14,
+ 256, -35, -271,
+ 322, 123, 53,
+ -214, 4, -76,
+ -156, 86, -18,
+ 128, -197, -232,
+ 265, -90, -98,
+ -308, 332, -145,
+ -131, 308, 58,
+ 509, 59, -339,
+ 562, 196, -14,
+ -378, 100, -47,
+ -234, 202, 1,
+ 104, -270, -493,
+ 319, -210, -325};
+
+
+/*---------------------------------------------------*
+ * 2nd stage codebook; 4th split: isf2_9 to isf2_11
+ *---------------------------------------------------*/
+
+static Word16 dico24_isf[SIZE_BK24*3] = {
+
+ -79, -89, -4,
+ -171, 77, -211,
+ 160, -193, 98,
+ 120, -103, 323,
+ 32, -22, -129,
+ 72, 78, -268,
+ 182, -76, -66,
+ 309, 99, -145,
+ -229, -157, -84,
+ -383, 98, -71,
+ -90, -352, 12,
+ -284, -178, 178,
+ -65, -125, -166,
+ -87, -175, -351,
+ 42, -198, -48,
+ 154, -140, -243,
+ -77, 18, 108,
+ -39, 355, 91,
+ 87, 8, 155,
+ -4, 158, 239,
+ 128, 95, -54,
+ 7, 246, -124,
+ 258, 15, 89,
+ 206, 216, 98,
+ -201, 9, 18,
+ -312, 233, 204,
+ -39, -174, 155,
+ -144, -9, 284,
+ -57, 70, -69,
+ -157, 187, 18,
+ 54, -30, 23,
+ 24, 135, 55};
+
+
+/*---------------------------------------------------*
+ * 2nd stage codebook; 5th split: isf2_12 to isf2_15
+ *---------------------------------------------------*/
+
+static Word16 dico25_isf[SIZE_BK25*4] = {
+
+ 169, 142, -119, 115,
+ 206, -20, 94, 226,
+ -106, 313, -21, 16,
+ -62, 161, 71, 255,
+ -89, 101, -185, 125,
+ 72, -30, -201, 344,
+ -258, 33, -8, 81,
+ -104, -154, 72, 296,
+ 144, -68, -268, -25,
+ 81, -78, -87, 106,
+ 22, 155, -186, -119,
+ -46, -28, 27, 91,
+ -114, -37, -175, -33,
+ -94, -222, -189, 122,
+ -132, -119, -191, -270,
+ -172, -173, 18, -43,
+ 279, 135, -42, -128,
+ 187, -86, 229, -138,
+ 159, 240, 140, 46,
+ 69, 25, 227, 77,
+ 21, 115, 13, 8,
+ 68, -248, 126, 81,
+ -150, 137, 207, -9,
+ -154, -133, 289, 67,
+ 143, -37, -86, -326,
+ 180, -32, 19, -23,
+ 26, 168, 116, -233,
+ -32, -26, 118, -78,
+ 3, -8, -45, -115,
+ 57, -215, -54, -83,
+ -209, 112, -22, -167,
+ -91, -151, 168, -262};
+
+
+
+ /* 36 bit */
+/*-------------------------------------------------------------------*
+ * isf codebooks: two-stage VQ with split-by-3 in 2nd stage *
+ * 1st stage is kept the same as the 46 bit quantizer *
+ * *
+ * codebook vector dimension number of vectors *
+ * ~~~~~~~~ ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ *
+ * 1_1 9 256 *
+ * 1_2 7 256 *
+ * 2_1 5 128 *
+ * 2_2 4 128 *
+ * 2_3 7 64 *
+ *-------------------------------------------------------------------*/
+
+static Word16 dico21_isf_36b[SIZE_BK21_36b*5] = {
+
+ -52, -96, 212, 315, -73,
+ 82, -204, 363, 136, -197,
+ -126, -331, 183, 218, 143,
+ -49, -41, 557, 230, 72,
+ 2, -73, 163, 377, 221,
+ 133, 111, 278, 215, -110,
+ -102, -20, 284, 113, 273,
+ 84, 319, 290, 18, 85,
+ -25, -5, 125, 132, -204,
+ -38, -5, 286, -9, -356,
+ -140, -256, 92, 117, -189,
+ -144, 191, 313, 51, -98,
+ 167, -10, 44, 247, 36,
+ 381, 197, 238, 74, 6,
+ 38, -408, 29, -3, -85,
+ 92, 266, 157, -25, -200,
+ 161, -121, 70, 84, -140,
+ -16, -86, 112, -94, -189,
+ -269, -270, 351, 107, -24,
+ -68, -67, 492, -103, -155,
+ -53, -131, 62, 122, 10,
+ 135, 84, 283, -55, -120,
+ -12, -219, 331, -81, 167,
+ 220, -136, 147, -172, -42,
+ 140, -95, -109, -88, -194,
+ 0, -2, -4, -33, -381,
+ -66, -217, 152, -186, -402,
+ 244, 108, 156, -140, -395,
+ 113, -136, -196, 110, -24,
+ 214, 118, 11, -64, -131,
+ -110, -286, -6, -332, 16,
+ 94, 97, 79, -291, -205,
+ -5, -39, -20, 252, -96,
+ 76, 174, 101, 163, 61,
+ -69, -239, -55, 399, 6,
+ -115, 319, 164, 275, 196,
+ -15, 36, -47, 331, 121,
+ 226, 209, 271, 325, 184,
+ 13, -80, -218, 471, 353,
+ 288, 378, 16, -51, 251,
+ 174, 116, 52, 149, -279,
+ 235, 276, 39, 120, -48,
+ 0, -108, -108, 241, -339,
+ -93, 534, 45, 33, -87,
+ 194, 149, -71, 405, -44,
+ 409, 370, 81, -186, -154,
+ 25, -102, -448, 124, -173,
+ 22, 408, -110, -310, -214,
+ -26, 23, -83, 114, 14,
+ -110, 164, 52, 223, -82,
+ 37, -25, -263, 306, -15,
+ -466, 415, 292, 165, -18,
+ 29, -19, -171, 155, 182,
+ 179, 144, -27, 231, 258,
+ -103, -247, -396, 238, 113,
+ 375, -154, -109, -4, 156,
+ 98, 85, -292, -5, -124,
+ 116, 139, -116, -98, -294,
+ -14, -83, -278, -117, -378,
+ 106, 33, -106, -344, -484,
+ 119, 17, -412, 138, 166,
+ 384, 101, -204, 88, -156,
+ -121, -284, -300, -1, -166,
+ 280, 33, -152, -313, -81,
+ -37, 22, 229, 153, 37,
+ -60, -83, 236, -8, -41,
+ -169, -228, 126, -20, 363,
+ -235, 17, 364, -156, 156,
+ -25, -30, 72, 144, 156,
+ 153, -26, 256, 97, 144,
+ -21, -37, 48, -65, 250,
+ 63, 77, 273, -128, 124,
+ -129, -26, 40, 9, -115,
+ -6, 82, 38, -90, -182,
+ -336, -13, 28, 158, 91,
+ -30, 241, 137, -170, -17,
+ 146, 14, -11, 33, 61,
+ 192, 197, 54, -84, 85,
+ 23, -200, -78, -29, 140,
+ 122, 237, 106, -341, 136,
+ -57, -142, -85, -16, -74,
+ -59, -90, -8, -187, -20,
+ -211, -267, 216, -179, -110,
+ -50, -7, 220, -267, -70,
+ -57, -42, -17, -15, 71,
+ 32, 21, 63, -137, 33,
+ -137, -175, 104, -68, 97,
+ -67, -43, 133, -301, 221,
+ -116, -200, -81, -92, -272,
+ -64, -41, -54, -244, -220,
+ -287, -242, -50, -87, -89,
+ -245, 236, 102, -166, -295,
+ 66, 24, -162, -71, 95,
+ 66, 136, -90, -220, -36,
+ -98, -161, -222, -188, 29,
+ -18, 18, -19, -415, 9,
+ 49, 61, 100, 39, -56,
+ -111, 82, 135, -31, 52,
+ -90, -153, -93, 189, 182,
+ -214, 295, 119, -74, 284,
+ 2, 137, 37, 47, 182,
+ 92, 117, 184, -53, 373,
+ -21, -14, -35, 136, 391,
+ 146, 129, -164, -28, 333,
+ 92, 80, -84, 100, -134,
+ -8, 217, -32, 3, -47,
+ -151, 251, -215, 142, 92,
+ -224, 310, -172, -275, 98,
+ 159, 155, -177, 112, 53,
+ 205, 27, 8, -240, 192,
+ 169, 120, -319, -201, 106,
+ 11, 36, -86, -237, 455,
+ -109, -154, -163, 174, -55,
+ -38, 32, -101, -78, -59,
+ -205, -321, -97, 69, 79,
+ -310, 44, 18, -185, 34,
+ -115, -20, -148, -39, 203,
+ -29, 154, -30, -158, 166,
+ -45, -131, -317, -24, 363,
+ -165, -205, -112, -222, 265,
+ -32, -44, -150, 54, -193,
+ -6, -38, -255, -169, -115,
+ -266, 87, -189, -36, -169,
+ -60, -87, -266, -436, -170,
+ -68, -81, -278, 24, 38,
+ -23, -19, -155, -256, 141,
+ -61, -226, -565, -175, 71,
+ 9, -29, -237, -515, 263};
+
+static Word16 dico22_isf_36b[SIZE_BK22_36b*4] = {
+
+ -298, -6, 95, 31,
+ -213, -87, -122, 261,
+ 4, -49, 208, 14,
+ -129, -110, 30, 118,
+ -214, 258, 110, -235,
+ -41, -18, -126, 120,
+ 103, 65, 127, -37,
+ 126, -36, -24, 25,
+ -138, -67, -278, -186,
+ -164, -194, -201, 78,
+ -211, -87, -51, -221,
+ -174, -79, -94, -39,
+ 23, -6, -157, -240,
+ 22, -110, -153, -68,
+ 148, -5, -2, -149,
+ -1, -135, -39, -179,
+ 68, 360, -117, -15,
+ 137, 47, -278, 146,
+ 136, 260, 135, 65,
+ 61, 116, -45, 97,
+ 231, 379, 87, -120,
+ 338, 177, -272, 3,
+ 266, 156, 28, -69,
+ 260, 84, -85, 86,
+ -266, 154, -256, -182,
+ -17, -65, -304, -6,
+ -40, 175, -151, -180,
+ -27, 27, -87, -63,
+ 121, 114, -166, -469,
+ 159, -66, -323, -231,
+ 214, 152, -141, -212,
+ 137, 36, -184, -51,
+ -282, -237, 40, 10,
+ -48, -235, -37, 251,
+ -54, -323, 136, 29,
+ -88, -174, 213, 198,
+ -390, 99, -63, -375,
+ 107, -169, -164, 424,
+ 69, -111, 141, -167,
+ 74, -129, 65, 144,
+ -353, -207, -205, -109,
+ -160, -386, -355, 98,
+ -176, -493, -20, -143,
+ -252, -432, -2, 216,
+ -90, -174, -168, -411,
+ 13, -284, -229, -160,
+ -87, -279, 34, -251,
+ -75, -263, -58, -42,
+ 420, 53, -211, -358,
+ 384, -35, -374, 396,
+ 68, -228, 323, -2,
+ 167, -307, 192, 194,
+ 459, 329, -5, -332,
+ 375, 79, -7, 313,
+ 282, -124, 200, -92,
+ 271, -162, -70, 180,
+ -157, -298, -514, -309,
+ 58, -163, -546, 18,
+ 124, -364, 167, -238,
+ 83, -411, -117, 96,
+ 140, -112, -388, -624,
+ 259, -133, -317, 41,
+ 163, -130, -64, -334,
+ 226, -165, -124, -110,
+ -466, -61, 6, 229,
+ -153, 205, -145, 242,
+ -159, 48, 195, 148,
+ -58, 28, 31, 279,
+ -303, 185, 279, -4,
+ -61, 197, 59, 86,
+ -114, 123, 168, -52,
+ 35, 36, 100, 126,
+ -407, 102, -77, -40,
+ -338, -1, -342, 156,
+ -179, 105, -34, -97,
+ -185, 84, -35, 108,
+ -133, 107, -91, -357,
+ -180, 54, -229, 24,
+ -44, 47, 47, -182,
+ -66, 13, 45, 4,
+ -339, 251, 64, 226,
+ -42, 101, -350, 275,
+ -99, 398, 142, 121,
+ 111, 12, -102, 260,
+ 0, 505, 260, -94,
+ 161, 285, -96, 224,
+ -4, 206, 314, 33,
+ 167, 139, 88, 204,
+ -235, 316, -60, -25,
+ -8, -150, -312, 201,
+ -36, 292, 61, -104,
+ -40, 174, -162, 42,
+ -21, 402, -29, -351,
+ 21, 152, -360, -93,
+ 57, 191, 212, -196,
+ 76, 158, -21, -69,
+ -328, -185, 331, 119,
+ -53, 285, 56, 337,
+ -107, -24, 405, 29,
+ -18, 137, 272, 277,
+ -255, 22, 173, -191,
+ 295, 322, 325, 302,
+ 21, -27, 332, -178,
+ 119, 13, 271, 129,
+ -455, -180, 116, -191,
+ -227, 62, -148, 524,
+ -176, -287, 282, -157,
+ -243, 13, 199, 430,
+ -59, -49, 115, -365,
+ 72, -172, -137, 93,
+ -138, -126, 141, -84,
+ 5, -124, 38, -20,
+ -258, 311, 601, 213,
+ 94, 130, -61, 502,
+ -1, -157, 485, 313,
+ 146, -74, 158, 345,
+ 276, 135, 280, -57,
+ 490, 252, 99, 43,
+ 267, -74, 429, 105,
+ 278, -23, 119, 94,
+ -542, 488, 257, -115,
+ -84, -244, -438, 478,
+ -113, -545, 387, 101,
+ -95, -306, 111, 498,
+ 95, 166, 22, -301,
+ 420, -15, -58, -78,
+ 270, 29, 122, -282,
+ 160, -240, 50, -38};
+
+static Word16 dico23_isf_36b[SIZE_BK23_36b*7] = {
+
+ 81, -18, 68, -27, -122, -280, -4,
+ 45, -177, 209, -30, -136, -74, 131,
+ -44, 101, -75, -88, -48, -137, -54,
+ -245, -28, 63, -18, -112, -103, 58,
+ -79, -6, 220, -65, 114, -35, -50,
+ 109, -65, 143, -114, 129, 76, 125,
+ 166, 90, -61, -242, 186, -74, -43,
+ -46, -92, 49, -227, 24, -155, 39,
+ 67, 85, 99, -42, 53, -184, -281,
+ 142, -122, 0, 21, -142, -15, -17,
+ 223, 92, -21, -48, -82, -14, -167,
+ 51, -37, -243, -30, -90, 18, -56,
+ 54, 105, 74, 86, 69, 13, -101,
+ 196, 72, -89, 43, 65, 19, 39,
+ 121, 34, 131, -82, 25, 213, -156,
+ 101, -102, -136, -21, 57, 214, 22,
+ 36, -124, 205, 204, 58, -156, -83,
+ 83, -117, 137, 137, 85, 116, 44,
+ -92, -148, -68, 11, -102, -197, -220,
+ -76, -185, -58, 132, -26, -183, 85,
+ -7, -31, -2, 23, 205, -151, 10,
+ -27, -37, -5, -18, 292, 131, 1,
+ 117, -168, 9, -93, 80, -59, -125,
+ -182, -244, 98, -24, 135, -22, 94,
+ 221, 97, 106, 42, 43, -160, 83,
+ 25, -64, -21, 6, 14, -15, 154,
+ 126, 15, -140, 150, -10, -207, -114,
+ 79, -63, -211, -70, -28, -217, 165,
+ 46, 38, -22, 281, 132, -62, 109,
+ 112, 54, -112, -93, 208, 27, 296,
+ 115, 10, -147, 41, 216, 42, -276,
+ 50, -115, -254, 167, 117, -2, 61,
+ 17, 144, 34, -72, -186, -150, 272,
+ -29, -66, -89, -95, -149, 129, 251,
+ 122, 0, -50, -234, -91, 36, 26,
+ -105, -102, -88, -121, -236, -7, -11,
+ -204, 109, 5, -191, 105, -15, 163,
+ -80, 32, -24, -209, 41, 294, 70,
+ -106, -94, -204, -118, 120, -50, -37,
+ -82, -241, 46, -131, -29, 150, -55,
+ 33, 155, 120, -89, -8, 7, 62,
+ 213, 82, 61, 18, -161, 144, 152,
+ 30, 131, 65, -87, -255, -17, -107,
+ -8, 85, -64, 51, -162, 223, -53,
+ -134, 261, 69, -56, 218, 72, -111,
+ 2, 155, -113, -87, 49, 85, -28,
+ -163, 42, -1, -196, 7, 39, -245,
+ 14, -137, -79, 11, -160, 202, -293,
+ -94, 33, 208, 100, 56, -44, 326,
+ -78, -41, 232, 13, -142, 227, 80,
+ -16, -87, 201, 33, -133, 15, -183,
+ -58, -192, -47, 184, -128, 133, 99,
+ -205, 11, -155, 78, 52, 72, 141,
+ -246, 26, 99, 151, 59, 115, -64,
+ -79, -47, -16, -14, 6, 47, -43,
+ -72, -178, -27, 162, 112, 43, -174,
+ -175, 238, 186, 71, -54, -188, -76,
+ -225, 233, 39, -39, -158, 122, 44,
+ -26, 43, 84, 130, -93, -51, 22,
+ 3, 92, -150, 136, -182, -57, 97,
+ -131, 179, -78, 80, 91, -165, 90,
+ -2, 148, 15, 130, 65, 175, 117,
+ -138, 114, -137, 132, 3, -10, -186,
+ 140, -4, -37, 254, -62, 92, -109};
+
+
--- /dev/null
+++ b/amr-wb/random.c
@@ -1,0 +1,19 @@
+/*-------------------------------------------------------------------*
+ * RANDOM.C *
+ *-------------------------------------------------------------------*
+ * Signed 16 bits random generator. *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+
+Word16 Random(Word16 * seed)
+{
+ /* static Word16 seed = 21845; */
+
+ *seed = extract_l(L_add(L_shr(L_mult(*seed, 31821), 1), 13849L)); move16();
+
+ return (*seed);
+}
--- /dev/null
+++ b/amr-wb/residu.c
@@ -1,0 +1,35 @@
+/*-----------------------------------------------------------------------*
+ * RESIDU.C *
+ *-----------------------------------------------------------------------*
+ * Compute the LPC residual by filtering the input speech through A(z) *
+ *-----------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+
+void Residu(
+ Word16 a[], /* (i) Q12 : prediction coefficients */
+ Word16 m, /* (i) : order of LP filter */
+ Word16 x[], /* (i) : speech (values x[-m..-1] are needed */
+ Word16 y[], /* (o) x2 : residual signal */
+ Word16 lg /* (i) : size of filtering */
+)
+{
+ Word16 i, j;
+ Word32 s;
+
+ for (i = 0; i < lg; i++)
+ {
+ s = L_mult(x[i], a[0]);
+
+ for (j = 1; j <= m; j++)
+ s = L_mac(s, a[j], x[i - j]);
+
+ s = L_shl(s, 3 + 1); /* saturation can occur here */
+ y[i] = round(s); move16();
+ }
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/scale.c
@@ -1,0 +1,29 @@
+/*-------------------------------------------------------------------*
+ * SCALE.C *
+ *-------------------------------------------------------------------*
+ * Scale signal to get maximum of dynamic. *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+
+void Scale_sig(
+ Word16 x[], /* (i/o) : signal to scale */
+ Word16 lg, /* (i) : size of x[] */
+ Word16 exp /* (i) : exponent: x = round(x << exp) */
+)
+{
+ Word16 i;
+ Word32 L_tmp;
+
+ for (i = 0; i < lg; i++)
+ {
+ L_tmp = L_deposit_h(x[i]);
+ L_tmp = L_shl(L_tmp, exp); /* saturation can occur here */
+ x[i] = round(L_tmp); move16();
+ }
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/syn_filt.c
@@ -1,0 +1,107 @@
+/*-------------------------------------------------------------------*
+ * SYN_FILT.C *
+ *-------------------------------------------------------------------*
+ * Do the synthesis filtering 1/A(z). *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "math_op.h"
+#include "count.h"
+#include "cnst.h"
+
+
+void Syn_filt(
+ Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */
+ Word16 m, /* (i) : order of LP filter */
+ Word16 x[], /* (i) : input signal */
+ Word16 y[], /* (o) : output signal */
+ Word16 lg, /* (i) : size of filtering */
+ Word16 mem[], /* (i/o) : memory associated with this filtering. */
+ Word16 update /* (i) : 0=no update, 1=update of memory. */
+)
+{
+ Word16 i, j, y_buf[L_SUBFR16k + M16k], a0, s;
+ Word32 L_tmp;
+ Word16 *yy;
+
+ yy = &y_buf[0]; move16();
+
+ /* copy initial filter states into synthesis buffer */
+ for (i = 0; i < m; i++)
+ {
+ *yy++ = mem[i]; move16();
+ }
+
+ s = sub(norm_s(a[0]), 2);
+ a0 = shr(a[0], 1); /* input / 2 */
+
+ /* Do the filtering. */
+
+ for (i = 0; i < lg; i++)
+ {
+ L_tmp = L_mult(x[i], a0);
+
+ for (j = 1; j <= m; j++)
+ L_tmp = L_msu(L_tmp, a[j], yy[i - j]);
+
+ L_tmp = L_shl(L_tmp, add(3, s));
+
+ y[i] = yy[i] = round(L_tmp); move16();move16();
+ }
+
+ /* Update memory if required */
+ test();
+ if (update)
+ for (i = 0; i < m; i++)
+ {
+ mem[i] = yy[lg - m + i]; move16();
+ }
+
+ return;
+}
+
+
+void Syn_filt_32(
+ Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */
+ Word16 m, /* (i) : order of LP filter */
+ Word16 exc[], /* (i) Qnew: excitation (exc[i] >> Qnew) */
+ Word16 Qnew, /* (i) : exc scaling = 0(min) to 8(max) */
+ Word16 sig_hi[], /* (o) /16 : synthesis high */
+ Word16 sig_lo[], /* (o) /16 : synthesis low */
+ Word16 lg /* (i) : size of filtering */
+)
+{
+ Word16 i, j, a0, s;
+ Word32 L_tmp;
+
+ s = sub(norm_s(a[0]), 2);
+
+ a0 = shr(a[0], add(4, Qnew)); /* input / 16 and >>Qnew */
+
+ /* Do the filtering. */
+
+ for (i = 0; i < lg; i++)
+ {
+ L_tmp = 0; move32();
+ for (j = 1; j <= m; j++)
+ L_tmp = L_msu(L_tmp, sig_lo[i - j], a[j]);
+
+ L_tmp = L_shr(L_tmp, 16 - 4); /* -4 : sig_lo[i] << 4 */
+
+ L_tmp = L_mac(L_tmp, exc[i], a0);
+
+ for (j = 1; j <= m; j++)
+ L_tmp = L_msu(L_tmp, sig_hi[i - j], a[j]);
+
+ /* sig_hi = bit16 to bit31 of synthesis */
+ L_tmp = L_shl(L_tmp, add(3, s)); /* ai in Q12 */
+ sig_hi[i] = extract_h(L_tmp); move16();
+
+ /* sig_lo = bit4 to bit15 of synthesis */
+ L_tmp = L_shr(L_tmp, 4); /* 4 : sig_lo[i] >> 4 */
+ sig_lo[i] = extract_l(L_msu(L_tmp, sig_hi[i], 2048)); move16();
+ }
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/typedef.h
@@ -1,0 +1,52 @@
+/*
+********************************************************************************
+*
+* File : typedef.c
+* Purpose : Basic types.
+*
+********************************************************************************
+*/
+
+
+#ifndef typedef_h
+#define typedef_h "$Id $"
+
+#undef ORIGINAL_TYPEDEF_H /* define to get "original" ETSI version
+ of typedef.h */
+
+#ifdef ORIGINAL_TYPEDEF_H
+/*
+ * this is the original code from the ETSI file typedef.h
+ */
+
+#if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(_MSC_VER) || defined(__ZTC__)
+typedef signed char Word8;
+typedef short Word16;
+typedef long Word32;
+typedef int Flag;
+
+#elif defined(__sun)
+typedef signed char Word8;
+typedef short Word16;
+typedef long Word32;
+typedef int Flag;
+
+#elif defined(__unix__) || defined(__unix)
+typedef signed char Word8;
+typedef short Word16;
+typedef int Word32;
+typedef int Flag;
+
+#endif
+#else /* not original typedef.h */
+
+/*
+ * use (improved) type definition file typdefs.h and add a "Flag" type
+ */
+#include "typedefs.h"
+typedef int Flag;
+
+#endif
+
+#endif
+
--- /dev/null
+++ b/amr-wb/typedefs.h
@@ -1,0 +1,176 @@
+/*
+*
+* File : typedefs.h
+* Description : Definition of platform independent data
+* types and constants
+*
+*
+* The following platform independent data types and corresponding
+* preprocessor (#define) constants are defined:
+*
+* defined type meaning corresponding constants
+* ----------------------------------------------------------
+* Char character (none)
+* Bool boolean true, false
+* Word8 8-bit signed minWord8, maxWord8
+* UWord8 8-bit unsigned minUWord8, maxUWord8
+* Word16 16-bit signed minWord16, maxWord16
+* UWord16 16-bit unsigned minUWord16, maxUWord16
+* Word32 32-bit signed minWord32, maxWord32
+* UWord32 32-bit unsigned minUWord32, maxUWord32
+* Float floating point minFloat, maxFloat
+*
+*
+* The following compile switches are #defined:
+*
+* PLATFORM string indicating platform progam is compiled on
+* possible values: "OSF", "PC", "SUN"
+*
+* OSF only defined if the current platform is an Alpha
+* PC only defined if the current platform is a PC
+* SUN only defined if the current platform is a Sun
+*
+* LSBFIRST is defined if the byte order on this platform is
+* "least significant byte first" -> defined on DEC Alpha
+* and PC, undefined on Sun
+*
+********************************************************************************
+*/
+#ifndef typedefs_h
+#define typedefs_h "$Id $"
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include <float.h>
+#include <limits.h>
+
+
+
+/*
+********************************************************************************
+* DEFINITION OF CONSTANTS
+********************************************************************************
+*/
+/*
+ ********* define char type
+ */
+typedef char Char;
+
+/*
+ ********* define 8 bit signed/unsigned types & constants
+ */
+#if SCHAR_MAX == 127
+typedef signed char Word8;
+#define minWord8 SCHAR_MIN
+#define maxWord8 SCHAR_MAX
+
+typedef unsigned char UWord8;
+#define minUWord8 0
+#define maxUWord8 UCHAR_MAX
+#else
+#error cannot find 8-bit type
+#endif
+
+
+/*
+ ********* define 16 bit signed/unsigned types & constants
+ */
+#if INT_MAX == 32767
+typedef int Word16;
+#define minWord16 INT_MIN
+#define maxWord16 INT_MAX
+typedef unsigned int UWord16;
+#define minUWord16 0
+#define maxUWord16 UINT_MAX
+#elif SHRT_MAX == 32767
+typedef short Word16;
+#define minWord16 SHRT_MIN
+#define maxWord16 SHRT_MAX
+typedef unsigned short UWord16;
+#define minUWord16 0
+#define maxUWord16 USHRT_MAX
+#else
+#error cannot find 16-bit type
+#endif
+
+
+/*
+ ********* define 32 bit signed/unsigned types & constants
+ */
+#if INT_MAX == 2147483647
+typedef int Word32;
+#define minWord32 INT_MIN
+#define maxWord32 INT_MAX
+typedef unsigned int UWord32;
+#define minUWord32 0
+#define maxUWord32 UINT_MAX
+#elif LONG_MAX == 2147483647
+typedef long Word32;
+#define minWord32 LONG_MIN
+#define maxWord32 LONG_MAX
+typedef unsigned long UWord32;
+#define minUWord32 0
+#define maxUWord32 ULONG_MAX
+#else
+#error cannot find 32-bit type
+#endif
+
+/*
+ ********* define floating point type & constants
+ */
+/* use "#if 0" below if Float should be double;
+ use "#if 1" below if Float should be float
+ */
+#if 0
+typedef float Float;
+#define maxFloat FLT_MAX
+#define minFloat FLT_MIN
+#else
+typedef double Float;
+#define maxFloat DBL_MAX
+#define minFloat DBL_MIN
+#endif
+
+/*
+ ********* define complex type
+ */
+typedef struct {
+ Float r; /* real part */
+ Float i; /* imaginary part */
+} CPX;
+
+/*
+ ********* define boolean type
+ */
+typedef int Bool;
+#define false 0
+#define true 1
+
+/*
+ ********* Check current platform
+ */
+#if defined(__MSDOS__)
+#define PC
+#define PLATFORM "PC"
+#define LSBFIRST
+#elif defined(__osf__)
+#define OSF
+#define PLATFORM "OSF"
+#define LSBFIRST
+#elif defined(__sun__) || defined(__sun)
+#define SUN
+#define PLATFORM "SUN"
+#undef LSBFIRST
+#elif defined(linux) && defined(i386)
+#define PC
+#define PLATFORM "PC"
+#define LSBFIRST
+#else
+#error "can't determine architecture; adapt typedefs.h to your platform"
+#endif
+
+#endif
+
--- /dev/null
+++ b/amr-wb/updt_tar.c
@@ -1,0 +1,30 @@
+/*-------------------------------------------------------------------*
+ * UPD_TAR.C *
+ *-------------------------------------------------------------------*
+ * Update the target vector for codebook search. *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+void Updt_tar(
+ Word16 * x, /* (i) Q0 : old target (for pitch search) */
+ Word16 * x2, /* (o) Q0 : new target (for codebook search) */
+ Word16 * y, /* (i) Q0 : filtered adaptive codebook vector */
+ Word16 gain, /* (i) Q14 : adaptive codebook gain */
+ Word16 L /* (i) : subframe size */
+)
+{
+ Word16 i;
+ Word32 L_tmp;
+
+ for (i = 0; i < L; i++)
+ {
+ L_tmp = L_mult(x[i], 16384);
+ L_tmp = L_msu(L_tmp, y[i], gain);
+ x2[i] = extract_h(L_shl(L_tmp, 1)); move16();
+ }
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/util.c
@@ -1,0 +1,54 @@
+/*-------------------------------------------------------------------*
+ * UTIL.C *
+ *-------------------------------------------------------------------*
+ * Vector routines *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+
+/*-------------------------------------------------------------------*
+ * Function Set zero() *
+ * ~~~~~~~~~~ *
+ * Set vector x[] to zero *
+ *-------------------------------------------------------------------*/
+
+void Set_zero(
+ Word16 x[], /* (o) : vector to clear */
+ Word16 L /* (i) : length of vector */
+)
+{
+ Word16 i;
+
+ for (i = 0; i < L; i++)
+ {
+ x[i] = 0; move16();
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * Function Copy: *
+ * ~~~~~ *
+ * Copy vector x[] to y[] *
+ *-------------------------------------------------------------------*/
+
+void Copy(
+ Word16 x[], /* (i) : input vector */
+ Word16 y[], /* (o) : output vector */
+ Word16 L /* (i) : vector length */
+)
+{
+ Word16 i;
+
+ for (i = 0; i < L; i++)
+ {
+ y[i] = x[i]; move16();
+ }
+
+ return;
+}
--- /dev/null
+++ b/amr-wb/voicefac.c
@@ -1,0 +1,66 @@
+/*-------------------------------------------------------------------*
+ * VOICEFAC.C *
+ *-------------------------------------------------------------------*
+ * Find the voicing factor (1=voice to -1=unvoiced). *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "math_op.h"
+#include "count.h"
+
+Word16 voice_factor( /* (o) Q15 : factor (-1=unvoiced to 1=voiced) */
+ Word16 exc[], /* (i) Q_exc : pitch excitation */
+ Word16 Q_exc, /* (i) : exc format */
+ Word16 gain_pit, /* (i) Q14 : gain of pitch */
+ Word16 code[], /* (i) Q9 : Fixed codebook excitation */
+ Word16 gain_code, /* (i) Q0 : gain of code */
+ Word16 L_subfr /* (i) : subframe length */
+)
+{
+ Word16 i, tmp, exp, ener1, exp1, ener2, exp2;
+ Word32 L_tmp;
+
+ ener1 = extract_h(Dot_product12(exc, exc, L_subfr, &exp1));
+ exp1 = sub(exp1, add(Q_exc, Q_exc));
+ L_tmp = L_mult(gain_pit, gain_pit);
+ exp = norm_l(L_tmp);
+ tmp = extract_h(L_shl(L_tmp, exp));
+ ener1 = mult(ener1, tmp);
+ exp1 = sub(sub(exp1, exp), 10); /* 10 -> gain_pit Q14 to Q9 */
+
+ ener2 = extract_h(Dot_product12(code, code, L_subfr, &exp2));
+
+ exp = norm_s(gain_code);
+ tmp = shl(gain_code, exp);
+ tmp = mult(tmp, tmp);
+ ener2 = mult(ener2, tmp);
+ exp2 = sub(exp2, add(exp, exp));
+
+ i = sub(exp1, exp2);
+
+ test();
+ if (i >= 0)
+ {
+ ener1 = shr(ener1, 1);
+ ener2 = shr(ener2, add(i, 1));
+ } else
+ {
+ ener1 = shr(ener1, sub(1, i));
+ ener2 = shr(ener2, 1);
+ }
+
+ tmp = sub(ener1, ener2);
+ ener1 = add(add(ener1, ener2), 1);
+
+ test();
+ if (tmp >= 0)
+ {
+ tmp = div_s(tmp, ener1);
+ } else
+ {
+ tmp = negate(div_s(negate(tmp), ener1));
+ }
+
+ return (tmp);
+}
--- /dev/null
+++ b/amr-wb/wb_vad.c
@@ -1,0 +1,850 @@
+/*-------------------------------------------------------------------*
+ * WB_VAD.C *
+ *-------------------------------------------------------------------*
+ * Voice Activity Detection. *
+ *-------------------------------------------------------------------*/
+
+/******************************************************************************
+* INCLUDE FILES
+******************************************************************************/
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cnst.h"
+#include "wb_vad.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+#include "math_op.h"
+#include "wb_vad_c.h"
+
+/******************************************************************************
+* PRIVATE PROGRAM CODE
+******************************************************************************/
+
+/******************************************************************************
+* log2
+*
+* Calculate Log2 and scale the signal:
+*
+* ilog2(Word32 in) = -1024*log10(in * 2^-31)/log10(2), where in = [1, 2^31-1]
+*
+* input output
+* 32768 16384
+* 1 31744
+*
+* When input is in the range of [1,2^16], max error is 0.0380%.
+*
+*
+*/
+
+Word16 ilog2( /* return: output value of the log2 */
+ Word16 mant /* i: value to be converted */
+)
+{
+ Word16 i, ex, ex2, res;
+ Word32 l_temp;
+
+ test();
+ if (mant <= 0)
+ {
+ mant = 1; move16();
+ }
+ ex = norm_s(mant);
+ mant = shl(mant, ex);
+
+ for (i = 0; i < 3; i++)
+ mant = mult(mant, mant);
+ l_temp = L_mult(mant, mant);
+
+ ex2 = norm_l(l_temp);
+ mant = extract_h(L_shl(l_temp, ex2));
+
+ res = shl(add(ex, 16), 10);
+ res = add(res, shl(ex2, 6));
+ res = sub(add(res, 127), shr(mant, 8));
+ return (res);
+}
+
+/******************************************************************************
+*
+* Function : filter5
+* Purpose : Fifth-order half-band lowpass/highpass filter pair with
+* decimation.
+*
+*/
+static void filter5(
+ Word16 * in0, /* i/o : input values; output low-pass part */
+ Word16 * in1, /* i/o : input values; output high-pass part */
+ Word16 data[] /* i/o : filter memory */
+)
+{
+ Word16 temp0, temp1, temp2;
+
+ temp0 = sub(*in0, mult(COEFF5_1, data[0]));
+ temp1 = add(data[0], mult(COEFF5_1, temp0));
+ data[0] = temp0; move16();
+
+ temp0 = sub(*in1, mult(COEFF5_2, data[1]));
+ temp2 = add(data[1], mult(COEFF5_2, temp0));
+ data[1] = temp0; move16();
+
+ *in0 = extract_h(L_shl(L_add(temp1, temp2), 15)); move16();
+ *in1 = extract_h(L_shl(L_sub(temp1, temp2), 15)); move16();
+}
+
+/******************************************************************************
+*
+* Function : filter3
+* Purpose : Third-order half-band lowpass/highpass filter pair with
+* decimation.
+*
+*/
+static void filter3(
+ Word16 * in0, /* i/o : input values; output low-pass part */
+ Word16 * in1, /* i/o : input values; output high-pass part */
+ Word16 * data /* i/o : filter memory */
+)
+{
+ Word16 temp1, temp2;
+
+ temp1 = sub(*in1, mult(COEFF3, *data));
+ temp2 = add(*data, mult(COEFF3, temp1));
+ *data = temp1; move16();
+
+ *in1 = extract_h(L_shl(L_sub(*in0, temp2), 15)); move16();
+ *in0 = extract_h(L_shl(L_add(*in0, temp2), 15)); move16();
+}
+
+/******************************************************************************
+*
+* Function : level_calculation
+* Purpose : Calculate signal level in a sub-band. Level is calculated
+* by summing absolute values of the input data.
+*
+* Signal level calculated from of the end of the frame
+* (data[count1 - count2]) is stored to (*sub_level)
+* and added to the level of the next frame.
+*
+*/
+static Word16 level_calculation( /* return: signal level */
+ Word16 data[], /* i : signal buffer */
+ Word16 * sub_level, /* i : level calculated at the end of the previous frame*/
+ /* o : level of signal calculated from the last */
+ /* (count2 - count1) samples */
+ Word16 count1, /* i : number of samples to be counted */
+ Word16 count2, /* i : number of samples to be counted */
+ Word16 ind_m, /* i : step size for the index of the data buffer */
+ Word16 ind_a, /* i : starting index of the data buffer */
+ Word16 scale /* i : scaling for the level calculation */
+)
+{
+ Word32 l_temp1, l_temp2;
+ Word16 level, i;
+
+ l_temp1 = 0L; move32();
+ for (i = count1; i < count2; i++)
+ {
+ l_temp1 = L_mac(l_temp1, 1, abs_s(data[ind_m * i + ind_a]));
+ }
+
+ l_temp2 = L_add(l_temp1, L_shl(*sub_level, sub(16, scale)));
+ *sub_level = extract_h(L_shl(l_temp1, scale)); move16();
+
+ for (i = 0; i < count1; i++)
+ {
+ l_temp2 = L_mac(l_temp2, 1, abs_s(data[ind_m * i + ind_a]));
+ }
+ level = extract_h(L_shl(l_temp2, scale));
+
+ return level;
+}
+
+/******************************************************************************
+*
+* Function : filter_bank
+* Purpose : Divide input signal into bands and calculate level of
+* the signal in each band
+*
+*/
+static void filter_bank(
+ VadVars * st, /* i/o : State struct */
+ Word16 in[], /* i : input frame */
+ Word16 level[] /* 0 : signal levels at each band */
+)
+{
+ Word16 i;
+ Word16 tmp_buf[FRAME_LEN];
+
+ /* shift input 1 bit down for safe scaling */
+ for (i = 0; i < FRAME_LEN; i++)
+ {
+ tmp_buf[i] = shr(in[i], 1); move16();
+ }
+
+ /* run the filter bank */
+ for (i = 0; i < FRAME_LEN / 2; i++)
+ {
+ filter5(&tmp_buf[2 * i], &tmp_buf[2 * i + 1], st->a_data5[0]);
+ }
+ for (i = 0; i < FRAME_LEN / 4; i++)
+ {
+ filter5(&tmp_buf[4 * i], &tmp_buf[4 * i + 2], st->a_data5[1]);
+ filter5(&tmp_buf[4 * i + 1], &tmp_buf[4 * i + 3], st->a_data5[2]);
+ }
+ for (i = 0; i < FRAME_LEN / 8; i++)
+ {
+ filter5(&tmp_buf[8 * i], &tmp_buf[8 * i + 4], st->a_data5[3]);
+ filter5(&tmp_buf[8 * i + 2], &tmp_buf[8 * i + 6], st->a_data5[4]);
+ filter3(&tmp_buf[8 * i + 3], &tmp_buf[8 * i + 7], &st->a_data3[0]);
+ }
+ for (i = 0; i < FRAME_LEN / 16; i++)
+ {
+ filter3(&tmp_buf[16 * i + 0], &tmp_buf[16 * i + 8], &st->a_data3[1]);
+ filter3(&tmp_buf[16 * i + 4], &tmp_buf[16 * i + 12], &st->a_data3[2]);
+ filter3(&tmp_buf[16 * i + 6], &tmp_buf[16 * i + 14], &st->a_data3[3]);
+ }
+
+ for (i = 0; i < FRAME_LEN / 32; i++)
+ {
+ filter3(&tmp_buf[32 * i + 0], &tmp_buf[32 * i + 16], &st->a_data3[4]);
+ filter3(&tmp_buf[32 * i + 8], &tmp_buf[32 * i + 24], &st->a_data3[5]);
+ }
+
+ /* calculate levels in each frequency band */
+
+ /* 4800 - 6400 Hz */
+ level[11] = level_calculation(tmp_buf, &st->sub_level[11],
+ FRAME_LEN / 4 - 48, FRAME_LEN / 4, 4, 1, 14); move16();
+ /* 4000 - 4800 Hz */
+ level[10] = level_calculation(tmp_buf, &st->sub_level[10],
+ FRAME_LEN / 8 - 24, FRAME_LEN / 8, 8, 7, 15); move16();
+ /* 3200 - 4000 Hz */
+ level[9] = level_calculation(tmp_buf, &st->sub_level[9],
+ FRAME_LEN / 8 - 24, FRAME_LEN / 8, 8, 3, 15); move16();
+ /* 2400 - 3200 Hz */
+ level[8] = level_calculation(tmp_buf, &st->sub_level[8],
+ FRAME_LEN / 8 - 24, FRAME_LEN / 8, 8, 2, 15); move16();
+ /* 2000 - 2400 Hz */
+ level[7] = level_calculation(tmp_buf, &st->sub_level[7],
+ FRAME_LEN / 16 - 12, FRAME_LEN / 16, 16, 14, 16); move16();
+ /* 1600 - 2000 Hz */
+ level[6] = level_calculation(tmp_buf, &st->sub_level[6],
+ FRAME_LEN / 16 - 12, FRAME_LEN / 16, 16, 6, 16); move16();
+ /* 1200 - 1600 Hz */
+ level[5] = level_calculation(tmp_buf, &st->sub_level[5],
+ FRAME_LEN / 16 - 12, FRAME_LEN / 16, 16, 4, 16); move16();
+ /* 800 - 1200 Hz */
+ level[4] = level_calculation(tmp_buf, &st->sub_level[4],
+ FRAME_LEN / 16 - 12, FRAME_LEN / 16, 16, 12, 16); move16();
+ /* 600 - 800 Hz */
+ level[3] = level_calculation(tmp_buf, &st->sub_level[3],
+ FRAME_LEN / 32 - 6, FRAME_LEN / 32, 32, 8, 17); move16();
+ /* 400 - 600 Hz */
+ level[2] = level_calculation(tmp_buf, &st->sub_level[2],
+ FRAME_LEN / 32 - 6, FRAME_LEN / 32, 32, 24, 17); move16();
+ /* 200 - 400 Hz */
+ level[1] = level_calculation(tmp_buf, &st->sub_level[1],
+ FRAME_LEN / 32 - 6, FRAME_LEN / 32, 32, 16, 17); move16();
+ /* 0 - 200 Hz */
+ level[0] = level_calculation(tmp_buf, &st->sub_level[0],
+ FRAME_LEN / 32 - 6, FRAME_LEN / 32, 32, 0, 17); move16();
+}
+
+/******************************************************************************
+*
+* Function : update_cntrl
+* Purpose : Control update of the background noise estimate.
+*
+*/
+static void update_cntrl(
+ VadVars * st, /* i/o : State structure */
+ Word16 level[] /* i : sub-band levels of the input frame */
+)
+{
+ Word16 i, temp, stat_rat, exp;
+ Word16 num, denom;
+ Word16 alpha;
+
+ /* if a tone has been detected for a while, initialize stat_count */
+ logic16();test();
+ if (sub((Word16) (st->tone_flag & 0x7c00), 0x7c00) == 0)
+ {
+ st->stat_count = STAT_COUNT; move16();
+ } else
+ {
+ /* if 8 last vad-decisions have been "0", reinitialize stat_count */
+ logic16();test();
+ if ((st->vadreg & 0x7f80) == 0)
+ {
+ st->stat_count = STAT_COUNT; move16();
+ } else
+ {
+ stat_rat = 0; move16();
+ for (i = 0; i < COMPLEN; i++)
+ {
+ test();
+ if (sub(level[i], st->ave_level[i]) > 0)
+ {
+ num = level[i]; move16();
+ denom = st->ave_level[i]; move16();
+ } else
+ {
+ num = st->ave_level[i];move16();
+ denom = level[i]; move16();
+ }
+ /* Limit nimimum value of num and denom to STAT_THR_LEVEL */
+ test();
+ if (sub(num, STAT_THR_LEVEL) < 0)
+ {
+ num = STAT_THR_LEVEL; move16();
+ }
+ test();
+ if (sub(denom, STAT_THR_LEVEL) < 0)
+ {
+ denom = STAT_THR_LEVEL;move16();
+ }
+ exp = norm_s(denom);
+ denom = shl(denom, exp);
+
+ /* stat_rat = num/denom * 64 */
+ temp = div_s(shr(num, 1), denom);
+ stat_rat = add(stat_rat, shr(temp, sub(8, exp)));
+ }
+
+ /* compare stat_rat with a threshold and update stat_count */
+ test();
+ if (sub(stat_rat, STAT_THR) > 0)
+ {
+ st->stat_count = STAT_COUNT; move16();
+ } else
+ {
+ logic16();test();
+ if ((st->vadreg & 0x4000) != 0)
+ {
+ test();
+ if (st->stat_count != 0)
+ {
+ st->stat_count = sub(st->stat_count, 1); move16();
+ }
+ }
+ }
+ }
+ }
+
+ /* Update average amplitude estimate for stationarity estimation */
+ alpha = ALPHA4; move16();
+ test();test();logic16();
+ if (sub(st->stat_count, STAT_COUNT) == 0)
+ {
+ alpha = 32767; move16();
+ } else if ((st->vadreg & 0x4000) == 0)
+ {
+ logic16();test();
+ alpha = ALPHA5; move16();
+ }
+ for (i = 0; i < COMPLEN; i++)
+ {
+ st->ave_level[i] = add(st->ave_level[i],
+ mult_r(alpha, sub(level[i], st->ave_level[i]))); move16();
+ }
+}
+
+/******************************************************************************
+*
+* Function : hangover_addition
+* Purpose : Add hangover after speech bursts
+*
+*/
+
+static Word16 hangover_addition( /* return: VAD_flag indicating final VAD decision */
+ VadVars * st, /* i/o : State structure */
+ Word16 low_power, /* i : flag power of the input frame */
+ Word16 hang_len, /* i : hangover length */
+ Word16 burst_len /* i : minimum burst length for hangover addition */
+)
+{
+ /* if the input power (pow_sum) is lower than a threshold, clear counters and set VAD_flag to "0" */
+ test();
+ if (low_power != 0)
+ {
+ st->burst_count = 0; move16();
+ st->hang_count = 0; move16();
+ return 0;
+ }
+ /* update the counters (hang_count, burst_count) */
+ logic16();test();
+ if ((st->vadreg & 0x4000) != 0)
+ {
+ st->burst_count = add(st->burst_count, 1); move16();
+ test();
+ if (sub(st->burst_count, burst_len) >= 0)
+ {
+ st->hang_count = hang_len; move16();
+ }
+ return 1;
+ } else
+ {
+ st->burst_count = 0; move16();
+ test();
+ if (st->hang_count > 0)
+ {
+ st->hang_count = sub(st->hang_count, 1); move16();
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************
+*
+* Function : noise_estimate_update
+* Purpose : Update of background noise estimate
+*
+*/
+
+static void noise_estimate_update(
+ VadVars * st, /* i/o : State structure */
+ Word16 level[] /* i : sub-band levels of the input frame */
+)
+{
+ Word16 i, alpha_up, alpha_down, bckr_add;
+
+ /* Control update of bckr_est[] */
+ update_cntrl(st, level);
+
+ /* Reason for using bckr_add is to avoid problems caused by fixed-point dynamics when noise level and
+ * required change is very small. */
+ bckr_add = 2; move16();
+
+ /* Choose update speed */
+ logic16();test();
+ if ((0x7800 & st->vadreg) == 0)
+ {
+ alpha_up = ALPHA_UP1; move16();
+ alpha_down = ALPHA_DOWN1; move16();
+ } else
+ {
+ test();
+ if ((st->stat_count == 0))
+ {
+ alpha_up = ALPHA_UP2; move16();
+ alpha_down = ALPHA_DOWN2; move16();
+ } else
+ {
+ alpha_up = 0; move16();
+ alpha_down = ALPHA3; move16();
+ bckr_add = 0; move16();
+ }
+ }
+
+ /* Update noise estimate (bckr_est) */
+ for (i = 0; i < COMPLEN; i++)
+ {
+ Word16 temp;
+
+ temp = sub(st->old_level[i], st->bckr_est[i]);
+
+ test();
+ if (temp < 0)
+ { /* update downwards */
+ st->bckr_est[i] = add(-2, add(st->bckr_est[i],
+ mult_r(alpha_down, temp))); move16();
+
+ /* limit minimum value of the noise estimate to NOISE_MIN */
+ test();
+ if (sub(st->bckr_est[i], NOISE_MIN) < 0)
+ {
+ st->bckr_est[i] = NOISE_MIN; move16();
+ }
+ } else
+ { /* update upwards */
+ st->bckr_est[i] = add(bckr_add, add(st->bckr_est[i],
+ mult_r(alpha_up, temp))); move16();
+
+ /* limit maximum value of the noise estimate to NOISE_MAX */
+ test();
+ if (sub(st->bckr_est[i], NOISE_MAX) > 0)
+ {
+ st->bckr_est[i] = NOISE_MAX; move16();
+ }
+ }
+ }
+
+ /* Update signal levels of the previous frame (old_level) */
+ for (i = 0; i < COMPLEN; i++)
+ {
+ st->old_level[i] = level[i]; move16();
+ }
+}
+
+/******************************************************************************
+*
+* Function : vad_decision
+* Purpose : Calculates VAD_flag
+*
+*/
+
+static Word16 vad_decision( /* return value : VAD_flag */
+ VadVars * st, /* i/o : State structure */
+ Word16 level[COMPLEN], /* i : sub-band levels of the input frame */
+ Word32 pow_sum /* i : power of the input frame */
+)
+{
+ Word16 i;
+ Word32 L_snr_sum;
+ Word32 L_temp;
+ Word16 vad_thr, temp, noise_level;
+ Word16 low_power_flag;
+ Word16 hang_len, burst_len;
+ Word16 ilog2_speech_level, ilog2_noise_level;
+ Word16 temp2;
+
+ /* Calculate squared sum of the input levels (level) divided by the background noise components
+ * (bckr_est). */
+ L_snr_sum = 0; move32();
+ for (i = 0; i < COMPLEN; i++)
+ {
+ Word16 exp;
+
+ exp = norm_s(st->bckr_est[i]);
+ temp = shl(st->bckr_est[i], exp);
+ temp = div_s(shr(level[i], 1), temp);
+ temp = shl(temp, sub(exp, UNIRSHFT - 1));
+ L_snr_sum = L_mac(L_snr_sum, temp, temp);
+ }
+
+ /* Calculate average level of estimated background noise */
+ L_temp = 0; move32();
+ for (i = 1; i < COMPLEN; i++) /* ignore lowest band */
+ {
+ L_temp = L_add(L_temp, st->bckr_est[i]);
+ }
+
+ noise_level = extract_h(L_shl(L_temp, 12));
+ /* if SNR is lower than a threshold (MIN_SPEECH_SNR), and increase speech_level */
+ temp = shl(mult(noise_level, MIN_SPEECH_SNR), 3);
+
+ test();
+ if (sub(st->speech_level, temp) < 0)
+ {
+ st->speech_level = temp; move16();
+ }
+ ilog2_noise_level = ilog2(noise_level);
+
+ /* If SNR is very poor, speech_level is probably corrupted by noise level. This is correctred by
+ * subtracting MIN_SPEECH_SNR*noise_level from speech level */
+ ilog2_speech_level = ilog2(sub(st->speech_level, temp));
+
+ temp = add(mult(NO_SLOPE, sub(ilog2_noise_level, NO_P1)), THR_HIGH);
+
+ temp2 = add(SP_CH_MIN, mult(SP_SLOPE, sub(ilog2_speech_level, SP_P1)));
+ test();
+ if (sub(temp2, SP_CH_MIN) < 0)
+ {
+ temp2 = SP_CH_MIN; move16();
+ }
+ test();
+ if (sub(temp2, SP_CH_MAX) > 0)
+ {
+ temp2 = SP_CH_MAX; move16();
+ }
+ vad_thr = add(temp, temp2);
+
+ test();
+ if (sub(vad_thr, THR_MIN) < 0)
+ {
+ vad_thr = THR_MIN; move16();
+ }
+ /* Shift VAD decision register */
+ st->vadreg = shr(st->vadreg, 1); move16();
+
+ /* Make intermediate VAD decision */
+ test();
+ if (L_sub(L_snr_sum, L_mult(vad_thr, 512 * COMPLEN)) > 0)
+ {
+ st->vadreg = (Word16) (st->vadreg | 0x4000); logic16();move16();
+ }
+ /* check if the input power (pow_sum) is lower than a threshold" */
+ test();
+ if (L_sub(pow_sum, VAD_POW_LOW) < 0)
+ {
+ low_power_flag = 1; move16();
+ } else
+ {
+ low_power_flag = 0; move16();
+ }
+ /* Update background noise estimates */
+ noise_estimate_update(st, level);
+
+ /* Calculate values for hang_len and burst_len based on vad_thr */
+ hang_len = add(mult(HANG_SLOPE, sub(vad_thr, HANG_P1)), HANG_HIGH);
+ test();
+ if (sub(hang_len, HANG_LOW) < 0)
+ {
+ hang_len = HANG_LOW; move16();
+ };
+
+ burst_len = add(mult(BURST_SLOPE, sub(vad_thr, BURST_P1)), BURST_HIGH);
+
+ return (hangover_addition(st, low_power_flag, hang_len, burst_len));
+}
+
+/******************************************************************************
+*
+* Estimate_Speech()
+* Purpose : Estimate speech level
+*
+* Maximum signal level is searched and stored to the variable sp_max.
+* The speech frames must locate within SP_EST_COUNT number of frames.
+* Thus, noisy frames having occasional VAD = "1" decisions will not
+* affect to the estimated speech_level.
+*
+*/
+static void Estimate_Speech(
+ VadVars * st, /* i/o : State structure */
+ Word16 in_level /* level of the input frame */
+)
+{
+ Word16 alpha;
+
+ /* if the required activity count cannot be achieved, reset counters */
+ test();
+ /* if (SP_ACTIVITY_COUNT > SP_EST_COUNT - st->sp_est_cnt + st->sp_max_cnt) */
+ if (sub(sub(st->sp_est_cnt, st->sp_max_cnt), SP_EST_COUNT - SP_ACTIVITY_COUNT) > 0)
+ {
+ st->sp_est_cnt = 0; move16();
+ st->sp_max = 0; move16();
+ st->sp_max_cnt = 0; move16();
+ }
+ st->sp_est_cnt = add(st->sp_est_cnt, 1); move16();
+
+ logic16();test();test();test();
+ if (((st->vadreg & 0x4000) || (sub(in_level, st->speech_level) > 0))
+ && (sub(in_level, MIN_SPEECH_LEVEL1) > 0))
+ {
+ /* update sp_max */
+ test();
+ if (sub(in_level, st->sp_max) > 0)
+ {
+ st->sp_max = in_level; move16();
+ }
+ st->sp_max_cnt = add(st->sp_max_cnt, 1); move16();
+ test();
+ if (sub(st->sp_max_cnt, SP_ACTIVITY_COUNT) >= 0)
+ {
+ Word16 tmp;
+
+ /* update speech estimate */
+ tmp = shr(st->sp_max, 1); /* scale to get "average" speech level */
+
+ /* select update speed */
+ test();
+ if (sub(tmp, st->speech_level) > 0)
+ {
+ alpha = ALPHA_SP_UP; move16();
+ } else
+ {
+ alpha = ALPHA_SP_DOWN; move16();
+ }
+ test();
+ if (sub(tmp, MIN_SPEECH_LEVEL2) > 0)
+ {
+ st->speech_level = add(st->speech_level,
+ mult_r(alpha, sub(tmp, st->speech_level))); move16();
+ }
+ /* clear all counters used for speech estimation */
+ st->sp_max = 0; move16();
+ st->sp_max_cnt = 0; move16();
+ st->sp_est_cnt = 0; move16();
+ }
+ }
+}
+
+/******************************************************************************
+* PUBLIC PROGRAM CODE
+******************************************************************************/
+
+/******************************************************************************
+*
+* Function: wb_vad_init
+* Purpose: Allocates state memory and initializes state memory
+*
+*/
+
+Word16 wb_vad_init( /* return: non-zero with error, zero for ok. */
+ VadVars ** state /* i/o : State structure */
+)
+{
+ VadVars *s;
+
+ if (state == (VadVars **) NULL)
+ {
+ fprintf(stderr, "vad_init: invalid parameter\n");
+ return -1;
+ }
+ *state = NULL;
+
+ /* allocate memory */
+ if ((s = (VadVars *) malloc(sizeof(VadVars))) == NULL)
+ {
+ fprintf(stderr, "vad_init: can not malloc state structure\n");
+ return -1;
+ }
+ wb_vad_reset(s);
+
+ *state = s;
+
+ return 0;
+}
+
+/******************************************************************************
+*
+* Function: wb_vad_reset
+* Purpose: Initializes state memory
+*
+*/
+Word16 wb_vad_reset( /* return: non-zero with error, zero for ok. */
+ VadVars * state /* i/o : State structure */
+)
+{
+ Word16 i, j;
+
+ if (state == (VadVars *) NULL)
+ {
+ fprintf(stderr, "vad_reset: invalid parameter\n");
+ return -1;
+ }
+ state->tone_flag = 0;
+ state->vadreg = 0;
+ state->hang_count = 0;
+ state->burst_count = 0;
+ state->hang_count = 0;
+
+ /* initialize memory used by the filter bank */
+ for (i = 0; i < F_5TH_CNT; i++)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ state->a_data5[i][j] = 0;
+ }
+ }
+
+ for (i = 0; i < F_3TH_CNT; i++)
+ {
+ state->a_data3[i] = 0;
+ }
+
+ /* initialize the rest of the memory */
+ for (i = 0; i < COMPLEN; i++)
+ {
+ state->bckr_est[i] = NOISE_INIT;
+ state->old_level[i] = NOISE_INIT;
+ state->ave_level[i] = NOISE_INIT;
+ state->sub_level[i] = 0;
+ }
+
+ state->sp_est_cnt = 0;
+ state->sp_max = 0;
+ state->sp_max_cnt = 0;
+ state->speech_level = SPEECH_LEVEL_INIT;
+ state->prev_pow_sum = 0;
+ return 0;
+}
+
+/******************************************************************************
+*
+* Function: wb_vad_exit
+* Purpose: The memory used for state memory is freed
+*
+*/
+void wb_vad_exit(
+ VadVars ** state /* i/o : State structure */
+)
+{
+ if (state == NULL || *state == NULL)
+ return;
+
+ /* deallocate memory */
+ free(*state);
+ *state = NULL;
+ return;
+}
+
+/******************************************************************************
+*
+* Function : wb_vad_tone_detection
+* Purpose : Search maximum pitch gain from a frame. Set tone flag if
+* pitch gain is high. This is used to detect
+* signaling tones and other signals with high pitch gain.
+*
+*/
+void wb_vad_tone_detection(
+ VadVars * st, /* i/o : State struct */
+ Word16 p_gain /* pitch gain */
+)
+{
+ /* update tone flag */
+ st->tone_flag = shr(st->tone_flag, 1); move16();
+
+ /* if (pitch_gain > TONE_THR) set tone flag */
+ test();
+ if (sub(p_gain, TONE_THR) > 0)
+ {
+ st->tone_flag = (Word16) (st->tone_flag | 0x4000); logic16();move16();
+ }
+}
+
+/******************************************************************************
+*
+* Function : wb_vad
+* Purpose : Main program for Voice Activity Detection (VAD) for AMR
+*
+*/
+Word16 wb_vad( /* Return value : VAD Decision, 1 = speech, 0 = noise */
+ VadVars * st, /* i/o : State structure */
+ Word16 in_buf[] /* i : samples of the input frame */
+)
+{
+ Word16 level[COMPLEN];
+ Word16 i;
+ Word16 VAD_flag, temp;
+ Word32 L_temp, pow_sum;
+
+ /* Calculate power of the input frame. */
+ L_temp = 0L; move32();
+ for (i = 0; i < FRAME_LEN; i++)
+ {
+ L_temp = L_mac(L_temp, in_buf[i], in_buf[i]);
+ }
+
+ /* pow_sum = power of current frame and previous frame */
+ pow_sum = L_add(L_temp, st->prev_pow_sum); move32();
+
+ /* save power of current frame for next call */
+ st->prev_pow_sum = L_temp; move32();
+
+ /* If input power is very low, clear tone flag */
+ test();
+ if (L_sub(pow_sum, POW_TONE_THR) < 0)
+ {
+ st->tone_flag = (Word16) (st->tone_flag & 0x1fff); logic16();move16();
+ }
+ /* Run the filter bank and calculate signal levels at each band */
+ filter_bank(st, in_buf, level);
+
+ /* compute VAD decision */
+ VAD_flag = vad_decision(st, level, pow_sum);
+
+ /* Calculate input level */
+ L_temp = 0; move32();
+ for (i = 1; i < COMPLEN; i++) /* ignore lowest band */
+ {
+ L_temp = L_add(L_temp, level[i]);
+ }
+
+ temp = extract_h(L_shl(L_temp, 12));
+
+ Estimate_Speech(st, temp); /* Estimate speech level */
+ return (VAD_flag);
+}
--- /dev/null
+++ b/amr-wb/wb_vad.h
@@ -1,0 +1,58 @@
+/*-------------------------------------------------------------------*
+ * WB_VAD.H *
+ *-------------------------------------------------------------------*
+ * Functions and static memory for Voice Activity Detection. *
+ *-------------------------------------------------------------------*/
+
+#ifndef wb_vad_h
+#define wb_vad_h
+
+/******************************************************************************
+ * INCLUDE FILES
+ ******************************************************************************/
+#include "typedef.h"
+#include "wb_vad_c.h"
+
+/******************************************************************************
+ * DEFINITION OF DATA TYPES
+ ******************************************************************************/
+
+typedef struct
+{
+ Word16 bckr_est[COMPLEN]; /* background noise estimate */
+ Word16 ave_level[COMPLEN]; /* averaged input components for stationary */
+ /* estimation */
+ Word16 old_level[COMPLEN]; /* input levels of the previous frame */
+ Word16 sub_level[COMPLEN]; /* input levels calculated at the end of a frame (lookahead) */
+ Word16 a_data5[F_5TH_CNT][2]; /* memory for the filter bank */
+ Word16 a_data3[F_3TH_CNT]; /* memory for the filter bank */
+
+ Word16 burst_count; /* counts length of a speech burst */
+ Word16 hang_count; /* hangover counter */
+ Word16 stat_count; /* stationary counter */
+
+ /* Note that each of the following two variables holds 15 flags. Each flag reserves 1 bit of the
+ * variable. The newest flag is in the bit 15 (assuming that LSB is bit 1 and MSB is bit 16). */
+ Word16 vadreg; /* flags for intermediate VAD decisions */
+ Word16 tone_flag; /* tone detection flags */
+
+ Word16 sp_est_cnt; /* counter for speech level estimation */
+ Word16 sp_max; /* maximum level */
+ Word16 sp_max_cnt; /* counts frames that contains speech */
+ Word16 speech_level; /* estimated speech level */
+ Word32 prev_pow_sum; /* power of previous frame */
+
+} VadVars;
+
+/********************************************************************************
+ *
+ * DECLARATION OF PROTOTYPES
+ ********************************************************************************/
+
+Word16 wb_vad_init(VadVars ** st);
+Word16 wb_vad_reset(VadVars * st);
+void wb_vad_exit(VadVars ** st);
+void wb_vad_tone_detection(VadVars * st, Word16 p_gain);
+Word16 wb_vad(VadVars * st, Word16 in_buf[]);
+
+#endif
--- /dev/null
+++ b/amr-wb/wb_vad_c.h
@@ -1,0 +1,89 @@
+/*-------------------------------------------------------------------*
+ * WB_VAD_C.H *
+ *-------------------------------------------------------------------*
+ * Constants for Voice Activity Detection. *
+ *-------------------------------------------------------------------*/
+
+#ifndef wb_vad_c_h
+#define wb_vad_c_h
+
+#define FRAME_LEN 256 /* Length (samples) of the input frame */
+#define COMPLEN 12 /* Number of sub-bands used by VAD */
+
+#define UNIRSHFT 7 /* = log2(MAX_16/UNITY), UNITY = 256 */
+#define SCALE 128 /* (UNITY*UNITY)/512 */
+
+#define TONE_THR (Word16)(0.65*MAX_16) /* Threshold for tone detection */
+
+/* constants for speech level estimation */
+#define SP_EST_COUNT 80
+#define SP_ACTIVITY_COUNT 25
+#define ALPHA_SP_UP (Word16)((1.0 - 0.85)*MAX_16)
+#define ALPHA_SP_DOWN (Word16)((1.0 - 0.85)*MAX_16)
+
+#define NOM_LEVEL 2050 /* about -26 dBov Q15 */
+#define SPEECH_LEVEL_INIT NOM_LEVEL /* initial speech level */
+#define MIN_SPEECH_LEVEL1 (Word16)(NOM_LEVEL * 0.063) /* NOM_LEVEL -24 dB */
+#define MIN_SPEECH_LEVEL2 (Word16)(NOM_LEVEL * 0.2) /* NOM_LEVEL -14 dB */
+#define MIN_SPEECH_SNR 4096 /* 0 dB, lowest SNR estimation, Q12 */
+
+/* Time constants for background spectrum update */
+#define ALPHA_UP1 (Word16)((1.0 - 0.95)*MAX_16) /* Normal update, upwards: */
+#define ALPHA_DOWN1 (Word16)((1.0 - 0.936)*MAX_16) /* Normal update, downwards */
+#define ALPHA_UP2 (Word16)((1.0 - 0.985)*MAX_16) /* Forced update, upwards */
+#define ALPHA_DOWN2 (Word16)((1.0 - 0.943)*MAX_16) /* Forced update, downwards */
+#define ALPHA3 (Word16)((1.0 - 0.95)*MAX_16) /* Update downwards */
+#define ALPHA4 (Word16)((1.0 - 0.9)*MAX_16) /* For stationary estimation */
+#define ALPHA5 (Word16)((1.0 - 0.5)*MAX_16) /* For stationary estimation */
+
+/* Constants for VAD threshold */
+#define THR_MIN (Word16)(1.6*SCALE) /* Minimum threshold */
+#define THR_HIGH (Word16)(6*SCALE) /* Highest threshold */
+#define THR_LOW (Word16)(1.7*SCALE) /* Lowest threshold */
+#define NO_P1 31744 /* ilog2(1), Noise level for highest threshold */
+#define NO_P2 19786 /* ilog2(0.1*MAX_16), Noise level for lowest threshold */
+#define NO_SLOPE (Word16)(MAX_16*(float)(THR_LOW-THR_HIGH)/(float)(NO_P2-NO_P1))
+
+#define SP_CH_MIN (Word16)(-0.75*SCALE)
+#define SP_CH_MAX (Word16)(0.75*SCALE)
+#define SP_P1 22527 /* ilog2(NOM_LEVEL/4) */
+#define SP_P2 17832 /* ilog2(NOM_LEVEL*4) */
+#define SP_SLOPE (Word16)(MAX_16*(float)(SP_CH_MAX-SP_CH_MIN)/(float)(SP_P2-SP_P1))
+
+/* Constants for hangover length */
+#define HANG_HIGH 12 /* longest hangover */
+#define HANG_LOW 2 /* shortest hangover */
+#define HANG_P1 THR_LOW /* threshold for longest hangover */
+#define HANG_P2 (Word16)(4*SCALE) /* threshold for shortest hangover */
+#define HANG_SLOPE (Word16)(MAX_16*(float)(HANG_LOW-HANG_HIGH)/(float)(HANG_P2-HANG_P1))
+
+/* Constants for burst length */
+#define BURST_HIGH 8 /* longest burst length */
+#define BURST_LOW 3 /* shortest burst length */
+#define BURST_P1 THR_HIGH /* threshold for longest burst */
+#define BURST_P2 THR_LOW /* threshold for shortest burst */
+#define BURST_SLOPE (Word16)(MAX_16*(float)(BURST_LOW-BURST_HIGH)/(float)(BURST_P2-BURST_P1))
+
+/* Parameters for background spectrum recovery function */
+#define STAT_COUNT 20 /* threshold of stationary detection counter */
+
+#define STAT_THR_LEVEL 184 /* Threshold level for stationarity detection */
+#define STAT_THR 1000 /* Threshold for stationarity detection */
+
+/* Limits for background noise estimate */
+#define NOISE_MIN 40 /* minimum */
+#define NOISE_MAX 20000 /* maximum */
+#define NOISE_INIT 150 /* initial */
+
+/* Thresholds for signal power (now calculated on 2 frames) */
+#define VAD_POW_LOW (Word32)30000L /* If input power is lower than this, VAD is set to 0 */
+#define POW_TONE_THR (Word32)686080L /* If input power is lower,tone detection flag is ignored */
+
+/* Constants for the filter bank */
+#define COEFF3 13363 /* coefficient for the 3rd order filter */
+#define COEFF5_1 21955 /* 1st coefficient the for 5th order filter */
+#define COEFF5_2 6390 /* 2nd coefficient the for 5th order filter */
+#define F_5TH_CNT 5 /* number of 5th order filters */
+#define F_3TH_CNT 6 /* number of 3th order filters */
+
+#endif
--- /dev/null
+++ b/amr-wb/weight_a.c
@@ -1,0 +1,31 @@
+/*-------------------------------------------------------------------*
+ * WB_VAD.C *
+ *-------------------------------------------------------------------*
+ * Weighting of LPC coefficients. *
+ * ap[i] = a[i] * (gamma ** i) *
+ *-------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+void Weight_a(
+ Word16 a[], /* (i) Q12 : a[m+1] LPC coefficients */
+ Word16 ap[], /* (o) Q12 : Spectral expanded LPC coefficients */
+ Word16 gamma, /* (i) Q15 : Spectral expansion factor. */
+ Word16 m /* (i) : LPC order. */
+)
+{
+ Word16 i, fac;
+
+ ap[0] = a[0]; move16();
+ fac = gamma; move16();
+ for (i = 1; i < m; i++)
+ {
+ ap[i] = round(L_mult(a[i], fac)); move16();
+ fac = round(L_mult(fac, gamma));
+ }
+ ap[m] = round(L_mult(a[m], fac)); move16();
+
+ return;
+}
--- a/configure.ac
+++ b/configure.ac
@@ -180,7 +180,8 @@
dnl Generate output files.
AX_CREATE_STDINT_H(src/ststdint.h)
-AC_CONFIG_FILES(Makefile src/Makefile src/libgsm/Makefile src/libst-config)
+AC_CONFIG_FILES(Makefile src/Makefile src/libgsm/Makefile
+ amr-wb/Makefile src/libst-config)
AC_OUTPUT
if test "$found_libgsm" = "yes"; then
--- a/sox.1
+++ b/sox.1
@@ -777,6 +777,17 @@
the highest quality format your ALSA system can handle. Example:
.B sox infile \-t alsa default
.TP
+\&\fB.amr\-wb\fR
+Adaptive Multi Rate\*mWideband speech codec; a lossy format used in 3rd
+generation mobile telephony and defined in 3GPP TS 26.173.
+.SP
+AMR-WB audio has a fixed sampling rate of 16 kHz and supports encoding
+to the following bit-rates (as selected by the
+.B -C
+option): 0 = 6\*d6 kbit/s, 1 = 8\*d85 kbit/s, 2 = 12\*d65 kbit/s, 3 =
+14\*d25 kbit/s, 4 = 15\*d85 kbit/s 5 = 18\*d25 kbit/s, 6 = 19\*d85
+kbit/s, 7 = 23\*d05 kbit/s, 8 = 23\*d85 kbit/s
+.TP
\&\fB.au\fR, \fB.snd\fR \fB(also with \-t sndfile)\fR
Sun Microsystems AU files.
There are many types of AU file;
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -16,7 +16,7 @@
g723_40.c g72x.c g72x.h gsm.c hcom.c ima_rw.c ima_rw.h \
maud.c mp3.c nulfile.c prc.c raw.c sf.c sfircam.h skelform.c smp.c \
sndfile.c sndrtool.c sphere.c tx16w.c voc.c vorbis.c vox.c wav.c \
- wav.h wve.c xa.c
+ wav.h wve.c xa.c amr-wb.c
effects = band.h biquad.c biquad.h biquads.c chorus.c compand.c \
compandt.c compandt.h dcshift.c\
@@ -33,7 +33,7 @@
libst_la_LIBADD = @LIBGSM_LIBADD@
sox_SOURCES = sox.c
-sox_LDADD = libst.la
+sox_LDADD = libst.la ../amr-wb/libamrwb.la
EXTRA_DIST = tests.sh testall.sh tests.bat testall.bat monkey.au monkey.wav
--- /dev/null
+++ b/src/amr-wb.c
@@ -1,0 +1,211 @@
+/*
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, write to the Free Software Foundation,
+ * Fifth Floor, 51 Franklin Street, Boston, MA 02111-1301, USA.
+ */
+
+/* File format: AMR-WB (c) 2007 robs@users.sourceforge.net */
+
+#include "st_i.h"
+#include "../amr-wb/amr-wb.h"
+#include <string.h>
+#include <math.h>
+
+static char const magic[] = "#!AMR-WB\n";
+
+typedef struct amr_wb
+{
+ RX_State * rx_state;
+ TX_State * tx_state;
+ void * state;
+ Word16 coding_mode;
+ Word16 mode_previous;
+ st_bool reset;
+ st_bool reset_previous;
+ Word16 pcm[L_FRAME16k];
+ st_size_t pcm_index;
+} * amr_wb_t;
+
+assert_static(sizeof(struct amr_wb) <= ST_MAX_FILE_PRIVSIZE,
+ /* else */ amr_wb_PRIVSIZE_too_big);
+
+#define ENCODING 2 /* 0..2 */
+
+static st_size_t decode_1_frame(ft_t ft)
+{
+ amr_wb_t this = (amr_wb_t) ft->priv;
+ Word16 nb_bits, i;
+ Word16 mode, frame_type, frame_length;
+ Word16 prms[NB_BITS_MAX];
+
+ nb_bits = Read_serial(ft->fp, prms, &frame_type, &mode, this->rx_state, ENCODING);
+ if (nb_bits == 0)
+ return L_FRAME16k;
+
+ if (frame_type == RX_NO_DATA || frame_type == RX_SPEECH_LOST) {
+ mode = this->mode_previous;
+ this->reset = st_false;
+ } else {
+ this->mode_previous = mode;
+
+ if (this->reset_previous)
+ this->reset = decoder_homing_frame_test_first(prms, mode);
+ }
+ if (this->reset && this->reset_previous)
+ for (i = 0; i < L_FRAME16k; i++)
+ this->pcm[i] = EHF_MASK;
+ else
+ decoder(mode, prms, this->pcm, &frame_length, this->state, frame_type);
+ if (!this->reset_previous)
+ this->reset = decoder_homing_frame_test(prms, mode);
+ if (this->reset)
+ Reset_decoder(this->state, 1);
+ this->reset_previous = this->reset;
+ return 0;
+}
+
+static void encode_1_frame(ft_t ft)
+{
+ amr_wb_t this = (amr_wb_t) ft->priv;
+ st_size_t i;
+ Word16 nb_bits;
+ Word16 prms[NB_BITS_MAX];
+ Word16 reset = encoder_homing_frame_test(this->pcm);
+ Word16 mode = this->coding_mode;
+
+ for (i = 0; i < L_FRAME16k; ++i)
+ this->pcm[i] = this->pcm[i] & ~3;
+ coder(&mode, this->pcm, prms, &nb_bits, this->state, 1);
+ Write_serial(ft->fp, prms, mode, this->coding_mode, this->tx_state, ENCODING);
+ if (reset)
+ Reset_encoder(this->state, 1);
+}
+
+static void set_format(ft_t ft)
+{
+ ft->signal.rate = 16000;
+ ft->signal.size = ST_SIZE_16BIT;
+ ft->signal.encoding = ST_ENCODING_AMR_WB;
+ ft->signal.channels = 1;
+}
+
+static int startread(ft_t ft)
+{
+ amr_wb_t this = (amr_wb_t) ft->priv;
+
+ this->reset_previous = st_true;
+ this->pcm_index = L_FRAME16k;
+
+ Init_decoder(&this->state);
+ Init_read_serial(&this->rx_state);
+
+ if (ENCODING == 2) {
+ char buffer[sizeof(magic)];
+
+ fread(buffer, sizeof(char), sizeof(buffer) - 1, ft->fp);
+ buffer[sizeof(buffer) - 1] = 0;
+ if (strcmp(buffer, magic)) {
+ st_fail("Invalid magic number");
+ return ST_EOF;
+ }
+ }
+ set_format(ft);
+ return ST_SUCCESS;
+}
+
+static st_size_t read(ft_t ft, st_sample_t * buf, st_size_t len)
+{
+ amr_wb_t this = (amr_wb_t) ft->priv;
+ st_size_t done;
+
+ for (done = 0; done < len; done++) {
+ if (this->pcm_index >= L_FRAME16k)
+ this->pcm_index = decode_1_frame(ft);
+ if (this->pcm_index >= L_FRAME16k)
+ break;
+ *buf++ = ST_SIGNED_WORD_TO_SAMPLE(0xfffc & this->pcm[this->pcm_index++], ft->clips);
+ }
+ return done;
+}
+
+static int stopread(ft_t ft)
+{
+ amr_wb_t this = (amr_wb_t) ft->priv;
+ Close_decoder(this->state);
+ Close_read_serial(this->rx_state);
+ return ST_SUCCESS;
+}
+
+static int startwrite(ft_t ft)
+{
+ amr_wb_t this = (amr_wb_t) ft->priv;
+
+ if (ft->signal.compression != HUGE_VAL) {
+ this->coding_mode = ft->signal.compression;
+ if (this->coding_mode != ft->signal.compression || this->coding_mode > 8) {
+ st_fail_errno(ft, ST_EINVAL, "compression level must be a whole number from 0 to 8");
+ return ST_EOF;
+ }
+ }
+ else this->coding_mode = 0;
+
+ set_format(ft);
+ Init_coder(&this->state);
+ Init_write_serial(&this->tx_state);
+ if (ENCODING == 2)
+ st_writes(ft, magic);
+ this->pcm_index = 0;
+ return ST_SUCCESS;
+}
+
+static st_size_t write(ft_t ft, const st_sample_t * buf, st_size_t len)
+{
+ amr_wb_t this = (amr_wb_t) ft->priv;
+ st_size_t done;
+
+ for (done = 0; done < len; ++done) {
+ this->pcm[this->pcm_index++] = (Word16) (ST_SAMPLE_TO_SIGNED_WORD(*buf++, ft->clips));
+ if (this->pcm_index == L_FRAME16k) {
+ this->pcm_index = 0;
+ encode_1_frame(ft);
+ }
+ }
+ return done;
+}
+
+static int stopwrite(ft_t ft)
+{
+ amr_wb_t this = (amr_wb_t) ft->priv;
+
+ if (this->pcm_index) {
+ do {
+ this->pcm[this->pcm_index++] = 0;
+ } while (this->pcm_index < L_FRAME16k);
+ encode_1_frame(ft);
+ }
+ Close_coder(this->state);
+ Close_write_serial(this->tx_state);
+ return ST_SUCCESS;
+}
+
+st_format_t const * st_amr_wb_format_fn(void)
+{
+ static char const * names[] = {"amr-wb", NULL};
+ static st_format_t driver = {
+ names, NULL, 0,
+ startread, read, stopread,
+ startwrite, write, stopwrite,
+ st_format_nothing_seek
+ };
+ return &driver;
+}
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -21,6 +21,7 @@
#ifdef HAVE_ALSA
st_alsa_format_fn,
#endif
+ st_amr_wb_format_fn,
st_au_format_fn,
st_auto_format_fn,
st_avr_format_fn,
--- a/src/misc.c
+++ b/src/misc.c
@@ -72,6 +72,7 @@
"MPEG audio (layer I, II or III)",
"Vorbis",
"FLAC",
+ "AMR-WB",
};
assert_static(array_length(st_encodings_str) == ST_ENCODINGS,
--- a/src/st.h
+++ b/src/st.h
@@ -179,6 +179,7 @@
ST_ENCODING_MP3 , /* MP3 compression */
ST_ENCODING_VORBIS , /* Vorbis compression */
ST_ENCODING_FLAC , /* FLAC compression */
+ ST_ENCODING_AMR_WB , /* AMR-WB compression */
ST_ENCODINGS /* End of list marker */
} st_encoding_t;
--- a/src/st_i.h
+++ b/src/st_i.h
@@ -207,6 +207,7 @@
#ifdef HAVE_ALSA
extern const st_format_t *st_alsa_format_fn(void);
#endif
+extern const st_format_t *st_amr_wb_format_fn(void);
extern const st_format_t *st_au_format_fn(void);
extern const st_format_t *st_auto_format_fn(void);
extern const st_format_t *st_avr_format_fn(void);