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