comparison spandsp-0.0.6pre17/spandsp-sim/test_utils.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 * test_utils.c - Utility routines for module tests.
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 * $Id: test_utils.c,v 1.14 2009/06/01 16:27:12 steveu Exp $
26 */
27
28 /*! \file */
29
30 #if defined(HAVE_CONFIG_H)
31 #include "config.h"
32 #endif
33
34 #include <stdlib.h>
35 #include <inttypes.h>
36 #include <string.h>
37 #include <stdio.h>
38 #if defined(HAVE_TGMATH_H)
39 #include <tgmath.h>
40 #endif
41 #if defined(HAVE_MATH_H)
42 #include <math.h>
43 #endif
44 #include "floating_fudge.h"
45 #include <time.h>
46 #include <fcntl.h>
47 #include <sndfile.h>
48
49 #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
50 #include "spandsp.h"
51 #include "spandsp-sim.h"
52
53 #define MAX_FFT_LEN 8192
54
55 struct codec_munge_state_s
56 {
57 int munging_codec;
58 g726_state_t g726_enc_state;
59 g726_state_t g726_dec_state;
60 int rbs_pattern;
61 int sequence;
62 };
63
64 struct complexify_state_s
65 {
66 float history[128];
67 int ptr;
68 };
69
70 static complex_t circle[MAX_FFT_LEN/2];
71 static int circle_init = FALSE;
72 static complex_t icircle[MAX_FFT_LEN/2];
73 static int icircle_init = FALSE;
74
75 SPAN_DECLARE(complexify_state_t *) complexify_init(void)
76 {
77 complexify_state_t *s;
78 int i;
79
80 if ((s = (complexify_state_t *) malloc(sizeof(*s))))
81 {
82 s->ptr = 0;
83 for (i = 0; i < 128; i++)
84 s->history[i] = 0.0f;
85 }
86 return s;
87 }
88 /*- End of function --------------------------------------------------------*/
89
90 SPAN_DECLARE(void) complexify_release(complexify_state_t *s)
91 {
92 free(s);
93 }
94 /*- End of function --------------------------------------------------------*/
95
96 SPAN_DECLARE(complexf_t) complexify(complexify_state_t *s, int16_t amp)
97 {
98 #define HILBERT_GAIN 1.569546344
99 static const float hilbert_coeffs[] =
100 {
101 +0.0012698413f, +0.0013489483f,
102 +0.0015105196f, +0.0017620440f,
103 +0.0021112899f, +0.0025663788f,
104 +0.0031358856f, +0.0038289705f,
105 +0.0046555545f, +0.0056265487f,
106 +0.0067541562f, +0.0080522707f,
107 +0.0095370033f, +0.0112273888f,
108 +0.0131463382f, +0.0153219442f,
109 +0.0177892941f, +0.0205930381f,
110 +0.0237910974f, +0.0274601544f,
111 +0.0317040029f, +0.0366666667f,
112 +0.0425537942f, +0.0496691462f,
113 +0.0584802574f, +0.0697446887f,
114 +0.0847739823f, +0.1060495199f,
115 +0.1388940865f, +0.1971551103f,
116 +0.3316207267f, +0.9994281838f,
117 };
118 float famp;
119 int i;
120 int j;
121 int k;
122 complexf_t res;
123
124 s->history[s->ptr] = amp;
125 i = s->ptr - 63;
126 if (i < 0)
127 i += 128;
128 res.re = s->history[i];
129
130 famp = 0.0f;
131 j = s->ptr - 126;
132 if (j < 0)
133 j += 128;
134 for (i = 0, k = s->ptr; i < 32; i++)
135 {
136 famp += (s->history[k] - s->history[j])*hilbert_coeffs[i];
137 j += 2;
138 if (j >= 128)
139 j -= 128;
140 k -= 2;
141 if (k < 0)
142 k += 128;
143 }
144 res.im = famp/HILBERT_GAIN;
145
146 if (++s->ptr >= 128)
147 s->ptr = 0;
148 return res;
149 }
150 /*- End of function --------------------------------------------------------*/
151
152 static __inline__ complex_t expj(double theta)
153 {
154 return complex_set(cos(theta), sin(theta));
155 }
156 /*- End of function --------------------------------------------------------*/
157
158 static void fftx(complex_t data[], complex_t temp[], int n)
159 {
160 int i;
161 int h;
162 int p;
163 int t;
164 int i2;
165 complex_t wkt;
166
167 if (n > 1)
168 {
169 h = n/2;
170 for (i = 0; i < h; i++)
171 {
172 i2 = i*2;
173 temp[i] = data[i2]; /* Even */
174 temp[h + i] = data[i2 + 1]; /* Odd */
175 }
176 fftx(&temp[0], &data[0], h);
177 fftx(&temp[h], &data[h], h);
178 p = 0;
179 t = MAX_FFT_LEN/n;
180 for (i = 0; i < h; i++)
181 {
182 wkt = complex_mul(&circle[p], &temp[h + i]);
183 data[i] = complex_add(&temp[i], &wkt);
184 data[h + i] = complex_sub(&temp[i], &wkt);
185 p += t;
186 }
187 }
188 }
189 /*- End of function --------------------------------------------------------*/
190
191 static void ifftx(complex_t data[], complex_t temp[], int n)
192 {
193 int i;
194 int h;
195 int p;
196 int t;
197 int i2;
198 complex_t wkt;
199
200 if (n > 1)
201 {
202 h = n/2;
203 for (i = 0; i < h; i++)
204 {
205 i2 = i*2;
206 temp[i] = data[i2]; /* Even */
207 temp[h + i] = data[i2 + 1]; /* Odd */
208 }
209 fftx(&temp[0], &data[0], h);
210 fftx(&temp[h], &data[h], h);
211 p = 0;
212 t = MAX_FFT_LEN/n;
213 for (i = 0; i < h; i++)
214 {
215 wkt = complex_mul(&icircle[p], &temp[h + i]);
216 data[i] = complex_add(&temp[i], &wkt);
217 data[h + i] = complex_sub(&temp[i], &wkt);
218 p += t;
219 }
220 }
221 }
222 /*- End of function --------------------------------------------------------*/
223
224 SPAN_DECLARE(void) fft(complex_t data[], int len)
225 {
226 int i;
227 double x;
228 complex_t temp[MAX_FFT_LEN];
229
230 /* A very slow and clunky FFT, that's just fine for tests. */
231 if (!circle_init)
232 {
233 for (i = 0; i < MAX_FFT_LEN/2; i++)
234 {
235 x = -(2.0*3.1415926535*i)/(double) MAX_FFT_LEN;
236 circle[i] = expj(x);
237 }
238 circle_init = TRUE;
239 }
240 fftx(data, temp, len);
241 }
242 /*- End of function --------------------------------------------------------*/
243
244 SPAN_DECLARE(void) ifft(complex_t data[], int len)
245 {
246 int i;
247 double x;
248 complex_t temp[MAX_FFT_LEN];
249
250 /* A very slow and clunky FFT, that's just fine for tests. */
251 if (!icircle_init)
252 {
253 for (i = 0; i < MAX_FFT_LEN/2; i++)
254 {
255 x = (2.0*3.1415926535*i)/(double) MAX_FFT_LEN;
256 icircle[i] = expj(x);
257 }
258 icircle_init = TRUE;
259 }
260 ifftx(data, temp, len);
261 }
262 /*- End of function --------------------------------------------------------*/
263
264 SPAN_DECLARE(codec_munge_state_t *) codec_munge_init(int codec, int info)
265 {
266 codec_munge_state_t *s;
267
268 if ((s = (codec_munge_state_t *) malloc(sizeof(*s))))
269 {
270 switch (codec)
271 {
272 case MUNGE_CODEC_G726_40K:
273 g726_init(&s->g726_enc_state, 40000, G726_ENCODING_LINEAR, G726_PACKING_NONE);
274 g726_init(&s->g726_dec_state, 40000, G726_ENCODING_LINEAR, G726_PACKING_NONE);
275 s->munging_codec = MUNGE_CODEC_G726_32K;
276 break;
277 case MUNGE_CODEC_G726_32K:
278 g726_init(&s->g726_enc_state, 32000, G726_ENCODING_LINEAR, G726_PACKING_NONE);
279 g726_init(&s->g726_dec_state, 32000, G726_ENCODING_LINEAR, G726_PACKING_NONE);
280 s->munging_codec = MUNGE_CODEC_G726_32K;
281 break;
282 case MUNGE_CODEC_G726_24K:
283 g726_init(&s->g726_enc_state, 24000, G726_ENCODING_LINEAR, G726_PACKING_NONE);
284 g726_init(&s->g726_dec_state, 24000, G726_ENCODING_LINEAR, G726_PACKING_NONE);
285 s->munging_codec = MUNGE_CODEC_G726_32K;
286 break;
287 case MUNGE_CODEC_G726_16K:
288 g726_init(&s->g726_enc_state, 16000, G726_ENCODING_LINEAR, G726_PACKING_NONE);
289 g726_init(&s->g726_dec_state, 16000, G726_ENCODING_LINEAR, G726_PACKING_NONE);
290 s->munging_codec = MUNGE_CODEC_G726_32K;
291 break;
292 default:
293 s->munging_codec = codec;
294 break;
295 }
296 s->sequence = 0;
297 s->rbs_pattern = info;
298 }
299 return s;
300 }
301 /*- End of function --------------------------------------------------------*/
302
303 SPAN_DECLARE(void) codec_munge_release(codec_munge_state_t *s)
304 {
305 free(s);
306 }
307 /*- End of function --------------------------------------------------------*/
308
309 SPAN_DECLARE(void) codec_munge(codec_munge_state_t *s, int16_t amp[], int len)
310 {
311 uint8_t law;
312 uint8_t adpcmdata[160];
313 int i;
314 int adpcm;
315 int x;
316
317 switch (s->munging_codec)
318 {
319 case MUNGE_CODEC_NONE:
320 /* Do nothing */
321 break;
322 case MUNGE_CODEC_ALAW:
323 for (i = 0; i < len; i++)
324 {
325 law = linear_to_alaw(amp[i]);
326 amp[i] = alaw_to_linear(law);
327 }
328 break;
329 case MUNGE_CODEC_ULAW:
330 for (i = 0; i < len; i++)
331 {
332 law = linear_to_ulaw(amp[i]);
333 if (s->rbs_pattern & (1 << s->sequence))
334 {
335 /* Strip the bottom bit at the RBS rate */
336 law &= 0xFE;
337 }
338 amp[i] = ulaw_to_linear(law);
339 }
340 break;
341 case MUNGE_CODEC_G726_32K:
342 /* This could actually be any of the G.726 rates */
343 for (i = 0; i < len; i += x)
344 {
345 x = (len - i >= 160) ? 160 : (len - i);
346 adpcm = g726_encode(&s->g726_enc_state, adpcmdata, amp + i, x);
347 g726_decode(&s->g726_dec_state, amp + i, adpcmdata, adpcm);
348 }
349 break;
350 }
351 }
352 /*- End of function --------------------------------------------------------*/
353
354 SPAN_DECLARE(SNDFILE *) sf_open_telephony_read(const char *name, int channels)
355 {
356 SNDFILE *handle;
357 SF_INFO info;
358
359 memset(&info, 0, sizeof(info));
360 if ((handle = sf_open(name, SFM_READ, &info)) == NULL)
361 {
362 fprintf(stderr, " Cannot open audio file '%s' for reading\n", name);
363 exit(2);
364 }
365 if (info.samplerate != SAMPLE_RATE)
366 {
367 printf(" Unexpected sample rate in audio file '%s'\n", name);
368 exit(2);
369 }
370 if (info.channels != channels)
371 {
372 printf(" Unexpected number of channels in audio file '%s'\n", name);
373 exit(2);
374 }
375
376 return handle;
377 }
378 /*- End of function --------------------------------------------------------*/
379
380 SPAN_DECLARE(SNDFILE *) sf_open_telephony_write(const char *name, int channels)
381 {
382 SNDFILE *handle;
383 SF_INFO info;
384
385 memset(&info, 0, sizeof(info));
386 info.frames = 0;
387 info.samplerate = SAMPLE_RATE;
388 info.channels = channels;
389 info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
390 info.sections = 1;
391 info.seekable = 1;
392
393 if ((handle = sf_open(name, SFM_WRITE, &info)) == NULL)
394 {
395 fprintf(stderr, " Cannot open audio file '%s' for writing\n", name);
396 exit(2);
397 }
398
399 return handle;
400 }
401 /*- End of function --------------------------------------------------------*/
402 /*- End of file ------------------------------------------------------------*/

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