comparison spandsp-0.0.6pre17/tests/noise_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 * noise_tests.c
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2005 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: noise_tests.c,v 1.18 2009/05/30 15:23:14 steveu Exp $
26 */
27
28 /*! \page noise_tests_page Noise generator tests
29 \section noise_tests_page_sec_1 What does it do?
30 */
31
32 #if defined(HAVE_CONFIG_H)
33 #include "config.h"
34 #endif
35
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <sndfile.h>
40
41 //#if defined(WITH_SPANDSP_INTERNALS)
42 #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
43 //#endif
44
45 #include "spandsp.h"
46 #include "spandsp-sim.h"
47
48 #if !defined(M_PI)
49 # define M_PI 3.14159265358979323846 /* pi */
50 #endif
51
52 #define OUT_FILE_NAME "noise.wav"
53
54 /* Some simple sanity tests for the noise generation routines */
55
56 int main (int argc, char *argv[])
57 {
58 int i;
59 int j;
60 int level;
61 int clip_high;
62 int clip_low;
63 int quality;
64 int total_samples;
65 int seed = 1234567;
66 int outframes;
67 int16_t value;
68 double total;
69 double x;
70 double p;
71 double o;
72 int bins[65536];
73 int16_t amp[1024];
74 noise_state_t noise_source;
75 SNDFILE *outhandle;
76
77 if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME, 1)) == NULL)
78 {
79 fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME);
80 exit(2);
81 }
82
83 for (quality = 7; quality <= 20; quality += (20 - 7))
84 {
85 /* Generate AWGN at several RMS levels between -50dBOv and 0dBOv. Noise is
86 generated for a large number of samples (1,000,000), and the RMS value
87 of the noise is calculated along the way. If the resulting level is
88 close to the requested RMS level, at least the scaling of the noise
89 should be Ok. At high levels some clipping may distort the result a
90 little. */
91 printf("Testing AWGN power, with quality %d\n", quality);
92 for (level = -50; level <= 0; level += 5)
93 {
94 clip_high = 0;
95 clip_low = 0;
96 total = 0.0;
97 noise_init_dbov(&noise_source, seed, (float) level, NOISE_CLASS_AWGN, quality);
98 total_samples = 1000000;
99 for (i = 0; i < total_samples; i++)
100 {
101 value = noise(&noise_source);
102 if (value == 32767)
103 clip_high++;
104 else if (value == -32768)
105 clip_low++;
106 total += ((double) value)*((double) value);
107 }
108 printf ("RMS = %.3f (expected %d) %.2f%% error [clipped samples %d+%d]\n",
109 log10(sqrt(total/total_samples)/32768.0)*20.0,
110 level,
111 100.0*(1.0 - sqrt(total/total_samples)/(pow(10.0, level/20.0)*32768.0)),
112 clip_low,
113 clip_high);
114 if (level < -5 && fabs(log10(sqrt(total/total_samples)/32768.0)*20.0 - level) > 0.2)
115 {
116 printf("Test failed\n");
117 exit(2);
118 }
119 }
120 }
121
122 /* Now look at the statistical spread of the results, by collecting data in
123 bins from a large number of samples. Use a fairly high noise level, but
124 low enough to avoid significant clipping. Use the Gaussian model to
125 predict the real probability, and present the results for graphing. */
126 quality = 7;
127 printf("Testing the statistical spread of AWGN, with quality %d\n", quality);
128 memset(bins, 0, sizeof(bins));
129 clip_high = 0;
130 clip_low = 0;
131 level = -15;
132 noise_init_dbov(&noise_source, seed, (float) level, NOISE_CLASS_AWGN, quality);
133 total_samples = 10000000;
134 for (i = 0; i < total_samples; i++)
135 {
136 value = noise(&noise_source);
137 if (value == 32767)
138 clip_high++;
139 else if (value == -32768)
140 clip_low++;
141 bins[value + 32768]++;
142 }
143 /* Find the RMS power level to expect */
144 o = pow(10.0, level/20.0)*(32768.0*0.70711);
145 for (i = 0; i < 65536 - 10; i++)
146 {
147 x = i - 32768;
148 /* Find the real probability for this bin */
149 p = (1.0/(o*sqrt(2.0*M_PI)))*exp(-(x*x)/(2.0*o*o));
150 /* Now do a little smoothing on the real data to get a reasonably
151 steady answer */
152 x = 0;
153 for (j = 0; j < 10; j++)
154 x += bins[i + j];
155 x /= 10.0;
156 x /= total_samples;
157 /* Now send it out for graphing. */
158 if (p > 0.0000001)
159 printf("%6d %.7f %.7f\n", i - 32768, x, p);
160 }
161
162 printf("Generating AWGN at -15dBOv to file\n");
163 for (j = 0; j < 50; j++)
164 {
165 for (i = 0; i < 1024; i++)
166 amp[i] = noise(&noise_source);
167 outframes = sf_writef_short(outhandle, amp, 1024);
168 if (outframes != 1024)
169 {
170 fprintf(stderr, " Error writing audio file\n");
171 exit(2);
172 }
173 }
174
175 /* Generate Hoth noise at several RMS levels between -50dBm and 0dBm. Noise
176 is generated for a large number of samples (1,000,000), and the RMS value
177 of the noise is calculated along the way. If the resulting level is
178 close to the requested RMS level, at least the scaling of the noise
179 should be Ok. At high levels some clipping may distort the result a
180 little. */
181 quality = 7;
182 printf("Testing Hoth noise power, with quality %d\n", quality);
183 for (level = -50; level <= 0; level += 5)
184 {
185 clip_high = 0;
186 clip_low = 0;
187 total = 0.0;
188 noise_init_dbov(&noise_source, seed, (float) level, NOISE_CLASS_HOTH, quality);
189 total_samples = 1000000;
190 for (i = 0; i < total_samples; i++)
191 {
192 value = noise(&noise_source);
193 if (value == 32767)
194 clip_high++;
195 else if (value == -32768)
196 clip_low++;
197 total += ((double) value)*((double) value);
198 }
199 printf ("RMS = %.3f (expected %d) %.2f%% error [clipped samples %d+%d]\n",
200 log10(sqrt(total/total_samples)/32768.0)*20.0,
201 level,
202 100.0*(1.0 - sqrt(total/total_samples)/(pow(10.0, level/20.0)*32768.0)),
203 clip_low,
204 clip_high);
205 if (level < -5 && fabs(log10(sqrt(total/total_samples)/32768.0)*20.0 - level) > 0.2)
206 {
207 printf("Test failed\n");
208 exit(2);
209 }
210 }
211
212 quality = 7;
213 printf("Generating Hoth noise at -15dBOv to file\n");
214 level = -15;
215 noise_init_dbov(&noise_source, seed, (float) level, NOISE_CLASS_HOTH, quality);
216 for (j = 0; j < 50; j++)
217 {
218 for (i = 0; i < 1024; i++)
219 amp[i] = noise(&noise_source);
220 outframes = sf_writef_short(outhandle, amp, 1024);
221 if (outframes != 1024)
222 {
223 fprintf(stderr, " Error writing audio file\n");
224 exit(2);
225 }
226 }
227
228 if (sf_close(outhandle))
229 {
230 fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
231 exit(2);
232 }
233
234 printf("Tests passed.\n");
235 return 0;
236 }
237 /*- End of function --------------------------------------------------------*/
238 /*- End of file ------------------------------------------------------------*/

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