Mercurial > SDL_sound_CoreAudio
comparison decoders/voc.c @ 385:9efb760c4a6b
FIXME removal and cleanups.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Fri, 05 Jul 2002 22:32:54 +0000 |
parents | cbb15ecf423a |
children | fb519e6028e3 |
comparison
equal
deleted
inserted
replaced
384:fd44db5a5c08 | 385:9efb760c4a6b |
---|---|
80 }; | 80 }; |
81 | 81 |
82 | 82 |
83 /* Private data for VOC file */ | 83 /* Private data for VOC file */ |
84 typedef struct vocstuff { | 84 typedef struct vocstuff { |
85 Uint32 rest; /* bytes remaining in current block */ | 85 Uint32 rest; /* bytes remaining in current block */ |
86 Uint32 rate; /* rate code (byte) of this chunk */ | 86 Uint32 rate; /* rate code (byte) of this chunk */ |
87 int silent; /* sound or silence? */ | 87 int silent; /* sound or silence? */ |
88 Uint32 srate; /* rate code (byte) of silence */ | 88 Uint32 srate; /* rate code (byte) of silence */ |
89 Uint32 blockseek; /* start of current output block */ | 89 Uint32 blockseek; /* start of current output block */ |
90 Uint32 samples; /* number of samples output */ | 90 Uint32 samples; /* number of samples output */ |
91 Uint32 size; /* word length of data */ | 91 Uint32 size; /* word length of data */ |
92 Uint8 channels; /* number of sound channels */ | 92 Uint8 channels; /* number of sound channels */ |
93 int extended; /* Has an extended block been read? */ | 93 int extended; /* Has an extended block been read? */ |
94 Uint32 bufpos; /* byte position in internal->buffer. */ | 94 Uint32 bufpos; /* byte position in internal->buffer. */ |
95 Uint32 start_pos; /* offset to seek to in stream when rewinding. */ | 95 Uint32 start_pos; /* offset to seek to in stream when rewinding. */ |
96 int error; /* error condition (as opposed to EOF). */ | |
96 } vs_t; | 97 } vs_t; |
98 | |
97 | 99 |
98 /* Size field */ | 100 /* Size field */ |
99 /* SJB: note that the 1st 3 are sometimes used as sizeof(type) */ | 101 /* SJB: note that the 1st 3 are sometimes used as sizeof(type) */ |
100 #define ST_SIZE_BYTE 1 | 102 #define ST_SIZE_BYTE 1 |
101 #define ST_SIZE_8BIT 1 | 103 #define ST_SIZE_8BIT 1 |
138 { | 140 { |
139 /* it's a no-op. */ | 141 /* it's a no-op. */ |
140 } /* VOC_quit */ | 142 } /* VOC_quit */ |
141 | 143 |
142 | 144 |
145 static inline int voc_readbytes(SDL_RWops *src, vs_t *v, void *p, int size) | |
146 { | |
147 if (SDL_RWread(src, p, size, 1) != 1) | |
148 { | |
149 Sound_SetError("VOC: i/o error"); | |
150 v->error = 1; | |
151 return 0; | |
152 } /* if */ | |
153 | |
154 return(1); | |
155 } /* voc_readbytes */ | |
156 | |
157 | |
143 static inline int voc_check_header(SDL_RWops *src) | 158 static inline int voc_check_header(SDL_RWops *src) |
144 { | 159 { |
145 /* VOC magic header */ | 160 /* VOC magic header */ |
146 Uint8 signature[20]; /* "Creative Voice File\032" */ | 161 Uint8 signature[20]; /* "Creative Voice File\032" */ |
147 Uint16 datablockofs; | 162 Uint16 datablockofs; |
148 | 163 vs_t v; /* dummy struct for voc_readbytes */ |
149 if (SDL_RWread(src, signature, sizeof (signature), 1) != 1) | 164 |
165 if (!voc_readbytes(src, &v, signature, sizeof (signature))) | |
150 return(0); | 166 return(0); |
151 | 167 |
152 if (memcmp(signature, "Creative Voice File\032", sizeof (signature)) != 0) { | 168 if (memcmp(signature, "Creative Voice File\032", sizeof (signature)) != 0) |
153 Sound_SetError("Unrecognized file type (not VOC)"); | 169 { |
170 Sound_SetError("VOC: Wrong signature; not a VOC file."); | |
154 return(0); | 171 return(0); |
155 } | 172 } /* if */ |
156 | 173 |
157 /* get the offset where the first datablock is located */ | 174 /* get the offset where the first datablock is located */ |
158 if (SDL_RWread(src, &datablockofs, sizeof (Uint16), 1) != 1) | 175 if (!voc_readbytes(src, &v, &datablockofs, sizeof (Uint16))) |
159 return(0); | 176 return(0); |
160 | 177 |
161 datablockofs = SDL_SwapLE16(datablockofs); | 178 datablockofs = SDL_SwapLE16(datablockofs); |
162 | 179 |
163 if (SDL_RWseek(src, datablockofs, SEEK_SET) != datablockofs) | 180 if (SDL_RWseek(src, datablockofs, SEEK_SET) != datablockofs) |
181 { | |
182 Sound_SetError("VOC: Failed to seek to data block."); | |
164 return(0); | 183 return(0); |
184 } /* if */ | |
165 | 185 |
166 return(1); /* success! */ | 186 return(1); /* success! */ |
167 } /* voc_check_header */ | 187 } /* voc_check_header */ |
168 | 188 |
169 /* !!! FIXME : Add a flag to vs_t that distinguishes EOF and Error conditions. */ | |
170 | 189 |
171 /* Read next block header, save info, leave position at start of data */ | 190 /* Read next block header, save info, leave position at start of data */ |
172 static int voc_get_block(Sound_Sample *sample) | 191 static int voc_get_block(Sound_Sample *sample) |
173 { | 192 { |
174 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | 193 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; |
199 sblen = ( (bits24[0]) | (bits24[1] << 8) | (bits24[2] << 16) ); | 218 sblen = ( (bits24[0]) | (bits24[1] << 8) | (bits24[2] << 16) ); |
200 | 219 |
201 switch(block) | 220 switch(block) |
202 { | 221 { |
203 case VOC_DATA: | 222 case VOC_DATA: |
204 if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1) | 223 if (!voc_readbytes(src, v, &uc, sizeof (uc))) |
205 return 0; | 224 return 0; |
206 | 225 |
207 /* When DATA block preceeded by an EXTENDED */ | 226 /* When DATA block preceeded by an EXTENDED */ |
208 /* block, the DATA blocks rate value is invalid */ | 227 /* block, the DATA blocks rate value is invalid */ |
209 if (!v->extended) | 228 if (!v->extended) |
210 { | 229 { |
211 if (uc == 0) | 230 if (uc == 0) |
212 { | 231 { |
213 Sound_SetError("VOC Sample rate is zero?"); | 232 Sound_SetError("VOC Sample rate is zero?"); |
214 return 0; | 233 return 0; |
215 } | 234 } /* if */ |
216 | 235 |
217 if ((v->rate != -1) && (uc != v->rate)) | 236 if ((v->rate != -1) && (uc != v->rate)) |
218 { | 237 { |
219 Sound_SetError("VOC sample rate codes differ"); | 238 Sound_SetError("VOC sample rate codes differ"); |
220 return 0; | 239 return 0; |
221 } | 240 } /* if */ |
222 | 241 |
223 v->rate = uc; | 242 v->rate = uc; |
224 sample->actual.rate = 1000000.0/(256 - v->rate); | 243 sample->actual.rate = 1000000.0/(256 - v->rate); |
225 v->channels = 1; | 244 v->channels = 1; |
226 } | 245 } /* if */ |
227 | 246 |
228 if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1) | 247 if (!voc_readbytes(src, v, &uc, sizeof (uc))) |
229 return 0; | 248 return 0; |
230 | 249 |
231 if (uc != 0) | 250 if (uc != 0) |
232 { | 251 { |
233 Sound_SetError("VOC decoder only interprets 8-bit data"); | 252 Sound_SetError("VOC decoder only interprets 8-bit data"); |
234 return 0; | 253 return 0; |
235 } | 254 } /* if */ |
236 | 255 |
237 v->extended = 0; | 256 v->extended = 0; |
238 v->rest = sblen - 2; | 257 v->rest = sblen - 2; |
239 v->size = ST_SIZE_BYTE; | 258 v->size = ST_SIZE_BYTE; |
240 return 1; | 259 return 1; |
241 | 260 |
242 case VOC_DATA_16: | 261 case VOC_DATA_16: |
243 if (SDL_RWread(src, &new_rate_long, sizeof (new_rate_long), 1) != 1) | 262 if (!voc_readbytes(src, v, &new_rate_long, sizeof (Uint32))) |
244 return 0; | 263 return 0; |
264 | |
245 new_rate_long = SDL_SwapLE32(new_rate_long); | 265 new_rate_long = SDL_SwapLE32(new_rate_long); |
246 if (new_rate_long == 0) | 266 if (new_rate_long == 0) |
247 { | 267 { |
248 Sound_SetError("VOC Sample rate is zero?"); | 268 Sound_SetError("VOC Sample rate is zero?"); |
249 return 0; | 269 return 0; |
250 } | 270 } /* if */ |
251 if ((v->rate != -1) && (new_rate_long != v->rate)) | 271 if ((v->rate != -1) && (new_rate_long != v->rate)) |
252 { | 272 { |
253 Sound_SetError("VOC sample rate codes differ"); | 273 Sound_SetError("VOC sample rate codes differ"); |
254 return 0; | 274 return 0; |
255 } | 275 } /* if */ |
256 v->rate = new_rate_long; | 276 v->rate = new_rate_long; |
257 sample->actual.rate = new_rate_long; | 277 sample->actual.rate = new_rate_long; |
258 | 278 |
259 if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1) | 279 if (!voc_readbytes(src, v, &uc, sizeof (uc))) |
260 return 0; | 280 return 0; |
261 | 281 |
262 switch (uc) | 282 switch (uc) |
263 { | 283 { |
264 case 8: v->size = ST_SIZE_BYTE; break; | 284 case 8: v->size = ST_SIZE_BYTE; break; |
265 case 16: v->size = ST_SIZE_WORD; break; | 285 case 16: v->size = ST_SIZE_WORD; break; |
266 default: | 286 default: |
267 Sound_SetError("VOC with unknown data size"); | 287 Sound_SetError("VOC with unknown data size"); |
268 return 0; | 288 return 0; |
269 } | 289 } /* switch */ |
270 | 290 |
271 if (SDL_RWread(src, &v->channels, sizeof (Uint8), 1) != 1) | 291 if (!voc_readbytes(src, v, &v->channels, sizeof (Uint8))) |
272 return 0; | 292 return 0; |
273 | 293 |
274 if (SDL_RWread(src, trash, sizeof (Uint8), 6) != 6) | 294 if (!voc_readbytes(src, v, trash, sizeof (Uint8) * 6)) |
275 return 0; | 295 return 0; |
276 | 296 |
277 v->rest = sblen - 12; | 297 v->rest = sblen - 12; |
278 return 1; | 298 return 1; |
279 | 299 |
280 case VOC_CONT: | 300 case VOC_CONT: |
281 v->rest = sblen; | 301 v->rest = sblen; |
282 return 1; | 302 return 1; |
283 | 303 |
284 case VOC_SILENCE: | 304 case VOC_SILENCE: |
285 if (SDL_RWread(src, &period, sizeof (period), 1) != 1) | 305 if (!voc_readbytes(src, v, &period, sizeof (period))) |
286 return 0; | 306 return 0; |
307 | |
287 period = SDL_SwapLE16(period); | 308 period = SDL_SwapLE16(period); |
288 | 309 |
289 if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1) | 310 if (!voc_readbytes(src, v, &uc, sizeof (uc))) |
290 return 0; | 311 return 0; |
312 | |
291 if (uc == 0) | 313 if (uc == 0) |
292 { | 314 { |
293 Sound_SetError("VOC silence sample rate is zero"); | 315 Sound_SetError("VOC silence sample rate is zero"); |
294 return 0; | 316 return 0; |
295 } | 317 } /* if */ |
296 | 318 |
297 /* | 319 /* |
298 * Some silence-packed files have gratuitously | 320 * Some silence-packed files have gratuitously |
299 * different sample rate codes in silence. | 321 * different sample rate codes in silence. |
300 * Adjust period. | 322 * Adjust period. |
309 | 331 |
310 case VOC_LOOP: | 332 case VOC_LOOP: |
311 case VOC_LOOPEND: | 333 case VOC_LOOPEND: |
312 for(i = 0; i < sblen; i++) /* skip repeat loops. */ | 334 for(i = 0; i < sblen; i++) /* skip repeat loops. */ |
313 { | 335 { |
314 if (SDL_RWread(src, trash, sizeof (Uint8), 1) != 1) | 336 if (!voc_readbytes(src, v, trash, sizeof (Uint8))) |
315 return 0; | 337 return 0; |
316 } | 338 } /* for */ |
317 break; | 339 break; |
318 | 340 |
319 case VOC_EXTENDED: | 341 case VOC_EXTENDED: |
320 /* An Extended block is followed by a data block */ | 342 /* An Extended block is followed by a data block */ |
321 /* Set this byte so we know to use the rate */ | 343 /* Set this byte so we know to use the rate */ |
322 /* value from the extended block and not the */ | 344 /* value from the extended block and not the */ |
323 /* data block. */ | 345 /* data block. */ |
324 v->extended = 1; | 346 v->extended = 1; |
325 if (SDL_RWread(src, &new_rate_short, sizeof (new_rate_short), 1) != 1) | 347 if (!voc_readbytes(src, v, &new_rate_short, sizeof (Uint16))) |
326 return 0; | 348 return 0; |
349 | |
327 new_rate_short = SDL_SwapLE16(new_rate_short); | 350 new_rate_short = SDL_SwapLE16(new_rate_short); |
328 if (new_rate_short == 0) | 351 if (new_rate_short == 0) |
329 { | 352 { |
330 Sound_SetError("VOC sample rate is zero"); | 353 Sound_SetError("VOC sample rate is zero"); |
331 return 0; | 354 return 0; |
332 } | 355 } /* if */ |
333 if ((v->rate != -1) && (new_rate_short != v->rate)) | 356 if ((v->rate != -1) && (new_rate_short != v->rate)) |
334 { | 357 { |
335 Sound_SetError("VOC sample rate codes differ"); | 358 Sound_SetError("VOC sample rate codes differ"); |
336 return 0; | 359 return 0; |
337 } | 360 } /* if */ |
338 v->rate = new_rate_short; | 361 v->rate = new_rate_short; |
339 | 362 |
340 if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1) | 363 if (!voc_readbytes(src, v, &uc, sizeof (uc))) |
341 return 0; | 364 return 0; |
342 | 365 |
343 if (uc != 0) | 366 if (uc != 0) |
344 { | 367 { |
345 Sound_SetError("VOC decoder only interprets 8-bit data"); | 368 Sound_SetError("VOC decoder only interprets 8-bit data"); |
346 return 0; | 369 return 0; |
347 } | 370 } /* if */ |
348 | 371 |
349 if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1) | 372 if (!voc_readbytes(src, v, &uc, sizeof (uc))) |
350 return 0; | 373 return 0; |
351 | 374 |
352 if (uc) | 375 if (uc) |
353 sample->actual.channels = 2; /* Stereo */ | 376 sample->actual.channels = 2; /* Stereo */ |
377 | |
354 /* Needed number of channels before finishing | 378 /* Needed number of channels before finishing |
355 compute for rate */ | 379 compute for rate */ |
356 sample->actual.rate = | 380 sample->actual.rate = |
357 (256000000L/(65536L - v->rate)) / sample->actual.channels; | 381 (256000000L/(65536L - v->rate)) / sample->actual.channels; |
358 /* An extended block must be followed by a data */ | 382 /* An extended block must be followed by a data */ |
359 /* block to be valid so loop back to top so it */ | 383 /* block to be valid so loop back to top so it */ |
360 /* can be grabed. */ | 384 /* can be grabed. */ |
361 continue; | 385 continue; |
362 | 386 |
363 case VOC_MARKER: | 387 case VOC_MARKER: |
364 if (SDL_RWread(src, trash, sizeof (Uint8), 2) != 2) | 388 if (!voc_readbytes(src, v, trash, sizeof (Uint8) * 2)) |
365 return 0; | 389 return 0; |
366 | 390 |
367 /* Falling! Falling! */ | 391 /* Falling! Falling! */ |
368 | 392 |
369 default: /* text block or other krapola. */ | 393 default: /* text block or other krapola. */ |
370 for(i = 0; i < sblen; i++) | 394 if (!voc_readbytes(src, v, &trash, sizeof (Uint8) * sblen)) |
371 { | 395 return 0; |
372 if (SDL_RWread(src, &trash, sizeof (Uint8), 1) != 1) | |
373 return 0; | |
374 } | |
375 | 396 |
376 if (block == VOC_TEXT) | 397 if (block == VOC_TEXT) |
377 continue; /* get next block */ | 398 continue; /* get next block */ |
378 } | 399 } /* switch */ |
379 } | 400 } /* while */ |
380 | 401 |
381 return 1; | 402 return 1; |
382 } /* voc_get_block */ | 403 } /* voc_get_block */ |
383 | 404 |
384 | 405 |
416 } /* if */ | 437 } /* if */ |
417 | 438 |
418 else | 439 else |
419 { | 440 { |
420 if (fill_buf) | 441 if (fill_buf) |
442 { | |
421 done = SDL_RWread(src, buf + v->bufpos, 1, max); | 443 done = SDL_RWread(src, buf + v->bufpos, 1, max); |
444 if (done < max) | |
445 { | |
446 Sound_SetError("VOC: i/o error"); | |
447 sample->flags |= SOUND_SAMPLEFLAG_ERROR; | |
448 } /* if */ | |
449 } /* if */ | |
450 | |
422 else | 451 else |
423 { | 452 { |
424 int cur, rc; | 453 int cur, rc; |
425 cur = SDL_RWtell(src); | 454 cur = SDL_RWtell(src); |
426 if (cur >= 0) | 455 if (cur >= 0) |
427 { | 456 { |
428 rc = SDL_RWseek(src, max, SEEK_CUR); | 457 rc = SDL_RWseek(src, max, SEEK_CUR); |
429 if (rc >= 0) | 458 if (rc >= 0) |
430 done = rc - cur; | 459 done = rc - cur; |
460 else | |
461 { | |
462 Sound_SetError("VOC: seek error"); | |
463 sample->flags |= SOUND_SAMPLEFLAG_ERROR; | |
464 } /* else */ | |
431 } /* if */ | 465 } /* if */ |
432 } /* else */ | 466 } /* else */ |
433 | 467 |
434 v->rest -= done; | 468 v->rest -= done; |
435 v->bufpos += done; | 469 v->bufpos += done; |
436 } /* else */ | 470 } /* else */ |
437 | 471 |
438 return done; | 472 return(done); |
439 } /* voc_read_waveform */ | 473 } /* voc_read_waveform */ |
440 | 474 |
441 | 475 |
442 static int VOC_open(Sound_Sample *sample, const char *ext) | 476 static int VOC_open(Sound_Sample *sample, const char *ext) |
443 { | 477 { |
489 | 523 |
490 v->bufpos = 0; | 524 v->bufpos = 0; |
491 while (v->bufpos < internal->buffer_size) | 525 while (v->bufpos < internal->buffer_size) |
492 { | 526 { |
493 Uint32 rc = voc_read_waveform(sample, 1, internal->buffer_size); | 527 Uint32 rc = voc_read_waveform(sample, 1, internal->buffer_size); |
494 if (rc == 0) /* !!! FIXME: Could be an error... */ | 528 if (rc == 0) |
495 { | 529 { |
496 sample->flags |= SOUND_SAMPLEFLAG_EOF; | 530 sample->flags |= (v->error) ? |
531 SOUND_SAMPLEFLAG_ERROR : | |
532 SOUND_SAMPLEFLAG_EOF; | |
497 break; | 533 break; |
498 } /* if */ | 534 } /* if */ |
499 | 535 |
500 if (!voc_get_block(sample)) | 536 if (!voc_get_block(sample)) |
501 { | 537 { |
502 sample->flags |= SOUND_SAMPLEFLAG_ERROR; | 538 sample->flags |= (v->error) ? |
539 SOUND_SAMPLEFLAG_ERROR : | |
540 SOUND_SAMPLEFLAG_EOF; | |
503 break; | 541 break; |
504 } /* if */ | 542 } /* if */ |
505 } /* while */ | 543 } /* while */ |
506 | 544 |
507 return(v->bufpos); | 545 return(v->bufpos); |