comparison spandsp-0.0.6pre17/src/gsm0610_short_term.c @ 4:26cd8f1ef0b1

import spandsp-0.0.6pre17
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 15:50:58 +0200
parents
children
comparison
equal deleted inserted replaced
3:c6c5a16ce2f2 4:26cd8f1ef0b1
1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * gsm0610_short_term.c - GSM 06.10 full rate speech codec.
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2006 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 2.1,
14 * as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * This code is based on the widely used GSM 06.10 code available from
26 * http://kbs.cs.tu-berlin.de/~jutta/toast.html
27 *
28 * $Id: gsm0610_short_term.c,v 1.19 2009/02/03 16:28:39 steveu Exp $
29 */
30
31 /*! \file */
32
33 #if defined(HAVE_CONFIG_H)
34 #include "config.h"
35 #endif
36
37 #include <assert.h>
38 #include <inttypes.h>
39 #if defined(HAVE_TGMATH_H)
40 #include <tgmath.h>
41 #endif
42 #if defined(HAVE_MATH_H)
43 #include <math.h>
44 #endif
45 #include "floating_fudge.h"
46 #include <stdlib.h>
47
48 #include "spandsp/telephony.h"
49 #include "spandsp/fast_convert.h"
50 #include "spandsp/bitstream.h"
51 #include "spandsp/saturated.h"
52 #include "spandsp/gsm0610.h"
53
54 #include "gsm0610_local.h"
55
56 /* SHORT TERM ANALYSIS FILTERING SECTION */
57
58 /* 4.2.8 */
59 static void decode_log_area_ratios(int16_t LARc[8], int16_t *LARpp)
60 {
61 int16_t temp1;
62
63 /* This procedure requires for efficient implementation
64 two tables.
65 INVA[1..8] = integer((32768*8)/real_A[1..8])
66 MIC[1..8] = minimum value of the LARc[1..8]
67 */
68
69 /* Compute the LARpp[1..8] */
70
71 #undef STEP
72 #define STEP(B,MIC,INVA) \
73 temp1 = saturated_add16(*LARc++, MIC) << 10; \
74 temp1 = saturated_sub16(temp1, B << 1); \
75 temp1 = gsm_mult_r(INVA, temp1); \
76 *LARpp++ = saturated_add16(temp1, temp1);
77
78 STEP( 0, -32, 13107);
79 STEP( 0, -32, 13107);
80 STEP( 2048, -16, 13107);
81 STEP(-2560, -16, 13107);
82
83 STEP( 94, -8, 19223);
84 STEP(-1792, -8, 17476);
85 STEP( -341, -4, 31454);
86 STEP(-1144, -4, 29708);
87
88 /* NOTE: the addition of *MIC is used to restore the sign of *LARc. */
89 }
90 /*- End of function --------------------------------------------------------*/
91
92 /* 4.2.9 */
93
94 /* Computation of the quantized reflection coefficients */
95
96 /* 4.2.9.1 Interpolation of the LARpp[1..8] to get the LARp[1..8] */
97
98 /* Within each frame of 160 analyzed speech samples the short term
99 analysis and synthesis filters operate with four different sets of
100 coefficients, derived from the previous set of decoded LARs(LARpp(j - 1))
101 and the actual set of decoded LARs (LARpp(j))
102
103 (Initial value: LARpp(j - 1)[1..8] = 0.)
104 */
105
106 static void coefficients_0_12(int16_t *LARpp_j_1,
107 int16_t *LARpp_j,
108 int16_t *LARp)
109 {
110 int i;
111
112 for (i = 1; i <= 8; i++, LARp++, LARpp_j_1++, LARpp_j++)
113 {
114 *LARp = saturated_add16(*LARpp_j_1 >> 2, *LARpp_j >> 2);
115 *LARp = saturated_add16(*LARp, *LARpp_j_1 >> 1);
116 }
117 /*endfor*/
118 }
119 /*- End of function --------------------------------------------------------*/
120
121 static void coefficients_13_26(int16_t *LARpp_j_1,
122 int16_t *LARpp_j,
123 int16_t *LARp)
124 {
125 int i;
126
127 for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++)
128 *LARp = saturated_add16(*LARpp_j_1 >> 1, *LARpp_j >> 1);
129 /*endfor*/
130 }
131 /*- End of function --------------------------------------------------------*/
132
133 static void coefficients_27_39(int16_t *LARpp_j_1,
134 int16_t *LARpp_j,
135 int16_t *LARp)
136 {
137 int i;
138
139 for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++)
140 {
141 *LARp = saturated_add16(*LARpp_j_1 >> 2, *LARpp_j >> 2);
142 *LARp = saturated_add16(*LARp, *LARpp_j >> 1);
143 }
144 /*endfor*/
145 }
146 /*- End of function --------------------------------------------------------*/
147
148 static void coefficients_40_159(int16_t *LARpp_j, int16_t *LARp)
149 {
150 int i;
151
152 for (i = 1; i <= 8; i++)
153 *LARp++ = *LARpp_j++;
154 /*endfor*/
155 }
156 /*- End of function --------------------------------------------------------*/
157
158 /* 4.2.9.2 */
159 static void larp_to_rp(int16_t LARp[8])
160 {
161 int i;
162 int16_t *LARpx;
163 int16_t temp;
164
165 /* The input to this procedure is the interpolated LARp[0..7] array.
166 The reflection coefficients, rp[i], are used in the analysis
167 filter and in the synthesis filter.
168 */
169
170 LARpx = LARp;
171 for (i = 1; i <= 8; i++, LARpx++)
172 {
173 temp = *LARpx;
174 if (temp < 0)
175 {
176 if (temp == INT16_MIN)
177 temp = INT16_MAX;
178 else
179 temp = -temp;
180 /*endif*/
181 if (temp < 11059)
182 temp <<= 1;
183 else if (temp < 20070)
184 temp += 11059;
185 else
186 temp = saturated_add16(temp >> 2, 26112);
187 /*endif*/
188 *LARpx = -temp;
189 }
190 else
191 {
192 if (temp < 11059)
193 temp <<= 1;
194 else if (temp < 20070)
195 temp += 11059;
196 else
197 temp = saturated_add16(temp >> 2, 26112);
198 /*endif*/
199 *LARpx = temp;
200 }
201 /*endif*/
202 }
203 /*endfor*/
204 }
205 /*- End of function --------------------------------------------------------*/
206
207 /* 4.2.10 */
208 static void short_term_analysis_filtering(gsm0610_state_t *s,
209 int16_t rp[8],
210 int k_n, // k_end - k_start
211 int16_t amp[]) // [0..n-1] IN/OUT
212 {
213 /* This procedure computes the short term residual signal d[..] to be fed
214 to the RPE-LTP loop from the s[..] signal and from the local rp[..]
215 array (quantized reflection coefficients). As the call of this
216 procedure can be done in many ways (see the interpolation of the LAR
217 coefficient), it is assumed that the computation begins with index
218 k_start (for arrays d[..] and s[..]) and stops with index k_end
219 (k_start and k_end are defined in 4.2.9.1). This procedure also
220 needs to keep the array u[0..7] in memory for each call.
221 */
222 int16_t *u0;
223 int16_t *u_top;
224 int i;
225 int16_t *u;
226 int16_t *rpx;
227 int32_t di;
228 int32_t u_out;
229
230 u0 = s->u;
231 u_top = u0 + 8;
232
233 for (i = 0; i < k_n; i++)
234 {
235 di =
236 u_out = amp[i];
237 for (rpx = rp, u = u0; u < u_top; )
238 {
239 int32_t ui;
240 int32_t rpi;
241
242 ui = *u;
243 *u++ = (int16_t) u_out;
244 rpi = *rpx++;
245 u_out = ui + (((rpi*di) + 0x4000) >> 15);
246 di = di + (((rpi*ui) + 0x4000) >> 15);
247 u_out = saturate(u_out);
248 di = saturate(di);
249 }
250 /*endfor*/
251 amp[i] = (int16_t) di;
252 }
253 /*endfor*/
254 }
255 /*- End of function --------------------------------------------------------*/
256
257 static void short_term_synthesis_filtering(gsm0610_state_t *s,
258 int16_t rrp[8],
259 int k, // k_end - k_start
260 int16_t *wt, // [0..k - 1]
261 int16_t *sr) // [0..k - 1]
262 {
263 int16_t *v;
264 int i;
265 int16_t sri;
266 int16_t tmp1;
267 int16_t tmp2;
268
269 v = s->v;
270 while (k--)
271 {
272 sri = *wt++;
273 for (i = 8; i--; )
274 {
275 tmp1 = rrp[i];
276 tmp2 = v[i];
277 tmp2 = ((tmp1 == INT16_MIN && tmp2 == INT16_MIN)
278 ?
279 INT16_MAX
280 :
281 (int16_t) (((int32_t) tmp1*(int32_t) tmp2 + 16384) >> 15) & 0xFFFF);
282
283 sri = saturated_sub16(sri, tmp2);
284
285 tmp1 = ((tmp1 == INT16_MIN && sri == INT16_MIN)
286 ?
287 INT16_MAX
288 :
289 (int16_t) (((int32_t) tmp1*(int32_t) sri + 16384) >> 15) & 0xFFFF);
290
291 v[i + 1] = saturated_add16(v[i], tmp1);
292 }
293 /*endfor*/
294 *sr++ =
295 v[0] = sri;
296 }
297 /*endwhile*/
298 }
299 /*- End of function --------------------------------------------------------*/
300
301 void gsm0610_short_term_analysis_filter(gsm0610_state_t *s,
302 int16_t LARc[8],
303 int16_t amp[GSM0610_FRAME_LEN])
304 {
305 int16_t *LARpp_j;
306 int16_t *LARpp_j_1;
307 int16_t LARp[8];
308
309 LARpp_j = s->LARpp[s->j];
310 LARpp_j_1 = s->LARpp[s->j ^= 1];
311
312 decode_log_area_ratios(LARc, LARpp_j);
313
314 coefficients_0_12(LARpp_j_1, LARpp_j, LARp);
315 larp_to_rp(LARp);
316 short_term_analysis_filtering(s, LARp, 13, amp);
317
318 coefficients_13_26(LARpp_j_1, LARpp_j, LARp);
319 larp_to_rp(LARp);
320 short_term_analysis_filtering(s, LARp, 14, amp + 13);
321
322 coefficients_27_39(LARpp_j_1, LARpp_j, LARp);
323 larp_to_rp(LARp);
324 short_term_analysis_filtering(s, LARp, 13, amp + 27);
325
326 coefficients_40_159(LARpp_j, LARp);
327 larp_to_rp(LARp);
328 short_term_analysis_filtering(s, LARp, 120, amp + 40);
329 }
330 /*- End of function --------------------------------------------------------*/
331
332 void gsm0610_short_term_synthesis_filter(gsm0610_state_t *s,
333 int16_t LARcr[8],
334 int16_t wt[GSM0610_FRAME_LEN],
335 int16_t amp[GSM0610_FRAME_LEN])
336 {
337 int16_t *LARpp_j;
338 int16_t *LARpp_j_1;
339 int16_t LARp[8];
340
341 LARpp_j = s->LARpp[s->j];
342 LARpp_j_1 = s->LARpp[s->j ^= 1];
343
344 decode_log_area_ratios(LARcr, LARpp_j);
345
346 coefficients_0_12(LARpp_j_1, LARpp_j, LARp);
347 larp_to_rp(LARp);
348 short_term_synthesis_filtering(s, LARp, 13, wt, amp);
349
350 coefficients_13_26(LARpp_j_1, LARpp_j, LARp);
351 larp_to_rp(LARp);
352 short_term_synthesis_filtering(s, LARp, 14, wt + 13, amp + 13);
353
354 coefficients_27_39(LARpp_j_1, LARpp_j, LARp);
355 larp_to_rp(LARp);
356 short_term_synthesis_filtering(s, LARp, 13, wt + 27, amp + 27);
357
358 coefficients_40_159(LARpp_j, LARp);
359 larp_to_rp(LARp);
360 short_term_synthesis_filtering(s, LARp, 120, wt + 40, amp + 40);
361 }
362 /*- End of function --------------------------------------------------------*/
363 /*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.