libsndfile source files.
[Faustine.git] / interpretor / libsndfile-1.0.25 / tests / benchmark.c
1 /*
2 ** Copyright (C) 2002-2011 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
24 #if HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27
28 #if (HAVE_DECL_S_IRGRP == 0)
29 #include <sf_unistd.h>
30 #endif
31
32 #include <string.h>
33 #include <math.h>
34 #include <time.h>
35 #include <fcntl.h>
36 #include <sys/stat.h>
37
38 #include <sndfile.h>
39
40 #ifndef M_PI
41 #define M_PI 3.14159265358979323846264338
42 #endif
43
44 /*
45 ** Neat solution to the Win32/OS2 binary file flage requirement.
46 ** If O_BINARY isn't already defined by the inclusion of the system
47 ** headers, set it to zero.
48 */
49 #ifndef O_BINARY
50 #define O_BINARY 0
51 #endif
52
53 #define WRITE_FLAGS (O_WRONLY | O_CREAT | O_TRUNC | O_BINARY)
54 #define READ_FLAGS (O_RDONLY | O_BINARY)
55
56 #if (defined (WIN32) || defined (_WIN32) || defined (__OS2__))
57 #define WRITE_PERMS 0777
58 #else
59 #define WRITE_PERMS (S_IRUSR | S_IWUSR | S_IRGRP)
60 #endif
61
62 #define BUFFER_SIZE (1<<18)
63 #define BLOCK_COUNT (30)
64 #define TEST_DURATION (5) /* 5 Seconds. */
65
66 typedef struct
67 { double write_rate ;
68 double read_rate ;
69 } PERF_STATS ;
70
71 static void *data = NULL ;
72
73 static void calc_raw_performance (PERF_STATS *stats) ;
74
75 static void calc_short_performance (int format, double read_rate, double write_rate) ;
76 static void calc_int_performance (int format, double read_rate, double write_rate) ;
77 static void calc_float_performance (int format, double read_rate, double write_rate) ;
78
79
80 static int cpu_is_big_endian (void) ;
81
82 static const char* get_subtype_str (int subtype) ;
83
84 int
85 main (int argc, char *argv [])
86 { PERF_STATS stats ;
87 char buffer [256] = "Benchmarking " ;
88 int format_major ;
89
90 if (! (data = malloc (BUFFER_SIZE * sizeof (double))))
91 { perror ("Error : malloc failed") ;
92 exit (1) ;
93 } ;
94
95 sf_command (NULL, SFC_GET_LIB_VERSION, buffer + strlen (buffer), sizeof (buffer) - strlen (buffer)) ;
96
97 puts (buffer) ;
98 memset (buffer, '-', strlen (buffer)) ;
99 puts (buffer) ;
100 printf ("Each test takes a little over %d seconds.\n\n", TEST_DURATION) ;
101
102 calc_raw_performance (&stats) ;
103
104 if (argc < 2 || strcmp ("--native-only", argv [1]) == 0)
105 { puts ("\nNative endian I/O :") ;
106 format_major = cpu_is_big_endian () ? SF_FORMAT_AIFF : SF_FORMAT_WAV ;
107
108 calc_short_performance (format_major | SF_FORMAT_PCM_16, stats.read_rate, stats.write_rate) ;
109 calc_int_performance (format_major | SF_FORMAT_PCM_24, stats.read_rate, stats.write_rate) ;
110 calc_int_performance (format_major | SF_FORMAT_PCM_32, stats.read_rate, stats.write_rate) ;
111 calc_float_performance (format_major | SF_FORMAT_PCM_16, stats.read_rate, stats.write_rate) ;
112 calc_float_performance (format_major | SF_FORMAT_PCM_24, stats.read_rate, stats.write_rate) ;
113 calc_float_performance (format_major | SF_FORMAT_PCM_32, stats.read_rate, stats.write_rate) ;
114 calc_float_performance (format_major | SF_FORMAT_FLOAT , stats.read_rate, stats.write_rate) ;
115 } ;
116
117 if (argc < 2 || strcmp ("--swap-only", argv [1]) == 0)
118 { puts ("\nEndian swapped I/O :") ;
119 format_major = cpu_is_big_endian () ? SF_FORMAT_WAV : SF_FORMAT_AIFF ;
120
121 calc_short_performance (format_major | SF_FORMAT_PCM_16, stats.read_rate, stats.write_rate) ;
122 calc_int_performance (format_major | SF_FORMAT_PCM_24, stats.read_rate, stats.write_rate) ;
123 calc_int_performance (format_major | SF_FORMAT_PCM_32, stats.read_rate, stats.write_rate) ;
124 calc_float_performance (format_major | SF_FORMAT_PCM_16, stats.read_rate, stats.write_rate) ;
125 calc_float_performance (format_major | SF_FORMAT_PCM_24, stats.read_rate, stats.write_rate) ;
126 calc_float_performance (format_major | SF_FORMAT_PCM_32, stats.read_rate, stats.write_rate) ;
127 calc_float_performance (format_major | SF_FORMAT_FLOAT , stats.read_rate, stats.write_rate) ;
128 } ;
129
130 puts ("") ;
131
132 free (data) ;
133
134 return 0 ;
135 } /* main */
136
137 /*==============================================================================
138 */
139
140 static void
141 calc_raw_performance (PERF_STATS *stats)
142 { clock_t start_clock, clock_time ;
143 int fd, k, byte_count, retval, op_count ;
144 const char *filename ;
145
146 filename = "benchmark.dat" ;
147
148 byte_count = BUFFER_SIZE * sizeof (short) ;
149
150 /* Collect write stats */
151 printf (" Raw write PCM_16 : ") ;
152 fflush (stdout) ;
153
154 clock_time = 0 ;
155 op_count = 0 ;
156 start_clock = clock () ;
157
158 while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
159 { if ((fd = open (filename, WRITE_FLAGS, WRITE_PERMS)) < 0)
160 { printf ("Error : not able to open file : %s\n", filename) ;
161 perror ("") ;
162 exit (1) ;
163 } ;
164
165 for (k = 0 ; k < BLOCK_COUNT ; k++)
166 { if ((retval = write (fd, data, byte_count)) != byte_count)
167 { printf ("Error : write returned %d (should have been %d)\n", retval, byte_count) ;
168 exit (1) ;
169 } ;
170 } ;
171
172 close (fd) ;
173
174 clock_time = clock () - start_clock ;
175 op_count ++ ;
176 } ;
177
178 stats->write_rate = (1.0 * BUFFER_SIZE) * BLOCK_COUNT * op_count ;
179 stats->write_rate *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
180 printf ("%10.0f samples per sec\n", stats->write_rate) ;
181
182 /* Collect read stats */
183 printf (" Raw read PCM_16 : ") ;
184 fflush (stdout) ;
185
186 clock_time = 0 ;
187 op_count = 0 ;
188 start_clock = clock () ;
189
190 while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
191 { if ((fd = open (filename, READ_FLAGS)) < 0)
192 { printf ("Error : not able to open file : %s\n", filename) ;
193 perror ("") ;
194 exit (1) ;
195 } ;
196
197 for (k = 0 ; k < BLOCK_COUNT ; k++)
198 { if ((retval = read (fd, data, byte_count)) != byte_count)
199 { printf ("Error : write returned %d (should have been %d)\n", retval, byte_count) ;
200 exit (1) ;
201 } ;
202 } ;
203
204 close (fd) ;
205
206 clock_time = clock () - start_clock ;
207 op_count ++ ;
208 } ;
209
210 stats->read_rate = (1.0 * BUFFER_SIZE) * BLOCK_COUNT * op_count ;
211 stats->read_rate *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
212 printf ("%10.0f samples per sec\n", stats->read_rate) ;
213
214 unlink (filename) ;
215 } /* calc_raw_performance */
216
217 /*------------------------------------------------------------------------------
218 */
219
220 static void
221 calc_short_performance (int format, double read_rate, double write_rate)
222 { SNDFILE *file ;
223 SF_INFO sfinfo ;
224 clock_t start_clock, clock_time ;
225 double performance ;
226 int k, item_count, retval, op_count ;
227 const char* subtype ;
228 short *short_data ;
229 const char *filename ;
230
231 filename = "benchmark.dat" ;
232 subtype = get_subtype_str (format & SF_FORMAT_SUBMASK) ;
233
234 short_data = data ;
235 item_count = BUFFER_SIZE ;
236 for (k = 0 ; k < item_count ; k++)
237 short_data [k] = 32700.0 * sin (2 * M_PI * k / 32000.0) ;
238
239 /* Collect write stats */
240 printf (" Write %-5s to %s : ", "short", subtype) ;
241 fflush (stdout) ;
242
243 sfinfo.channels = 1 ;
244 sfinfo.format = format ;
245 sfinfo.frames = 1 ;
246 sfinfo.samplerate = 32000 ;
247
248 clock_time = 0 ;
249 op_count = 0 ;
250 start_clock = clock () ;
251
252 while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
253 { if (! (file = sf_open (filename, SFM_WRITE, &sfinfo)))
254 { printf ("Error : not able to open file : %s\n", filename) ;
255 perror ("") ;
256 exit (1) ;
257 } ;
258
259 /* Turn off the addition of a PEAK chunk. */
260 sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
261
262 for (k = 0 ; k < BLOCK_COUNT ; k++)
263 { if ((retval = sf_write_short (file, short_data, item_count)) != item_count)
264 { printf ("Error : sf_write_short returned %d (should have been %d)\n", retval, item_count) ;
265 exit (1) ;
266 } ;
267 } ;
268
269 sf_close (file) ;
270
271 clock_time = clock () - start_clock ;
272 op_count ++ ;
273 } ;
274
275 performance = (1.0 * BUFFER_SIZE) * BLOCK_COUNT * op_count ;
276 performance *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
277 printf ("%6.2f%% of raw write\n", 100.0 * performance / write_rate) ;
278
279 /* Collect read stats */
280 printf (" Read %-5s from %s : ", "short", subtype) ;
281 fflush (stdout) ;
282
283 clock_time = 0 ;
284 op_count = 0 ;
285 start_clock = clock () ;
286
287 while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
288 { if (! (file = sf_open (filename, SFM_READ, &sfinfo)))
289 { printf ("Error : not able to open file : %s\n", filename) ;
290 perror ("") ;
291 exit (1) ;
292 } ;
293
294 for (k = 0 ; k < BLOCK_COUNT ; k++)
295 { if ((retval = sf_read_short (file, short_data, item_count)) != item_count)
296 { printf ("Error : write returned %d (should have been %d)\n", retval, item_count) ;
297 exit (1) ;
298 } ;
299 } ;
300
301 sf_close (file) ;
302
303 clock_time = clock () - start_clock ;
304 op_count ++ ;
305 } ;
306
307 performance = (1.0 * item_count) * BLOCK_COUNT * op_count ;
308 performance *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
309 printf ("%6.2f%% of raw read\n", 100.0 * performance / read_rate) ;
310
311 unlink (filename) ;
312
313 } /* calc_short_performance */
314 static void
315 calc_int_performance (int format, double read_rate, double write_rate)
316 { SNDFILE *file ;
317 SF_INFO sfinfo ;
318 clock_t start_clock, clock_time ;
319 double performance ;
320 int k, item_count, retval, op_count ;
321 const char* subtype ;
322 int *int_data ;
323 const char *filename ;
324
325 filename = "benchmark.dat" ;
326 subtype = get_subtype_str (format & SF_FORMAT_SUBMASK) ;
327
328 int_data = data ;
329 item_count = BUFFER_SIZE ;
330 for (k = 0 ; k < item_count ; k++)
331 int_data [k] = 32700.0 * (1<<16) * sin (2 * M_PI * k / 32000.0) ;
332
333 /* Collect write stats */
334 printf (" Write %-5s to %s : ", "int", subtype) ;
335 fflush (stdout) ;
336
337 sfinfo.channels = 1 ;
338 sfinfo.format = format ;
339 sfinfo.frames = 1 ;
340 sfinfo.samplerate = 32000 ;
341
342 clock_time = 0 ;
343 op_count = 0 ;
344 start_clock = clock () ;
345
346 while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
347 { if (! (file = sf_open (filename, SFM_WRITE, &sfinfo)))
348 { printf ("Error : not able to open file : %s\n", filename) ;
349 perror ("") ;
350 exit (1) ;
351 } ;
352
353 /* Turn off the addition of a PEAK chunk. */
354 sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
355
356 for (k = 0 ; k < BLOCK_COUNT ; k++)
357 { if ((retval = sf_write_int (file, int_data, item_count)) != item_count)
358 { printf ("Error : sf_write_short returned %d (should have been %d)\n", retval, item_count) ;
359 exit (1) ;
360 } ;
361 } ;
362
363 sf_close (file) ;
364
365 clock_time = clock () - start_clock ;
366 op_count ++ ;
367 } ;
368
369 performance = (1.0 * BUFFER_SIZE) * BLOCK_COUNT * op_count ;
370 performance *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
371 printf ("%6.2f%% of raw write\n", 100.0 * performance / write_rate) ;
372
373 /* Collect read stats */
374 printf (" Read %-5s from %s : ", "int", subtype) ;
375 fflush (stdout) ;
376
377 clock_time = 0 ;
378 op_count = 0 ;
379 start_clock = clock () ;
380
381 while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
382 { if (! (file = sf_open (filename, SFM_READ, &sfinfo)))
383 { printf ("Error : not able to open file : %s\n", filename) ;
384 perror ("") ;
385 exit (1) ;
386 } ;
387
388 for (k = 0 ; k < BLOCK_COUNT ; k++)
389 { if ((retval = sf_read_int (file, int_data, item_count)) != item_count)
390 { printf ("Error : write returned %d (should have been %d)\n", retval, item_count) ;
391 exit (1) ;
392 } ;
393 } ;
394
395 sf_close (file) ;
396
397 clock_time = clock () - start_clock ;
398 op_count ++ ;
399 } ;
400
401 performance = (1.0 * item_count) * BLOCK_COUNT * op_count ;
402 performance *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
403 printf ("%6.2f%% of raw read\n", 100.0 * performance / read_rate) ;
404
405 unlink (filename) ;
406
407 } /* calc_int_performance */
408 static void
409 calc_float_performance (int format, double read_rate, double write_rate)
410 { SNDFILE *file ;
411 SF_INFO sfinfo ;
412 clock_t start_clock, clock_time ;
413 double performance ;
414 int k, item_count, retval, op_count ;
415 const char* subtype ;
416 float *float_data ;
417 const char *filename ;
418
419 filename = "benchmark.dat" ;
420 subtype = get_subtype_str (format & SF_FORMAT_SUBMASK) ;
421
422 float_data = data ;
423 item_count = BUFFER_SIZE ;
424 for (k = 0 ; k < item_count ; k++)
425 float_data [k] = 1.0 * sin (2 * M_PI * k / 32000.0) ;
426
427 /* Collect write stats */
428 printf (" Write %-5s to %s : ", "float", subtype) ;
429 fflush (stdout) ;
430
431 sfinfo.channels = 1 ;
432 sfinfo.format = format ;
433 sfinfo.frames = 1 ;
434 sfinfo.samplerate = 32000 ;
435
436 clock_time = 0 ;
437 op_count = 0 ;
438 start_clock = clock () ;
439
440 while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
441 { if (! (file = sf_open (filename, SFM_WRITE, &sfinfo)))
442 { printf ("Error : not able to open file : %s\n", filename) ;
443 perror ("") ;
444 exit (1) ;
445 } ;
446
447 /* Turn off the addition of a PEAK chunk. */
448 sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
449
450 for (k = 0 ; k < BLOCK_COUNT ; k++)
451 { if ((retval = sf_write_float (file, float_data, item_count)) != item_count)
452 { printf ("Error : sf_write_short returned %d (should have been %d)\n", retval, item_count) ;
453 exit (1) ;
454 } ;
455 } ;
456
457 sf_close (file) ;
458
459 clock_time = clock () - start_clock ;
460 op_count ++ ;
461 } ;
462
463 performance = (1.0 * BUFFER_SIZE) * BLOCK_COUNT * op_count ;
464 performance *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
465 printf ("%6.2f%% of raw write\n", 100.0 * performance / write_rate) ;
466
467 /* Collect read stats */
468 printf (" Read %-5s from %s : ", "float", subtype) ;
469 fflush (stdout) ;
470
471 clock_time = 0 ;
472 op_count = 0 ;
473 start_clock = clock () ;
474
475 while (clock_time < (CLOCKS_PER_SEC * TEST_DURATION))
476 { if (! (file = sf_open (filename, SFM_READ, &sfinfo)))
477 { printf ("Error : not able to open file : %s\n", filename) ;
478 perror ("") ;
479 exit (1) ;
480 } ;
481
482 for (k = 0 ; k < BLOCK_COUNT ; k++)
483 { if ((retval = sf_read_float (file, float_data, item_count)) != item_count)
484 { printf ("Error : write returned %d (should have been %d)\n", retval, item_count) ;
485 exit (1) ;
486 } ;
487 } ;
488
489 sf_close (file) ;
490
491 clock_time = clock () - start_clock ;
492 op_count ++ ;
493 } ;
494
495 performance = (1.0 * item_count) * BLOCK_COUNT * op_count ;
496 performance *= (1.0 * CLOCKS_PER_SEC) / clock_time ;
497 printf ("%6.2f%% of raw read\n", 100.0 * performance / read_rate) ;
498
499 unlink (filename) ;
500
501 } /* calc_float_performance */
502
503
504 /*==============================================================================
505 */
506
507 static int
508 cpu_is_big_endian (void)
509 { unsigned char *cptr ;
510 int endtest ;
511
512 endtest = 0x12345678 ;
513
514 cptr = (unsigned char*) (&endtest) ;
515
516 if (cptr [0] == 0x12 && cptr [1] == 0x34 && cptr [3] == 0x78)
517 return SF_TRUE ;
518
519 return SF_FALSE ;
520 } /* cpu_is_big_endian */
521
522 static const char*
523 get_subtype_str (int subtype)
524 { switch (subtype)
525 { case SF_FORMAT_PCM_16 :
526 return "PCM_16" ;
527
528 case SF_FORMAT_PCM_24 :
529 return "PCM_24" ;
530
531 case SF_FORMAT_PCM_32 :
532 return "PCM_32" ;
533
534 case SF_FORMAT_FLOAT :
535 return "FLOAT " ;
536
537 case SF_FORMAT_DOUBLE :
538 return "DOUBLE" ;
539
540 default : break ;
541 } ;
542
543 return "UNKNOWN" ;
544 } /* get_subtype_str */
545