From d4607b18aadb5ec044c628856be6d99dd131e93d Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 5 Jul 2024 16:28:01 +0600 Subject: [PATCH] libsndfile support --- src/cdrom/CMakeLists.txt | 8 +++ src/cdrom/cdrom_image_backend.c | 95 +++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) diff --git a/src/cdrom/CMakeLists.txt b/src/cdrom/CMakeLists.txt index d3b38095e7a..f2acce4e2e0 100644 --- a/src/cdrom/CMakeLists.txt +++ b/src/cdrom/CMakeLists.txt @@ -13,4 +13,12 @@ # Copyright 2020-2021 David Hrdlička. # +find_package(PkgConfig REQUIRED) + +pkg_check_modules(SNDFILE REQUIRED IMPORTED_TARGET sndfile) + add_library(cdrom OBJECT cdrom.c cdrom_image_backend.c cdrom_image_viso.c cdrom_image.c cdrom_ioctl.c cdrom_mitsumi.c) +target_link_libraries(86Box PkgConfig::SNDFILE) +if (WIN32) + target_link_libraries(86Box -static ${SNDFILE_STATIC_LIBRARIES}) +endif() diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index 9ce78e5b493..e7373a3199f 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -40,6 +40,8 @@ #include <86box/plat.h> #include <86box/cdrom_image_backend.h> +#include + #define CDROM_BCD(x) (((x) % 10) | (((x) / 10) << 4)) #define MAX_LINE_LENGTH 512 @@ -66,6 +68,96 @@ cdrom_image_backend_log(const char *fmt, ...) # define cdrom_image_backend_log(fmt, ...) #endif +typedef struct audio_file { + SNDFILE *file; + SF_INFO info; +} audio_file; + +/* Audio file functions */ +static int +audio_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count) +{ + track_file_t *tf = (track_file_t*)priv; + audio_file *audio = (audio_file*)tf->priv; + uint64_t samples_seek = seek / 4; + uint64_t samples_count = count / 4; + + if ((seek & 3) || (count & 3)) { + pclog("Reading on non-4-aligned boundaries\n"); + } + + sf_count_t res = sf_seek(audio->file, seek, SEEK_SET); + + if (res == -1) + return 0; + + return !!sf_readf_short(audio->file, (short*)buffer, samples_count); +} + +static uint64_t +audio_get_length(void *priv) +{ + track_file_t *tf = (track_file_t*)priv; + audio_file *audio = (audio_file*)tf->priv; + + return audio->info.frames * 4ull; +} + +static void +audio_close(void *priv) +{ + track_file_t *tf = (track_file_t*)priv; + audio_file *audio = (audio_file*)tf->priv; + + memset(tf->fn, 0x00, sizeof(tf->fn)); + if (audio && audio->file) + sf_close(audio->file); + free(audio); + free(tf); +} + +static track_file_t * +audio_init(const char *filename, int *error) +{ + track_file_t *tf = (track_file_t *) calloc(sizeof(track_file_t), 1); + audio_file *audio = (audio_file*) calloc(sizeof(audio_file), 1); +#ifdef _WIN32 + wchar_t filename_w[4096]; +#endif + + if (tf == NULL || audio == NULL) { + free(tf); + free(audio); + *error = 1; + return NULL; + } + + memset(tf->fn, 0x00, sizeof(tf->fn)); + strncpy(tf->fn, filename, sizeof(tf->fn) - 1); +#ifdef _WIN32 + mbstowcs(filename_w, filename, 4096); + audio->file = sf_wchar_open(filename_w, SFM_READ, &audio->info); +#else + audio->file = sf_open(filename, SFM_READ, &audio->info); +#endif + + if (!audio->file) { + goto cleanup_error; + } + + if (audio->info.channels != 2 || audio->info.samplerate != 44100) { + sf_close(audio->file); + goto cleanup_error; + } + + return tf; +cleanup_error: + free(tf); + free(audio); + *error = 1; + return NULL; +} + /* Binary file functions. */ static int bin_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count) @@ -995,6 +1087,9 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) if (!strcmp(type, "BINARY")) { path_append_filename(filename, pathname, ansi); trk.file = track_file_init(filename, &error); + } else if (!strcmp(type, "WAVE")) { + path_append_filename(filename, pathname, ansi); + trk.file = audio_init(filename, &error); } if (error) { #ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG