Git init
[external/libsndfile.git] / src / sd2.c
1 /*
2 ** Copyright (C) 2001-2009 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