Mercurial > hg > audiostuff
view intercom/gsm/lpc.c @ 2:13be24d74cd2
import intercom-0.4.1
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 09:57:52 +0200 |
parents | |
children |
line wrap: on
line source
/* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ /* $Header: /home/kbs/jutta/src/gsm/gsm-1.0/src/RCS/lpc.c,v 1.1 1992/10/28 00:15:50 jutta Exp $ */ #include <stdio.h> #include <assert.h> #include "private.h" #include "gsm.h" #include "proto.h" #undef P /* * 4.2.4 .. 4.2.7 LPC ANALYSIS SECTION */ /* 4.2.4 */ static void Autocorrelation P2((s, L_ACF), word * s, /* [0..159] IN/OUT */ longword * L_ACF) { /* [0..8] OUT */ /* * The goal is to compute the array L_ACF[k]. The signal s[i] must * be scaled in order to avoid an overflow situation. */ register int k, i; word temp, smax, scalauto; /* longword L_temp; */ #ifdef USE_FLOAT_MUL float float_s[160]; /* longword L_temp2; */ #else longword L_temp2; #endif /* Dynamic scaling of the array s[0..159] */ /* Search for the maximum. */ smax = 0; for (k = 0; k <= 159; k++) { temp = GSM_ABS(s[k]); if (temp > smax) smax = temp; } /* Computation of the scaling factor. */ if (smax == 0) scalauto = 0; else { assert(smax > 0); scalauto = 4 - gsm_norm((longword) smax << 16); /* sub(4,..) */ } /* Scaling of the array s[0...159] */ if (scalauto > 0) { # ifdef USE_FLOAT_MUL # define SCALE(n) \ case n: for (k = 0; k <= 159; k++) \ float_s[k] = (float) \ (s[k] = GSM_MULT_R(s[k], 16384 >> (n-1)));\ break; # else # define SCALE(n) \ case n: for (k = 0; k <= 159; k++) \ s[k] = GSM_MULT_R( s[k], 16384 >> (n-1) );\ break; # endif /* USE_FLOAT_MUL */ switch (scalauto) { SCALE(1) SCALE(2) SCALE(3) SCALE(4) } # undef SCALE } # ifdef USE_FLOAT_MUL else for (k = 0; k <= 159; k++) float_s[k] = (float) s[k]; # endif /* Compute the L_ACF[..]. */ { # ifdef USE_FLOAT_MUL register float *sp = float_s; register float sl = *sp; # else word *sp = s; word sl = *sp; # endif # define STEP(k) L_ACF[k] += (longword)(sl * sp[ -(k) ]); # define NEXTI sl = *++sp for (k = 9; k--; L_ACF[k] = 0); STEP(0); NEXTI; STEP(0); STEP(1); NEXTI; STEP(0); STEP(1); STEP(2); NEXTI; STEP(0); STEP(1); STEP(2); STEP(3); NEXTI; STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); NEXTI; STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); NEXTI; STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); NEXTI; STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); STEP(7); for (i = 8; i <= 159; i++) { NEXTI; STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); STEP(7); STEP(8); } for (k = 9; k--; L_ACF[k] <<= 1); } /* Rescaling of the array s[0..159] */ if (scalauto > 0) { assert(scalauto <= 4); for (k = 160; k--; *s++ <<= scalauto); } } #if defined(USE_FLOAT_MUL) && defined(FAST) static void Fast_Autocorrelation P2((s, L_ACF), word * s, /* [0..159] IN/OUT */ longword * L_ACF) { /* [0..8] OUT */ register int k, i; float f_L_ACF[9]; float scale; float s_f[160]; register float *sf = s_f; for (i = 0; i < 160; ++i) sf[i] = s[i]; for (k = 0; k <= 8; k++) { register float L_temp2 = 0; register float *sfl = sf - k; for (i = k; i < 160; ++i) L_temp2 += sf[i] * sfl[i]; f_L_ACF[k] = L_temp2; } scale = MAX_LONGWORD / f_L_ACF[0]; for (k = 0; k <= 8; k++) { L_ACF[k] = f_L_ACF[k] * scale; } } #endif /* defined (USE_FLOAT_MUL) && defined (FAST) */ /* 4.2.5 */ static void Reflection_coefficients P2((L_ACF, r), longword * L_ACF, /* 0...8 IN */ register word * r /* 0...7 OUT */ ) { register int i, m, n; register word temp; register longword ltmp; word ACF[9]; /* 0..8 */ word P[9]; /* 0..8 */ word K[9]; /* 2..8 */ /* Schur recursion with 16 bits arithmetic. */ if (L_ACF[0] == 0) { /* everything is the same. */ for (i = 8; i--; *r++ = 0); return; } assert(L_ACF[0] != 0); temp = gsm_norm(L_ACF[0]); assert(temp >= 0 && temp < 32); /* ? overflow ? */ for (i = 0; i <= 8; i++) ACF[i] = SASR(L_ACF[i] << temp, 16); /* Initialize array P[..] and K[..] for the recursion. */ for (i = 1; i <= 7; i++) K[i] = ACF[i]; for (i = 0; i <= 8; i++) P[i] = ACF[i]; /* Compute reflection coefficients */ for (n = 1; n <= 8; n++, r++) { temp = P[1]; temp = GSM_ABS(temp); if (P[0] < temp) { for (i = n; i <= 8; i++) *r++ = 0; return; } *r = gsm_div(temp, P[0]); assert(*r >= 0); if (P[1] > 0) *r = -*r; /* r[n] = sub(0, r[n]) */ assert(*r != MIN_WORD); if (n == 8) return; /* Schur recursion */ temp = GSM_MULT_R(P[1], *r); P[0] = GSM_ADD(P[0], temp); for (m = 1; m <= 8 - n; m++) { temp = GSM_MULT_R(K[m], *r); P[m] = GSM_ADD(P[m + 1], temp); temp = GSM_MULT_R(P[m + 1], *r); K[m] = GSM_ADD(K[m], temp); } } } /* 4.2.6 */ static void Transformation_to_Log_Area_Ratios P1((r), register word * r /* 0..7 IN/OUT */ ) /* * The following scaling for r[..] and LAR[..] has been used: * * r[..] = integer( real_r[..]*32768. ); -1 <= real_r < 1. * LAR[..] = integer( real_LAR[..] * 16384 ); * with -1.625 <= real_LAR <= 1.625 */ { register word temp; register int i; /* Computation of the LAR[0..7] from the r[0..7] */ for (i = 1; i <= 8; i++, r++) { temp = *r; temp = GSM_ABS(temp); assert(temp >= 0); if (temp < 22118) { temp >>= 1; } else if (temp < 31130) { assert(temp >= 11059); temp -= 11059; } else { assert(temp >= 26112); temp -= 26112; temp <<= 2; } *r = *r < 0 ? -temp : temp; assert(*r != MIN_WORD); } } /* 4.2.7 */ static void Quantization_and_coding P1((LAR), register word * LAR /* [0..7] IN/OUT */ ) { register word temp; longword ltmp; /* ulongword utmp; reported as unused */ /* This procedure needs four tables; the following equations * give the optimum scaling for the constants: * * A[0..7] = integer( real_A[0..7] * 1024 ) * B[0..7] = integer( real_B[0..7] * 512 ) * MAC[0..7] = maximum of the LARc[0..7] * MIC[0..7] = minimum of the LARc[0..7] */ # undef STEP # define STEP( A, B, MAC, MIC ) \ temp = GSM_MULT( A, *LAR ); \ temp = GSM_ADD( temp, B ); \ temp = GSM_ADD( temp, 256 ); \ temp = SASR( temp, 9 ); \ *LAR = temp>MAC ? MAC - MIC : (temp<MIC ? 0 : temp - MIC); \ LAR++; STEP(20480, 0, 31, -32); STEP(20480, 0, 31, -32); STEP(20480, 2048, 15, -16); STEP(20480, -2560, 15, -16); STEP(13964, 94, 7, -8); STEP(15360, -1792, 7, -8); STEP(8534, -341, 3, -4); STEP(9036, -1144, 3, -4); # undef STEP } void Gsm_LPC_Analysis P3((S, s, LARc), struct gsm_state *S, word * s, /* 0..159 signals IN/OUT */ word * LARc) { /* 0..7 LARc's OUT */ longword L_ACF[9]; #if defined(USE_FLOAT_MUL) && defined(FAST) if (S->fast) Fast_Autocorrelation(s, L_ACF); else #endif Autocorrelation(s, L_ACF); Reflection_coefficients(L_ACF, LARc); Transformation_to_Log_Area_Ratios(LARc); Quantization_and_coding(LARc); }