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 ------------------------------------------------------------*/ |
