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