Chris@0
|
1 /*
|
Chris@0
|
2 ** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
Chris@0
|
3 **
|
Chris@0
|
4 ** All rights reserved.
|
Chris@0
|
5 **
|
Chris@0
|
6 ** Redistribution and use in source and binary forms, with or without
|
Chris@0
|
7 ** modification, are permitted provided that the following conditions are
|
Chris@0
|
8 ** met:
|
Chris@0
|
9 **
|
Chris@0
|
10 ** * Redistributions of source code must retain the above copyright
|
Chris@0
|
11 ** notice, this list of conditions and the following disclaimer.
|
Chris@0
|
12 ** * Redistributions in binary form must reproduce the above copyright
|
Chris@0
|
13 ** notice, this list of conditions and the following disclaimer in
|
Chris@0
|
14 ** the documentation and/or other materials provided with the
|
Chris@0
|
15 ** distribution.
|
Chris@0
|
16 ** * Neither the author nor the names of any contributors may be used
|
Chris@0
|
17 ** to endorse or promote products derived from this software without
|
Chris@0
|
18 ** specific prior written permission.
|
Chris@0
|
19 **
|
Chris@0
|
20 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
Chris@0
|
21 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
Chris@0
|
22 ** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
Chris@0
|
23 ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
Chris@0
|
24 ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
Chris@0
|
25 ** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
Chris@0
|
26 ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
Chris@0
|
27 ** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
Chris@0
|
28 ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
Chris@0
|
29 ** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
Chris@0
|
30 ** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
Chris@0
|
31 */
|
Chris@0
|
32
|
Chris@0
|
33 #include <stdio.h>
|
Chris@0
|
34 #include <stdlib.h>
|
Chris@0
|
35 #include <string.h>
|
Chris@0
|
36 #include <inttypes.h>
|
Chris@0
|
37 #include <ctype.h>
|
Chris@0
|
38 #include <math.h>
|
Chris@0
|
39
|
Chris@0
|
40 #include <sndfile.h>
|
Chris@0
|
41
|
Chris@0
|
42 #include "common.h"
|
Chris@0
|
43
|
Chris@0
|
44 #define BUFFER_LEN (1 << 16)
|
Chris@0
|
45
|
Chris@0
|
46 #if (defined (WIN32) || defined (_WIN32))
|
Chris@0
|
47 #include <windows.h>
|
Chris@0
|
48 #endif
|
Chris@0
|
49
|
Chris@0
|
50 static void print_version (void) ;
|
Chris@0
|
51 static void usage_exit (const char *progname) ;
|
Chris@0
|
52
|
Chris@0
|
53 static void info_dump (const char *filename) ;
|
Chris@0
|
54 static int instrument_dump (const char *filename) ;
|
Chris@0
|
55 static int broadcast_dump (const char *filename) ;
|
Chris@0
|
56 static int chanmap_dump (const char *filename) ;
|
Chris@0
|
57 static void total_dump (void) ;
|
Chris@0
|
58
|
Chris@0
|
59 static double total_seconds = 0.0 ;
|
Chris@0
|
60
|
Chris@0
|
61 int
|
Chris@0
|
62 main (int argc, char *argv [])
|
Chris@0
|
63 { int k ;
|
Chris@0
|
64
|
Chris@0
|
65 print_version () ;
|
Chris@0
|
66
|
Chris@0
|
67 if (argc < 2 || strcmp (argv [1], "--help") == 0 || strcmp (argv [1], "-h") == 0)
|
Chris@0
|
68 { usage_exit (program_name (argv [0])) ;
|
Chris@0
|
69 return 1 ;
|
Chris@0
|
70 } ;
|
Chris@0
|
71
|
Chris@0
|
72 if (strcmp (argv [1], "-i") == 0)
|
Chris@0
|
73 { int error = 0 ;
|
Chris@0
|
74
|
Chris@0
|
75 for (k = 2 ; k < argc ; k++)
|
Chris@0
|
76 error += instrument_dump (argv [k]) ;
|
Chris@0
|
77 return error ;
|
Chris@0
|
78 } ;
|
Chris@0
|
79
|
Chris@0
|
80 if (strcmp (argv [1], "-b") == 0)
|
Chris@0
|
81 { int error = 0 ;
|
Chris@0
|
82
|
Chris@0
|
83 for (k = 2 ; k < argc ; k++)
|
Chris@0
|
84 error += broadcast_dump (argv [k]) ;
|
Chris@0
|
85 return error ;
|
Chris@0
|
86 } ;
|
Chris@0
|
87
|
Chris@0
|
88 if (strcmp (argv [1], "-c") == 0)
|
Chris@0
|
89 { int error = 0 ;
|
Chris@0
|
90
|
Chris@0
|
91 for (k = 2 ; k < argc ; k++)
|
Chris@0
|
92 error += chanmap_dump (argv [k]) ;
|
Chris@0
|
93 return error ;
|
Chris@0
|
94 } ;
|
Chris@0
|
95
|
Chris@0
|
96 for (k = 1 ; k < argc ; k++)
|
Chris@0
|
97 info_dump (argv [k]) ;
|
Chris@0
|
98
|
Chris@0
|
99 if (argc > 2)
|
Chris@0
|
100 total_dump () ;
|
Chris@0
|
101
|
Chris@0
|
102 return 0 ;
|
Chris@0
|
103 } /* main */
|
Chris@0
|
104
|
Chris@0
|
105 /*==============================================================================
|
Chris@0
|
106 ** Print version and usage.
|
Chris@0
|
107 */
|
Chris@0
|
108
|
Chris@0
|
109 static double data [BUFFER_LEN] ;
|
Chris@0
|
110
|
Chris@0
|
111 static void
|
Chris@0
|
112 print_version (void)
|
Chris@0
|
113 { char buffer [256] ;
|
Chris@0
|
114
|
Chris@0
|
115 sf_command (NULL, SFC_GET_LIB_VERSION, buffer, sizeof (buffer)) ;
|
Chris@0
|
116 printf ("\nVersion : %s\n\n", buffer) ;
|
Chris@0
|
117 } /* print_version */
|
Chris@0
|
118
|
Chris@0
|
119
|
Chris@0
|
120 static void
|
Chris@0
|
121 usage_exit (const char *progname)
|
Chris@0
|
122 { printf ("Usage :\n %s <file> ...\n", progname) ;
|
Chris@0
|
123 printf (" Prints out information about one or more sound files.\n\n") ;
|
Chris@0
|
124 printf (" %s -i <file>\n", progname) ;
|
Chris@0
|
125 printf (" Prints out the instrument data for the given file.\n\n") ;
|
Chris@0
|
126 printf (" %s -b <file>\n", progname) ;
|
Chris@0
|
127 printf (" Prints out the broadcast WAV info for the given file.\n\n") ;
|
Chris@0
|
128 #if (defined (_WIN32) || defined (WIN32))
|
Chris@0
|
129 printf ("This is a Unix style command line application which\n"
|
Chris@0
|
130 "should be run in a MSDOS box or Command Shell window.\n\n") ;
|
Chris@0
|
131 printf ("Sleeping for 5 seconds before exiting.\n\n") ;
|
Chris@0
|
132 fflush (stdout) ;
|
Chris@0
|
133
|
Chris@0
|
134 /* This is the officially blessed by microsoft way but I can't get
|
Chris@0
|
135 ** it to link.
|
Chris@0
|
136 ** Sleep (15) ;
|
Chris@0
|
137 ** Instead, use this:
|
Chris@0
|
138 */
|
Chris@0
|
139 Sleep (5 * 1000) ;
|
Chris@0
|
140 #endif
|
Chris@0
|
141 printf ("Using %s.\n\n", sf_version_string ()) ;
|
Chris@0
|
142 exit (0) ;
|
Chris@0
|
143 } /* usage_exit */
|
Chris@0
|
144
|
Chris@0
|
145 /*==============================================================================
|
Chris@0
|
146 ** Dumping of sndfile info.
|
Chris@0
|
147 */
|
Chris@0
|
148
|
Chris@0
|
149 static double data [BUFFER_LEN] ;
|
Chris@0
|
150
|
Chris@0
|
151 static double
|
Chris@0
|
152 get_signal_max (SNDFILE *file)
|
Chris@0
|
153 { double max ;
|
Chris@0
|
154
|
Chris@0
|
155 sf_command (file, SFC_CALC_SIGNAL_MAX, &max, sizeof (max)) ;
|
Chris@0
|
156
|
Chris@0
|
157 return max ;
|
Chris@0
|
158 } /* get_signal_max */
|
Chris@0
|
159
|
Chris@0
|
160 static double
|
Chris@0
|
161 calc_decibels (SF_INFO * sfinfo, double max)
|
Chris@0
|
162 { double decibels ;
|
Chris@0
|
163
|
Chris@0
|
164 switch (sfinfo->format & SF_FORMAT_SUBMASK)
|
Chris@0
|
165 { case SF_FORMAT_PCM_U8 :
|
Chris@0
|
166 case SF_FORMAT_PCM_S8 :
|
Chris@0
|
167 decibels = max / 0x80 ;
|
Chris@0
|
168 break ;
|
Chris@0
|
169
|
Chris@0
|
170 case SF_FORMAT_PCM_16 :
|
Chris@0
|
171 decibels = max / 0x8000 ;
|
Chris@0
|
172 break ;
|
Chris@0
|
173
|
Chris@0
|
174 case SF_FORMAT_PCM_24 :
|
Chris@0
|
175 decibels = max / 0x800000 ;
|
Chris@0
|
176 break ;
|
Chris@0
|
177
|
Chris@0
|
178 case SF_FORMAT_PCM_32 :
|
Chris@0
|
179 decibels = max / 0x80000000 ;
|
Chris@0
|
180 break ;
|
Chris@0
|
181
|
Chris@0
|
182 case SF_FORMAT_FLOAT :
|
Chris@0
|
183 case SF_FORMAT_DOUBLE :
|
Chris@0
|
184 decibels = max / 1.0 ;
|
Chris@0
|
185 break ;
|
Chris@0
|
186
|
Chris@0
|
187 default :
|
Chris@0
|
188 decibels = max / 0x8000 ;
|
Chris@0
|
189 break ;
|
Chris@0
|
190 } ;
|
Chris@0
|
191
|
Chris@0
|
192 return 20.0 * log10 (decibels) ;
|
Chris@0
|
193 } /* calc_decibels */
|
Chris@0
|
194
|
Chris@0
|
195 static const char *
|
Chris@0
|
196 format_duration_str (double seconds)
|
Chris@0
|
197 { static char str [128] ;
|
Chris@0
|
198 int hrs, min ;
|
Chris@0
|
199 double sec ;
|
Chris@0
|
200
|
Chris@0
|
201 memset (str, 0, sizeof (str)) ;
|
Chris@0
|
202
|
Chris@0
|
203 hrs = (int) (seconds / 3600.0) ;
|
Chris@0
|
204 min = (int) ((seconds - (hrs * 3600.0)) / 60.0) ;
|
Chris@0
|
205 sec = seconds - (hrs * 3600.0) - (min * 60.0) ;
|
Chris@0
|
206
|
Chris@0
|
207 snprintf (str, sizeof (str) - 1, "%02d:%02d:%06.3f", hrs, min, sec) ;
|
Chris@0
|
208
|
Chris@0
|
209 return str ;
|
Chris@0
|
210 } /* format_duration_str */
|
Chris@0
|
211
|
Chris@0
|
212 static const char *
|
Chris@0
|
213 generate_duration_str (SF_INFO *sfinfo)
|
Chris@0
|
214 {
|
Chris@0
|
215 double seconds ;
|
Chris@0
|
216
|
Chris@0
|
217 if (sfinfo->samplerate < 1)
|
Chris@0
|
218 return NULL ;
|
Chris@0
|
219
|
Chris@0
|
220 if (sfinfo->frames / sfinfo->samplerate > 0x7FFFFFFF)
|
Chris@0
|
221 return "unknown" ;
|
Chris@0
|
222
|
Chris@0
|
223 seconds = (1.0 * sfinfo->frames) / sfinfo->samplerate ;
|
Chris@0
|
224
|
Chris@0
|
225 /* Accumulate the total of all known file durations */
|
Chris@0
|
226 total_seconds += seconds ;
|
Chris@0
|
227
|
Chris@0
|
228 return format_duration_str (seconds) ;
|
Chris@0
|
229 } /* generate_duration_str */
|
Chris@0
|
230
|
Chris@0
|
231 static void
|
Chris@0
|
232 info_dump (const char *filename)
|
Chris@0
|
233 { static char strbuffer [BUFFER_LEN] ;
|
Chris@0
|
234 SNDFILE *file ;
|
Chris@0
|
235 SF_INFO sfinfo ;
|
Chris@0
|
236 double signal_max, decibels ;
|
Chris@0
|
237
|
Chris@0
|
238 memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
Chris@0
|
239
|
Chris@0
|
240 if ((file = sf_open (filename, SFM_READ, &sfinfo)) == NULL)
|
Chris@0
|
241 { printf ("Error : Not able to open input file %s.\n", filename) ;
|
Chris@0
|
242 fflush (stdout) ;
|
Chris@0
|
243 memset (data, 0, sizeof (data)) ;
|
Chris@0
|
244 sf_command (file, SFC_GET_LOG_INFO, strbuffer, BUFFER_LEN) ;
|
Chris@0
|
245 puts (strbuffer) ;
|
Chris@0
|
246 puts (sf_strerror (NULL)) ;
|
Chris@0
|
247 return ;
|
Chris@0
|
248 } ;
|
Chris@0
|
249
|
Chris@0
|
250 printf ("========================================\n") ;
|
Chris@0
|
251 sf_command (file, SFC_GET_LOG_INFO, strbuffer, BUFFER_LEN) ;
|
Chris@0
|
252 puts (strbuffer) ;
|
Chris@0
|
253 printf ("----------------------------------------\n") ;
|
Chris@0
|
254
|
Chris@0
|
255 printf ("Sample Rate : %d\n", sfinfo.samplerate) ;
|
Chris@0
|
256
|
Chris@0
|
257 if (sfinfo.frames == SF_COUNT_MAX)
|
Chris@0
|
258 printf ("Frames : unknown\n") ;
|
Chris@0
|
259 else
|
Chris@0
|
260 printf ("Frames : %" PRId64 "\n", sfinfo.frames) ;
|
Chris@0
|
261
|
Chris@0
|
262 printf ("Channels : %d\n", sfinfo.channels) ;
|
Chris@0
|
263 printf ("Format : 0x%08X\n", sfinfo.format) ;
|
Chris@0
|
264 printf ("Sections : %d\n", sfinfo.sections) ;
|
Chris@0
|
265 printf ("Seekable : %s\n", (sfinfo.seekable ? "TRUE" : "FALSE")) ;
|
Chris@0
|
266 printf ("Duration : %s\n", generate_duration_str (&sfinfo)) ;
|
Chris@0
|
267
|
Chris@0
|
268 if (sfinfo.frames < 100 * 1024 * 1024)
|
Chris@0
|
269 { /* Do not use sf_signal_max because it doesn't work for non-seekable files . */
|
Chris@0
|
270 signal_max = get_signal_max (file) ;
|
Chris@0
|
271 decibels = calc_decibels (&sfinfo, signal_max) ;
|
Chris@0
|
272 printf ("Signal Max : %g (%4.2f dB)\n", signal_max, decibels) ;
|
Chris@0
|
273 } ;
|
Chris@0
|
274 putchar ('\n') ;
|
Chris@0
|
275
|
Chris@0
|
276 sf_close (file) ;
|
Chris@0
|
277
|
Chris@0
|
278 } /* info_dump */
|
Chris@0
|
279
|
Chris@0
|
280 /*==============================================================================
|
Chris@0
|
281 ** Dumping of SF_INSTRUMENT data.
|
Chris@0
|
282 */
|
Chris@0
|
283
|
Chris@0
|
284 static const char *
|
Chris@0
|
285 str_of_type (int mode)
|
Chris@0
|
286 { switch (mode)
|
Chris@0
|
287 { case SF_LOOP_NONE : return "none" ;
|
Chris@0
|
288 case SF_LOOP_FORWARD : return "fwd " ;
|
Chris@0
|
289 case SF_LOOP_BACKWARD : return "back" ;
|
Chris@0
|
290 case SF_LOOP_ALTERNATING : return "alt " ;
|
Chris@0
|
291 default : break ;
|
Chris@0
|
292 } ;
|
Chris@0
|
293
|
Chris@0
|
294 return "????" ;
|
Chris@0
|
295 } /* str_of_mode */
|
Chris@0
|
296
|
Chris@0
|
297 static int
|
Chris@0
|
298 instrument_dump (const char *filename)
|
Chris@0
|
299 { SNDFILE *file ;
|
Chris@0
|
300 SF_INFO sfinfo ;
|
Chris@0
|
301 SF_INSTRUMENT inst ;
|
Chris@0
|
302 int got_inst, k ;
|
Chris@0
|
303
|
Chris@0
|
304 memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
Chris@0
|
305
|
Chris@0
|
306 if ((file = sf_open (filename, SFM_READ, &sfinfo)) == NULL)
|
Chris@0
|
307 { printf ("Error : Not able to open input file %s.\n", filename) ;
|
Chris@0
|
308 fflush (stdout) ;
|
Chris@0
|
309 memset (data, 0, sizeof (data)) ;
|
Chris@0
|
310 puts (sf_strerror (NULL)) ;
|
Chris@0
|
311 return 1 ;
|
Chris@0
|
312 } ;
|
Chris@0
|
313
|
Chris@0
|
314 got_inst = sf_command (file, SFC_GET_INSTRUMENT, &inst, sizeof (inst)) ;
|
Chris@0
|
315 sf_close (file) ;
|
Chris@0
|
316
|
Chris@0
|
317 if (got_inst == SF_FALSE)
|
Chris@0
|
318 { printf ("Error : File '%s' does not contain instrument data.\n\n", filename) ;
|
Chris@0
|
319 return 1 ;
|
Chris@0
|
320 } ;
|
Chris@0
|
321
|
Chris@0
|
322 printf ("Instrument : %s\n\n", filename) ;
|
Chris@0
|
323 printf (" Gain : %d\n", inst.gain) ;
|
Chris@0
|
324 printf (" Base note : %d\n", inst.basenote) ;
|
Chris@0
|
325 printf (" Velocity : %d - %d\n", (int) inst.velocity_lo, (int) inst.velocity_hi) ;
|
Chris@0
|
326 printf (" Key : %d - %d\n", (int) inst.key_lo, (int) inst.key_hi) ;
|
Chris@0
|
327 printf (" Loop points : %d\n", inst.loop_count) ;
|
Chris@0
|
328
|
Chris@0
|
329 for (k = 0 ; k < inst.loop_count ; k++)
|
Chris@0
|
330 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) ;
|
Chris@0
|
331
|
Chris@0
|
332 putchar ('\n') ;
|
Chris@0
|
333 return 0 ;
|
Chris@0
|
334 } /* instrument_dump */
|
Chris@0
|
335
|
Chris@0
|
336 static int
|
Chris@0
|
337 broadcast_dump (const char *filename)
|
Chris@0
|
338 { SNDFILE *file ;
|
Chris@0
|
339 SF_INFO sfinfo ;
|
Chris@0
|
340 SF_BROADCAST_INFO_2K bext ;
|
Chris@0
|
341 double time_ref_sec ;
|
Chris@0
|
342 int got_bext ;
|
Chris@0
|
343
|
Chris@0
|
344 memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
Chris@0
|
345
|
Chris@0
|
346 if ((file = sf_open (filename, SFM_READ, &sfinfo)) == NULL)
|
Chris@0
|
347 { printf ("Error : Not able to open input file %s.\n", filename) ;
|
Chris@0
|
348 fflush (stdout) ;
|
Chris@0
|
349 memset (data, 0, sizeof (data)) ;
|
Chris@0
|
350 puts (sf_strerror (NULL)) ;
|
Chris@0
|
351 return 1 ;
|
Chris@0
|
352 } ;
|
Chris@0
|
353
|
Chris@0
|
354 memset (&bext, 0, sizeof (SF_BROADCAST_INFO_2K)) ;
|
Chris@0
|
355
|
Chris@0
|
356 got_bext = sf_command (file, SFC_GET_BROADCAST_INFO, &bext, sizeof (bext)) ;
|
Chris@0
|
357 sf_close (file) ;
|
Chris@0
|
358
|
Chris@0
|
359 if (got_bext == SF_FALSE)
|
Chris@0
|
360 { printf ("Error : File '%s' does not contain broadcast information.\n\n", filename) ;
|
Chris@0
|
361 return 1 ;
|
Chris@0
|
362 } ;
|
Chris@0
|
363
|
Chris@0
|
364 /*
|
Chris@0
|
365 ** From : http://www.ebu.ch/en/technical/publications/userguides/bwf_user_guide.php
|
Chris@0
|
366 **
|
Chris@0
|
367 ** Time Reference:
|
Chris@0
|
368 ** This field is a count from midnight in samples to the first sample
|
Chris@0
|
369 ** of the audio sequence.
|
Chris@0
|
370 */
|
Chris@0
|
371
|
Chris@0
|
372 time_ref_sec = ((pow (2.0, 32) * bext.time_reference_high) + (1.0 * bext.time_reference_low)) / sfinfo.samplerate ;
|
Chris@0
|
373
|
Chris@0
|
374 printf ("Description : %.*s\n", (int) sizeof (bext.description), bext.description) ;
|
Chris@0
|
375 printf ("Originator : %.*s\n", (int) sizeof (bext.originator), bext.originator) ;
|
Chris@0
|
376 printf ("Origination ref : %.*s\n", (int) sizeof (bext.originator_reference), bext.originator_reference) ;
|
Chris@0
|
377 printf ("Origination date : %.*s\n", (int) sizeof (bext.origination_date), bext.origination_date) ;
|
Chris@0
|
378 printf ("Origination time : %.*s\n", (int) sizeof (bext.origination_time), bext.origination_time) ;
|
Chris@0
|
379
|
Chris@0
|
380 if (bext.time_reference_high == 0 && bext.time_reference_low == 0)
|
Chris@0
|
381 printf ("Time ref : 0\n") ;
|
Chris@0
|
382 else
|
Chris@0
|
383 printf ("Time ref : 0x%x%08x (%.6f seconds)\n", bext.time_reference_high, bext.time_reference_low, time_ref_sec) ;
|
Chris@0
|
384
|
Chris@0
|
385 printf ("BWF version : %d\n", bext.version) ;
|
Chris@0
|
386 printf ("UMID : %.*s\n", (int) sizeof (bext.umid), bext.umid) ;
|
Chris@0
|
387 printf ("Coding history : %.*s\n", bext.coding_history_size, bext.coding_history) ;
|
Chris@0
|
388
|
Chris@0
|
389 return 0 ;
|
Chris@0
|
390 } /* broadcast_dump */
|
Chris@0
|
391
|
Chris@0
|
392 static int
|
Chris@0
|
393 chanmap_dump (const char *filename)
|
Chris@0
|
394 { SNDFILE *file ;
|
Chris@0
|
395 SF_INFO sfinfo ;
|
Chris@0
|
396 int * channel_map ;
|
Chris@0
|
397 int got_chanmap, k ;
|
Chris@0
|
398
|
Chris@0
|
399 memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
Chris@0
|
400
|
Chris@0
|
401 if ((file = sf_open (filename, SFM_READ, &sfinfo)) == NULL)
|
Chris@0
|
402 { printf ("Error : Not able to open input file %s.\n", filename) ;
|
Chris@0
|
403 fflush (stdout) ;
|
Chris@0
|
404 memset (data, 0, sizeof (data)) ;
|
Chris@0
|
405 puts (sf_strerror (NULL)) ;
|
Chris@0
|
406 return 1 ;
|
Chris@0
|
407 } ;
|
Chris@0
|
408
|
Chris@0
|
409 if ((channel_map = calloc (sfinfo.channels, sizeof (int))) == NULL)
|
Chris@0
|
410 { printf ("Error : malloc failed.\n\n") ;
|
Chris@0
|
411 return 1 ;
|
Chris@0
|
412 } ;
|
Chris@0
|
413
|
Chris@0
|
414 got_chanmap = sf_command (file, SFC_GET_CHANNEL_MAP_INFO, channel_map, sfinfo.channels * sizeof (int)) ;
|
Chris@0
|
415 sf_close (file) ;
|
Chris@0
|
416
|
Chris@0
|
417 if (got_chanmap == SF_FALSE)
|
Chris@0
|
418 { printf ("Error : File '%s' does not contain channel map information.\n\n", filename) ;
|
Chris@0
|
419 free (channel_map) ;
|
Chris@0
|
420 return 1 ;
|
Chris@0
|
421 } ;
|
Chris@0
|
422
|
Chris@0
|
423 printf ("File : %s\n\n", filename) ;
|
Chris@0
|
424
|
Chris@0
|
425 puts (" Chan Position") ;
|
Chris@0
|
426 for (k = 0 ; k < sfinfo.channels ; k ++)
|
Chris@0
|
427 { const char * name ;
|
Chris@0
|
428
|
Chris@0
|
429 #define CASE_NAME(x) case x : name = #x ; break ;
|
Chris@0
|
430 switch (channel_map [k])
|
Chris@0
|
431 { CASE_NAME (SF_CHANNEL_MAP_INVALID) ;
|
Chris@0
|
432 CASE_NAME (SF_CHANNEL_MAP_MONO) ;
|
Chris@0
|
433 CASE_NAME (SF_CHANNEL_MAP_LEFT) ;
|
Chris@0
|
434 CASE_NAME (SF_CHANNEL_MAP_RIGHT) ;
|
Chris@0
|
435 CASE_NAME (SF_CHANNEL_MAP_CENTER) ;
|
Chris@0
|
436 CASE_NAME (SF_CHANNEL_MAP_FRONT_LEFT) ;
|
Chris@0
|
437 CASE_NAME (SF_CHANNEL_MAP_FRONT_RIGHT) ;
|
Chris@0
|
438 CASE_NAME (SF_CHANNEL_MAP_FRONT_CENTER) ;
|
Chris@0
|
439 CASE_NAME (SF_CHANNEL_MAP_REAR_CENTER) ;
|
Chris@0
|
440 CASE_NAME (SF_CHANNEL_MAP_REAR_LEFT) ;
|
Chris@0
|
441 CASE_NAME (SF_CHANNEL_MAP_REAR_RIGHT) ;
|
Chris@0
|
442 CASE_NAME (SF_CHANNEL_MAP_LFE) ;
|
Chris@0
|
443 CASE_NAME (SF_CHANNEL_MAP_FRONT_LEFT_OF_CENTER) ;
|
Chris@0
|
444 CASE_NAME (SF_CHANNEL_MAP_FRONT_RIGHT_OF_CENTER) ;
|
Chris@0
|
445 CASE_NAME (SF_CHANNEL_MAP_SIDE_LEFT) ;
|
Chris@0
|
446 CASE_NAME (SF_CHANNEL_MAP_SIDE_RIGHT) ;
|
Chris@0
|
447 CASE_NAME (SF_CHANNEL_MAP_TOP_CENTER) ;
|
Chris@0
|
448 CASE_NAME (SF_CHANNEL_MAP_TOP_FRONT_LEFT) ;
|
Chris@0
|
449 CASE_NAME (SF_CHANNEL_MAP_TOP_FRONT_RIGHT) ;
|
Chris@0
|
450 CASE_NAME (SF_CHANNEL_MAP_TOP_FRONT_CENTER) ;
|
Chris@0
|
451 CASE_NAME (SF_CHANNEL_MAP_TOP_REAR_LEFT) ;
|
Chris@0
|
452 CASE_NAME (SF_CHANNEL_MAP_TOP_REAR_RIGHT) ;
|
Chris@0
|
453 CASE_NAME (SF_CHANNEL_MAP_TOP_REAR_CENTER) ;
|
Chris@0
|
454 CASE_NAME (SF_CHANNEL_MAP_MAX) ;
|
Chris@0
|
455 default : name = "default" ;
|
Chris@0
|
456 break ;
|
Chris@0
|
457 } ;
|
Chris@0
|
458
|
Chris@0
|
459 printf (" %3d %s\n", k, name) ;
|
Chris@0
|
460 } ;
|
Chris@0
|
461
|
Chris@0
|
462 putchar ('\n') ;
|
Chris@0
|
463 free (channel_map) ;
|
Chris@0
|
464
|
Chris@0
|
465 return 0 ;
|
Chris@0
|
466 } /* chanmap_dump */
|
Chris@0
|
467
|
Chris@0
|
468 static void
|
Chris@0
|
469 total_dump (void)
|
Chris@0
|
470 { printf ("========================================\n") ;
|
Chris@0
|
471 printf ("Total Duration : %s\n", format_duration_str (total_seconds)) ;
|
Chris@0
|
472 } /* total_dump */
|