Mercurial > hg > audiostuff
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spandsp-0.0.6pre17/tests/power_meter_tests.c Fri Jun 25 15:50:58 2010 +0200 @@ -0,0 +1,368 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * power_meter_tests.c + * + * Written by Steve Underwood <steveu@coppice.org> + * + * Copyright (C) 2003 Steve Underwood + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: power_meter_tests.c,v 1.24 2009/05/30 15:23:14 steveu Exp $ + */ + +/*! \page power_meter_tests_page Power meter tests +\section power_meter_tests_page_sec_1 What does it do? +These tests assess the accuracy of power meters built from the power meter module. +Both tones and noise are used to check the meter's behaviour. + +\section power_meter_tests_page_sec_2 How does it work? +???. +*/ + +#if defined(HAVE_CONFIG_H) +#include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <memory.h> +#include <float.h> +#include <time.h> +#include <sndfile.h> + +//#if defined(WITH_SPANDSP_INTERNALS) +#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES +//#endif + +#include "spandsp.h" +#include "spandsp-sim.h" + +#define IN_FILE_NAME "../test-data/local/short_nb_voice.wav" +#define OUT_FILE_NAME "power_meter_tests.wav" + +static int power_surge_detector_tests(void) +{ + SNDFILE *outhandle; + power_surge_detector_state_t *sig; + int i; + int sample; + int16_t amp[8000]; + int16_t amp_out[2*8000]; + awgn_state_t *awgnx; + int32_t phase_rate; + uint32_t phase_acc; + int16_t phase_scale; + float signal_power; + int32_t signal_level; + int signal_present; + int prev_signal_present; + int ok; + int extremes[4]; + + if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME, 2)) == NULL) + { + fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME); + exit(2); + } + sig = power_surge_detector_init(NULL, -50.0f, 5.0f); + prev_signal_present = FALSE; + + phase_rate = dds_phase_rate(450.0f); + phase_acc = 0; + + phase_scale = dds_scaling_dbm0(-33.0f); + awgnx = awgn_init_dbm0(NULL, 1234567, -45.0f); + + extremes[0] = 8001; + extremes[1] = -1; + extremes[2] = 8001; + extremes[3] = -1; + for (sample = 0; sample < 800000; sample += 8000) + { + ok = 0; + for (i = 0; i < 8000; i++) + { + amp[i] = awgn(awgnx); + if (i < 4000) + amp[i] += dds_mod(&phase_acc, phase_rate, phase_scale, 0); + + signal_level = power_surge_detector(sig, amp[i]); + signal_present = (signal_level != 0); + if (prev_signal_present != signal_present) + { + signal_power = power_surge_detector_current_dbm0(sig); + if (signal_present) + { + if (ok == 0 && i >= 0 && i < 25) + ok = 1; + if (extremes[0] > i) + extremes[0] = i; + if (extremes[1] < i) + extremes[1] = i; + printf("On at %f (%fdBm0)\n", (sample + i)/8000.0, signal_power); + } + else + { + if (ok == 1 && i >= 4000 + 0 && i < 4000 + 35) + ok = 2; + if (extremes[2] > i) + extremes[2] = i; + if (extremes[3] < i) + extremes[3] = i; + printf("Off at %f (%fdBm0)\n", (sample + i)/8000.0, signal_power); + } + prev_signal_present = signal_present; + } + amp_out[2*i] = amp[i]; + amp_out[2*i + 1] = signal_present*5000; + } + sf_writef_short(outhandle, amp_out, 8000); + if (ok != 2 + || + extremes[0] < 1 + || + extremes[1] > 30 + || + extremes[2] < 4001 + || + extremes[3] > 4030) + { + printf(" Surge not detected correctly (%d)\n", ok); + exit(2); + } + } + sf_close(outhandle); + printf("Min on %d, max on %d, min off %d, max off %d\n", extremes[0], extremes[1], extremes[2], extremes[3]); + return 0; +} +/*- End of function --------------------------------------------------------*/ + +static int power_surge_detector_file_test(const char *file) +{ + SNDFILE *inhandle; + SNDFILE *outhandle; + int inframes; + power_surge_detector_state_t *sig; + int i; + int16_t amp[8000]; + int16_t amp_out[2*8000]; + int sample; + float signal_power; + int32_t signal_level; + int signal_present; + int prev_signal_present; + + if ((inhandle = sf_open_telephony_read(file, 1)) == NULL) + { + printf(" Cannot open speech file '%s'\n", file); + exit(2); + } + + if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME, 1)) == NULL) + { + fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME); + exit(2); + } + sig = power_surge_detector_init(NULL, -50.0f, 6.0f); + prev_signal_present = FALSE; + + sample = 0; + while ((inframes = sf_readf_short(inhandle, amp, 8000))) + { + for (i = 0; i < inframes; i++) + { + signal_level = power_surge_detector(sig, amp[i]); + signal_present = (signal_level != 0); + if (prev_signal_present != signal_present) + { + signal_power = power_surge_detector_current_dbm0(sig); + if (signal_present) + printf("On at %f (%fdBm0)\n", (sample + i)/8000.0, signal_power); + else + printf("Off at %f (%fdBm0)\n", (sample + i)/8000.0, signal_power); + prev_signal_present = signal_present; + } + amp_out[2*i] = amp[i]; + amp_out[2*i + 1] = signal_present*5000; + } + sf_writef_short(outhandle, amp_out, inframes); + sample += inframes; + } + sf_close(inhandle); + sf_close(outhandle); + return 0; +} +/*- End of function --------------------------------------------------------*/ + +static int power_meter_tests(void) +{ + awgn_state_t noise_source; + power_meter_t meter; + tone_gen_descriptor_t tone_desc; + tone_gen_state_t gen; + int i; + int idum = 1234567; + int16_t amp[1000]; + int len; + int32_t level; + + power_meter_init(&meter, 7); + printf("Testing with zero in the power register\n"); + printf("Power: expected %fdBm0, got %fdBm0\n", -90.169f, power_meter_current_dbm0(&meter)); + printf("Power: expected %fdBOv, got %fdBOv\n", -96.329f, power_meter_current_dbov(&meter)); + + printf("Testing with a square wave 10dB from maximum\n"); + for (i = 0; i < 1000; i++) + { + amp[i] = (i & 1) ? 10362 : -10362; + level = power_meter_update(&meter, amp[i]); + //printf("%12d %fdBm0 %fdBov\n", level, power_meter_current_dbm0(&meter), power_meter_current_dbov(&meter)); + } + printf("Level: expected %" PRId32 "/%" PRId32 ", got %" PRId32 "\n", power_meter_level_dbov(-10.0f), power_meter_level_dbm0(-10.0f + DBM0_MAX_POWER), level); + printf("Power: expected %fdBm0, got %fdBm0\n", -10.0f + DBM0_MAX_POWER, power_meter_current_dbm0(&meter)); + printf("Power: expected %fdBOv, got %fdBOv\n", -10.0f, power_meter_current_dbov(&meter)); + if (level < power_meter_level_dbov(-10.0f)*0.99f + || + level > power_meter_level_dbov(-10.0f)*1.01f) + { + printf("Test failed (level)\n"); + exit(2); + } + if (0.1f < fabsf(power_meter_current_dbm0(&meter) + 10.0f - DBM0_MAX_POWER)) + { + printf("Test failed (dBm0)\n"); + exit(2); + } + if (0.1f < fabsf(power_meter_current_dbov(&meter) + 10.0)) + { + printf("Test failed (dBOv)\n"); + exit(2); + } + + printf("Testing with a sine wave tone 10dB from maximum\n"); + make_tone_gen_descriptor(&tone_desc, + 1000, + -4, + 0, + 1, + 1, + 0, + 0, + 0, + TRUE); + tone_gen_init(&gen, &tone_desc); + len = tone_gen(&gen, amp, 1000); + for (i = 0; i < len; i++) + { + level = power_meter_update(&meter, amp[i]); + //printf("%12d %fdBm0 %fdBov\n", level, power_meter_current_dbm0(&meter), power_meter_current_dbov(&meter)); + } + printf("Level: expected %" PRId32 "/%" PRId32 ", got %" PRId32 "\n", power_meter_level_dbov(-10.0f), power_meter_level_dbm0(-10.0f + DBM0_MAX_POWER), level); + printf("Power: expected %fdBm0, got %fdBm0\n", -10.0f + DBM0_MAX_POWER, power_meter_current_dbm0(&meter)); + printf("Power: expected %fdBOv, got %fdBOv\n", -10.0f, power_meter_current_dbov(&meter)); + if (level < power_meter_level_dbov(-10.0f)*0.95f + || + level > power_meter_level_dbov(-10.0f)*1.05f) + { + printf("Test failed (level)\n"); + exit(2); + } + if (0.2f < fabsf(power_meter_current_dbm0(&meter) + 10.0f - DBM0_MAX_POWER)) + { + printf("Test failed (dBm0)\n"); + exit(2); + } + if (0.2f < fabsf(power_meter_current_dbov(&meter) + 10.0)) + { + printf("Test failed (dBOv)\n"); + exit(2); + } + + printf("Testing with AWGN 10dB from maximum\n"); + awgn_init_dbov(&noise_source, idum, -10.0f); + for (i = 0; i < 1000; i++) + amp[i] = awgn(&noise_source); + for (i = 0; i < 1000; i++) + { + level = power_meter_update(&meter, amp[i]); + //printf("%12d %fdBm0 %fdBov\n", level, power_meter_current_dbm0(&meter), power_meter_current_dbov(&meter)); + } + printf("Level: expected %" PRId32 "/%" PRId32 ", got %" PRId32 "\n", power_meter_level_dbov(-10.0f), power_meter_level_dbm0(-10.0f + DBM0_MAX_POWER), level); + printf("Power: expected %fdBm0, got %fdBm0\n", -10.0f + DBM0_MAX_POWER, power_meter_current_dbm0(&meter)); + printf("Power: expected %fdBOv, got %fdBOv\n", -10.0f, power_meter_current_dbov(&meter)); + if (level < power_meter_level_dbov(-10.0f)*0.95f + || + level > power_meter_level_dbov(-10.0f)*1.05f) + { + printf("Test failed (level)\n"); + exit(2); + } + if (0.2f < fabsf(power_meter_current_dbm0(&meter) + 10.0f - DBM0_MAX_POWER)) + { + printf("Test failed (dBm0)\n"); + exit(2); + } + if (0.2f < fabsf(power_meter_current_dbov(&meter) + 10.0f)) + { + printf("Test failed (dBOv)\n"); + exit(2); + } + return 0; +} +/*- End of function --------------------------------------------------------*/ + +int main(int argc, char *argv[]) +{ + int basic_tests; + int decode; + int opt; + const char *in_file; + + basic_tests = TRUE; + decode = FALSE; + in_file = IN_FILE_NAME; + while ((opt = getopt(argc, argv, "d:")) != -1) + { + switch (opt) + { + case 'd': + in_file = optarg; + basic_tests = FALSE; + decode = TRUE; + break; + default: + //usage(); + exit(2); + } + } + + if (basic_tests) + { + power_meter_tests(); + power_surge_detector_tests(); + } + if (decode) + { + power_surge_detector_file_test(in_file); + } + printf("Tests passed\n"); + return 0; +} +/*- End of function --------------------------------------------------------*/ +/*- End of file ------------------------------------------------------------*/