FreeCalypso > hg > gsm-codec-lib
comparison libgsmfr2/lpc.c @ 268:0cfb7c95cce2
libgsmfr2: integrate lpc.c from libgsm
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Sun, 14 Apr 2024 01:50:48 +0000 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 267:65d3304502bd | 268:0cfb7c95cce2 |
|---|---|
| 1 /* | |
| 2 * This C source file has been adapted from TU-Berlin libgsm source, | |
| 3 * original notice follows: | |
| 4 * | |
| 5 * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische | |
| 6 * Universitaet Berlin. See the accompanying file "COPYRIGHT" for | |
| 7 * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. | |
| 8 */ | |
| 9 | |
| 10 #include <stdint.h> | |
| 11 #include <assert.h> | |
| 12 #include "tw_gsmfr.h" | |
| 13 #include "typedef.h" | |
| 14 #include "ed_state.h" | |
| 15 #include "ed_internal.h" | |
| 16 | |
| 17 /* | |
| 18 * 4.2.4 .. 4.2.7 LPC ANALYSIS SECTION | |
| 19 */ | |
| 20 | |
| 21 /* 4.2.4 */ | |
| 22 | |
| 23 static void Autocorrelation ( | |
| 24 word * s, /* [0..159] IN/OUT */ | |
| 25 longword * L_ACF) /* [0..8] OUT */ | |
| 26 /* | |
| 27 * The goal is to compute the array L_ACF[k]. The signal s[i] must | |
| 28 * be scaled in order to avoid an overflow situation. | |
| 29 */ | |
| 30 { | |
| 31 register int k, i; | |
| 32 | |
| 33 word temp, smax, scalauto; | |
| 34 | |
| 35 /* Dynamic scaling of the array s[0..159] | |
| 36 */ | |
| 37 | |
| 38 /* Search for the maximum. | |
| 39 */ | |
| 40 smax = 0; | |
| 41 for (k = 0; k <= 159; k++) { | |
| 42 temp = GSM_ABS( s[k] ); | |
| 43 if (temp > smax) smax = temp; | |
| 44 } | |
| 45 | |
| 46 /* Computation of the scaling factor. | |
| 47 */ | |
| 48 if (smax == 0) scalauto = 0; | |
| 49 else { | |
| 50 assert(smax > 0); | |
| 51 scalauto = 4 - gsm_norm( (longword)smax << 16 );/* sub(4,..) */ | |
| 52 } | |
| 53 | |
| 54 /* Scaling of the array s[0...159] | |
| 55 */ | |
| 56 | |
| 57 if (scalauto > 0) { | |
| 58 | |
| 59 # define SCALE(n) \ | |
| 60 case n: for (k = 0; k <= 159; k++) \ | |
| 61 s[k] = GSM_MULT_R( s[k], 16384 >> (n-1) );\ | |
| 62 break; | |
| 63 | |
| 64 switch (scalauto) { | |
| 65 SCALE(1) | |
| 66 SCALE(2) | |
| 67 SCALE(3) | |
| 68 SCALE(4) | |
| 69 } | |
| 70 # undef SCALE | |
| 71 } | |
| 72 | |
| 73 /* Compute the L_ACF[..]. | |
| 74 */ | |
| 75 { | |
| 76 word * sp = s; | |
| 77 word sl = *sp; | |
| 78 | |
| 79 # define STEP(k) L_ACF[k] += ((longword)sl * sp[ -(k) ]); | |
| 80 | |
| 81 # define NEXTI sl = *++sp | |
| 82 | |
| 83 | |
| 84 for (k = 9; k--; L_ACF[k] = 0) ; | |
| 85 | |
| 86 STEP (0); | |
| 87 NEXTI; | |
| 88 STEP(0); STEP(1); | |
| 89 NEXTI; | |
| 90 STEP(0); STEP(1); STEP(2); | |
| 91 NEXTI; | |
| 92 STEP(0); STEP(1); STEP(2); STEP(3); | |
| 93 NEXTI; | |
| 94 STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); | |
| 95 NEXTI; | |
| 96 STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); | |
| 97 NEXTI; | |
| 98 STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); | |
| 99 NEXTI; | |
| 100 STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); STEP(7); | |
| 101 | |
| 102 for (i = 8; i <= 159; i++) { | |
| 103 | |
| 104 NEXTI; | |
| 105 | |
| 106 STEP(0); | |
| 107 STEP(1); STEP(2); STEP(3); STEP(4); | |
| 108 STEP(5); STEP(6); STEP(7); STEP(8); | |
| 109 } | |
| 110 | |
| 111 for (k = 9; k--; L_ACF[k] <<= 1) ; | |
| 112 | |
| 113 } | |
| 114 /* Rescaling of the array s[0..159] | |
| 115 */ | |
| 116 if (scalauto > 0) { | |
| 117 assert(scalauto <= 4); | |
| 118 for (k = 160; k--; *s++ <<= scalauto) ; | |
| 119 } | |
| 120 } | |
| 121 | |
| 122 /* 4.2.5 */ | |
| 123 | |
| 124 static void Reflection_coefficients ( | |
| 125 longword * L_ACF, /* 0...8 IN */ | |
| 126 register word * r /* 0...7 OUT */ | |
| 127 ) | |
| 128 { | |
| 129 register int i, m, n; | |
| 130 register word temp; | |
| 131 register longword ltmp; | |
| 132 word ACF[9]; /* 0..8 */ | |
| 133 word P[ 9]; /* 0..8 */ | |
| 134 word K[ 9]; /* 2..8 */ | |
| 135 | |
| 136 /* Schur recursion with 16 bits arithmetic. | |
| 137 */ | |
| 138 | |
| 139 if (L_ACF[0] == 0) { | |
| 140 for (i = 8; i--; *r++ = 0) ; | |
| 141 return; | |
| 142 } | |
| 143 | |
| 144 assert( L_ACF[0] != 0 ); | |
| 145 temp = gsm_norm( L_ACF[0] ); | |
| 146 | |
| 147 assert(temp >= 0 && temp < 32); | |
| 148 | |
| 149 /* ? overflow ? */ | |
| 150 for (i = 0; i <= 8; i++) ACF[i] = SASR( L_ACF[i] << temp, 16 ); | |
| 151 | |
| 152 /* Initialize array P[..] and K[..] for the recursion. | |
| 153 */ | |
| 154 | |
| 155 for (i = 1; i <= 7; i++) K[ i ] = ACF[ i ]; | |
| 156 for (i = 0; i <= 8; i++) P[ i ] = ACF[ i ]; | |
| 157 | |
| 158 /* Compute reflection coefficients | |
| 159 */ | |
| 160 for (n = 1; n <= 8; n++, r++) { | |
| 161 | |
| 162 temp = P[1]; | |
| 163 temp = GSM_ABS(temp); | |
| 164 if (P[0] < temp) { | |
| 165 for (i = n; i <= 8; i++) *r++ = 0; | |
| 166 return; | |
| 167 } | |
| 168 | |
| 169 *r = gsm_div( temp, P[0] ); | |
| 170 | |
| 171 assert(*r >= 0); | |
| 172 if (P[1] > 0) *r = -*r; /* r[n] = sub(0, r[n]) */ | |
| 173 assert (*r != MIN_WORD); | |
| 174 if (n == 8) return; | |
| 175 | |
| 176 /* Schur recursion | |
| 177 */ | |
| 178 temp = GSM_MULT_R( P[1], *r ); | |
| 179 P[0] = GSM_ADD( P[0], temp ); | |
| 180 | |
| 181 for (m = 1; m <= 8 - n; m++) { | |
| 182 temp = GSM_MULT_R( K[ m ], *r ); | |
| 183 P[m] = GSM_ADD( P[ m+1 ], temp ); | |
| 184 | |
| 185 temp = GSM_MULT_R( P[ m+1 ], *r ); | |
| 186 K[m] = GSM_ADD( K[ m ], temp ); | |
| 187 } | |
| 188 } | |
| 189 } | |
| 190 | |
| 191 /* 4.2.6 */ | |
| 192 | |
| 193 static void Transformation_to_Log_Area_Ratios ( | |
| 194 register word * r /* 0..7 IN/OUT */ | |
| 195 ) | |
| 196 /* | |
| 197 * The following scaling for r[..] and LAR[..] has been used: | |
| 198 * | |
| 199 * r[..] = integer( real_r[..]*32768. ); -1 <= real_r < 1. | |
| 200 * LAR[..] = integer( real_LAR[..] * 16384 ); | |
| 201 * with -1.625 <= real_LAR <= 1.625 | |
| 202 */ | |
| 203 { | |
| 204 register word temp; | |
| 205 register int i; | |
| 206 | |
| 207 /* Computation of the LAR[0..7] from the r[0..7] | |
| 208 */ | |
| 209 for (i = 1; i <= 8; i++, r++) { | |
| 210 | |
| 211 temp = *r; | |
| 212 temp = GSM_ABS(temp); | |
| 213 assert(temp >= 0); | |
| 214 | |
| 215 if (temp < 22118) { | |
| 216 temp >>= 1; | |
| 217 } else if (temp < 31130) { | |
| 218 assert( temp >= 11059 ); | |
| 219 temp -= 11059; | |
| 220 } else { | |
| 221 assert( temp >= 26112 ); | |
| 222 temp -= 26112; | |
| 223 temp <<= 2; | |
| 224 } | |
| 225 | |
| 226 *r = *r < 0 ? -temp : temp; | |
| 227 assert( *r != MIN_WORD ); | |
| 228 } | |
| 229 } | |
| 230 | |
| 231 /* 4.2.7 */ | |
| 232 | |
| 233 static void Quantization_and_coding ( | |
| 234 register word * LAR /* [0..7] IN/OUT */ | |
| 235 ) | |
| 236 { | |
| 237 register word temp; | |
| 238 longword ltmp; | |
| 239 | |
| 240 /* This procedure needs four tables; the following equations | |
| 241 * give the optimum scaling for the constants: | |
| 242 * | |
| 243 * A[0..7] = integer( real_A[0..7] * 1024 ) | |
| 244 * B[0..7] = integer( real_B[0..7] * 512 ) | |
| 245 * MAC[0..7] = maximum of the LARc[0..7] | |
| 246 * MIC[0..7] = minimum of the LARc[0..7] | |
| 247 */ | |
| 248 | |
| 249 # undef STEP | |
| 250 # define STEP( A, B, MAC, MIC ) \ | |
| 251 temp = GSM_MULT( A, *LAR ); \ | |
| 252 temp = GSM_ADD( temp, B ); \ | |
| 253 temp = GSM_ADD( temp, 256 ); \ | |
| 254 temp = SASR( temp, 9 ); \ | |
| 255 *LAR = temp>MAC ? MAC - MIC : (temp<MIC ? 0 : temp - MIC); \ | |
| 256 LAR++; | |
| 257 | |
| 258 STEP( 20480, 0, 31, -32 ); | |
| 259 STEP( 20480, 0, 31, -32 ); | |
| 260 STEP( 20480, 2048, 15, -16 ); | |
| 261 STEP( 20480, -2560, 15, -16 ); | |
| 262 | |
| 263 STEP( 13964, 94, 7, -8 ); | |
| 264 STEP( 15360, -1792, 7, -8 ); | |
| 265 STEP( 8534, -341, 3, -4 ); | |
| 266 STEP( 9036, -1144, 3, -4 ); | |
| 267 | |
| 268 # undef STEP | |
| 269 } | |
| 270 | |
| 271 void Gsm_LPC_Analysis ( | |
| 272 struct gsmfr_0610_state *S, | |
| 273 word * s, /* 0..159 signals IN/OUT */ | |
| 274 word * LARc) /* 0..7 LARc's OUT */ | |
| 275 { | |
| 276 longword L_ACF[9]; | |
| 277 | |
| 278 Autocorrelation (s, L_ACF ); | |
| 279 Reflection_coefficients (L_ACF, LARc ); | |
| 280 Transformation_to_Log_Area_Ratios (LARc); | |
| 281 Quantization_and_coding (LARc); | |
| 282 } |
