Mercurial > hg > sv-dependency-builds
comparison src/libsndfile-1.0.27/tests/peak_chunk_test.c @ 125:cd6cdf86811e
Current libsndfile source
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Tue, 18 Oct 2016 13:22:47 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
124:e3d5853d5918 | 125:cd6cdf86811e |
---|---|
1 /* | |
2 ** Copyright (C) 2001-2016 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 | |
19 #include "sfconfig.h" | |
20 | |
21 #include <stdio.h> | |
22 #include <stdlib.h> | |
23 #include <string.h> | |
24 #include <math.h> | |
25 #include <inttypes.h> | |
26 | |
27 #if HAVE_UNISTD_H | |
28 #include <unistd.h> | |
29 #endif | |
30 | |
31 #include <sndfile.h> | |
32 | |
33 #include "utils.h" | |
34 | |
35 #define BUFFER_LEN (1 << 15) | |
36 #define LOG_BUFFER_SIZE 1024 | |
37 | |
38 | |
39 static void test_float_peak (const char *filename, int filetype) ; | |
40 static void read_write_peak_test (const char *filename, int filetype) ; | |
41 | |
42 static void check_logged_peaks (char *buffer) ; | |
43 | |
44 /* Force the start of this buffer to be double aligned. Sparc-solaris will | |
45 ** choke if its not. | |
46 */ | |
47 static double data [BUFFER_LEN] ; | |
48 static char log_buffer [LOG_BUFFER_SIZE] ; | |
49 | |
50 int | |
51 main (int argc, char *argv []) | |
52 { int do_all = 0 ; | |
53 int test_count = 0 ; | |
54 | |
55 if (argc != 2) | |
56 { printf ("Usage : %s <test>\n", argv [0]) ; | |
57 printf (" Where <test> is one of the following:\n") ; | |
58 printf (" aiff - test AIFF file PEAK chunk\n") ; | |
59 printf (" caf - test CAF file PEAK chunk\n") ; | |
60 printf (" wav - test WAV file peak chunk\n") ; | |
61 printf (" all - perform all tests\n") ; | |
62 exit (1) ; | |
63 } ; | |
64 | |
65 do_all = ! strcmp (argv [1], "all") ; | |
66 | |
67 if (do_all || ! strcmp (argv [1], "wav")) | |
68 { test_float_peak ("peak_float.wav", SF_FORMAT_WAV | SF_FORMAT_FLOAT) ; | |
69 test_float_peak ("peak_float.wavex", SF_FORMAT_WAVEX | SF_FORMAT_FLOAT) ; | |
70 test_float_peak ("peak_float.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_FLOAT) ; | |
71 | |
72 read_write_peak_test ("rw_peak.wav", SF_FORMAT_WAV | SF_FORMAT_FLOAT) ; | |
73 read_write_peak_test ("rw_peak.wavex", SF_FORMAT_WAVEX | SF_FORMAT_FLOAT) ; | |
74 test_count++ ; | |
75 } ; | |
76 | |
77 if (do_all || ! strcmp (argv [1], "aiff")) | |
78 { test_float_peak ("peak_float.aiff", SF_FORMAT_AIFF | SF_FORMAT_FLOAT) ; | |
79 | |
80 read_write_peak_test ("rw_peak.aiff", SF_FORMAT_AIFF | SF_FORMAT_FLOAT) ; | |
81 test_count++ ; | |
82 } ; | |
83 | |
84 if (do_all || ! strcmp (argv [1], "caf")) | |
85 { test_float_peak ("peak_float.caf", SF_FORMAT_CAF | SF_FORMAT_FLOAT) ; | |
86 | |
87 read_write_peak_test ("rw_peak.caf", SF_FORMAT_CAF | SF_FORMAT_FLOAT) ; | |
88 test_count++ ; | |
89 } ; | |
90 | |
91 if (do_all || ! strcmp (argv [1], "rf64")) | |
92 { test_float_peak ("peak_float.rf64", SF_FORMAT_RF64 | SF_FORMAT_FLOAT) ; | |
93 | |
94 read_write_peak_test ("rw_peak.rf64", SF_FORMAT_RF64 | SF_FORMAT_FLOAT) ; | |
95 test_count++ ; | |
96 } ; | |
97 | |
98 if (test_count == 0) | |
99 { printf ("Mono : ************************************\n") ; | |
100 printf ("Mono : * No '%s' test defined.\n", argv [1]) ; | |
101 printf ("Mono : ************************************\n") ; | |
102 return 1 ; | |
103 } ; | |
104 | |
105 return 0 ; | |
106 } /* main */ | |
107 | |
108 /*============================================================================================ | |
109 ** Here are the test functions. | |
110 */ | |
111 | |
112 static void | |
113 test_float_peak (const char *filename, int filetype) | |
114 { SNDFILE *file ; | |
115 SF_INFO sfinfo ; | |
116 int k, frames, count ; | |
117 | |
118 print_test_name ("test_float_peak", filename) ; | |
119 | |
120 memset (&sfinfo, 0, sizeof (sfinfo)) ; | |
121 sfinfo.samplerate = 44100 ; | |
122 sfinfo.format = filetype ; | |
123 sfinfo.channels = 4 ; | |
124 sfinfo.frames = 0 ; | |
125 | |
126 frames = BUFFER_LEN / sfinfo.channels ; | |
127 | |
128 /* Create some random data with a peak value of 0.66. */ | |
129 for (k = 0 ; k < BUFFER_LEN ; k++) | |
130 data [k] = (rand () % 2000) / 3000.0 ; | |
131 | |
132 /* Insert some larger peaks a know locations. */ | |
133 data [4 * (frames / 8) + 0] = (frames / 8) * 0.01 ; /* First channel */ | |
134 data [4 * (frames / 6) + 1] = (frames / 6) * 0.01 ; /* Second channel */ | |
135 data [4 * (frames / 4) + 2] = (frames / 4) * 0.01 ; /* Third channel */ | |
136 data [4 * (frames / 2) + 3] = (frames / 2) * 0.01 ; /* Fourth channel */ | |
137 | |
138 /* Write a file with PEAK chunks. */ | |
139 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, 0, __LINE__) ; | |
140 | |
141 /* Try to confuse the header writer by adding a removing the PEAK chunk. */ | |
142 sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ; | |
143 sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ; | |
144 sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ; | |
145 | |
146 /* Write the data in four passed. The data is designed so that peaks will | |
147 ** be written in the different calls to sf_write_double (). | |
148 */ | |
149 for (count = 0 ; count < 4 ; count ++) | |
150 test_write_double_or_die (file, 0, data + count * BUFFER_LEN / 4, BUFFER_LEN / 4, BUFFER_LEN / 4) ; | |
151 | |
152 sf_close (file) ; | |
153 | |
154 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, 0, __LINE__) ; | |
155 | |
156 if (sfinfo.format != filetype) | |
157 { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ; | |
158 exit (1) ; | |
159 } ; | |
160 | |
161 if (sfinfo.frames != frames) | |
162 { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, frames, (long) sfinfo.frames) ; | |
163 exit (1) ; | |
164 } ; | |
165 | |
166 if (sfinfo.channels != 4) | |
167 { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ; | |
168 exit (1) ; | |
169 } ; | |
170 | |
171 /* Check these two commands. */ | |
172 if (sf_command (file, SFC_GET_SIGNAL_MAX, data, sizeof (double)) == SF_FALSE) | |
173 { printf ("\n\nLine %d: Command should have returned SF_TRUE.\n", __LINE__) ; | |
174 exit (1) ; | |
175 } ; | |
176 | |
177 if (fabs (data [0] - (frames / 2) * 0.01) > 0.01) | |
178 { printf ("\n\nLine %d: Bad peak value (%f should be %f) for command SFC_GET_SIGNAL_MAX.\n", __LINE__, data [0], (frames / 2) * 0.01) ; | |
179 exit (1) ; | |
180 } ; | |
181 | |
182 if (sf_command (file, SFC_GET_MAX_ALL_CHANNELS, data, sizeof (double) * sfinfo.channels) == SF_FALSE) | |
183 { printf ("\n\nLine %d: Command should have returned SF_TRUE.\n", __LINE__) ; | |
184 exit (1) ; | |
185 } ; | |
186 | |
187 if (fabs (data [3] - (frames / 2) * 0.01) > 0.01) | |
188 { printf ("\n\nLine %d: Bad peak value (%f should be %f) for command SFC_GET_MAX_ALL_CHANNELS.\n", __LINE__, data [0], (frames / 2) * 0.01) ; | |
189 exit (1) ; | |
190 } ; | |
191 | |
192 /* Get the log buffer data. */ | |
193 log_buffer [0] = 0 ; | |
194 sf_command (file, SFC_GET_LOG_INFO, log_buffer, LOG_BUFFER_SIZE) ; | |
195 | |
196 if (strlen (log_buffer) == 0) | |
197 { printf ("\n\nLine %d: Empty log buffer,\n", __LINE__) ; | |
198 exit (1) ; | |
199 } ; | |
200 | |
201 check_logged_peaks (log_buffer) ; | |
202 | |
203 sf_close (file) ; | |
204 | |
205 /* Write a file ***without*** PEAK chunks. */ | |
206 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, 0, __LINE__) ; | |
207 | |
208 /* Try to confuse the header writer by adding a removing the PEAK chunk. */ | |
209 sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ; | |
210 sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ; | |
211 sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ; | |
212 | |
213 /* Write the data in four passed. The data is designed so that peaks will | |
214 ** be written in the different calls to sf_write_double (). | |
215 */ | |
216 for (count = 0 ; count < 4 ; count ++) | |
217 test_write_double_or_die (file, 0, data + count * BUFFER_LEN / 4, BUFFER_LEN / 4, BUFFER_LEN / 4) ; | |
218 | |
219 sf_close (file) ; | |
220 | |
221 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, 0, __LINE__) ; | |
222 | |
223 /* Check these two commands. */ | |
224 if (sf_command (file, SFC_GET_SIGNAL_MAX, data, sizeof (double))) | |
225 { printf ("\n\nLine %d: Command should have returned SF_FALSE.\n", __LINE__) ; | |
226 exit (1) ; | |
227 } ; | |
228 | |
229 if (sf_command (file, SFC_GET_MAX_ALL_CHANNELS, data, sizeof (double) * sfinfo.channels)) | |
230 { printf ("\n\nLine %d: Command should have returned SF_FALSE.\n", __LINE__) ; | |
231 exit (1) ; | |
232 } ; | |
233 | |
234 /* Get the log buffer data. */ | |
235 log_buffer [0] = 0 ; | |
236 sf_command (file, SFC_GET_LOG_INFO, log_buffer, LOG_BUFFER_SIZE) ; | |
237 | |
238 if (strlen (log_buffer) == 0) | |
239 { printf ("\n\nLine %d: Empty log buffer,\n", __LINE__) ; | |
240 exit (1) ; | |
241 } ; | |
242 | |
243 if (strstr (log_buffer, "PEAK :") != NULL) | |
244 { printf ("\n\nLine %d: Should not have a PEAK chunk in this file.\n\n", __LINE__) ; | |
245 puts (log_buffer) ; | |
246 exit (1) ; | |
247 } ; | |
248 | |
249 sf_close (file) ; | |
250 | |
251 unlink (filename) ; | |
252 printf ("ok\n") ; | |
253 } /* test_float_peak */ | |
254 | |
255 static void | |
256 check_logged_peaks (char *buffer) | |
257 { char *cptr ; | |
258 int k, chan, channel_count, position ; | |
259 float value ; | |
260 | |
261 if (strstr (buffer, "should") || strstr (buffer, "*")) | |
262 { printf ("\n\nLine %d: Something wrong in buffer. Dumping.\n", __LINE__) ; | |
263 puts (buffer) ; | |
264 exit (1) ; | |
265 } ; | |
266 | |
267 channel_count = 0 ; | |
268 cptr = strstr (buffer, "Channels") ; | |
269 if (cptr && sscanf (cptr, "Channels : %d", &k) == 1) | |
270 channel_count = k ; | |
271 else if (cptr && sscanf (cptr, "Channels / frame : %d", &k) == 1) | |
272 channel_count = k ; | |
273 else | |
274 { printf ("\n\nLine %d: Couldn't find channel count.\n", __LINE__) ; | |
275 exit (1) ; | |
276 } ; | |
277 | |
278 if (channel_count != 4) | |
279 { printf ("\n\nLine %d: Wrong channel count (4 ->%d).\n", __LINE__, channel_count) ; | |
280 exit (1) ; | |
281 } ; | |
282 | |
283 if (! (cptr = strstr (buffer, "Ch Position Value"))) | |
284 { printf ("\n\nLine %d: Can't find PEAK data.\n", __LINE__) ; | |
285 exit (1) ; | |
286 } ; | |
287 | |
288 for (k = 0 ; k < channel_count ; k++) | |
289 { if (! (cptr = strchr (cptr, '\n'))) | |
290 { printf ("\n\nLine %d: Got lost.\n", __LINE__) ; | |
291 exit (1) ; | |
292 } ; | |
293 if (sscanf (cptr, "%d %d %f", &chan, &position, &value) != 3) | |
294 { printf ("\n\nLine %d: sscanf failed.\n", __LINE__) ; | |
295 exit (1) ; | |
296 } ; | |
297 if (position == 0) | |
298 { printf ("\n\nLine %d: peak position for channel %d should not be at offset 0.\n", __LINE__, chan) ; | |
299 printf ("%s", buffer) ; | |
300 exit (1) ; | |
301 } ; | |
302 if (chan != k || fabs ((position) * 0.01 - value) > 1e-6) | |
303 { printf ("\n\nLine %d: Error : peak value incorrect!\n", __LINE__) ; | |
304 printf ("%s", buffer) ; | |
305 printf ("\n\nLine %d: %d %f %f\n", __LINE__, chan, position * 0.01, value) ; | |
306 exit (1) ; | |
307 } ; | |
308 cptr ++ ; /* Move past current newline. */ | |
309 } ; | |
310 | |
311 } /* check_logged_peaks */ | |
312 | |
313 static void | |
314 read_write_peak_test (const char *filename, int filetype) | |
315 { SNDFILE *file ; | |
316 SF_INFO sfinfo ; | |
317 | |
318 double small_data [10], max_peak = 0.0 ; | |
319 unsigned k ; | |
320 | |
321 print_test_name (__func__, filename) ; | |
322 | |
323 for (k = 0 ; k < ARRAY_LEN (small_data) ; k ++) | |
324 small_data [k] = 0.1 ; | |
325 | |
326 sfinfo.samplerate = 44100 ; | |
327 sfinfo.channels = 2 ; | |
328 sfinfo.format = filetype ; | |
329 sfinfo.frames = 0 ; | |
330 | |
331 /* Open the file, add peak chunk and write samples with value 0.1. */ | |
332 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ; | |
333 | |
334 sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ; | |
335 | |
336 test_write_double_or_die (file, 0, small_data, ARRAY_LEN (small_data), __LINE__) ; | |
337 | |
338 sf_close (file) ; | |
339 | |
340 /* Open the fiel RDWR, write sample valied 1.25. */ | |
341 file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_FALSE, __LINE__) ; | |
342 | |
343 for (k = 0 ; k < ARRAY_LEN (small_data) ; k ++) | |
344 small_data [k] = 1.0 ; | |
345 | |
346 test_write_double_or_die (file, 0, small_data, ARRAY_LEN (small_data), __LINE__) ; | |
347 | |
348 sf_command (file, SFC_GET_SIGNAL_MAX, &max_peak, sizeof (max_peak)) ; | |
349 | |
350 sf_close (file) ; | |
351 | |
352 exit_if_true (max_peak < 0.1, "\n\nLine %d : max peak (%5.3f) should not be 0.1.\n\n", __LINE__, max_peak) ; | |
353 | |
354 /* Open the file and test the values written to the PEAK chunk. */ | |
355 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; | |
356 | |
357 exit_if_true (sfinfo.channels * sfinfo.frames != 2 * ARRAY_LEN (small_data), | |
358 "Line %d : frame count is %" PRId64 ", should be %zd\n", __LINE__, sfinfo.frames, 2 * ARRAY_LEN (small_data)) ; | |
359 | |
360 sf_command (file, SFC_GET_SIGNAL_MAX, &max_peak, sizeof (double)) ; | |
361 | |
362 sf_close (file) ; | |
363 | |
364 exit_if_true (max_peak < 1.0, "\n\nLine %d : max peak (%5.3f) should be 1.0.\n\n", __LINE__, max_peak) ; | |
365 | |
366 unlink (filename) ; | |
367 puts ("ok") ; | |
368 } /* read_write_peak_test */ | |
369 |