libsndfile source files.
[Faustine.git] / interpretor / libsndfile-1.0.25 / src / sd2.c
1 /*
2 ** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
3 ** Copyright (C) 2004 Paavo Jumppanen
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU Lesser General Public License as published by
7 ** the Free Software Foundation; either version 2.1 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU Lesser General Public License for more details.
14 **
15 ** You should have received a copy of the GNU Lesser General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 /*
21 ** The sd2 support implemented in this file was partially sponsored
22 ** (financially) by Paavo Jumppanen.
23 */
24
25 /*
26 ** Documentation on the Mac resource fork was obtained here :
27 ** http://developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html
28 */
29
30 #include "sfconfig.h"
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36
37 #include "sndfile.h"
38 #include "sfendian.h"
39 #include "common.h"
40
41 /*------------------------------------------------------------------------------
42 * Markers.
43 */
44
45 #define Sd2f_MARKER MAKE_MARKER ('S', 'd', '2', 'f')
46 #define Sd2a_MARKER MAKE_MARKER ('S', 'd', '2', 'a')
47 #define ALCH_MARKER MAKE_MARKER ('A', 'L', 'C', 'H')
48 #define lsf1_MARKER MAKE_MARKER ('l', 's', 'f', '1')
49
50 #define STR_MARKER MAKE_MARKER ('S', 'T', 'R', ' ')
51 #define sdML_MARKER MAKE_MARKER ('s', 'd', 'M', 'L')
52
53 enum
54 { RSRC_STR = 111,
55 RSRC_BIN
56 } ;
57
58 typedef struct
59 { unsigned char * rsrc_data ;
60 int rsrc_len ;
61 int need_to_free_rsrc_data ;
62
63 int data_offset, data_length ;
64 int map_offset, map_length ;
65
66 int type_count, type_offset ;
67 int item_offset ;
68
69 int str_index, str_count ;
70
71 int string_offset ;
72
73 /* All the above just to get these three. */
74 int sample_size, sample_rate, channels ;
75 } SD2_RSRC ;
76
77 typedef struct
78 { int type ;
79 int id ;
80 char name [32] ;
81 char value [32] ;
82 int value_len ;
83 } STR_RSRC ;
84
85 /*------------------------------------------------------------------------------
86 * Private static functions.
87 */
88
89 static int sd2_close (SF_PRIVATE *psf) ;
90
91 static int sd2_parse_rsrc_fork (SF_PRIVATE *psf) ;
92 static int parse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc) ;
93
94 static int sd2_write_rsrc_fork (SF_PRIVATE *psf, int calc_length) ;
95
96 /*------------------------------------------------------------------------------
97 ** Public functions.
98 */
99
100 int
101 sd2_open (SF_PRIVATE *psf)
102 { int subformat, error = 0, valid ;
103
104 /* SD2 is always big endian. */
105 psf->endian = SF_ENDIAN_BIG ;
106
107 if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->rsrclength > 0))
108 { psf_use_rsrc (psf, SF_TRUE) ;
109 valid = psf_file_valid (psf) ;
110 psf_use_rsrc (psf, SF_FALSE) ;
111 if (! valid)
112 { psf_log_printf (psf, "sd2_open : psf->rsrc.filedes < 0\n") ;
113 return SFE_SD2_BAD_RSRC ;
114 } ;
115
116 error = sd2_parse_rsrc_fork (psf) ;
117
118 if (error)
119 goto error_cleanup ;
120 } ;
121
122 if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_SD2)
123 { error = SFE_BAD_OPEN_FORMAT ;
124 goto error_cleanup ;
125 } ;
126
127 subformat = SF_CODEC (psf->sf.format) ;
128 psf->dataoffset = 0 ;
129
130 /* Only open and write the resource in RDWR mode is its current length is zero. */
131 if (psf->file.mode == SFM_WRITE || (psf->file.mode == SFM_RDWR && psf->rsrclength == 0))
132 { psf->rsrc.mode = psf->file.mode ;
133 psf_open_rsrc (psf) ;
134
135 error = sd2_write_rsrc_fork (psf, SF_FALSE) ;
136
137 if (error)
138 goto error_cleanup ;
139
140 /* Not needed. */
141 psf->write_header = NULL ;
142 } ;
143
144 psf->container_close = sd2_close ;
145
146 psf->blockwidth = psf->bytewidth * psf->sf.channels ;
147
148 switch (subformat)
149 { case SF_FORMAT_PCM_S8 : /* 8-bit linear PCM. */
150 case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */
151 case SF_FORMAT_PCM_24 : /* 24-bit linear PCM */
152 error = pcm_init (psf) ;
153 break ;
154
155 default :
156 error = SFE_UNIMPLEMENTED ;
157 break ;
158 } ;
159
160 psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
161
162 error_cleanup:
163
164 /* Close the resource fork regardless. We won't need it again. */
165 psf_close_rsrc (psf) ;
166
167 return error ;
168 } /* sd2_open */
169
170 /*------------------------------------------------------------------------------
171 */
172
173 static int
174 sd2_close (SF_PRIVATE *psf)
175 {
176 if (psf->file.mode == SFM_WRITE)
177 { /* Now we know for certain the audio_length of the file we can re-write
178 ** correct values for the FORM, 8SVX and BODY chunks.
179 */
180
181 } ;
182
183 return 0 ;
184 } /* sd2_close */
185
186 /*------------------------------------------------------------------------------
187 */
188
189 static inline void
190 write_char (unsigned char * data, int offset, char value)
191 { data [offset] = value ;
192 } /* write_char */
193
194 static inline void
195 write_short (unsigned char * data, int offset, short value)
196 { data [offset] = value >> 8 ;
197 data [offset + 1] = value ;
198 } /* write_char */
199
200 static inline void
201 write_int (unsigned char * data, int offset, int value)
202 { data [offset] = value >> 24 ;
203 data [offset + 1] = value >> 16 ;
204 data [offset + 2] = value >> 8 ;
205 data [offset + 3] = value ;
206 } /* write_int */
207
208 static inline void
209 write_marker (unsigned char * data, int offset, int value)
210 {
211 if (CPU_IS_BIG_ENDIAN)
212 { data [offset] = value >> 24 ;
213 data [offset + 1] = value >> 16 ;
214 data [offset + 2] = value >> 8 ;
215 data [offset + 3] = value ;
216 }
217 else
218 { data [offset] = value ;
219 data [offset + 1] = value >> 8 ;
220 data [offset + 2] = value >> 16 ;
221 data [offset + 3] = value >> 24 ;
222 } ;
223 } /* write_marker */
224
225 static void
226 write_str (unsigned char * data, int offset, const char * buffer, int buffer_len)
227 { memcpy (data + offset, buffer, buffer_len) ;
228 } /* write_str */
229
230 static int
231 sd2_write_rsrc_fork (SF_PRIVATE *psf, int UNUSED (calc_length))
232 { SD2_RSRC rsrc ;
233 STR_RSRC str_rsrc [] =
234 { { RSRC_STR, 1000, "_sample-size", "", 0 },
235 { RSRC_STR, 1001, "_sample-rate", "", 0 },
236 { RSRC_STR, 1002, "_channels", "", 0 },
237 { RSRC_BIN, 1000, "_Markers", "", 8 }
238 } ;
239
240 int k, str_offset, data_offset, next_str ;
241
242 psf_use_rsrc (psf, SF_TRUE) ;
243
244 memset (&rsrc, 0, sizeof (rsrc)) ;
245
246 rsrc.sample_rate = psf->sf.samplerate ;
247 rsrc.sample_size = psf->bytewidth ;
248 rsrc.channels = psf->sf.channels ;
249
250 rsrc.rsrc_data = psf->header ;
251 rsrc.rsrc_len = sizeof (psf->header) ;
252 memset (rsrc.rsrc_data, 0xea, rsrc.rsrc_len) ;
253
254 snprintf (str_rsrc [0].value, sizeof (str_rsrc [0].value), "_%d", rsrc.sample_size) ;
255 snprintf (str_rsrc [1].value, sizeof (str_rsrc [1].value), "_%d.000000", rsrc.sample_rate) ;
256 snprintf (str_rsrc [2].value, sizeof (str_rsrc [2].value), "_%d", rsrc.channels) ;
257
258 for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++)
259 { if (str_rsrc [k].value_len == 0)
260 { str_rsrc [k].value_len = strlen (str_rsrc [k].value) ;
261 str_rsrc [k].value [0] = str_rsrc [k].value_len - 1 ;
262 } ;
263
264 /* Turn name string into a pascal string. */
265 str_rsrc [k].name [0] = strlen (str_rsrc [k].name) - 1 ;
266 } ;
267
268 rsrc.data_offset = 0x100 ;
269
270 /*
271 ** Calculate data length :
272 ** length of strings, plus the length of the sdML chunk.
273 */
274 rsrc.data_length = 0 ;
275 for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++)
276 rsrc.data_length += str_rsrc [k].value_len + 4 ;
277
278 rsrc.map_offset = rsrc.data_offset + rsrc.data_length ;
279
280 /* Very start of resource fork. */
281 write_int (rsrc.rsrc_data, 0, rsrc.data_offset) ;
282 write_int (rsrc.rsrc_data, 4, rsrc.map_offset) ;
283 write_int (rsrc.rsrc_data, 8, rsrc.data_length) ;
284
285 write_char (rsrc.rsrc_data, 0x30, strlen (psf->file.name.c)) ;
286 write_str (rsrc.rsrc_data, 0x31, psf->file.name.c, strlen (psf->file.name.c)) ;
287
288 write_short (rsrc.rsrc_data, 0x50, 0) ;
289 write_marker (rsrc.rsrc_data, 0x52, Sd2f_MARKER) ;
290 write_marker (rsrc.rsrc_data, 0x56, lsf1_MARKER) ;
291
292 /* Very start of resource map. */
293 write_int (rsrc.rsrc_data, rsrc.map_offset + 0, rsrc.data_offset) ;
294 write_int (rsrc.rsrc_data, rsrc.map_offset + 4, rsrc.map_offset) ;
295 write_int (rsrc.rsrc_data, rsrc.map_offset + 8, rsrc.data_length) ;
296
297 /* These I don't currently understand. */
298 if (1)
299 { write_char (rsrc.rsrc_data, rsrc.map_offset+ 16, 1) ;
300 /* Next resource map. */
301 write_int (rsrc.rsrc_data, rsrc.map_offset + 17, 0x12345678) ;
302 /* File ref number. */
303 write_short (rsrc.rsrc_data, rsrc.map_offset + 21, 0xabcd) ;
304 /* Fork attributes. */
305 write_short (rsrc.rsrc_data, rsrc.map_offset + 23, 0) ;
306 } ;
307
308 /* Resource type offset. */
309 rsrc.type_offset = rsrc.map_offset + 30 ;
310 write_short (rsrc.rsrc_data, rsrc.map_offset + 24, rsrc.type_offset - rsrc.map_offset - 2) ;
311
312 /* Type index max. */
313 rsrc.type_count = 2 ;
314 write_short (rsrc.rsrc_data, rsrc.map_offset + 28, rsrc.type_count - 1) ;
315
316 rsrc.item_offset = rsrc.type_offset + rsrc.type_count * 8 ;
317
318 rsrc.str_count = ARRAY_LEN (str_rsrc) ;
319 rsrc.string_offset = rsrc.item_offset + (rsrc.str_count + 1) * 12 - rsrc.map_offset ;
320 write_short (rsrc.rsrc_data, rsrc.map_offset + 26, rsrc.string_offset) ;
321
322 /* Write 'STR ' resource type. */
323 rsrc.str_count = 3 ;
324 write_marker (rsrc.rsrc_data, rsrc.type_offset, STR_MARKER) ;
325 write_short (rsrc.rsrc_data, rsrc.type_offset + 4, rsrc.str_count - 1) ;
326 write_short (rsrc.rsrc_data, rsrc.type_offset + 6, 0x12) ;
327
328 /* Write 'sdML' resource type. */
329 write_marker (rsrc.rsrc_data, rsrc.type_offset + 8, sdML_MARKER) ;
330 write_short (rsrc.rsrc_data, rsrc.type_offset + 12, 0) ;
331 write_short (rsrc.rsrc_data, rsrc.type_offset + 14, 0x36) ;
332
333 str_offset = rsrc.map_offset + rsrc.string_offset ;
334 next_str = 0 ;
335 data_offset = rsrc.data_offset ;
336 for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++)
337 { write_str (rsrc.rsrc_data, str_offset, str_rsrc [k].name, strlen (str_rsrc [k].name)) ;
338
339 write_short (rsrc.rsrc_data, rsrc.item_offset + k * 12, str_rsrc [k].id) ;
340 write_short (rsrc.rsrc_data, rsrc.item_offset + k * 12 + 2, next_str) ;
341
342 str_offset += strlen (str_rsrc [k].name) ;
343 next_str += strlen (str_rsrc [k].name) ;
344
345 write_int (rsrc.rsrc_data, rsrc.item_offset + k * 12 + 4, data_offset - rsrc.data_offset) ;
346
347 write_int (rsrc.rsrc_data, data_offset, str_rsrc [k].value_len) ;
348 write_str (rsrc.rsrc_data, data_offset + 4, str_rsrc [k].value, str_rsrc [k].value_len) ;
349 data_offset += 4 + str_rsrc [k].value_len ;
350 } ;
351
352 /* Finally, calculate and set map length. */
353 rsrc.map_length = str_offset - rsrc.map_offset ;
354 write_int (rsrc.rsrc_data, 12, rsrc.map_length) ;
355 write_int (rsrc.rsrc_data, rsrc.map_offset + 12, rsrc.map_length) ;
356
357 rsrc.rsrc_len = rsrc.map_offset + rsrc.map_length ;
358
359 psf_fwrite (rsrc.rsrc_data, rsrc.rsrc_len, 1, psf) ;
360
361 psf_use_rsrc (psf, SF_FALSE) ;
362
363 if (psf->error)
364 return psf->error ;
365
366 return 0 ;
367 } /* sd2_write_rsrc_fork */
368
369 /*------------------------------------------------------------------------------
370 */
371
372 static inline int
373 read_char (const unsigned char * data, int offset)
374 { return data [offset] ;
375 } /* read_char */
376
377 static inline int
378 read_short (const unsigned char * data, int offset)
379 { return (data [offset] << 8) + data [offset + 1] ;
380 } /* read_short */
381
382 static inline int
383 read_int (const unsigned char * data, int offset)
384 { return (data [offset] << 24) + (data [offset + 1] << 16) + (data [offset + 2] << 8) + data [offset + 3] ;
385 } /* read_int */
386
387 static inline int
388 read_marker (const unsigned char * data, int offset)
389 {
390 if (CPU_IS_BIG_ENDIAN)
391 return (data [offset] << 24) + (data [offset + 1] << 16) + (data [offset + 2] << 8) + data [offset + 3] ;
392 else if (CPU_IS_LITTLE_ENDIAN)
393 return data [offset] + (data [offset + 1] << 8) + (data [offset + 2] << 16) + (data [offset + 3] << 24) ;
394 else
395 return 0x666 ;
396 } /* read_marker */
397
398 static void
399 read_str (const unsigned char * data, int offset, char * buffer, int buffer_len)
400 { int k ;
401
402 memset (buffer, 0, buffer_len) ;
403
404 for (k = 0 ; k < buffer_len - 1 ; k++)
405 { if (psf_isprint (data [offset + k]) == 0)
406 return ;
407 buffer [k] = data [offset + k] ;
408 } ;
409 return ;
410 } /* read_str */
411
412 static int
413 sd2_parse_rsrc_fork (SF_PRIVATE *psf)
414 { SD2_RSRC rsrc ;
415 int k, marker, error = 0 ;
416
417 psf_use_rsrc (psf, SF_TRUE) ;
418
419 memset (&rsrc, 0, sizeof (rsrc)) ;
420
421 rsrc.rsrc_len = psf_get_filelen (psf) ;
422 psf_log_printf (psf, "Resource length : %d (0x%04X)\n", rsrc.rsrc_len, rsrc.rsrc_len) ;
423
424 if (rsrc.rsrc_len > SIGNED_SIZEOF (psf->header))
425 { rsrc.rsrc_data = calloc (1, rsrc.rsrc_len) ;
426 rsrc.need_to_free_rsrc_data = SF_TRUE ;
427 }
428 else
429 rsrc.rsrc_data = psf->header ;
430
431 /* Read in the whole lot. */
432 psf_fread (rsrc.rsrc_data, rsrc.rsrc_len, 1, psf) ;
433
434 /* Reset the header storage because we have changed to the rsrcdes. */
435 psf->headindex = psf->headend = rsrc.rsrc_len ;
436
437 rsrc.data_offset = read_int (rsrc.rsrc_data, 0) ;
438 rsrc.map_offset = read_int (rsrc.rsrc_data, 4) ;
439 rsrc.data_length = read_int (rsrc.rsrc_data, 8) ;
440 rsrc.map_length = read_int (rsrc.rsrc_data, 12) ;
441
442 if (rsrc.data_offset == 0x51607 && rsrc.map_offset == 0x20000)
443 { psf_log_printf (psf, "Trying offset of 0x52 bytes.\n") ;
444 rsrc.data_offset = read_int (rsrc.rsrc_data, 0x52 + 0) + 0x52 ;
445 rsrc.map_offset = read_int (rsrc.rsrc_data, 0x52 + 4) + 0x52 ;
446 rsrc.data_length = read_int (rsrc.rsrc_data, 0x52 + 8) ;
447 rsrc.map_length = read_int (rsrc.rsrc_data, 0x52 + 12) ;
448 } ;
449
450 psf_log_printf (psf, " data offset : 0x%04X\n map offset : 0x%04X\n"
451 " data length : 0x%04X\n map length : 0x%04X\n",
452 rsrc.data_offset, rsrc.map_offset, rsrc.data_length, rsrc.map_length) ;
453
454 if (rsrc.data_offset > rsrc.rsrc_len)
455 { psf_log_printf (psf, "Error : rsrc.data_offset (%d, 0x%x) > len\n", rsrc.data_offset, rsrc.data_offset) ;
456 error = SFE_SD2_BAD_DATA_OFFSET ;
457 goto parse_rsrc_fork_cleanup ;
458 } ;
459
460 if (rsrc.map_offset > rsrc.rsrc_len)
461 { psf_log_printf (psf, "Error : rsrc.map_offset > len\n") ;
462 error = SFE_SD2_BAD_MAP_OFFSET ;
463 goto parse_rsrc_fork_cleanup ;
464 } ;
465
466 if (rsrc.data_length > rsrc.rsrc_len)
467 { psf_log_printf (psf, "Error : rsrc.data_length > len\n") ;
468 error = SFE_SD2_BAD_DATA_LENGTH ;
469 goto parse_rsrc_fork_cleanup ;
470 } ;
471
472 if (rsrc.map_length > rsrc.rsrc_len)
473 { psf_log_printf (psf, "Error : rsrc.map_length > len\n") ;
474 error = SFE_SD2_BAD_MAP_LENGTH ;
475 goto parse_rsrc_fork_cleanup ;
476 } ;
477
478 if (rsrc.data_offset + rsrc.data_length != rsrc.map_offset || rsrc.map_offset + rsrc.map_length != rsrc.rsrc_len)
479 { psf_log_printf (psf, "Error : This does not look like a MacOSX resource fork.\n") ;
480 error = SFE_SD2_BAD_RSRC ;
481 goto parse_rsrc_fork_cleanup ;
482 } ;
483
484 if (rsrc.map_offset + 28 >= rsrc.rsrc_len)
485 { psf_log_printf (psf, "Bad map offset (%d + 28 > %d).\n", rsrc.map_offset, rsrc.rsrc_len) ;
486 error = SFE_SD2_BAD_RSRC ;
487 goto parse_rsrc_fork_cleanup ;
488 } ;
489
490 rsrc.string_offset = rsrc.map_offset + read_short (rsrc.rsrc_data, rsrc.map_offset + 26) ;
491 if (rsrc.string_offset > rsrc.rsrc_len)
492 { psf_log_printf (psf, "Bad string offset (%d).\n", rsrc.string_offset) ;
493 error = SFE_SD2_BAD_RSRC ;
494 goto parse_rsrc_fork_cleanup ;
495 } ;
496
497 rsrc.type_offset = rsrc.map_offset + 30 ;
498
499 rsrc.type_count = read_short (rsrc.rsrc_data, rsrc.map_offset + 28) + 1 ;
500 if (rsrc.type_count < 1)
501 { psf_log_printf (psf, "Bad type count.\n") ;
502 error = SFE_SD2_BAD_RSRC ;
503 goto parse_rsrc_fork_cleanup ;
504 } ;
505
506 rsrc.item_offset = rsrc.type_offset + rsrc.type_count * 8 ;
507 if (rsrc.item_offset < 0 || rsrc.item_offset > rsrc.rsrc_len)
508 { psf_log_printf (psf, "Bad item offset (%d).\n", rsrc.item_offset) ;
509 error = SFE_SD2_BAD_RSRC ;
510 goto parse_rsrc_fork_cleanup ;
511 } ;
512
513 rsrc.str_index = -1 ;
514 for (k = 0 ; k < rsrc.type_count ; k ++)
515 { marker = read_marker (rsrc.rsrc_data, rsrc.type_offset + k * 8) ;
516
517 if (marker == STR_MARKER)
518 { rsrc.str_index = k ;
519 rsrc.str_count = read_short (rsrc.rsrc_data, rsrc.type_offset + k * 8 + 4) + 1 ;
520 error = parse_str_rsrc (psf, &rsrc) ;
521 goto parse_rsrc_fork_cleanup ;
522 } ;
523 } ;
524
525 psf_log_printf (psf, "No 'STR ' resource.\n") ;
526 error = SFE_SD2_BAD_RSRC ;
527
528 parse_rsrc_fork_cleanup :
529
530 psf_use_rsrc (psf, SF_FALSE) ;
531
532 if (rsrc.need_to_free_rsrc_data)
533 free (rsrc.rsrc_data) ;
534
535 return error ;
536 } /* sd2_parse_rsrc_fork */
537
538 static int
539 parse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc)
540 { char name [32], value [32] ;
541 int k, str_offset, rsrc_id, data_offset = 0, data_len = 0 ;
542
543 psf_log_printf (psf, "Finding parameters :\n") ;
544
545 str_offset = rsrc->string_offset ;
546 psf_log_printf (psf, " Offset RsrcId dlen slen Value\n") ;
547
548 for (k = 0 ; data_offset + data_len < rsrc->rsrc_len ; k++)
549 { int slen ;
550
551 slen = read_char (rsrc->rsrc_data, str_offset) ;
552 read_str (rsrc->rsrc_data, str_offset + 1, name, SF_MIN (SIGNED_SIZEOF (name), slen + 1)) ;
553 str_offset += slen + 1 ;
554
555 rsrc_id = read_short (rsrc->rsrc_data, rsrc->item_offset + k * 12) ;
556
557 data_offset = rsrc->data_offset + read_int (rsrc->rsrc_data, rsrc->item_offset + k * 12 + 4) ;
558 if (data_offset < 0 || data_offset > rsrc->rsrc_len)
559 { psf_log_printf (psf, "Exiting parser on data offset of %d.\n", data_offset) ;
560 break ;
561 } ;
562
563 data_len = read_int (rsrc->rsrc_data, data_offset) ;
564 if (data_len < 0 || data_len > rsrc->rsrc_len)
565 { psf_log_printf (psf, "Exiting parser on data length of %d.\n", data_len) ;
566 break ;
567 } ;
568
569 slen = read_char (rsrc->rsrc_data, data_offset + 4) ;
570 read_str (rsrc->rsrc_data, data_offset + 5, value, SF_MIN (SIGNED_SIZEOF (value), slen + 1)) ;
571
572 psf_log_printf (psf, " 0x%04x %4d %4d %3d '%s'\n", data_offset, rsrc_id, data_len, slen, value) ;
573
574 if (rsrc_id == 1000 && rsrc->sample_size == 0)
575 rsrc->sample_size = strtol (value, NULL, 10) ;
576 else if (rsrc_id == 1001 && rsrc->sample_rate == 0)
577 rsrc->sample_rate = strtol (value, NULL, 10) ;
578 else if (rsrc_id == 1002 && rsrc->channels == 0)
579 rsrc->channels = strtol (value, NULL, 10) ;
580 } ;
581
582 psf_log_printf (psf, "Found Parameters :\n") ;
583 psf_log_printf (psf, " sample-size : %d\n", rsrc->sample_size) ;
584 psf_log_printf (psf, " sample-rate : %d\n", rsrc->sample_rate) ;
585 psf_log_printf (psf, " channels : %d\n", rsrc->channels) ;
586
587 if (rsrc->sample_rate <= 4 && rsrc->sample_size > 4)
588 { int temp ;
589
590 psf_log_printf (psf, "Geez!! Looks like sample rate and sample size got switched.\nCorrecting this screw up.\n") ;
591 temp = rsrc->sample_rate ;
592 rsrc->sample_rate = rsrc->sample_size ;
593 rsrc->sample_size = temp ;
594 } ;
595
596 if (rsrc->sample_rate < 0)
597 { psf_log_printf (psf, "Bad sample rate (%d)\n", rsrc->sample_rate) ;
598 return SFE_SD2_BAD_RSRC ;
599 } ;
600
601 if (rsrc->channels < 0)
602 { psf_log_printf (psf, "Bad channel count (%d)\n", rsrc->channels) ;
603 return SFE_SD2_BAD_RSRC ;
604 } ;
605
606 psf->sf.samplerate = rsrc->sample_rate ;
607 psf->sf.channels = rsrc->channels ;
608 psf->bytewidth = rsrc->sample_size ;
609
610 switch (rsrc->sample_size)
611 { case 1 :
612 psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_S8 ;
613 break ;
614
615 case 2 :
616 psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_16 ;
617 break ;
618
619 case 3 :
620 psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_24 ;
621 break ;
622
623 default :
624 psf_log_printf (psf, "Bad sample size (%d)\n", rsrc->sample_size) ;
625 return SFE_SD2_BAD_SAMPLE_SIZE ;
626 } ;
627
628 psf_log_printf (psf, "ok\n") ;
629
630 return 0 ;
631 } /* parse_str_rsrc */
632