Mercurial > repos > blastem
comparison mediaplayer.c @ 2290:c4980d89614b
Support WAVE files in media player
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 04 Feb 2023 23:31:11 -0800 |
parents | 92449b47cce8 |
children | 789802d99629 |
comparison
equal
deleted
inserted
replaced
2289:92449b47cce8 | 2290:c4980d89614b |
---|---|
408 } | 408 } |
409 } | 409 } |
410 | 410 |
411 void wave_frame(media_player *player) | 411 void wave_frame(media_player *player) |
412 { | 412 { |
413 render_sleep_ms(15); | 413 for (uint32_t remaining_samples = player->wave->sample_rate / 60; remaining_samples > 0; remaining_samples--) |
414 { | |
415 uint32_t sample_size = player->wave->bits_per_sample * player->wave->num_channels / 8; | |
416 if (sample_size > player->media->size || player->current_offset > player->media->size - sample_size) { | |
417 player->current_offset = player->wave->format_header.size + offsetof(wave_header, audio_format); | |
418 player->state = STATE_PAUSED; | |
419 return; | |
420 } | |
421 if (player->wave->bits_per_sample == 16) { | |
422 int16_t value = read_word_le(player); | |
423 if (player->wave->num_channels == 1) { | |
424 render_put_mono_sample(player->audio, value); | |
425 } else { | |
426 int16_t right = read_word_le(player); | |
427 render_put_stereo_sample(player->audio, value, right); | |
428 } | |
429 } else { | |
430 uint8_t sample = read_byte(player); | |
431 int16_t value = sample * 257 - 128 * 257; | |
432 if (player->wave->num_channels == 1) { | |
433 render_put_mono_sample(player->audio, value); | |
434 } else { | |
435 sample = read_byte(player); | |
436 int16_t right = sample * 257 - 128 * 257; | |
437 render_put_stereo_sample(player->audio, value, right); | |
438 } | |
439 } | |
440 | |
441 } | |
414 } | 442 } |
415 | 443 |
416 void flac_frame(media_player *player) | 444 void flac_frame(media_player *player) |
417 { | 445 { |
418 render_sleep_ms(15); | 446 render_sleep_ms(15); |
509 }; | 537 }; |
510 } | 538 } |
511 player->current_offset = player->vgm->data_offset + offsetof(vgm_header, data_offset); | 539 player->current_offset = player->vgm->data_offset + offsetof(vgm_header, data_offset); |
512 } | 540 } |
513 | 541 |
542 static void wave_player_init(media_player *player) | |
543 { | |
544 player->wave = calloc(1, sizeof(wave_header)); | |
545 memcpy(player->wave, player->media->buffer, offsetof(wave_header, data_header)); | |
546 if (memcmp(player->wave->chunk.format, "WAVE", 4)) { | |
547 goto format_error; | |
548 } | |
549 if (player->wave->chunk.size < offsetof(wave_header, data_header)) { | |
550 goto format_error; | |
551 } | |
552 if (memcmp(player->wave->format_header.id, "fmt ", 4)) { | |
553 goto format_error; | |
554 } | |
555 if (player->wave->format_header.size < offsetof(wave_header, data_header) - offsetof(wave_header, audio_format)) { | |
556 goto format_error; | |
557 } | |
558 if (player->wave->bits_per_sample != 8 && player->wave->bits_per_sample != 16) { | |
559 goto format_error; | |
560 } | |
561 uint32_t data_sub_chunk = player->wave->format_header.size + offsetof(wave_header, audio_format); | |
562 if (data_sub_chunk > player->media->size || player->media->size - data_sub_chunk < sizeof(riff_sub_chunk)) { | |
563 goto format_error; | |
564 } | |
565 memcpy(&player->wave->data_header, ((uint8_t *)player->media->buffer) + data_sub_chunk, sizeof(riff_sub_chunk)); | |
566 player->current_offset = data_sub_chunk; | |
567 player->audio = render_audio_source("Audio File", player->wave->sample_rate, 1, player->wave->num_channels); | |
568 return; | |
569 format_error: | |
570 player->media_type = MEDIA_UNKNOWN; | |
571 free(player->wave); | |
572 } | |
573 | |
514 static void resume_player(system_header *system) | 574 static void resume_player(system_header *system) |
515 { | 575 { |
516 media_player *player = (media_player *)system; | 576 media_player *player = (media_player *)system; |
517 player->should_return = 0; | 577 player->should_return = 0; |
518 while (!player->header.should_exit && !player->should_return) | 578 while (!player->header.should_exit && !player->should_return) |
587 return MEDIA_UNKNOWN; | 647 return MEDIA_UNKNOWN; |
588 } | 648 } |
589 return AUDIO_VGM; | 649 return AUDIO_VGM; |
590 } | 650 } |
591 if (!memcmp(media->buffer, "RIFF", 4)) { | 651 if (!memcmp(media->buffer, "RIFF", 4)) { |
652 if (media->size < sizeof(wave_header)) { | |
653 return MEDIA_UNKNOWN; | |
654 } | |
592 return AUDIO_WAVE; | 655 return AUDIO_WAVE; |
593 } | 656 } |
594 if (!memcmp(media->buffer, "fLaC", 4)) { | 657 if (!memcmp(media->buffer, "fLaC", 4)) { |
595 return AUDIO_FLAC; | 658 return AUDIO_FLAC; |
596 } | 659 } |
621 switch (player->media_type) | 684 switch (player->media_type) |
622 { | 685 { |
623 case AUDIO_VGM: | 686 case AUDIO_VGM: |
624 vgm_init(player, opts); | 687 vgm_init(player, opts); |
625 break; | 688 break; |
689 case AUDIO_WAVE: | |
690 wave_player_init(player); | |
691 break; | |
626 } | 692 } |
627 | 693 |
628 return player; | 694 return player; |
629 } | 695 } |