2
0

noise_tests.c 7.7 KB

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