2 ** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
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.
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.
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.
28 #if (HAVE_DECL_S_IRGRP == 0)
29 #include <sf_unistd.h>
41 #define M_PI 3.14159265358979323846264338
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.
53 #define WRITE_FLAGS (O_WRONLY | O_CREAT | O_TRUNC | O_BINARY)
54 #define READ_FLAGS (O_RDONLY | O_BINARY)
56 #if (defined (WIN32) || defined (_WIN32) || defined (__OS2__))
57 #define WRITE_PERMS 0777
59 #define WRITE_PERMS (S_IRUSR | S_IWUSR | S_IRGRP)
62 #define BUFFER_SIZE (1<<18)
63 #define BLOCK_COUNT (30)
64 #define TEST_DURATION (5) /* 5 Seconds. */
71 static void *data
= NULL
;
73 static void calc_raw_performance (PERF_STATS
*stats
) ;
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
) ;
80 static int cpu_is_big_endian (void) ;
82 static const char* get_subtype_str (int subtype
) ;
85 main (int argc
, char *argv
[])
87 char buffer
[256] = "Benchmarking " ;
90 if (! (data
= malloc (BUFFER_SIZE
* sizeof (double))))
91 { perror ("Error : malloc failed") ;
95 sf_command (NULL
, SFC_GET_LIB_VERSION
, buffer
+ strlen (buffer
), sizeof (buffer
) - strlen (buffer
)) ;
98 memset (buffer
, '-', strlen (buffer
)) ;
100 printf ("Each test takes a little over %d seconds.\n\n", TEST_DURATION
) ;
102 calc_raw_performance (&stats
) ;
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
;
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
) ;
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
;
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
) ;
137 /*==============================================================================
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
;
146 filename
= "benchmark.dat" ;
148 byte_count
= BUFFER_SIZE
* sizeof (short) ;
150 /* Collect write stats */
151 printf (" Raw write PCM_16 : ") ;
156 start_clock
= clock () ;
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
) ;
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
) ;
174 clock_time
= clock () - start_clock
;
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
) ;
182 /* Collect read stats */
183 printf (" Raw read PCM_16 : ") ;
188 start_clock
= clock () ;
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
) ;
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
) ;
206 clock_time
= clock () - start_clock
;
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
) ;
215 } /* calc_raw_performance */
217 /*------------------------------------------------------------------------------
221 calc_short_performance (int format
, double read_rate
, double write_rate
)
224 clock_t start_clock
, clock_time
;
226 int k
, item_count
, retval
, op_count
;
227 const char* subtype
;
229 const char *filename
;
231 filename
= "benchmark.dat" ;
232 subtype
= get_subtype_str (format
& SF_FORMAT_SUBMASK
) ;
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) ;
239 /* Collect write stats */
240 printf (" Write %-5s to %s : ", "short", subtype
) ;
243 sfinfo
.channels
= 1 ;
244 sfinfo
.format
= format
;
246 sfinfo
.samplerate
= 32000 ;
250 start_clock
= clock () ;
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
) ;
259 /* Turn off the addition of a PEAK chunk. */
260 sf_command (file
, SFC_SET_ADD_PEAK_CHUNK
, NULL
, SF_FALSE
) ;
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
) ;
271 clock_time
= clock () - start_clock
;
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
) ;
279 /* Collect read stats */
280 printf (" Read %-5s from %s : ", "short", subtype
) ;
285 start_clock
= clock () ;
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
) ;
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
) ;
303 clock_time
= clock () - start_clock
;
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
) ;
313 } /* calc_short_performance */
315 calc_int_performance (int format
, double read_rate
, double write_rate
)
318 clock_t start_clock
, clock_time
;
320 int k
, item_count
, retval
, op_count
;
321 const char* subtype
;
323 const char *filename
;
325 filename
= "benchmark.dat" ;
326 subtype
= get_subtype_str (format
& SF_FORMAT_SUBMASK
) ;
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) ;
333 /* Collect write stats */
334 printf (" Write %-5s to %s : ", "int", subtype
) ;
337 sfinfo
.channels
= 1 ;
338 sfinfo
.format
= format
;
340 sfinfo
.samplerate
= 32000 ;
344 start_clock
= clock () ;
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
) ;
353 /* Turn off the addition of a PEAK chunk. */
354 sf_command (file
, SFC_SET_ADD_PEAK_CHUNK
, NULL
, SF_FALSE
) ;
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
) ;
365 clock_time
= clock () - start_clock
;
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
) ;
373 /* Collect read stats */
374 printf (" Read %-5s from %s : ", "int", subtype
) ;
379 start_clock
= clock () ;
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
) ;
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
) ;
397 clock_time
= clock () - start_clock
;
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
) ;
407 } /* calc_int_performance */
409 calc_float_performance (int format
, double read_rate
, double write_rate
)
412 clock_t start_clock
, clock_time
;
414 int k
, item_count
, retval
, op_count
;
415 const char* subtype
;
417 const char *filename
;
419 filename
= "benchmark.dat" ;
420 subtype
= get_subtype_str (format
& SF_FORMAT_SUBMASK
) ;
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) ;
427 /* Collect write stats */
428 printf (" Write %-5s to %s : ", "float", subtype
) ;
431 sfinfo
.channels
= 1 ;
432 sfinfo
.format
= format
;
434 sfinfo
.samplerate
= 32000 ;
438 start_clock
= clock () ;
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
) ;
447 /* Turn off the addition of a PEAK chunk. */
448 sf_command (file
, SFC_SET_ADD_PEAK_CHUNK
, NULL
, SF_FALSE
) ;
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
) ;
459 clock_time
= clock () - start_clock
;
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
) ;
467 /* Collect read stats */
468 printf (" Read %-5s from %s : ", "float", subtype
) ;
473 start_clock
= clock () ;
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
) ;
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
) ;
491 clock_time
= clock () - start_clock
;
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
) ;
501 } /* calc_float_performance */
504 /*==============================================================================
508 cpu_is_big_endian (void)
509 { unsigned char *cptr
;
512 endtest
= 0x12345678 ;
514 cptr
= (unsigned char*) (&endtest
) ;
516 if (cptr
[0] == 0x12 && cptr
[1] == 0x34 && cptr
[3] == 0x78)
520 } /* cpu_is_big_endian */
523 get_subtype_str (int subtype
)
525 { case SF_FORMAT_PCM_16
:
528 case SF_FORMAT_PCM_24
:
531 case SF_FORMAT_PCM_32
:
534 case SF_FORMAT_FLOAT
:
537 case SF_FORMAT_DOUBLE
:
544 } /* get_subtype_str */