2
** Copyright (C) 1999-2006 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.
27
#define BUFFER_LEN (1 << 16)
29
#if (defined (WIN32) || defined (_WIN32))
30
#define snprintf _snprintf
33
static void print_version (void) ;
34
static void print_usage (const char *progname) ;
36
static void info_dump (const char *filename) ;
37
static void instrument_dump (const char *filename) ;
38
static void broadcast_dump (const char *filename) ;
41
main (int argc, char *argv [])
46
if (argc < 2 || strcmp (argv [1], "--help") == 0 || strcmp (argv [1], "-h") == 0)
49
progname = strrchr (argv [0], '/') ;
50
progname = progname ? progname + 1 : argv [0] ;
52
print_usage (progname) ;
56
if (strcmp (argv [1], "-i") == 0)
57
{ instrument_dump (argv [2]) ;
61
if (strcmp (argv [1], "-b") == 0)
62
{ broadcast_dump (argv [2]) ;
66
for (k = 1 ; k < argc ; k++)
67
info_dump (argv [k]) ;
72
/*==============================================================================
73
** Print version and usage.
76
static double data [BUFFER_LEN] ;
82
sf_command (NULL, SFC_GET_LIB_VERSION, buffer, sizeof (buffer)) ;
83
printf ("\nVersion : %s\n\n", buffer) ;
88
print_usage (const char *progname)
89
{ printf ("Usage :\n %s <file> ...\n", progname) ;
90
printf (" Prints out information about one or more sound files.\n\n") ;
91
printf (" %s -i <file>\n", progname) ;
92
printf (" Prints out the instrument data for the given file.\n\n") ;
93
printf (" %s -b <file>\n", progname) ;
94
printf (" Prints out the broadcast WAV info for the given file.\n\n") ;
95
#if (defined (_WIN32) || defined (WIN32))
96
printf ("This is a Unix style command line application which\n"
97
"should be run in a MSDOS box or Command Shell window.\n\n") ;
98
printf ("Sleeping for 5 seconds before exiting.\n\n") ;
101
/* This is the officially blessed by microsoft way but I can't get
104
** Instead, use this:
110
/*==============================================================================
111
** Dumping of sndfile info.
114
static double data [BUFFER_LEN] ;
117
get_signal_max (SNDFILE *file)
119
int readcount, k, save_state ;
121
save_state = sf_command (file, SFC_GET_NORM_DOUBLE, NULL, 0) ;
122
sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
125
while ((readcount = sf_read_double (file, data, BUFFER_LEN)))
126
{ for (k = 0 ; k < readcount ; k++)
127
{ temp = fabs (data [k]) ;
133
sf_command (file, SFC_SET_NORM_DOUBLE, NULL, save_state) ;
136
} /* get_signal_max */
139
calc_decibels (SF_INFO * sfinfo, double max)
142
switch (sfinfo->format & SF_FORMAT_SUBMASK)
143
{ case SF_FORMAT_PCM_U8 :
144
case SF_FORMAT_PCM_S8 :
145
decibels = max / 0x80 ;
148
case SF_FORMAT_PCM_16 :
149
decibels = max / 0x8000 ;
152
case SF_FORMAT_PCM_24 :
153
decibels = max / 0x800000 ;
156
case SF_FORMAT_PCM_32 :
157
decibels = max / 0x80000000 ;
160
case SF_FORMAT_FLOAT :
161
case SF_FORMAT_DOUBLE :
162
decibels = max / 1.0 ;
166
decibels = max / 0x8000 ;
170
return 20.0 * log10 (decibels) ;
171
} /* calc_decibels */
174
generate_duration_str (SF_INFO *sfinfo)
175
{ static char str [128] ;
179
memset (str, 0, sizeof (str)) ;
181
if (sfinfo->samplerate < 1)
184
if (sfinfo->frames / sfinfo->samplerate > 0x7FFFFFFF)
187
seconds = sfinfo->frames / sfinfo->samplerate ;
189
snprintf (str, sizeof (str) - 1, "%02d:", seconds / 60 / 60) ;
191
seconds = seconds % (60 * 60) ;
192
snprintf (str + strlen (str), sizeof (str) - strlen (str) - 1, "%02d:", seconds / 60) ;
194
seconds = seconds % 60 ;
195
snprintf (str + strlen (str), sizeof (str) - strlen (str) - 1, "%02d.", seconds) ;
197
seconds = ((1000 * sfinfo->frames) / sfinfo->samplerate) % 1000 ;
198
snprintf (str + strlen (str), sizeof (str) - strlen (str) - 1, "%03d", seconds) ;
201
} /* generate_duration_str */
204
info_dump (const char *filename)
205
{ static char strbuffer [BUFFER_LEN] ;
208
double signal_max, decibels ;
212
file = sf_open (filename, SFM_READ, &sfinfo) ;
214
printf ("========================================\n") ;
215
sf_command (file, SFC_GET_LOG_INFO, strbuffer, BUFFER_LEN) ;
217
printf ("----------------------------------------\n") ;
220
{ printf ("Error : Not able to open input file %s.\n", filename) ;
222
memset (data, 0, sizeof (data)) ;
223
puts (sf_strerror (NULL)) ;
226
{ printf ("Sample Rate : %d\n", sfinfo.samplerate) ;
227
if (sfinfo.frames > 0x7FFFFFFF)
228
printf ("Frames : unknown\n") ;
230
printf ("Frames : %ld\n", (long) sfinfo.frames) ;
231
printf ("Channels : %d\n", sfinfo.channels) ;
232
printf ("Format : 0x%08X\n", sfinfo.format) ;
233
printf ("Sections : %d\n", sfinfo.sections) ;
234
printf ("Seekable : %s\n", (sfinfo.seekable ? "TRUE" : "FALSE")) ;
235
printf ("Duration : %s\n", generate_duration_str (&sfinfo)) ;
237
/* Do not use sf_signal_max because it doesn work for non-seekable files . */
238
signal_max = get_signal_max (file) ;
239
decibels = calc_decibels (&sfinfo, signal_max) ;
240
printf ("Signal Max : %g (%4.2f dB)\n\n", signal_max, decibels) ;
247
/*==============================================================================
248
** Dumping of SF_INSTRUMENT data.
252
str_of_type (int mode)
254
{ case SF_LOOP_NONE : return "none" ;
255
case SF_LOOP_FORWARD : return "fwd " ;
256
case SF_LOOP_BACKWARD : return "back" ;
257
case SF_LOOP_ALTERNATING : return "alt " ;
265
instrument_dump (const char *filename)
271
if ((file = sf_open (filename, SFM_READ, &sfinfo)) == NULL)
272
{ printf ("Error : Not able to open input file %s.\n", filename) ;
274
memset (data, 0, sizeof (data)) ;
275
puts (sf_strerror (NULL)) ;
279
got_inst = sf_command (file, SFC_GET_INSTRUMENT, &inst, sizeof (inst)) ;
282
if (got_inst == SF_FALSE)
283
{ printf ("Error : File '%s' does not contain instrument data.\n\n", filename) ;
287
printf ("Instrument : %s\n\n", filename) ;
288
printf (" Gain : %d\n", inst.gain) ;
289
printf (" Base note : %d\n", inst.basenote) ;
290
printf (" Velocity : %d - %d\n", (int) inst.velocity_lo, (int) inst.velocity_hi) ;
291
printf (" Key : %d - %d\n", (int) inst.key_lo, (int) inst.key_hi) ;
292
printf (" Loop points : %d\n", inst.loop_count) ;
294
for (k = 0 ; k < inst.loop_count ; k++)
295
printf (" %-2d Mode : %s Start : %6d End : %6d Count : %6d\n", k, str_of_type (inst.loops [k].mode), inst.loops [k].start, inst.loops [k].end, inst.loops [k].count) ;
298
} /* instrument_dump */
301
broadcast_dump (const char *filename)
304
SF_BROADCAST_INFO bext ;
307
if ((file = sf_open (filename, SFM_READ, &sfinfo)) == NULL)
308
{ printf ("Error : Not able to open input file %s.\n", filename) ;
310
memset (data, 0, sizeof (data)) ;
311
puts (sf_strerror (NULL)) ;
315
memset (&bext, 0, sizeof (SF_BROADCAST_INFO)) ;
317
got_bext = sf_command (file, SFC_GET_BROADCAST_INFO, &bext, sizeof (bext)) ;
320
if (got_bext == SF_FALSE)
321
{ printf ("Error : File '%s' does not contain broadcast information.\n\n", filename) ;
325
printf ("Description : %.*s\n", sizeof (bext.description), bext.description) ;
326
printf ("Originator : %.*s\n", sizeof (bext.originator), bext.originator) ;
327
printf ("Origination ref : %.*s\n", sizeof (bext.originator_reference), bext.originator_reference) ;
328
printf ("Origination date : %.*s\n", sizeof (bext.origination_date), bext.origination_date) ;
329
printf ("Origination time : %.*s\n", sizeof (bext.origination_time), bext.origination_time) ;
330
printf ("BWF version : %d\n", bext.version) ;
331
printf ("UMID : %.*s\n", sizeof (bext.umid), bext.umid) ;
332
printf ("Coding history : %.*s\n", bext.coding_history_size, bext.coding_history) ;
334
} /* broadcast_dump */
337
** Do not edit or modify anything in this comment block.
338
** The arch-tag line is a file identity tag for the GNU Arch
339
** revision control system.
341
** arch-tag: f59a05db-a182-41de-aedd-d717ce2bb099