Mercurial > hg > audiostuff
comparison spandsp-0.0.6pre17/tests/power_meter_tests.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 * power_meter_tests.c | |
5 * | |
6 * Written by Steve Underwood <steveu@coppice.org> | |
7 * | |
8 * Copyright (C) 2003 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: power_meter_tests.c,v 1.24 2009/05/30 15:23:14 steveu Exp $ | |
26 */ | |
27 | |
28 /*! \page power_meter_tests_page Power meter tests | |
29 \section power_meter_tests_page_sec_1 What does it do? | |
30 These tests assess the accuracy of power meters built from the power meter module. | |
31 Both tones and noise are used to check the meter's behaviour. | |
32 | |
33 \section power_meter_tests_page_sec_2 How does it work? | |
34 ???. | |
35 */ | |
36 | |
37 #if defined(HAVE_CONFIG_H) | |
38 #include <config.h> | |
39 #endif | |
40 | |
41 #include <stdlib.h> | |
42 #include <stdio.h> | |
43 #include <unistd.h> | |
44 #include <memory.h> | |
45 #include <float.h> | |
46 #include <time.h> | |
47 #include <sndfile.h> | |
48 | |
49 //#if defined(WITH_SPANDSP_INTERNALS) | |
50 #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES | |
51 //#endif | |
52 | |
53 #include "spandsp.h" | |
54 #include "spandsp-sim.h" | |
55 | |
56 #define IN_FILE_NAME "../test-data/local/short_nb_voice.wav" | |
57 #define OUT_FILE_NAME "power_meter_tests.wav" | |
58 | |
59 static int power_surge_detector_tests(void) | |
60 { | |
61 SNDFILE *outhandle; | |
62 power_surge_detector_state_t *sig; | |
63 int i; | |
64 int sample; | |
65 int16_t amp[8000]; | |
66 int16_t amp_out[2*8000]; | |
67 awgn_state_t *awgnx; | |
68 int32_t phase_rate; | |
69 uint32_t phase_acc; | |
70 int16_t phase_scale; | |
71 float signal_power; | |
72 int32_t signal_level; | |
73 int signal_present; | |
74 int prev_signal_present; | |
75 int ok; | |
76 int extremes[4]; | |
77 | |
78 if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME, 2)) == NULL) | |
79 { | |
80 fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME); | |
81 exit(2); | |
82 } | |
83 sig = power_surge_detector_init(NULL, -50.0f, 5.0f); | |
84 prev_signal_present = FALSE; | |
85 | |
86 phase_rate = dds_phase_rate(450.0f); | |
87 phase_acc = 0; | |
88 | |
89 phase_scale = dds_scaling_dbm0(-33.0f); | |
90 awgnx = awgn_init_dbm0(NULL, 1234567, -45.0f); | |
91 | |
92 extremes[0] = 8001; | |
93 extremes[1] = -1; | |
94 extremes[2] = 8001; | |
95 extremes[3] = -1; | |
96 for (sample = 0; sample < 800000; sample += 8000) | |
97 { | |
98 ok = 0; | |
99 for (i = 0; i < 8000; i++) | |
100 { | |
101 amp[i] = awgn(awgnx); | |
102 if (i < 4000) | |
103 amp[i] += dds_mod(&phase_acc, phase_rate, phase_scale, 0); | |
104 | |
105 signal_level = power_surge_detector(sig, amp[i]); | |
106 signal_present = (signal_level != 0); | |
107 if (prev_signal_present != signal_present) | |
108 { | |
109 signal_power = power_surge_detector_current_dbm0(sig); | |
110 if (signal_present) | |
111 { | |
112 if (ok == 0 && i >= 0 && i < 25) | |
113 ok = 1; | |
114 if (extremes[0] > i) | |
115 extremes[0] = i; | |
116 if (extremes[1] < i) | |
117 extremes[1] = i; | |
118 printf("On at %f (%fdBm0)\n", (sample + i)/8000.0, signal_power); | |
119 } | |
120 else | |
121 { | |
122 if (ok == 1 && i >= 4000 + 0 && i < 4000 + 35) | |
123 ok = 2; | |
124 if (extremes[2] > i) | |
125 extremes[2] = i; | |
126 if (extremes[3] < i) | |
127 extremes[3] = i; | |
128 printf("Off at %f (%fdBm0)\n", (sample + i)/8000.0, signal_power); | |
129 } | |
130 prev_signal_present = signal_present; | |
131 } | |
132 amp_out[2*i] = amp[i]; | |
133 amp_out[2*i + 1] = signal_present*5000; | |
134 } | |
135 sf_writef_short(outhandle, amp_out, 8000); | |
136 if (ok != 2 | |
137 || | |
138 extremes[0] < 1 | |
139 || | |
140 extremes[1] > 30 | |
141 || | |
142 extremes[2] < 4001 | |
143 || | |
144 extremes[3] > 4030) | |
145 { | |
146 printf(" Surge not detected correctly (%d)\n", ok); | |
147 exit(2); | |
148 } | |
149 } | |
150 sf_close(outhandle); | |
151 printf("Min on %d, max on %d, min off %d, max off %d\n", extremes[0], extremes[1], extremes[2], extremes[3]); | |
152 return 0; | |
153 } | |
154 /*- End of function --------------------------------------------------------*/ | |
155 | |
156 static int power_surge_detector_file_test(const char *file) | |
157 { | |
158 SNDFILE *inhandle; | |
159 SNDFILE *outhandle; | |
160 int inframes; | |
161 power_surge_detector_state_t *sig; | |
162 int i; | |
163 int16_t amp[8000]; | |
164 int16_t amp_out[2*8000]; | |
165 int sample; | |
166 float signal_power; | |
167 int32_t signal_level; | |
168 int signal_present; | |
169 int prev_signal_present; | |
170 | |
171 if ((inhandle = sf_open_telephony_read(file, 1)) == NULL) | |
172 { | |
173 printf(" Cannot open speech file '%s'\n", file); | |
174 exit(2); | |
175 } | |
176 | |
177 if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME, 1)) == NULL) | |
178 { | |
179 fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME); | |
180 exit(2); | |
181 } | |
182 sig = power_surge_detector_init(NULL, -50.0f, 6.0f); | |
183 prev_signal_present = FALSE; | |
184 | |
185 sample = 0; | |
186 while ((inframes = sf_readf_short(inhandle, amp, 8000))) | |
187 { | |
188 for (i = 0; i < inframes; i++) | |
189 { | |
190 signal_level = power_surge_detector(sig, amp[i]); | |
191 signal_present = (signal_level != 0); | |
192 if (prev_signal_present != signal_present) | |
193 { | |
194 signal_power = power_surge_detector_current_dbm0(sig); | |
195 if (signal_present) | |
196 printf("On at %f (%fdBm0)\n", (sample + i)/8000.0, signal_power); | |
197 else | |
198 printf("Off at %f (%fdBm0)\n", (sample + i)/8000.0, signal_power); | |
199 prev_signal_present = signal_present; | |
200 } | |
201 amp_out[2*i] = amp[i]; | |
202 amp_out[2*i + 1] = signal_present*5000; | |
203 } | |
204 sf_writef_short(outhandle, amp_out, inframes); | |
205 sample += inframes; | |
206 } | |
207 sf_close(inhandle); | |
208 sf_close(outhandle); | |
209 return 0; | |
210 } | |
211 /*- End of function --------------------------------------------------------*/ | |
212 | |
213 static int power_meter_tests(void) | |
214 { | |
215 awgn_state_t noise_source; | |
216 power_meter_t meter; | |
217 tone_gen_descriptor_t tone_desc; | |
218 tone_gen_state_t gen; | |
219 int i; | |
220 int idum = 1234567; | |
221 int16_t amp[1000]; | |
222 int len; | |
223 int32_t level; | |
224 | |
225 power_meter_init(&meter, 7); | |
226 printf("Testing with zero in the power register\n"); | |
227 printf("Power: expected %fdBm0, got %fdBm0\n", -90.169f, power_meter_current_dbm0(&meter)); | |
228 printf("Power: expected %fdBOv, got %fdBOv\n", -96.329f, power_meter_current_dbov(&meter)); | |
229 | |
230 printf("Testing with a square wave 10dB from maximum\n"); | |
231 for (i = 0; i < 1000; i++) | |
232 { | |
233 amp[i] = (i & 1) ? 10362 : -10362; | |
234 level = power_meter_update(&meter, amp[i]); | |
235 //printf("%12d %fdBm0 %fdBov\n", level, power_meter_current_dbm0(&meter), power_meter_current_dbov(&meter)); | |
236 } | |
237 printf("Level: expected %" PRId32 "/%" PRId32 ", got %" PRId32 "\n", power_meter_level_dbov(-10.0f), power_meter_level_dbm0(-10.0f + DBM0_MAX_POWER), level); | |
238 printf("Power: expected %fdBm0, got %fdBm0\n", -10.0f + DBM0_MAX_POWER, power_meter_current_dbm0(&meter)); | |
239 printf("Power: expected %fdBOv, got %fdBOv\n", -10.0f, power_meter_current_dbov(&meter)); | |
240 if (level < power_meter_level_dbov(-10.0f)*0.99f | |
241 || | |
242 level > power_meter_level_dbov(-10.0f)*1.01f) | |
243 { | |
244 printf("Test failed (level)\n"); | |
245 exit(2); | |
246 } | |
247 if (0.1f < fabsf(power_meter_current_dbm0(&meter) + 10.0f - DBM0_MAX_POWER)) | |
248 { | |
249 printf("Test failed (dBm0)\n"); | |
250 exit(2); | |
251 } | |
252 if (0.1f < fabsf(power_meter_current_dbov(&meter) + 10.0)) | |
253 { | |
254 printf("Test failed (dBOv)\n"); | |
255 exit(2); | |
256 } | |
257 | |
258 printf("Testing with a sine wave tone 10dB from maximum\n"); | |
259 make_tone_gen_descriptor(&tone_desc, | |
260 1000, | |
261 -4, | |
262 0, | |
263 1, | |
264 1, | |
265 0, | |
266 0, | |
267 0, | |
268 TRUE); | |
269 tone_gen_init(&gen, &tone_desc); | |
270 len = tone_gen(&gen, amp, 1000); | |
271 for (i = 0; i < len; i++) | |
272 { | |
273 level = power_meter_update(&meter, amp[i]); | |
274 //printf("%12d %fdBm0 %fdBov\n", level, power_meter_current_dbm0(&meter), power_meter_current_dbov(&meter)); | |
275 } | |
276 printf("Level: expected %" PRId32 "/%" PRId32 ", got %" PRId32 "\n", power_meter_level_dbov(-10.0f), power_meter_level_dbm0(-10.0f + DBM0_MAX_POWER), level); | |
277 printf("Power: expected %fdBm0, got %fdBm0\n", -10.0f + DBM0_MAX_POWER, power_meter_current_dbm0(&meter)); | |
278 printf("Power: expected %fdBOv, got %fdBOv\n", -10.0f, power_meter_current_dbov(&meter)); | |
279 if (level < power_meter_level_dbov(-10.0f)*0.95f | |
280 || | |
281 level > power_meter_level_dbov(-10.0f)*1.05f) | |
282 { | |
283 printf("Test failed (level)\n"); | |
284 exit(2); | |
285 } | |
286 if (0.2f < fabsf(power_meter_current_dbm0(&meter) + 10.0f - DBM0_MAX_POWER)) | |
287 { | |
288 printf("Test failed (dBm0)\n"); | |
289 exit(2); | |
290 } | |
291 if (0.2f < fabsf(power_meter_current_dbov(&meter) + 10.0)) | |
292 { | |
293 printf("Test failed (dBOv)\n"); | |
294 exit(2); | |
295 } | |
296 | |
297 printf("Testing with AWGN 10dB from maximum\n"); | |
298 awgn_init_dbov(&noise_source, idum, -10.0f); | |
299 for (i = 0; i < 1000; i++) | |
300 amp[i] = awgn(&noise_source); | |
301 for (i = 0; i < 1000; i++) | |
302 { | |
303 level = power_meter_update(&meter, amp[i]); | |
304 //printf("%12d %fdBm0 %fdBov\n", level, power_meter_current_dbm0(&meter), power_meter_current_dbov(&meter)); | |
305 } | |
306 printf("Level: expected %" PRId32 "/%" PRId32 ", got %" PRId32 "\n", power_meter_level_dbov(-10.0f), power_meter_level_dbm0(-10.0f + DBM0_MAX_POWER), level); | |
307 printf("Power: expected %fdBm0, got %fdBm0\n", -10.0f + DBM0_MAX_POWER, power_meter_current_dbm0(&meter)); | |
308 printf("Power: expected %fdBOv, got %fdBOv\n", -10.0f, power_meter_current_dbov(&meter)); | |
309 if (level < power_meter_level_dbov(-10.0f)*0.95f | |
310 || | |
311 level > power_meter_level_dbov(-10.0f)*1.05f) | |
312 { | |
313 printf("Test failed (level)\n"); | |
314 exit(2); | |
315 } | |
316 if (0.2f < fabsf(power_meter_current_dbm0(&meter) + 10.0f - DBM0_MAX_POWER)) | |
317 { | |
318 printf("Test failed (dBm0)\n"); | |
319 exit(2); | |
320 } | |
321 if (0.2f < fabsf(power_meter_current_dbov(&meter) + 10.0f)) | |
322 { | |
323 printf("Test failed (dBOv)\n"); | |
324 exit(2); | |
325 } | |
326 return 0; | |
327 } | |
328 /*- End of function --------------------------------------------------------*/ | |
329 | |
330 int main(int argc, char *argv[]) | |
331 { | |
332 int basic_tests; | |
333 int decode; | |
334 int opt; | |
335 const char *in_file; | |
336 | |
337 basic_tests = TRUE; | |
338 decode = FALSE; | |
339 in_file = IN_FILE_NAME; | |
340 while ((opt = getopt(argc, argv, "d:")) != -1) | |
341 { | |
342 switch (opt) | |
343 { | |
344 case 'd': | |
345 in_file = optarg; | |
346 basic_tests = FALSE; | |
347 decode = TRUE; | |
348 break; | |
349 default: | |
350 //usage(); | |
351 exit(2); | |
352 } | |
353 } | |
354 | |
355 if (basic_tests) | |
356 { | |
357 power_meter_tests(); | |
358 power_surge_detector_tests(); | |
359 } | |
360 if (decode) | |
361 { | |
362 power_surge_detector_file_test(in_file); | |
363 } | |
364 printf("Tests passed\n"); | |
365 return 0; | |
366 } | |
367 /*- End of function --------------------------------------------------------*/ | |
368 /*- End of file ------------------------------------------------------------*/ |