comparison spandsp-0.0.3/spandsp-0.0.3/src/gsm0610_short_term.c @ 5:f762bf195c4b

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

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