comparison decoders/aiff.c @ 180:db3f0ee7aac0

Modified to more easily allow for different compression types.
author Ryan C. Gordon <icculus@icculus.org>
date Fri, 07 Dec 2001 20:31:20 +0000
parents 1df5c106504e
children 47cc2de2ae36
comparison
equal deleted inserted replaced
179:bded4e43ae73 180:db3f0ee7aac0
54 54
55 #include "SDL_sound.h" 55 #include "SDL_sound.h"
56 56
57 #define __SDL_SOUND_INTERNAL__ 57 #define __SDL_SOUND_INTERNAL__
58 #include "SDL_sound_internal.h" 58 #include "SDL_sound_internal.h"
59
60 static Uint32 SANE_to_Uint32 (Uint8 *sanebuf);
61
59 62
60 static int AIFF_init(void); 63 static int AIFF_init(void);
61 static void AIFF_quit(void); 64 static void AIFF_quit(void);
62 static int AIFF_open(Sound_Sample *sample, const char *ext); 65 static int AIFF_open(Sound_Sample *sample, const char *ext);
63 static void AIFF_close(Sound_Sample *sample); 66 static void AIFF_close(Sound_Sample *sample);
79 AIFF_close, /* close() method */ 82 AIFF_close, /* close() method */
80 AIFF_read /* read() method */ 83 AIFF_read /* read() method */
81 }; 84 };
82 85
83 86
84 /* this is what we store in our internal->decoder_private field... */ 87 /*****************************************************************************
85 typedef struct { 88 * aiff_t is what we store in our internal->decoder_private field... *
89 *****************************************************************************/
90 typedef struct S_AIFF_FMT_T
91 {
92 Uint32 type;
93 void (*free)(struct S_AIFF_FMT_T *fmt);
94 Uint32(*read_sample)(Sound_Sample *sample);
95
96 #if 0
97 /*
98 this is ripped from wav.c as ann example of format-specific data.
99 please replace with something more appropriate when the need arises.
100 */
101 union
102 {
103 struct
104 {
105 Uint16 cbSize;
106 Uint16 wSamplesPerBlock;
107 Uint16 wNumCoef;
108 ADPCMCOEFSET *aCoeff;
109 } adpcm;
110
111 /* put other format-specific data here... */
112 } fmt;
113 #endif
114 } fmt_t;
115
116
117 typedef struct
118 {
119 fmt_t fmt;
86 Sint32 bytesLeft; 120 Sint32 bytesLeft;
87 } aiff_t; 121 } aiff_t;
88 122
89 123
124
90 /* Chunk management code... */ 125 /* Chunk management code... */
91 126
92 #define formID 0x4d524f46 /* "FORM", in ascii. */ 127 #define formID 0x4D524F46 /* "FORM", in ascii. */
93 #define aiffID 0x46464941 /* "AIFF", in ascii. */ 128 #define aiffID 0x46464941 /* "AIFF", in ascii. */
94 #define aifcID 0x43464941 /* "AIFC", in ascii. */ 129 #define aifcID 0x43464941 /* "AIFC", in ascii. */
95 #define ssndID 0x444e5353 /* "SSND", in ascii. */ 130 #define ssndID 0x444E5353 /* "SSND", in ascii. */
96 #define commID 0x4d4d4f43 /* "COMM", in ascii. */ 131
97 132
98 #define noneID 0x454e4f4e /* "NONE", in ascii. */ 133 /*****************************************************************************
134 * The COMM chunk... *
135 *****************************************************************************/
136
137 #define commID 0x4D4D4F43 /* "COMM", in ascii. */
138
139 /* format/compression types... */
140 #define noneID 0x454E4F4E /* "NONE", in ascii. */
99 141
100 typedef struct 142 typedef struct
101 { 143 {
102 Uint32 ckID; 144 Uint32 ckID;
103 Uint32 ckDataSize; 145 Uint32 ckDataSize;
137 pstring compressionName; 179 pstring compressionName;
138 #endif 180 #endif
139 } comm_t; 181 } comm_t;
140 182
141 183
142
143 static int AIFF_init(void)
144 {
145 return(1); /* always succeeds. */
146 } /* AIFF_init */
147
148
149 static void AIFF_quit(void)
150 {
151 /* it's a no-op. */
152 } /* AIFF_quit */
153
154
155 /*
156 * Sample rate is encoded as an "80 bit IEEE Standard 754 floating point
157 * number (Standard Apple Numeric Environment [SANE] data type Extended)".
158 * Whose bright idea was that?
159 *
160 * This function was adapted from libsndfile, and while I do know a little
161 * bit about the IEEE floating point standard I don't pretend to fully
162 * understand this.
163 */
164
165 static Uint32 SANE_to_Uint32 (Uint8 *sanebuf)
166 {
167 /* Is the frequency outside of what we can represent with Uint32? */
168 if ( (sanebuf[0] & 0x80)
169 || (sanebuf[0] <= 0x3F)
170 || (sanebuf[0] > 0x40)
171 || (sanebuf[0] == 0x40 && sanebuf[1] > 0x1C) )
172 return 0;
173
174 return ((sanebuf[2] << 23) | (sanebuf[3] << 15) | (sanebuf[4] << 7)
175 | (sanebuf[5] >> 1)) >> (29 - sanebuf[1]);
176 } /* SANE_to_Uint32 */
177
178
179 /* 184 /*
180 * Read in a comm_t from disk. This makes this process safe regardless of 185 * Read in a comm_t from disk. This makes this process safe regardless of
181 * the processor's byte order or how the comm_t structure is packed. 186 * the processor's byte order or how the comm_t structure is packed.
182 */ 187 */
183 188
218 sizeof (comm->compressionType), 1) != 1) 223 sizeof (comm->compressionType), 1) != 1)
219 return(0); 224 return(0);
220 comm->compressionType = SDL_SwapBE32(comm->compressionType); 225 comm->compressionType = SDL_SwapBE32(comm->compressionType);
221 } /* if */ 226 } /* if */
222 else 227 else
228 {
223 comm->compressionType = noneID; 229 comm->compressionType = noneID;
230 } /* else */
224 231
225 return(1); 232 return(1);
226 } /* read_comm_chunk */ 233 } /* read_comm_chunk */
234
235
236
237 /*****************************************************************************
238 * The SSND chunk... *
239 *****************************************************************************/
227 240
228 typedef struct 241 typedef struct
229 { 242 {
230 Uint32 ckID; 243 Uint32 ckID;
231 Uint32 ckDataSize; 244 Uint32 ckDataSize;
262 275
263 return(1); 276 return(1);
264 } /* read_ssnd_chunk */ 277 } /* read_ssnd_chunk */
265 278
266 279
280
281 /*****************************************************************************
282 * Normal, uncompressed aiff handler... *
283 *****************************************************************************/
284
285 static Uint32 read_sample_fmt_normal(Sound_Sample *sample)
286 {
287 Uint32 retval;
288 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
289 aiff_t *a = (aiff_t *) internal->decoder_private;
290 Uint32 max = (internal->buffer_size < (Uint32) a->bytesLeft) ?
291 internal->buffer_size : (Uint32) a->bytesLeft;
292
293 assert(max > 0);
294
295 /*
296 * We don't actually do any decoding, so we read the AIFF data
297 * directly into the internal buffer...
298 */
299 retval = SDL_RWread(internal->rw, internal->buffer, 1, max);
300
301 a->bytesLeft -= retval;
302
303 /* Make sure the read went smoothly... */
304 if ((retval == 0) || (a->bytesLeft == 0))
305 sample->flags |= SOUND_SAMPLEFLAG_EOF;
306
307 else if (retval == -1)
308 sample->flags |= SOUND_SAMPLEFLAG_ERROR;
309
310 /* (next call this EAGAIN may turn into an EOF or error.) */
311 else if (retval < internal->buffer_size)
312 sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
313
314 return(retval);
315 } /* read_sample_fmt_normal */
316
317
318 static void free_fmt_normal(fmt_t *fmt)
319 {
320 /* it's a no-op. */
321 } /* free_fmt_normal */
322
323
324 static int read_fmt_normal(SDL_RWops *rw, fmt_t *fmt)
325 {
326 /* (don't need to read more from the RWops...) */
327 fmt->free = free_fmt_normal;
328 fmt->read_sample = read_sample_fmt_normal;
329 return(1);
330 } /* read_fmt_normal */
331
332
333
334
335 /*****************************************************************************
336 * Everything else... *
337 *****************************************************************************/
338
339 static int AIFF_init(void)
340 {
341 return(1); /* always succeeds. */
342 } /* AIFF_init */
343
344
345 static void AIFF_quit(void)
346 {
347 /* it's a no-op. */
348 } /* AIFF_quit */
349
350
351 /*
352 * Sample rate is encoded as an "80 bit IEEE Standard 754 floating point
353 * number (Standard Apple Numeric Environment [SANE] data type Extended)".
354 * Whose bright idea was that?
355 *
356 * This function was adapted from libsndfile, and while I do know a little
357 * bit about the IEEE floating point standard I don't pretend to fully
358 * understand this.
359 */
360 static Uint32 SANE_to_Uint32 (Uint8 *sanebuf)
361 {
362 /* Is the frequency outside of what we can represent with Uint32? */
363 if ( (sanebuf[0] & 0x80)
364 || (sanebuf[0] <= 0x3F)
365 || (sanebuf[0] > 0x40)
366 || (sanebuf[0] == 0x40 && sanebuf[1] > 0x1C) )
367 return 0;
368
369 return ((sanebuf[2] << 23) | (sanebuf[3] << 15) | (sanebuf[4] << 7)
370 | (sanebuf[5] >> 1)) >> (29 - sanebuf[1]);
371 } /* SANE_to_Uint32 */
372
373
267 static int find_chunk(SDL_RWops *rw, Uint32 id) 374 static int find_chunk(SDL_RWops *rw, Uint32 id)
268 { 375 {
269 Sint32 siz = 0; 376 Sint32 siz = 0;
270 Uint32 _id = 0; 377 Uint32 _id = 0;
271 378
281 BAIL_IF_MACRO(SDL_RWseek(rw, siz, SEEK_CUR) == -1, NULL, 0); 388 BAIL_IF_MACRO(SDL_RWseek(rw, siz, SEEK_CUR) == -1, NULL, 0);
282 } /* while */ 389 } /* while */
283 390
284 return(0); /* shouldn't hit this, but just in case... */ 391 return(0); /* shouldn't hit this, but just in case... */
285 } /* find_chunk */ 392 } /* find_chunk */
393
394
395 static int read_fmt(SDL_RWops *rw, comm_t *c, fmt_t *fmt)
396 {
397 fmt->type = c->compressionType;
398
399 /* if it's in this switch statement, we support the format. */
400 switch (fmt->type)
401 {
402 case noneID:
403 SNDDBG(("AIFF: Appears to be uncompressed audio.\n"));
404 return(read_fmt_normal(rw, fmt));
405
406 /* add other types here. */
407
408 default:
409 SNDDBG(("AIFF: Format %lu is unknown.\n",
410 (unsigned int) fmt->type));
411 Sound_SetError("AIFF: Unsupported format");
412 return(0); /* not supported whatsoever. */
413 } /* switch */
414
415 assert(0); /* shouldn't hit this point. */
416 return(0);
417 } /* read_fmt */
286 418
287 419
288 static int AIFF_open(Sound_Sample *sample, const char *ext) 420 static int AIFF_open(Sound_Sample *sample, const char *ext)
289 { 421 {
290 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; 422 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
308 440
309 BAIL_IF_MACRO(!find_chunk(rw, commID), "AIFF: No common chunk.", 0); 441 BAIL_IF_MACRO(!find_chunk(rw, commID), "AIFF: No common chunk.", 0);
310 BAIL_IF_MACRO(!read_comm_chunk(rw, &c), 442 BAIL_IF_MACRO(!read_comm_chunk(rw, &c),
311 "AIFF: Can't read common chunk.", 0); 443 "AIFF: Can't read common chunk.", 0);
312 444
313 /* !!! FIXME: This will have to change for compression types... */
314 BAIL_IF_MACRO(c.compressionType != noneID,
315 "AIFF: Unsupported encoding.", 0);
316
317 BAIL_IF_MACRO(c.sampleRate == 0, "AIFF: Unsupported sample rate.", 0);
318
319 sample->actual.channels = (Uint8) c.numChannels; 445 sample->actual.channels = (Uint8) c.numChannels;
320 sample->actual.rate = c.sampleRate; 446 sample->actual.rate = c.sampleRate;
321 447
322 if (c.sampleSize <= 8) 448 if (c.sampleSize <= 8)
323 { 449 {
328 { 454 {
329 sample->actual.format = AUDIO_S16MSB; 455 sample->actual.format = AUDIO_S16MSB;
330 bytes_per_sample = 2; 456 bytes_per_sample = 2;
331 } /* if */ 457 } /* if */
332 else 458 else
459 {
333 BAIL_MACRO("AIFF: Unsupported sample size.", 0); 460 BAIL_MACRO("AIFF: Unsupported sample size.", 0);
334 461 } /* else */
335 SDL_RWseek(rw, pos, SEEK_SET); 462
336 463 BAIL_IF_MACRO(c.sampleRate == 0, "AIFF: Unsupported sample rate.", 0);
337 BAIL_IF_MACRO(!find_chunk(rw, ssndID), "AIFF: No sound data chunk.", 0);
338 BAIL_IF_MACRO(!read_ssnd_chunk(rw, &s),
339 "AIFF: Can't read sound data chunk.", 0);
340 464
341 a = (aiff_t *) malloc(sizeof(aiff_t)); 465 a = (aiff_t *) malloc(sizeof(aiff_t));
342 BAIL_IF_MACRO(a == NULL, ERR_OUT_OF_MEMORY, 0); 466 BAIL_IF_MACRO(a == NULL, ERR_OUT_OF_MEMORY, 0);
467
468 if (!read_fmt(rw, &c, &(a->fmt)))
469 {
470 free(a);
471 return(0);
472 } /* if */
473
474 SDL_RWseek(rw, pos, SEEK_SET); /* if the seek fails, let it go... */
475
476 if (!find_chunk(rw, ssndID))
477 {
478 Sound_SetError("AIFF: No sound data chunk.");
479 free(a);
480 return(0);
481 } /* if */
482
483 if (!read_ssnd_chunk(rw, &s))
484 {
485 Sound_SetError("AIFF: Can't read sound data chunk.");
486 free(a);
487 return(0);
488 } /* if */
489
343 a->bytesLeft = bytes_per_sample * c.numSampleFrames; 490 a->bytesLeft = bytes_per_sample * c.numSampleFrames;
344 internal->decoder_private = (void *) a; 491 internal->decoder_private = (void *) a;
345 492
346 sample->flags = SOUND_SAMPLEFLAG_NONE; 493 sample->flags = SOUND_SAMPLEFLAG_NONE;
347 494
351 498
352 499
353 static void AIFF_close(Sound_Sample *sample) 500 static void AIFF_close(Sound_Sample *sample)
354 { 501 {
355 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; 502 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
356 free(internal->decoder_private); 503 aiff_t *a = (aiff_t *) internal->decoder_private;
504 a->fmt.free(&(a->fmt));
505 free(a);
357 } /* WAV_close */ 506 } /* WAV_close */
358 507
359 508
360 static Uint32 AIFF_read(Sound_Sample *sample) 509 static Uint32 AIFF_read(Sound_Sample *sample)
361 { 510 {
362 Uint32 retval;
363 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; 511 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
364 aiff_t *a = (aiff_t *) internal->decoder_private; 512 aiff_t *a = (aiff_t *) internal->decoder_private;
365 Uint32 max = (internal->buffer_size < (Uint32) a->bytesLeft) ? 513 return(a->fmt.read_sample(sample));
366 internal->buffer_size : (Uint32) a->bytesLeft;
367
368 assert(max > 0);
369
370 /*
371 * We don't actually do any decoding, so we read the AIFF data
372 * directly into the internal buffer...
373 */
374 retval = SDL_RWread(internal->rw, internal->buffer, 1, max);
375
376 a->bytesLeft -= retval;
377
378 /* Make sure the read went smoothly... */
379 if ((retval == 0) || (a->bytesLeft == 0))
380 sample->flags |= SOUND_SAMPLEFLAG_EOF;
381
382 else if (retval == -1)
383 sample->flags |= SOUND_SAMPLEFLAG_ERROR;
384
385 /* (next call this EAGAIN may turn into an EOF or error.) */
386 else if (retval < internal->buffer_size)
387 sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
388
389 return(retval);
390 } /* AIFF_read */ 514 } /* AIFF_read */
391 515
392 #endif /* SOUND_SUPPORTS_AIFF */ 516 #endif /* SOUND_SUPPORTS_AIFF */
393 517
394
395 /* end of aiff.c ... */ 518 /* end of aiff.c ... */
519