comparison decoders/au.c @ 330:a81976ed5df7

Cleanups for robustness, potentially buggy seek method implementation.
author Ryan C. Gordon <icculus@icculus.org>
date Mon, 20 May 2002 09:22:42 +0000
parents c97be6e1bd27
children e683cb99f88f
comparison
equal deleted inserted replaced
329:41c650d468c3 330:a81976ed5df7
124 Uint32 start_offset; 124 Uint32 start_offset;
125 int encoding; 125 int encoding;
126 }; 126 };
127 127
128 128
129 /*
130 * Read in the AU header from disk. This makes this process safe
131 * regardless of the processor's byte order or how the au_file_hdr
132 * structure is packed.
133 */
134 static int read_au_header(SDL_RWops *rw, struct au_file_hdr *hdr)
135 {
136 if (SDL_RWread(rw, &hdr->magic, sizeof (hdr->magic), 1) != 1)
137 return(0);
138 hdr->magic = SDL_SwapBE32(hdr->magic);
139
140 if (SDL_RWread(rw, &hdr->hdr_size, sizeof (hdr->hdr_size), 1) != 1)
141 return(0);
142 hdr->hdr_size = SDL_SwapBE32(hdr->hdr_size);
143
144 if (SDL_RWread(rw, &hdr->data_size, sizeof (hdr->data_size), 1) != 1)
145 return(0);
146 hdr->data_size = SDL_SwapBE32(hdr->data_size);
147
148 if (SDL_RWread(rw, &hdr->encoding, sizeof (hdr->encoding), 1) != 1)
149 return(0);
150 hdr->encoding = SDL_SwapBE32(hdr->encoding);
151
152 if (SDL_RWread(rw, &hdr->sample_rate, sizeof (hdr->sample_rate), 1) != 1)
153 return(0);
154 hdr->sample_rate = SDL_SwapBE32(hdr->sample_rate);
155
156 if (SDL_RWread(rw, &hdr->channels, sizeof (hdr->channels), 1) != 1)
157 return(0);
158 hdr->channels = SDL_SwapBE32(hdr->channels);
159
160 return(1);
161 } /* read_au_header */
162
163
129 #define AU_MAGIC 0x2E736E64 /* ".snd", in ASCII (bigendian number) */ 164 #define AU_MAGIC 0x2E736E64 /* ".snd", in ASCII (bigendian number) */
130 165
131 static int AU_open(Sound_Sample *sample, const char *ext) 166 static int AU_open(Sound_Sample *sample, const char *ext)
132 { 167 {
133 Sound_SampleInternal *internal = sample->opaque; 168 Sound_SampleInternal *internal = sample->opaque;
134 SDL_RWops *rw = internal->rw; 169 SDL_RWops *rw = internal->rw;
135 int r, skip, hsize, i; 170 int skip, hsize, i;
136 struct au_file_hdr hdr; 171 struct au_file_hdr hdr;
172 struct audec *dec;
137 char c; 173 char c;
138 struct audec *dec = malloc(sizeof *dec); 174
175 if (!read_au_header(rw, &hdr)) /* does byte order swapping. */
176 {
177 Sound_SetError("AU: Not an .au file (bad header)");
178 return(0);
179 } /* if */
180
181 dec = malloc(sizeof *dec);
139 BAIL_IF_MACRO(dec == NULL, ERR_OUT_OF_MEMORY, 0); 182 BAIL_IF_MACRO(dec == NULL, ERR_OUT_OF_MEMORY, 0);
140 internal->decoder_private = dec; 183 internal->decoder_private = dec;
141 184
142 r = SDL_RWread(rw, &hdr, 1, HDR_SIZE); 185 if (hdr.magic == AU_MAGIC)
143 if (r < HDR_SIZE)
144 {
145 Sound_SetError("AU: Not an .au file (bad header)");
146 free(dec);
147 return(0);
148 } /* if */
149
150 if (SDL_SwapBE32(hdr.magic) == AU_MAGIC)
151 { 186 {
152 /* valid magic */ 187 /* valid magic */
153 dec->encoding = SDL_SwapBE32(hdr.encoding); 188 dec->encoding = hdr.encoding;
154 switch(dec->encoding) 189 switch(dec->encoding)
155 { 190 {
156 case AU_ENC_ULAW_8: 191 case AU_ENC_ULAW_8:
157 /* Convert 8-bit µ-law to 16-bit linear on the fly. This is 192 /* Convert 8-bit µ-law to 16-bit linear on the fly. This is
158 slightly wasteful if the audio driver must convert them 193 slightly wasteful if the audio driver must convert them
172 Sound_SetError("AU: Unsupported .au encoding"); 207 Sound_SetError("AU: Unsupported .au encoding");
173 free(dec); 208 free(dec);
174 return 0; 209 return 0;
175 } /* switch */ 210 } /* switch */
176 211
177 sample->actual.rate = SDL_SwapBE32(hdr.sample_rate); 212 sample->actual.rate = hdr.sample_rate;
178 sample->actual.channels = SDL_SwapBE32(hdr.channels); 213 sample->actual.channels = hdr.channels;
179 dec->remaining = SDL_SwapBE32(hdr.data_size); 214 dec->remaining = hdr.data_size;
180 hsize = SDL_SwapBE32(hdr.hdr_size); 215 hsize = hdr.hdr_size;
181 216
182 /* skip remaining part of header (input may be unseekable) */ 217 /* skip remaining part of header (input may be unseekable) */
183 for (i = HDR_SIZE; i < hsize; i++) 218 for (i = HDR_SIZE; i < hsize; i++)
184 SDL_RWread(rw, &c, 1, 1); 219 {
220 if (SDL_RWread(rw, &c, 1, 1) != 1)
221 {
222 free(dec);
223 BAIL_MACRO(ERR_IO_ERROR, 0);
224 } /* if */
225 } /* for */
185 } /* if */ 226 } /* if */
186 227
187 else if (__Sound_strcasecmp(ext, "au") == 0) 228 else if (__Sound_strcasecmp(ext, "au") == 0)
188 { 229 {
189 /* 230 /*
207 Sound_SetError("AU: Not an .AU stream."); 248 Sound_SetError("AU: Not an .AU stream.");
208 free(dec); 249 free(dec);
209 return(0); 250 return(0);
210 } /* else */ 251 } /* else */
211 252
212 sample->flags = SOUND_SAMPLEFLAG_NONE; 253 sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
213 dec->total = dec->remaining; 254 dec->total = dec->remaining;
214 dec->start_offset = SDL_RWtell(rw); 255 dec->start_offset = SDL_RWtell(rw);
215 256
216 SNDDBG(("AU: Accepting data stream.\n")); 257 SNDDBG(("AU: Accepting data stream.\n"));
217 return(1); 258 return(1);
319 } /* AU_rewind */ 360 } /* AU_rewind */
320 361
321 362
322 static int AU_seek(Sound_Sample *sample, Uint32 ms) 363 static int AU_seek(Sound_Sample *sample, Uint32 ms)
323 { 364 {
324 BAIL_MACRO("!!! FIXME: Not implemented", 0); 365 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
366 struct audec *dec = (struct audec *) internal->decoder_private;
367 int offset = dec->start_offset;
368 int frames = (int) (((float) sample->actual.rate / 1000.0) * ((float) ms));
369 int points = (int) (frames * sample->actual.channels);
370 int rc;
371
372 SNDDBG(("WARNING: AU_seek() may be buggy.\n")); /* !!! FIXME : remove this. */
373
374 switch (dec->encoding)
375 {
376 case AU_ENC_ULAW_8: /* halve the byte offset for compression. */
377 SNDDBG(("uLaw8 encoding\n")); /* !!! FIXME : remove this. */
378 offset += ((sizeof (Uint8) * points) >> 1);
379 break;
380
381 case AU_ENC_LINEAR_8:
382 SNDDBG(("linear8 encoding\n")); /* !!! FIXME : remove this. */
383 offset += (sizeof (Uint8) * points);
384 break;
385
386 case AU_ENC_LINEAR_16:
387 SNDDBG(("linear16 encoding\n")); /* !!! FIXME : remove this. */
388 offset += (sizeof (Uint16) * points);
389 break;
390
391 default:
392 BAIL_MACRO("Unexpected format. Something is very wrong.", 0);
393 break;
394 } /* switch */
395
396 SNDDBG(("Seek to %d (edge is %d).\n", (int) offset, (int) dec->total));
397
398 BAIL_IF_MACRO(offset >= dec->total, ERR_IO_ERROR, 0); /* seek past end? */
399
400 rc = SDL_RWseek(internal->rw, offset, SEEK_SET);
401 BAIL_IF_MACRO(rc != offset, ERR_IO_ERROR, 0);
402 dec->remaining = dec->total - (offset - 2);
403 return(1);
325 } /* AU_seek */ 404 } /* AU_seek */
326 405
327 #endif /* SOUND_SUPPORTS_AU */ 406 #endif /* SOUND_SUPPORTS_AU */
328 407