Mercurial > SDL_sound_CoreAudio
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 |