comparison decoders/voc.c @ 335:f6475949cd59

Implemented seek method.
author Ryan C. Gordon <icculus@icculus.org>
date Mon, 20 May 2002 12:11:55 +0000
parents c97be6e1bd27
children cbb15ecf423a
comparison
equal deleted inserted replaced
334:f0f894d897bf 335:f6475949cd59
378 continue; /* get next block */ 378 continue; /* get next block */
379 } 379 }
380 } 380 }
381 381
382 return 1; 382 return 1;
383 } 383 } /* voc_get_block */
384 384
385 385
386 static int voc_read_waveform(Sound_Sample *sample) 386 static int voc_read_waveform(Sound_Sample *sample, int fill_buf, Uint32 max)
387 { 387 {
388 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; 388 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
389 SDL_RWops *src = internal->rw; 389 SDL_RWops *src = internal->rw;
390 vs_t *v = (vs_t *) internal->decoder_private; 390 vs_t *v = (vs_t *) internal->decoder_private;
391 int done = 0; 391 int done = 0;
394 394
395 if (v->rest == 0) 395 if (v->rest == 0)
396 { 396 {
397 if (!voc_get_block(sample)) 397 if (!voc_get_block(sample))
398 return 0; 398 return 0;
399 } 399 } /* if */
400 400
401 if (v->rest == 0) 401 if (v->rest == 0)
402 return 0; 402 return 0;
403 403
404 max = (v->rest < max) ? v->rest : max;
405
404 if (v->silent) 406 if (v->silent)
405 { 407 {
406 if (v->size == ST_SIZE_WORD) 408 if (v->size == ST_SIZE_WORD)
407 silence = 0x00; 409 silence = 0x00;
408 410
409 /* Fill in silence */ 411 /* Fill in silence */
410 memset(buf, silence, v->rest); 412 if (fill_buf)
411 done = v->rest; 413 memset(buf + v->bufpos, silence, max);
412 v->rest = 0; 414
413 } 415 done = max;
416 v->rest -= done;
417 } /* if */
414 418
415 else 419 else
416 { 420 {
417 Uint32 max = (v->rest < internal->buffer_size) ? 421 if (fill_buf)
418 v->rest : internal->buffer_size; 422 done = SDL_RWread(src, buf + v->bufpos, 1, max);
419 done = SDL_RWread(src, buf + v->bufpos, 1, max); 423 else
424 {
425 int cur, rc;
426 cur = SDL_RWtell(src);
427 if (cur >= 0)
428 {
429 rc = SDL_RWseek(src, max, SEEK_CUR);
430 if (rc >= 0)
431 done = rc - cur;
432 } /* if */
433 } /* else */
434
420 v->rest -= done; 435 v->rest -= done;
421 v->bufpos += done; 436 v->bufpos += done;
422 } 437 } /* else */
423 438
424 return done; 439 return done;
425 } /* voc_read_waveform */ 440 } /* voc_read_waveform */
426 441
427 442
454 } /* if */ 469 } /* if */
455 470
456 SNDDBG(("VOC: Accepting data stream.\n")); 471 SNDDBG(("VOC: Accepting data stream.\n"));
457 sample->actual.format = (v->size == ST_SIZE_WORD) ? AUDIO_S16LSB:AUDIO_U8; 472 sample->actual.format = (v->size == ST_SIZE_WORD) ? AUDIO_S16LSB:AUDIO_U8;
458 sample->actual.channels = v->channels; 473 sample->actual.channels = v->channels;
459 sample->flags = SOUND_SAMPLEFLAG_NONE; 474 sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
460 return(1); 475 return(1);
461 } /* VOC_open */ 476 } /* VOC_open */
462 477
463 478
464 static void VOC_close(Sound_Sample *sample) 479 static void VOC_close(Sound_Sample *sample)
474 vs_t *v = (vs_t *) internal->decoder_private; 489 vs_t *v = (vs_t *) internal->decoder_private;
475 490
476 v->bufpos = 0; 491 v->bufpos = 0;
477 while (v->bufpos < internal->buffer_size) 492 while (v->bufpos < internal->buffer_size)
478 { 493 {
479 Uint32 rc = voc_read_waveform(sample); 494 Uint32 rc = voc_read_waveform(sample, 1, internal->buffer_size);
480 if (rc == 0) /* !!! FIXME: Could be an error... */ 495 if (rc == 0) /* !!! FIXME: Could be an error... */
481 { 496 {
482 sample->flags |= SOUND_SAMPLEFLAG_EOF; 497 sample->flags |= SOUND_SAMPLEFLAG_EOF;
483 break; 498 break;
484 } /* if */ 499 } /* if */
505 } /* VOC_rewind */ 520 } /* VOC_rewind */
506 521
507 522
508 static int VOC_seek(Sound_Sample *sample, Uint32 ms) 523 static int VOC_seek(Sound_Sample *sample, Uint32 ms)
509 { 524 {
510 BAIL_MACRO("!!! FIXME: Not implemented", 0); 525 /*
526 * VOCs don't lend themselves well to seeking, since you have to
527 * parse each section, which is an arbitrary size. The best we can do
528 * is rewind, set a flag saying not to write the waveforms to a buffer,
529 * and decode to the point that we want. Ugh. Fortunately, there's
530 * really no such thing as a large VOC, due to the era and hardware that
531 * spawned them, so even though this is inefficient, this is still a
532 * relatively fast operation in most cases.
533 */
534
535 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
536 vs_t *v = (vs_t *) internal->decoder_private;
537 int offset = __Sound_convertMsToBytePos(&sample->actual, ms);
538 int origpos = SDL_RWtell(internal->rw);
539 int origrest = v->rest;
540
541 BAIL_IF_MACRO(!VOC_rewind(sample), NULL, 0);
542
543 v->bufpos = 0;
544
545 while (offset > 0)
546 {
547 Uint32 rc = voc_read_waveform(sample, 0, offset);
548 if ( (rc == 0) || (!voc_get_block(sample)) )
549 {
550 SDL_RWseek(internal->rw, origpos, SEEK_SET);
551 v->rest = origrest;
552 return(0);
553 } /* if */
554
555 offset -= rc;
556 } /* while */
557
558 return(1);
511 } /* VOC_seek */ 559 } /* VOC_seek */
512 560
513
514 #endif /* SOUND_SUPPORTS_VOC */ 561 #endif /* SOUND_SUPPORTS_VOC */
515 562
516 /* end of voc.c ... */ 563 /* end of voc.c ... */