PageRenderTime 25ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/phono-phonegap-ios/libphono/src/iosaudio/GSM610/rpe.c

https://github.com/mastahype/PhonoSDK
C | 490 lines | 250 code | 96 blank | 144 comment | 33 complexity | adad916f09a821a8e271c9d591af896a MD5 | raw file
  1. /*
  2. * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
  3. * Universitaet Berlin. See the accompanying file "COPYRIGHT" for
  4. * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
  5. */
  6. #include <stdio.h>
  7. #include <assert.h>
  8. #include "gsm610_priv.h"
  9. #include "gsm.h"
  10. /* 4.2.13 .. 4.2.17 RPE ENCODING SECTION
  11. */
  12. /* 4.2.13 */
  13. static void Weighting_filter (
  14. register word * e, /* signal [-5..0.39.44] IN */
  15. word * x /* signal [0..39] OUT */
  16. )
  17. /*
  18. * The coefficients of the weighting filter are stored in a table
  19. * (see table 4.4). The following scaling is used:
  20. *
  21. * H[0..10] = integer( real_H[ 0..10] * 8192 );
  22. */
  23. {
  24. /* word wt[ 50 ]; */
  25. register longword L_result;
  26. register int k /* , i */ ;
  27. /* Initialization of a temporary working array wt[0...49]
  28. */
  29. /* for (k = 0; k <= 4; k++) wt[k] = 0;
  30. * for (k = 5; k <= 44; k++) wt[k] = *e++;
  31. * for (k = 45; k <= 49; k++) wt[k] = 0;
  32. *
  33. * (e[-5..-1] and e[40..44] are allocated by the caller,
  34. * are initially zero and are not written anywhere.)
  35. */
  36. e -= 5;
  37. /* Compute the signal x[0..39]
  38. */
  39. for (k = 0; k <= 39; k++) {
  40. L_result = 8192 >> 1;
  41. /* for (i = 0; i <= 10; i++) {
  42. * L_temp = GSM_L_MULT( wt[k+i], gsm_H[i] );
  43. * L_result = GSM_L_ADD( L_result, L_temp );
  44. * }
  45. */
  46. #undef STEP
  47. #define STEP( i, H ) (e[ k + i ] * (longword)H)
  48. /* Every one of these multiplications is done twice --
  49. * but I don't see an elegant way to optimize this.
  50. * Do you?
  51. */
  52. #ifdef STUPID_COMPILER
  53. L_result += STEP( 0, -134 ) ;
  54. L_result += STEP( 1, -374 ) ;
  55. /* + STEP( 2, 0 ) */
  56. L_result += STEP( 3, 2054 ) ;
  57. L_result += STEP( 4, 5741 ) ;
  58. L_result += STEP( 5, 8192 ) ;
  59. L_result += STEP( 6, 5741 ) ;
  60. L_result += STEP( 7, 2054 ) ;
  61. /* + STEP( 8, 0 ) */
  62. L_result += STEP( 9, -374 ) ;
  63. L_result += STEP( 10, -134 ) ;
  64. #else
  65. L_result +=
  66. STEP( 0, -134 )
  67. + STEP( 1, -374 )
  68. /* + STEP( 2, 0 ) */
  69. + STEP( 3, 2054 )
  70. + STEP( 4, 5741 )
  71. + STEP( 5, 8192 )
  72. + STEP( 6, 5741 )
  73. + STEP( 7, 2054 )
  74. /* + STEP( 8, 0 ) */
  75. + STEP( 9, -374 )
  76. + STEP(10, -134 )
  77. ;
  78. #endif
  79. /* L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x2) *)
  80. * L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x4) *)
  81. *
  82. * x[k] = SASR( L_result, 16 );
  83. */
  84. /* 2 adds vs. >>16 => 14, minus one shift to compensate for
  85. * those we lost when replacing L_MULT by '*'.
  86. */
  87. L_result = SASR_L( L_result, 13 );
  88. x[k] = ( L_result < MIN_WORD ? MIN_WORD
  89. : (L_result > MAX_WORD ? MAX_WORD : L_result ));
  90. }
  91. }
  92. /* 4.2.14 */
  93. static void RPE_grid_selection (
  94. word * x, /* [0..39] IN */
  95. word * xM, /* [0..12] OUT */
  96. word * Mc_out /* OUT */
  97. )
  98. /*
  99. * The signal x[0..39] is used to select the RPE grid which is
  100. * represented by Mc.
  101. */
  102. {
  103. /* register word temp1; */
  104. register int /* m, */ i;
  105. register longword L_result, L_temp;
  106. longword EM; /* xxx should be L_EM? */
  107. word Mc;
  108. longword L_common_0_3;
  109. EM = 0;
  110. Mc = 0;
  111. /* for (m = 0; m <= 3; m++) {
  112. * L_result = 0;
  113. *
  114. *
  115. * for (i = 0; i <= 12; i++) {
  116. *
  117. * temp1 = SASR_W( x[m + 3*i], 2 );
  118. *
  119. * assert(temp1 != MIN_WORD);
  120. *
  121. * L_temp = GSM_L_MULT( temp1, temp1 );
  122. * L_result = GSM_L_ADD( L_temp, L_result );
  123. * }
  124. *
  125. * if (L_result > EM) {
  126. * Mc = m;
  127. * EM = L_result;
  128. * }
  129. * }
  130. */
  131. #undef STEP
  132. #define STEP( m, i ) L_temp = SASR_W( x[m + 3 * i], 2 ); \
  133. L_result += L_temp * L_temp;
  134. /* common part of 0 and 3 */
  135. L_result = 0;
  136. STEP( 0, 1 ); STEP( 0, 2 ); STEP( 0, 3 ); STEP( 0, 4 );
  137. STEP( 0, 5 ); STEP( 0, 6 ); STEP( 0, 7 ); STEP( 0, 8 );
  138. STEP( 0, 9 ); STEP( 0, 10); STEP( 0, 11); STEP( 0, 12);
  139. L_common_0_3 = L_result;
  140. /* i = 0 */
  141. STEP( 0, 0 );
  142. L_result <<= 1; /* implicit in L_MULT */
  143. EM = L_result;
  144. /* i = 1 */
  145. L_result = 0;
  146. STEP( 1, 0 );
  147. STEP( 1, 1 ); STEP( 1, 2 ); STEP( 1, 3 ); STEP( 1, 4 );
  148. STEP( 1, 5 ); STEP( 1, 6 ); STEP( 1, 7 ); STEP( 1, 8 );
  149. STEP( 1, 9 ); STEP( 1, 10); STEP( 1, 11); STEP( 1, 12);
  150. L_result <<= 1;
  151. if (L_result > EM) {
  152. Mc = 1;
  153. EM = L_result;
  154. }
  155. /* i = 2 */
  156. L_result = 0;
  157. STEP( 2, 0 );
  158. STEP( 2, 1 ); STEP( 2, 2 ); STEP( 2, 3 ); STEP( 2, 4 );
  159. STEP( 2, 5 ); STEP( 2, 6 ); STEP( 2, 7 ); STEP( 2, 8 );
  160. STEP( 2, 9 ); STEP( 2, 10); STEP( 2, 11); STEP( 2, 12);
  161. L_result <<= 1;
  162. if (L_result > EM) {
  163. Mc = 2;
  164. EM = L_result;
  165. }
  166. /* i = 3 */
  167. L_result = L_common_0_3;
  168. STEP( 3, 12 );
  169. L_result <<= 1;
  170. if (L_result > EM) {
  171. Mc = 3;
  172. EM = L_result;
  173. }
  174. /**/
  175. /* Down-sampling by a factor 3 to get the selected xM[0..12]
  176. * RPE sequence.
  177. */
  178. for (i = 0; i <= 12; i ++) xM[i] = x[Mc + 3*i];
  179. *Mc_out = Mc;
  180. }
  181. /* 4.12.15 */
  182. static void APCM_quantization_xmaxc_to_exp_mant (
  183. word xmaxc, /* IN */
  184. word * expon_out, /* OUT */
  185. word * mant_out ) /* OUT */
  186. {
  187. word expon, mant;
  188. /* Compute expononent and mantissa of the decoded version of xmaxc
  189. */
  190. expon = 0;
  191. if (xmaxc > 15) expon = SASR_W(xmaxc, 3) - 1;
  192. mant = xmaxc - (expon << 3);
  193. if (mant == 0) {
  194. expon = -4;
  195. mant = 7;
  196. }
  197. else {
  198. while (mant <= 7) {
  199. mant = mant << 1 | 1;
  200. expon--;
  201. }
  202. mant -= 8;
  203. }
  204. assert( expon >= -4 && expon <= 6 );
  205. assert( mant >= 0 && mant <= 7 );
  206. *expon_out = expon;
  207. *mant_out = mant;
  208. }
  209. static void APCM_quantization (
  210. word * xM, /* [0..12] IN */
  211. word * xMc, /* [0..12] OUT */
  212. word * mant_out, /* OUT */
  213. word * expon_out, /* OUT */
  214. word * xmaxc_out /* OUT */
  215. )
  216. {
  217. int i, itest;
  218. word xmax, xmaxc, temp, temp1, temp2;
  219. word expon, mant;
  220. /* Find the maximum absolute value xmax of xM[0..12].
  221. */
  222. xmax = 0;
  223. for (i = 0; i <= 12; i++) {
  224. temp = xM[i];
  225. temp = GSM_ABS(temp);
  226. if (temp > xmax) xmax = temp;
  227. }
  228. /* Qantizing and coding of xmax to get xmaxc.
  229. */
  230. expon = 0;
  231. temp = SASR_W( xmax, 9 );
  232. itest = 0;
  233. for (i = 0; i <= 5; i++) {
  234. itest |= (temp <= 0);
  235. temp = SASR_W( temp, 1 );
  236. assert(expon <= 5);
  237. if (itest == 0) expon++; /* expon = add (expon, 1) */
  238. }
  239. assert(expon <= 6 && expon >= 0);
  240. temp = expon + 5;
  241. assert(temp <= 11 && temp >= 0);
  242. xmaxc = gsm_add( SASR_W(xmax, temp), (word) (expon << 3) );
  243. /* Quantizing and coding of the xM[0..12] RPE sequence
  244. * to get the xMc[0..12]
  245. */
  246. APCM_quantization_xmaxc_to_exp_mant( xmaxc, &expon, &mant );
  247. /* This computation uses the fact that the decoded version of xmaxc
  248. * can be calculated by using the expononent and the mantissa part of
  249. * xmaxc (logarithmic table).
  250. * So, this method avoids any division and uses only a scaling
  251. * of the RPE samples by a function of the expononent. A direct
  252. * multiplication by the inverse of the mantissa (NRFAC[0..7]
  253. * found in table 4.5) gives the 3 bit coded version xMc[0..12]
  254. * of the RPE samples.
  255. */
  256. /* Direct computation of xMc[0..12] using table 4.5
  257. */
  258. assert( expon <= 4096 && expon >= -4096);
  259. assert( mant >= 0 && mant <= 7 );
  260. temp1 = 6 - expon; /* normalization by the expononent */
  261. temp2 = gsm_NRFAC[ mant ]; /* inverse mantissa */
  262. for (i = 0; i <= 12; i++) {
  263. assert(temp1 >= 0 && temp1 < 16);
  264. temp = xM[i] << temp1;
  265. temp = GSM_MULT( temp, temp2 );
  266. temp = SASR_W(temp, 12);
  267. xMc[i] = temp + 4; /* see note below */
  268. }
  269. /* NOTE: This equation is used to make all the xMc[i] positive.
  270. */
  271. *mant_out = mant;
  272. *expon_out = expon;
  273. *xmaxc_out = xmaxc;
  274. }
  275. /* 4.2.16 */
  276. static void APCM_inverse_quantization (
  277. register word * xMc, /* [0..12] IN */
  278. word mant,
  279. word expon,
  280. register word * xMp) /* [0..12] OUT */
  281. /*
  282. * This part is for decoding the RPE sequence of coded xMc[0..12]
  283. * samples to obtain the xMp[0..12] array. Table 4.6 is used to get
  284. * the mantissa of xmaxc (FAC[0..7]).
  285. */
  286. {
  287. int i;
  288. word temp, temp1, temp2, temp3;
  289. assert( mant >= 0 && mant <= 7 );
  290. temp1 = gsm_FAC[ mant ]; /* see 4.2-15 for mant */
  291. temp2 = gsm_sub( 6, expon ); /* see 4.2-15 for exp */
  292. temp3 = gsm_asl( 1, gsm_sub( temp2, 1 ));
  293. for (i = 13; i--;) {
  294. assert( *xMc <= 7 && *xMc >= 0 ); /* 3 bit unsigned */
  295. /* temp = gsm_sub( *xMc++ << 1, 7 ); */
  296. temp = (*xMc++ << 1) - 7; /* restore sign */
  297. assert( temp <= 7 && temp >= -7 ); /* 4 bit signed */
  298. temp <<= 12; /* 16 bit signed */
  299. temp = GSM_MULT_R( temp1, temp );
  300. temp = GSM_ADD( temp, temp3 );
  301. *xMp++ = gsm_asr( temp, temp2 );
  302. }
  303. }
  304. /* 4.2.17 */
  305. static void RPE_grid_positioning (
  306. word Mc, /* grid position IN */
  307. register word * xMp, /* [0..12] IN */
  308. register word * ep /* [0..39] OUT */
  309. )
  310. /*
  311. * This procedure computes the reconstructed long term residual signal
  312. * ep[0..39] for the LTP analysis filter. The inputs are the Mc
  313. * which is the grid position selection and the xMp[0..12] decoded
  314. * RPE samples which are upsampled by a factor of 3 by inserting zero
  315. * values.
  316. */
  317. {
  318. int i = 13;
  319. assert(0 <= Mc && Mc <= 3);
  320. switch (Mc) {
  321. case 3: *ep++ = 0;
  322. case 2: do {
  323. *ep++ = 0;
  324. case 1: *ep++ = 0;
  325. case 0: *ep++ = *xMp++;
  326. } while (--i);
  327. }
  328. while (++Mc < 4) *ep++ = 0;
  329. /*
  330. int i, k;
  331. for (k = 0; k <= 39; k++) ep[k] = 0;
  332. for (i = 0; i <= 12; i++) {
  333. ep[ Mc + (3*i) ] = xMp[i];
  334. }
  335. */
  336. }
  337. /* 4.2.18 */
  338. /* This procedure adds the reconstructed long term residual signal
  339. * ep[0..39] to the estimated signal dpp[0..39] from the long term
  340. * analysis filter to compute the reconstructed short term residual
  341. * signal dp[-40..-1]; also the reconstructed short term residual
  342. * array dp[-120..-41] is updated.
  343. */
  344. #if 0 /* Has been inlined in code.c */
  345. void Gsm_Update_of_reconstructed_short_time_residual_signal (
  346. word * dpp, /* [0...39] IN */
  347. word * ep, /* [0...39] IN */
  348. word * dp) /* [-120...-1] IN/OUT */
  349. {
  350. int k;
  351. for (k = 0; k <= 79; k++)
  352. dp[ -120 + k ] = dp[ -80 + k ];
  353. for (k = 0; k <= 39; k++)
  354. dp[ -40 + k ] = gsm_add( ep[k], dpp[k] );
  355. }
  356. #endif /* Has been inlined in code.c */
  357. void Gsm_RPE_Encoding (
  358. /*-struct gsm_state * S,-*/
  359. word * e, /* -5..-1][0..39][40..44 IN/OUT */
  360. word * xmaxc, /* OUT */
  361. word * Mc, /* OUT */
  362. word * xMc) /* [0..12] OUT */
  363. {
  364. word x[40];
  365. word xM[13], xMp[13];
  366. word mant, expon;
  367. Weighting_filter(e, x);
  368. RPE_grid_selection(x, xM, Mc);
  369. APCM_quantization( xM, xMc, &mant, &expon, xmaxc);
  370. APCM_inverse_quantization( xMc, mant, expon, xMp);
  371. RPE_grid_positioning( *Mc, xMp, e );
  372. }
  373. void Gsm_RPE_Decoding (
  374. /*-struct gsm_state * S,-*/
  375. word xmaxcr,
  376. word Mcr,
  377. word * xMcr, /* [0..12], 3 bits IN */
  378. word * erp /* [0..39] OUT */
  379. )
  380. {
  381. word expon, mant;
  382. word xMp[ 13 ];
  383. APCM_quantization_xmaxc_to_exp_mant( xmaxcr, &expon, &mant );
  384. APCM_inverse_quantization( xMcr, mant, expon, xMp );
  385. RPE_grid_positioning( Mcr, xMp, erp );
  386. }
  387. /*
  388. ** Do not edit or modify anything in this comment block.
  389. ** The arch-tag line is a file identity tag for the GNU Arch
  390. ** revision control system.
  391. **
  392. ** arch-tag: 82005b9e-1560-4e94-9ddb-00cb14867295
  393. */