peak_chunk_test.c
上传用户:shw771010
上传日期:2022-01-05
资源大小:991k
文件大小:11k
源码类别:

Audio

开发平台:

Unix_Linux

  1. /*
  2. ** Copyright (C) 2001-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
  3. **
  4. ** This program is free software; you can redistribute it and/or modify
  5. ** it under the terms of the GNU General Public License as published by
  6. ** the Free Software Foundation; either version 2 of the License, or
  7. ** (at your option) any later version.
  8. **
  9. ** This program is distributed in the hope that it will be useful,
  10. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. ** GNU General Public License for more details.
  13. **
  14. ** You should have received a copy of the GNU General Public License
  15. ** along with this program; if not, write to the Free Software
  16. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #include "sfconfig.h"
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <math.h>
  23. #if HAVE_UNISTD_H
  24. #include <unistd.h>
  25. #endif
  26. #include <sndfile.h>
  27. #include "utils.h"
  28. #define BUFFER_LEN (1<<15)
  29. #define LOG_BUFFER_SIZE 1024
  30. static void test_float_peak (const char *filename, int filetype) ;
  31. static void read_write_peak_test (const char *filename, int filetype) ;
  32. static void check_logged_peaks (char *buffer) ;
  33. /* Force the start of this buffer to be double aligned. Sparc-solaris will
  34. ** choke if its not.
  35. */
  36. static double data [BUFFER_LEN] ;
  37. static char log_buffer [LOG_BUFFER_SIZE] ;
  38. int
  39. main (int argc, char *argv [])
  40. { int do_all = 0 ;
  41. int test_count = 0 ;
  42. if (argc != 2)
  43. { printf ("Usage : %s <test>n", argv [0]) ;
  44. printf ("    Where <test> is one of the following:n") ;
  45. printf ("           aiff - test AIFF file PEAK chunkn") ;
  46. printf ("           caf  - test CAF file PEAK chunkn") ;
  47. printf ("           wav  - test WAV file peak chunkn") ;
  48. printf ("           all  - perform all testsn") ;
  49. exit (1) ;
  50. } ;
  51. do_all = ! strcmp (argv [1], "all") ;
  52. if (do_all || ! strcmp (argv [1], "wav"))
  53. { test_float_peak ("peak_float.wav", SF_FORMAT_WAV | SF_FORMAT_FLOAT) ;
  54. test_float_peak ("peak_float.wavex", SF_FORMAT_WAVEX | SF_FORMAT_FLOAT) ;
  55. test_float_peak ("peak_float.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_FLOAT) ;
  56. read_write_peak_test ("rw_peak.wav", SF_FORMAT_WAV | SF_FORMAT_FLOAT) ;
  57. read_write_peak_test ("rw_peak.wavex", SF_FORMAT_WAVEX | SF_FORMAT_FLOAT) ;
  58. test_count++ ;
  59. } ;
  60. if (do_all || ! strcmp (argv [1], "aiff"))
  61. { test_float_peak ("peak_float.aiff", SF_FORMAT_AIFF | SF_FORMAT_FLOAT) ;
  62. read_write_peak_test ("rw_peak.aiff", SF_FORMAT_AIFF | SF_FORMAT_FLOAT) ;
  63. test_count++ ;
  64. } ;
  65. if (do_all || ! strcmp (argv [1], "caf"))
  66. { test_float_peak ("peak_float.caf", SF_FORMAT_CAF | SF_FORMAT_FLOAT) ;
  67. read_write_peak_test ("rw_peak.caf", SF_FORMAT_CAF | SF_FORMAT_FLOAT) ;
  68. test_count++ ;
  69. } ;
  70. if (test_count == 0)
  71. { printf ("Mono : ************************************n") ;
  72. printf ("Mono : *  No '%s' test defined.n", argv [1]) ;
  73. printf ("Mono : ************************************n") ;
  74. return 1 ;
  75. } ;
  76. return 0 ;
  77. } /* main */
  78. /*============================================================================================
  79. ** Here are the test functions.
  80. */
  81. static void
  82. test_float_peak (const char *filename, int filetype)
  83. { SNDFILE *file ;
  84. SF_INFO sfinfo ;
  85. int k, frames, count ;
  86. print_test_name ("test_float_peak", filename) ;
  87. memset (&sfinfo, 0, sizeof (sfinfo)) ;
  88. sfinfo.samplerate = 44100 ;
  89. sfinfo.format = filetype ;
  90. sfinfo.channels = 4 ;
  91. sfinfo.frames = 0 ;
  92. frames = BUFFER_LEN / sfinfo.channels ;
  93. /* Create some random data with a peak value of 0.66. */
  94. for (k = 0 ; k < BUFFER_LEN ; k++)
  95. data [k] = (rand () % 2000) / 3000.0 ;
  96. /* Insert some larger peaks a know locations. */
  97. data [4 * (frames / 8) + 0] = (frames / 8) * 0.01 ; /* First channel */
  98. data [4 * (frames / 6) + 1] = (frames / 6) * 0.01 ; /* Second channel */
  99. data [4 * (frames / 4) + 2] = (frames / 4) * 0.01 ; /* Third channel */
  100. data [4 * (frames / 2) + 3] = (frames / 2) * 0.01 ; /* Fourth channel */
  101. /* Write a file with PEAK chunks. */
  102. file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, 0, __LINE__) ;
  103. /* Try to confuse the header writer by adding a removing the PEAK chunk. */
  104. sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ;
  105. sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
  106. sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ;
  107. /* Write the data in four passed. The data is designed so that peaks will
  108. ** be written in the different calls to sf_write_double ().
  109. */
  110. for (count = 0 ; count < 4 ; count ++)
  111. test_write_double_or_die (file, 0, data + count * BUFFER_LEN / 4, BUFFER_LEN / 4, BUFFER_LEN / 4) ;
  112. sf_close (file) ;
  113. file = test_open_file_or_die (filename, SFM_READ, &sfinfo, 0, __LINE__) ;
  114. if (sfinfo.format != filetype)
  115. { printf ("nnLine %d: Returned format incorrect (0x%08X => 0x%08X).n", __LINE__, filetype, sfinfo.format) ;
  116. exit (1) ;
  117. } ;
  118. if (sfinfo.frames != frames)
  119. { printf ("nnLine %d: Incorrect number of frames in file. (%d => %ld)n", __LINE__, frames, (long) sfinfo.frames) ;
  120. exit (1) ;
  121. } ;
  122. if (sfinfo.channels != 4)
  123. { printf ("nnLine %d: Incorrect number of channels in file.n", __LINE__) ;
  124. exit (1) ;
  125. } ;
  126. /* Check these two commands. */
  127. if (sf_command (file, SFC_GET_SIGNAL_MAX, data, sizeof (double)) == SF_FALSE)
  128. { printf ("nnLine %d: Command should have returned SF_TRUE.n", __LINE__) ;
  129. exit (1) ;
  130. } ;
  131. if (fabs (data [0] - (frames / 2) * 0.01) > 0.01)
  132. { printf ("nnLine %d: Bad peak value (%f should be %f) for command SFC_GET_SIGNAL_MAX.n", __LINE__, data [0], (frames / 2) * 0.01) ;
  133. exit (1) ;
  134. } ;
  135. if (sf_command (file, SFC_GET_MAX_ALL_CHANNELS, data, sizeof (double) * sfinfo.channels) == SF_FALSE)
  136. { printf ("nnLine %d: Command should have returned SF_TRUE.n", __LINE__) ;
  137. exit (1) ;
  138. } ;
  139. if (fabs (data [3] - (frames / 2) * 0.01) > 0.01)
  140. { printf ("nnLine %d: Bad peak value (%f should be %f) for command SFC_GET_MAX_ALL_CHANNELS.n", __LINE__, data [0], (frames / 2) * 0.01) ;
  141. exit (1) ;
  142. } ;
  143. /* Get the log buffer data. */
  144. log_buffer [0] = 0 ;
  145. sf_command (file, SFC_GET_LOG_INFO, log_buffer, LOG_BUFFER_SIZE) ;
  146. if (strlen (log_buffer) == 0)
  147. { printf ("nnLine %d: Empty log buffer,n", __LINE__) ;
  148. exit (1) ;
  149. } ;
  150. check_logged_peaks (log_buffer) ;
  151. sf_close (file) ;
  152. /* Write a file ***without*** PEAK chunks. */
  153. file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, 0, __LINE__) ;
  154. /* Try to confuse the header writer by adding a removing the PEAK chunk. */
  155. sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
  156. sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ;
  157. sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
  158. /* Write the data in four passed. The data is designed so that peaks will
  159. ** be written in the different calls to sf_write_double ().
  160. */
  161. for (count = 0 ; count < 4 ; count ++)
  162. test_write_double_or_die (file, 0, data + count * BUFFER_LEN / 4, BUFFER_LEN / 4, BUFFER_LEN / 4) ;
  163. sf_close (file) ;
  164. file = test_open_file_or_die (filename, SFM_READ, &sfinfo, 0, __LINE__) ;
  165. /* Check these two commands. */
  166. if (sf_command (file, SFC_GET_SIGNAL_MAX, data, sizeof (double)))
  167. { printf ("nnLine %d: Command should have returned SF_FALSE.n", __LINE__) ;
  168. exit (1) ;
  169. } ;
  170. if (sf_command (file, SFC_GET_MAX_ALL_CHANNELS, data, sizeof (double) * sfinfo.channels))
  171. { printf ("nnLine %d: Command should have returned SF_FALSE.n", __LINE__) ;
  172. exit (1) ;
  173. } ;
  174. /* Get the log buffer data. */
  175. log_buffer [0] = 0 ;
  176. sf_command (file, SFC_GET_LOG_INFO, log_buffer, LOG_BUFFER_SIZE) ;
  177. if (strlen (log_buffer) == 0)
  178. { printf ("nnLine %d: Empty log buffer,n", __LINE__) ;
  179. exit (1) ;
  180. } ;
  181. if (strstr (log_buffer, "PEAK :") != NULL)
  182. { printf ("nnLine %d: Should not have a PEAK chunk in this file.nn", __LINE__) ;
  183. puts (log_buffer) ;
  184. exit (1) ;
  185. } ;
  186. sf_close (file) ;
  187. unlink (filename) ;
  188. printf ("okn") ;
  189. } /* test_float_peak */
  190. static void
  191. check_logged_peaks (char *buffer)
  192. { char  *cptr ;
  193. int k, chan, channel_count, position ;
  194. float value ;
  195. if (strstr (buffer, "should") || strstr (buffer, "*"))
  196. { printf ("nnLine %d: Something wrong in buffer. Dumping.n", __LINE__) ;
  197. puts (buffer) ;
  198. exit (1) ;
  199. } ;
  200. channel_count = 0 ;
  201. cptr = strstr (buffer, "Channels") ;
  202. if (cptr && sscanf (cptr, "Channels      : %d", &k) == 1)
  203. channel_count = k ;
  204. else if (cptr && sscanf (cptr, "Channels / frame : %d", &k) == 1)
  205. channel_count = k ;
  206. else
  207. { printf ("nnLine %d: Couldn't find channel count.n", __LINE__) ;
  208. exit (1) ;
  209. } ;
  210. if (channel_count != 4)
  211. { printf ("nnLine %d: Wrong channel count (4 ->%d).n", __LINE__, channel_count) ;
  212. exit (1) ;
  213. } ;
  214. if (! (cptr = strstr (buffer, "Ch   Position       Value")))
  215. { printf ("nnLine %d: Can't find PEAK data.n", __LINE__) ;
  216. exit (1) ;
  217. } ;
  218. for (k = 0 ; k < channel_count ; k++)
  219. { if (! (cptr = strchr (cptr, 'n')))
  220. { printf ("nnLine %d: Got lost.n", __LINE__) ;
  221. exit (1) ;
  222. } ;
  223. if (sscanf (cptr, "%d %d %f", &chan, &position, &value) != 3)
  224. { printf ("nnLine %d: sscanf failed.n", __LINE__) ;
  225. exit (1) ;
  226. } ;
  227. if (position == 0)
  228. { printf ("nnLine %d: peak position for channel %d should not be at offset 0.n", __LINE__, chan) ;
  229. printf ("%s", buffer) ;
  230. exit (1) ;
  231. } ;
  232. if (chan != k || fabs ((position) * 0.01 - value) > 1e-6)
  233. { printf ("nnLine %d: Error : peak value incorrect!n", __LINE__) ;
  234. printf ("%s", buffer) ;
  235. printf ("nnLine %d: %d %f %fn", __LINE__, chan, position * 0.01, value) ;
  236. exit (1) ;
  237. } ;
  238. cptr ++ ; /* Move past current newline. */
  239. } ;
  240. } /* check_logged_peaks */
  241. static void
  242. read_write_peak_test (const char *filename, int filetype)
  243. { SNDFILE *file ;
  244.     SF_INFO sfinfo ;
  245.     double   small_data [10] ;
  246.     double   max_peak = 0.0 ;
  247.     unsigned k ;
  248. print_test_name (__func__, filename) ;
  249.     for (k = 0 ; k < ARRAY_LEN (small_data) ; k ++)
  250.         small_data [k] = 0.1 ;
  251.     sfinfo.samplerate = 44100 ;
  252.     sfinfo.channels = 2 ;
  253.     sfinfo.format = filetype ;
  254.     sfinfo.frames = 0 ;
  255. /* Open the file, add peak chunk and write samples with value 0.1. */
  256.     file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
  257.     sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ;
  258. test_write_double_or_die (file, 0, small_data, ARRAY_LEN (small_data), __LINE__) ;
  259.     sf_close (file) ;
  260.     /* Open the fiel RDWR, write sample valied 1.25. */
  261.     file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_FALSE, __LINE__) ;
  262.     for (k = 0 ; k < ARRAY_LEN (small_data) ; k ++)
  263.         small_data [k] = 1.0 ;
  264. test_write_double_or_die (file, 0, small_data, ARRAY_LEN (small_data), __LINE__) ;
  265.     sf_command (file, SFC_GET_SIGNAL_MAX, &max_peak, sizeof (max_peak)) ;
  266.     sf_close (file) ;
  267.     exit_if_true (max_peak < 0.1, "nnLine %d : max peak (%5.3f) should not be 0.1.nn", __LINE__, max_peak) ;
  268.     /* Open the file and test the values written to the PEAK chunk. */
  269.     file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
  270. exit_if_true (sfinfo.channels * sfinfo.frames != 2 * ARRAY_LEN (small_data),
  271. "Line %d : frame count is %ld, should be %dn", __LINE__, SF_COUNT_TO_LONG (sfinfo.frames), 2 * ARRAY_LEN (small_data)) ;
  272.     sf_command (file, SFC_GET_SIGNAL_MAX, &max_peak, sizeof (double)) ;
  273.     sf_close (file) ;
  274.     exit_if_true (max_peak < 1.0, "nnLine %d : max peak (%5.3f) should be 1.0.nn", __LINE__, max_peak) ;
  275. unlink (filename) ;
  276. puts ("ok") ;
  277. } /* read_write_peak_test */