FreeCalypso > hg > gsm-codec-lib
view libgsmefr/c1035pf.c @ 467:ad032051166a
doc: AMR-EFR-hybrid-emu new article
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 12 May 2024 23:54:43 +0000 |
parents | 12d9d3649232 |
children |
line wrap: on
line source
#include "gsm_efr.h" #include "typedef.h" #include "namespace.h" #include "basic_op.h" #include "no_count.h" #include "sig_proc.h" #include "codec.h" #define L_CODE 40 #define NB_TRACK 5 #define NB_PULSE 10 #define STEP 5 /* local functions */ static void cor_h_x ( Word16 h[], /* (i) : impulse response of weighted synthesis filter */ Word16 x[], /* (i) : target */ Word16 dn[] /* (o) : correlation between target and h[] */ ); static void set_sign ( Word16 dn[], /* (i/o) : correlation between target and h[] */ Word16 cn[], /* (i) : residual after long term prediction */ Word16 sign[], /* (o) : sign of d[n] */ Word16 pos_max[], /* (o) : position of maximum of dn[] */ Word16 ipos[] /* (o) : starting position for each pulse */ ); static void cor_h ( Word16 h[], /* (i) : impulse response of weighted synthesis filter */ Word16 sign[], /* (i) : sign of d[n] */ Word16 rr[][L_CODE] /* (o) : matrix of autocorrelation */ ); static void search_10i40 ( Word16 dn[], /* (i) : correlation between target and h[] */ Word16 rr[][L_CODE], /* (i) : matrix of autocorrelation */ Word16 ipos[], /* (i) : starting position for each pulse */ Word16 pos_max[], /* (i) : position of maximum of dn[] */ Word16 codvec[] /* (o) : algebraic codebook vector */ ); static void build_code ( Word16 codvec[], /* (i) : algebraic codebook vector */ Word16 sign[], /* (i) : sign of dn[] */ Word16 cod[], /* (o) : algebraic (fixed) codebook excitation */ Word16 h[], /* (i) : impulse response of weighted synthesis filter*/ Word16 y[], /* (o) : filtered fixed codebook excitation */ Word16 indx[] /* (o) : index of 10 pulses (position+sign+ampl)*10 */ ); static void q_p ( Word16 *ind, /* Pulse position */ Word16 n /* Pulse number */ ); /************************************************************************* * * FUNCTION: code_10i40_35bits() * * PURPOSE: Searches a 35 bit algebraic codebook containing 10 pulses * in a frame of 40 samples. * * DESCRIPTION: * The code contains 10 nonzero pulses: i0...i9. * All pulses can have two possible amplitudes: +1 or -1. * The 40 positions in a subframe are divided into 5 tracks of * interleaved positions. Each track contains two pulses. * The pulses can have the following possible positions: * * i0, i5 : 0, 5, 10, 15, 20, 25, 30, 35. * i1, i6 : 1, 6, 11, 16, 21, 26, 31, 36. * i2, i7 : 2, 7, 12, 17, 22, 27, 32, 37. * i3, i8 : 3, 8, 13, 18, 23, 28, 33, 38. * i4, i9 : 4, 9, 14, 19, 24, 29, 34, 39. * * Each pair of pulses require 1 bit for their signs and 6 bits for their * positions (3 bits + 3 bits). This results in a 35 bit codebook. * The function determines the optimal pulse signs and positions, builds * the codevector, and computes the filtered codevector. * *************************************************************************/ void code_10i40_35bits ( Word16 x[], /* (i) : target vector */ Word16 cn[], /* (i) : residual after long term prediction */ Word16 h[], /* (i) : impulse response of weighted synthesis filter h[-L_subfr..-1] must be set to zero */ Word16 cod[], /* (o) : algebraic (fixed) codebook excitation */ Word16 y[], /* (o) : filtered fixed codebook excitation */ Word16 indx[] /* (o) : index of 10 pulses (sign + position) */ ) { Word16 ipos[NB_PULSE], pos_max[NB_TRACK], codvec[NB_PULSE]; Word16 dn[L_CODE], sign[L_CODE]; Word16 rr[L_CODE][L_CODE], i; cor_h_x (h, x, dn); set_sign (dn, cn, sign, pos_max, ipos); cor_h (h, sign, rr); search_10i40 (dn, rr, ipos, pos_max, codvec); build_code (codvec, sign, cod, h, y, indx); for (i = 0; i < 10; i++) { q_p (&indx[i], i); } return; } /************************************************************************* * * FUNCTION: cor_h_x() * * PURPOSE: Computes correlation between target signal "x[]" and * impulse response"h[]". * * DESCRIPTION: * The correlation is given by: * d[n] = sum_{i=n}^{L-1} x[i] h[i-n] n=0,...,L-1 * * d[n] is normalized such that the sum of 5 maxima of d[n] corresponding * to each position track does not saturate. * *************************************************************************/ static void cor_h_x ( Word16 h[], /* (i) : impulse response of weighted synthesis filter */ Word16 x[], /* (i) : target */ Word16 dn[] /* (o) : correlation between target and h[] */ ) { Word16 i, j, k; Word32 s, y32[L_CODE], max, tot; /* first keep the result on 32 bits and find absolute maximum */ tot = 5; move32 (); for (k = 0; k < NB_TRACK; k++) { max = 0; move32 (); for (i = k; i < L_CODE; i += STEP) { s = 0; move32 (); for (j = i; j < L_CODE; j++) s = L_mac (s, x[j], h[j - i]); y32[i] = s; move32 (); s = L_abs (s); test (); if (s > max) max = s; move32 (); } tot = L_add (tot, L_shr (max, 1)); } j = sub (norm_l (tot), 2); /* multiply tot by 4 */ for (i = 0; i < L_CODE; i++) { dn[i] = round (L_shl (y32[i], j)); move16 (); } } /************************************************************************* * * FUNCTION set_sign() * * PURPOSE: Builds sign[] vector according to "dn[]" and "cn[]", and modifies * dn[] to include the sign information (dn[i]=sign[i]*dn[i]). * Also finds the position of maximum of correlation in each track * and the starting position for each pulse. * *************************************************************************/ static void set_sign ( Word16 dn[], /* (i/o): correlation between target and h[] */ Word16 cn[], /* (i) : residual after long term prediction */ Word16 sign[], /* (o) : sign of d[n] */ Word16 pos_max[], /* (o) : position of maximum correlation */ Word16 ipos[] /* (o) : starting position for each pulse */ ) { Word16 i, j; Word16 val, cor, k_cn, k_dn, max, max_of_all, pos; Word16 en[L_CODE]; /* correlation vector */ Word32 s; /* calculate energy for normalization of cn[] and dn[] */ s = 256; move32 (); for (i = 0; i < L_CODE; i++) { s = L_mac (s, cn[i], cn[i]); } s = Inv_sqrt (s); move32 (); k_cn = extract_h (L_shl (s, 5)); s = 256; move32 (); for (i = 0; i < L_CODE; i++) { s = L_mac (s, dn[i], dn[i]); } s = Inv_sqrt (s); move32 (); k_dn = extract_h (L_shl (s, 5)); for (i = 0; i < L_CODE; i++) { val = dn[i]; move16 (); cor = round (L_shl (L_mac (L_mult (k_cn, cn[i]), k_dn, val), 10)); test (); if (cor >= 0) { sign[i] = 32767; move16 (); /* sign = +1 */ } else { sign[i] = -32767; move16 (); /* sign = -1 */ cor = negate (cor); val = negate (val); } /* modify dn[] according to the fixed sign */ dn[i] = val; move16 (); en[i] = cor; move16 (); } max_of_all = -1; move16 (); for (i = 0; i < NB_TRACK; i++) { max = -1; move16 (); for (j = i; j < L_CODE; j += STEP) { cor = en[j]; move16 (); val = sub (cor, max); test (); if (val > 0) { max = cor; move16 (); pos = j; move16 (); } } /* store maximum correlation position */ pos_max[i] = pos; move16 (); val = sub (max, max_of_all); test (); if (val > 0) { max_of_all = max; move16 (); /* starting position for i0 */ ipos[0] = i; move16 (); } } /*----------------------------------------------------------------* * Set starting position of each pulse. * *----------------------------------------------------------------*/ pos = ipos[0]; move16 (); ipos[5] = pos; move16 (); for (i = 1; i < NB_TRACK; i++) { pos++; if (pos >= NB_TRACK) { pos = 0; move16 (); } ipos[i] = pos; move16 (); ipos[i + 5] = pos; move16 (); } } static void q_p ( Word16 *ind, /* Pulse position */ Word16 n /* Pulse number */ ) { static const Word16 gray[8] = {0, 1, 3, 2, 6, 4, 5, 7}; Word16 tmp; tmp = *ind; move16 (); test (); if (n < 5) { tmp = (tmp & 0x8) | gray[tmp & 0x7]; logic16 (); logic16 (); logic16 (); } else { tmp = gray[tmp & 0x7]; logic16 (); move16 (); } *ind = tmp; move16 (); } /************************************************************************* * * FUNCTION: cor_h() * * PURPOSE: Computes correlations of h[] needed for the codebook search; * and includes the sign information into the correlations. * * DESCRIPTION: The correlations are given by * rr[i][j] = sum_{n=i}^{L-1} h[n-i] h[n-j]; i>=j; i,j=0,...,L-1 * * and the sign information is included by * rr[i][j] = rr[i][j]*sign[i]*sign[j] * *************************************************************************/ static void cor_h ( Word16 h[], /* (i) : impulse response of weighted synthesis filter */ Word16 sign[], /* (i) : sign of d[n] */ Word16 rr[][L_CODE] /* (o) : matrix of autocorrelation */ ) { Word16 i, j, k, dec, h2[L_CODE]; Word32 s; /* Scaling for maximum precision */ s = 2; move32 (); for (i = 0; i < L_CODE; i++) s = L_mac (s, h[i], h[i]); j = sub (extract_h (s), 32767); test (); if (j == 0) { for (i = 0; i < L_CODE; i++) { h2[i] = shr (h[i], 1); move16 (); } } else { s = L_shr (s, 1); k = extract_h (L_shl (Inv_sqrt (s), 7)); k = mult (k, 32440); /* k = 0.99*k */ for (i = 0; i < L_CODE; i++) { h2[i] = round (L_shl (L_mult (h[i], k), 9)); move16 (); } } /* build matrix rr[] */ s = 0; move32 (); i = L_CODE - 1; for (k = 0; k < L_CODE; k++, i--) { s = L_mac (s, h2[k], h2[k]); rr[i][i] = round (s); move16 (); } for (dec = 1; dec < L_CODE; dec++) { s = 0; move32 (); j = L_CODE - 1; i = sub (j, dec); for (k = 0; k < (L_CODE - dec); k++, i--, j--) { s = L_mac (s, h2[k], h2[k + dec]); rr[j][i] = mult (round (s), mult (sign[i], sign[j])); move16 (); rr[i][j] = rr[j][i]; move16 (); } } } /************************************************************************* * * FUNCTION search_10i40() * * PURPOSE: Search the best codevector; determine positions of the 10 pulses * in the 40-sample frame. * *************************************************************************/ #define _1_2 (Word16)(32768L/2) #define _1_4 (Word16)(32768L/4) #define _1_8 (Word16)(32768L/8) #define _1_16 (Word16)(32768L/16) #define _1_32 (Word16)(32768L/32) #define _1_64 (Word16)(32768L/64) #define _1_128 (Word16)(32768L/128) static void search_10i40 ( Word16 dn[], /* (i) : correlation between target and h[] */ Word16 rr[][L_CODE], /* (i) : matrix of autocorrelation */ Word16 ipos[], /* (i) : starting position for each pulse */ Word16 pos_max[], /* (i) : position of maximum of dn[] */ Word16 codvec[] /* (o) : algebraic codebook vector */ ) { Word16 i0, i1, i2, i3, i4, i5, i6, i7, i8, i9; Word16 i, j, k, pos, ia, ib; Word16 psk, ps, ps0, ps1, ps2, sq, sq2; Word16 alpk, alp, alp_16; Word16 rrv[L_CODE]; Word32 s, alp0, alp1, alp2; /* fix i0 on maximum of correlation position */ i0 = pos_max[ipos[0]]; move16 (); /*------------------------------------------------------------------* * i1 loop: * *------------------------------------------------------------------*/ /* Default value */ psk = -1; move16 (); alpk = 1; move16 (); for (i = 0; i < NB_PULSE; i++) { codvec[i] = i; move16 (); } for (i = 1; i < NB_TRACK; i++) { i1 = pos_max[ipos[1]]; move16 (); ps0 = add (dn[i0], dn[i1]); alp0 = L_mult (rr[i0][i0], _1_16); alp0 = L_mac (alp0, rr[i1][i1], _1_16); alp0 = L_mac (alp0, rr[i0][i1], _1_8); /*----------------------------------------------------------------* * i2 and i3 loop: * *----------------------------------------------------------------*/ /* initialize 4 indices for next loop. */ move16 (); /* initialize "rr[i3][i3]" pointer */ move16 (); /* initialize "rr[i0][i3]" pointer */ move16 (); /* initialize "rr[i1][i3]" pointer */ move16 (); /* initialize "rrv[i3]" pointer */ for (i3 = ipos[3]; i3 < L_CODE; i3 += STEP) { s = L_mult (rr[i3][i3], _1_8); /* index incr= STEP+L_CODE */ s = L_mac (s, rr[i0][i3], _1_4); /* index increment = STEP */ s = L_mac (s, rr[i1][i3], _1_4); /* index increment = STEP */ rrv[i3] = round (s); move16 (); } /* Default value */ sq = -1; move16 (); alp = 1; move16 (); ps = 0; move16 (); ia = ipos[2]; move16 (); ib = ipos[3]; move16 (); /* initialize 4 indices for i2 loop. */ move16 (); /* initialize "dn[i2]" pointer */ move16 (); /* initialize "rr[i2][i2]" pointer */ move16 (); /* initialize "rr[i0][i2]" pointer */ move16 (); /* initialize "rr[i1][i2]" pointer */ for (i2 = ipos[2]; i2 < L_CODE; i2 += STEP) { /* index increment = STEP */ ps1 = add (ps0, dn[i2]); /* index incr= STEP+L_CODE */ alp1 = L_mac (alp0, rr[i2][i2], _1_16); /* index increment = STEP */ alp1 = L_mac (alp1, rr[i0][i2], _1_8); /* index increment = STEP */ alp1 = L_mac (alp1, rr[i1][i2], _1_8); /* initialize 3 indices for i3 inner loop */ move16 (); /* initialize "dn[i3]" pointer */ move16 (); /* initialize "rrv[i3]" pointer */ move16 (); /* initialize "rr[i2][i3]" pointer */ for (i3 = ipos[3]; i3 < L_CODE; i3 += STEP) { /* index increment = STEP */ ps2 = add (ps1, dn[i3]); /* index increment = STEP */ alp2 = L_mac (alp1, rrv[i3], _1_2); /* index increment = STEP */ alp2 = L_mac (alp2, rr[i2][i3], _1_8); sq2 = mult (ps2, ps2); alp_16 = round (alp2); s = L_msu (L_mult (alp, sq2), sq, alp_16); test (); if (s > 0) { sq = sq2; move16 (); ps = ps2; move16 (); alp = alp_16; move16 (); ia = i2; move16 (); ib = i3; move16 (); } } } i2 = ia; move16 (); i3 = ib; move16 (); /*----------------------------------------------------------------* * i4 and i5 loop: * *----------------------------------------------------------------*/ ps0 = ps; move16 (); alp0 = L_mult (alp, _1_2); /* initialize 6 indices for next loop (see i2-i3 loop) */ move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); for (i5 = ipos[5]; i5 < L_CODE; i5 += STEP) { s = L_mult (rr[i5][i5], _1_8); s = L_mac (s, rr[i0][i5], _1_4); s = L_mac (s, rr[i1][i5], _1_4); s = L_mac (s, rr[i2][i5], _1_4); s = L_mac (s, rr[i3][i5], _1_4); rrv[i5] = round (s); move16 (); } /* Default value */ sq = -1; move16 (); alp = 1; move16 (); ps = 0; move16 (); ia = ipos[4]; move16 (); ib = ipos[5]; move16 (); /* initialize 6 indices for i4 loop (see i2-i3 loop) */ move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); for (i4 = ipos[4]; i4 < L_CODE; i4 += STEP) { ps1 = add (ps0, dn[i4]); alp1 = L_mac (alp0, rr[i4][i4], _1_32); alp1 = L_mac (alp1, rr[i0][i4], _1_16); alp1 = L_mac (alp1, rr[i1][i4], _1_16); alp1 = L_mac (alp1, rr[i2][i4], _1_16); alp1 = L_mac (alp1, rr[i3][i4], _1_16); /* initialize 3 indices for i5 inner loop (see i2-i3 loop) */ move16 (); move16 (); move16 (); for (i5 = ipos[5]; i5 < L_CODE; i5 += STEP) { ps2 = add (ps1, dn[i5]); alp2 = L_mac (alp1, rrv[i5], _1_4); alp2 = L_mac (alp2, rr[i4][i5], _1_16); sq2 = mult (ps2, ps2); alp_16 = round (alp2); s = L_msu (L_mult (alp, sq2), sq, alp_16); test (); if (s > 0) { sq = sq2; move16 (); ps = ps2; move16 (); alp = alp_16; move16 (); ia = i4; move16 (); ib = i5; move16 (); } } } i4 = ia; move16 (); i5 = ib; move16 (); /*----------------------------------------------------------------* * i6 and i7 loop: * *----------------------------------------------------------------*/ ps0 = ps; move16 (); alp0 = L_mult (alp, _1_2); /* initialize 8 indices for next loop (see i2-i3 loop) */ move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); for (i7 = ipos[7]; i7 < L_CODE; i7 += STEP) { s = L_mult (rr[i7][i7], _1_16); s = L_mac (s, rr[i0][i7], _1_8); s = L_mac (s, rr[i1][i7], _1_8); s = L_mac (s, rr[i2][i7], _1_8); s = L_mac (s, rr[i3][i7], _1_8); s = L_mac (s, rr[i4][i7], _1_8); s = L_mac (s, rr[i5][i7], _1_8); rrv[i7] = round (s); move16 (); } /* Default value */ sq = -1; move16 (); alp = 1; move16 (); ps = 0; move16 (); ia = ipos[6]; move16 (); ib = ipos[7]; move16 (); /* initialize 8 indices for i6 loop (see i2-i3 loop) */ move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); for (i6 = ipos[6]; i6 < L_CODE; i6 += STEP) { ps1 = add (ps0, dn[i6]); alp1 = L_mac (alp0, rr[i6][i6], _1_64); alp1 = L_mac (alp1, rr[i0][i6], _1_32); alp1 = L_mac (alp1, rr[i1][i6], _1_32); alp1 = L_mac (alp1, rr[i2][i6], _1_32); alp1 = L_mac (alp1, rr[i3][i6], _1_32); alp1 = L_mac (alp1, rr[i4][i6], _1_32); alp1 = L_mac (alp1, rr[i5][i6], _1_32); /* initialize 3 indices for i7 inner loop (see i2-i3 loop) */ move16 (); move16 (); move16 (); for (i7 = ipos[7]; i7 < L_CODE; i7 += STEP) { ps2 = add (ps1, dn[i7]); alp2 = L_mac (alp1, rrv[i7], _1_4); alp2 = L_mac (alp2, rr[i6][i7], _1_32); sq2 = mult (ps2, ps2); alp_16 = round (alp2); s = L_msu (L_mult (alp, sq2), sq, alp_16); test (); if (s > 0) { sq = sq2; move16 (); ps = ps2; move16 (); alp = alp_16; move16 (); ia = i6; move16 (); ib = i7; move16 (); } } } i6 = ia; move16 (); i7 = ib; move16 (); /*----------------------------------------------------------------* * i8 and i9 loop: * *----------------------------------------------------------------*/ ps0 = ps; move16 (); alp0 = L_mult (alp, _1_2); /* initialize 10 indices for next loop (see i2-i3 loop) */ move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); for (i9 = ipos[9]; i9 < L_CODE; i9 += STEP) { s = L_mult (rr[i9][i9], _1_16); s = L_mac (s, rr[i0][i9], _1_8); s = L_mac (s, rr[i1][i9], _1_8); s = L_mac (s, rr[i2][i9], _1_8); s = L_mac (s, rr[i3][i9], _1_8); s = L_mac (s, rr[i4][i9], _1_8); s = L_mac (s, rr[i5][i9], _1_8); s = L_mac (s, rr[i6][i9], _1_8); s = L_mac (s, rr[i7][i9], _1_8); rrv[i9] = round (s); move16 (); } /* Default value */ sq = -1; move16 (); alp = 1; move16 (); ps = 0; move16 (); ia = ipos[8]; move16 (); ib = ipos[9]; move16 (); /* initialize 10 indices for i8 loop (see i2-i3 loop) */ move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); for (i8 = ipos[8]; i8 < L_CODE; i8 += STEP) { ps1 = add (ps0, dn[i8]); alp1 = L_mac (alp0, rr[i8][i8], _1_128); alp1 = L_mac (alp1, rr[i0][i8], _1_64); alp1 = L_mac (alp1, rr[i1][i8], _1_64); alp1 = L_mac (alp1, rr[i2][i8], _1_64); alp1 = L_mac (alp1, rr[i3][i8], _1_64); alp1 = L_mac (alp1, rr[i4][i8], _1_64); alp1 = L_mac (alp1, rr[i5][i8], _1_64); alp1 = L_mac (alp1, rr[i6][i8], _1_64); alp1 = L_mac (alp1, rr[i7][i8], _1_64); /* initialize 3 indices for i9 inner loop (see i2-i3 loop) */ move16 (); move16 (); move16 (); for (i9 = ipos[9]; i9 < L_CODE; i9 += STEP) { ps2 = add (ps1, dn[i9]); alp2 = L_mac (alp1, rrv[i9], _1_8); alp2 = L_mac (alp2, rr[i8][i9], _1_64); sq2 = mult (ps2, ps2); alp_16 = round (alp2); s = L_msu (L_mult (alp, sq2), sq, alp_16); test (); if (s > 0) { sq = sq2; move16 (); ps = ps2; move16 (); alp = alp_16; move16 (); ia = i8; move16 (); ib = i9; move16 (); } } } /*----------------------------------------------------------------* * memorise codevector if this one is better than the last one. * *----------------------------------------------------------------*/ s = L_msu (L_mult (alpk, sq), psk, alp); test (); if (s > 0) { psk = sq; move16 (); alpk = alp; move16 (); codvec[0] = i0; move16 (); codvec[1] = i1; move16 (); codvec[2] = i2; move16 (); codvec[3] = i3; move16 (); codvec[4] = i4; move16 (); codvec[5] = i5; move16 (); codvec[6] = i6; move16 (); codvec[7] = i7; move16 (); codvec[8] = ia; move16 (); codvec[9] = ib; move16 (); } /*----------------------------------------------------------------* * Cyclic permutation of i1,i2,i3,i4,i5,i6,i7,i8 and i9. * *----------------------------------------------------------------*/ pos = ipos[1]; move16 (); for (j = 1, k = 2; k < NB_PULSE; j++, k++) { ipos[j] = ipos[k]; move16 (); } ipos[NB_PULSE - 1] = pos; move16 (); } } /************************************************************************* * * FUNCTION: build_code() * * PURPOSE: Builds the codeword, the filtered codeword and index of the * codevector, based on the signs and positions of 10 pulses. * *************************************************************************/ static void build_code ( Word16 codvec[], /* (i) : position of pulses */ Word16 sign[], /* (i) : sign of d[n] */ Word16 cod[], /* (o) : innovative code vector */ Word16 h[], /* (i) : impulse response of weighted synthesis filter*/ Word16 y[], /* (o) : filtered innovative code */ Word16 indx[] /* (o) : index of 10 pulses (sign+position) */ ) { Word16 i, j, k, track, index, _sign[NB_PULSE]; Word16 *p0, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9; Word32 s; for (i = 0; i < L_CODE; i++) { cod[i] = 0; move16 (); } for (i = 0; i < NB_TRACK; i++) { indx[i] = -1; move16 (); } for (k = 0; k < NB_PULSE; k++) { /* read pulse position */ i = codvec[k]; move16 (); /* read sign */ j = sign[i]; move16 (); index = mult (i, 6554); /* index = pos/5 */ /* track = pos%5 */ track = sub (i, extract_l (L_shr (L_mult (index, 5), 1))); test (); if (j > 0) { cod[i] = add (cod[i], 4096); _sign[k] = 8192; move16 (); } else { cod[i] = sub (cod[i], 4096); _sign[k] = -8192; move16 (); index = add (index, 8); } test (); if (indx[track] < 0) { indx[track] = index; move16 (); } else { test (); logic16 (); logic16 (); if (((index ^ indx[track]) & 8) == 0) { /* sign of 1st pulse == sign of 2nd pulse */ test (); if (indx[track] <= index) { indx[track + 5] = index; move16 (); } else { indx[track + 5] = indx[track]; move16 (); indx[track] = index; move16 (); } } else { /* sign of 1st pulse != sign of 2nd pulse */ test (); logic16 (); logic16 (); if ((indx[track] & 7) <= (index & 7)) { indx[track + 5] = indx[track]; move16 (); indx[track] = index; move16 (); } else { indx[track + 5] = index; move16 (); } } } } p0 = h - codvec[0]; move16 (); p1 = h - codvec[1]; move16 (); p2 = h - codvec[2]; move16 (); p3 = h - codvec[3]; move16 (); p4 = h - codvec[4]; move16 (); p5 = h - codvec[5]; move16 (); p6 = h - codvec[6]; move16 (); p7 = h - codvec[7]; move16 (); p8 = h - codvec[8]; move16 (); p9 = h - codvec[9]; move16 (); for (i = 0; i < L_CODE; i++) { s = 0; move32 (); s = L_mac (s, *p0++, _sign[0]); s = L_mac (s, *p1++, _sign[1]); s = L_mac (s, *p2++, _sign[2]); s = L_mac (s, *p3++, _sign[3]); s = L_mac (s, *p4++, _sign[4]); s = L_mac (s, *p5++, _sign[5]); s = L_mac (s, *p6++, _sign[6]); s = L_mac (s, *p7++, _sign[7]); s = L_mac (s, *p8++, _sign[8]); s = L_mac (s, *p9++, _sign[9]); y[i] = round (s); move16 (); } }