From 861d942657dc5f8484f5ed2fad331c1687737346 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 11:03:04 +0900 Subject: [PATCH 01/13] Adding skeleton that at least compiles for audio4.c --- CMakeLists.txt | 4 ++++ src/sound/CMakeLists.txt | 5 +++- src/sound/audio4.c | 51 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/sound/audio4.c diff --git a/CMakeLists.txt b/CMakeLists.txt index fb71553e2..55cbec8b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -144,6 +144,10 @@ else() option(NEW_DYNAREC "Use the PCem v15 (\"new\") dynamic recompiler" OFF) endif() +if((CMAKE_SYSTEM_NAME STREQUAL "NetBSD") OR (CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")) + set(AUDIO4 ON) +endif() + if(WIN32) set(QT ON) option(CPPTHREADS "C++11 threads" OFF) diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index a381051ba..955e96f5a 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -53,7 +53,10 @@ add_library(snd OBJECT snd_opl_esfm.c ) -if(OPENAL) +# TODO: Should platform-specific audio driver be here? +if(AUDIO4) + target_sources(snd PRIVATE audio4.c) +elseif(OPENAL) if(VCPKG_TOOLCHAIN) find_package(OpenAL CONFIG REQUIRED) elseif(MINGW) diff --git a/src/sound/audio4.c b/src/sound/audio4.c new file mode 100644 index 000000000..3b3d4a429 --- /dev/null +++ b/src/sound/audio4.c @@ -0,0 +1,51 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Interface to audio(4). + * + * + * + * Authors: Nishi + * + * Copyright 2025 Nishi. + */ +#include + +#include <86box/sound.h> + +#define FREQ SOUND_FREQ +#define BUFLEN SOUNDBUFLEN + +static int midi_freq = 44100; +static int midi_buf_size = 4410; + +void closeal(void){ +} + +void inital(void){ +} + +void givealbuffer(const void *buf){ +} + +void givealbuffer_music(const void *buf){ +} + +void givealbuffer_wt(const void *buf){ +} + +void givealbuffer_cd(const void *buf){ +} + +void givealbuffer_midi(const void *buf, const uint32_t size){ +} + +void al_set_midi(const int freq, const int buf_size){ + midi_freq = freq; + midi_buf_size = buf_size; +} From 7056c83bbb7c444fbdb55ea4a51382f77d7faa36 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 17:41:04 +0900 Subject: [PATCH 02/13] Add working NetBSD sound support --- src/sound/audio4.c | 104 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 94 insertions(+), 10 deletions(-) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index 3b3d4a429..e7b7dcf33 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -6,8 +6,8 @@ * * This file is part of the 86Box distribution. * - * Interface to audio(4). - * + * Interface to audio(4) for NetBSD/OpenBSD. + * TODO: Test on OpenBSD * * * Authors: Nishi @@ -15,37 +15,121 @@ * Copyright 2025 Nishi. */ #include +#include +#include +#include +#include +#include +#include +#include +#include + +#include <86box/86box.h> #include <86box/sound.h> +#include <86box/plat_unused.h> -#define FREQ SOUND_FREQ -#define BUFLEN SOUNDBUFLEN +#define I_NORMAL 0 +#define I_MUSIC 1 +#define I_WT 2 +#define I_CD 3 +#define I_MIDI 4 -static int midi_freq = 44100; -static int midi_buf_size = 4410; +static int audio[5] = {-1, -1, -1, -1, -1}; +static audio_offset_t offset[5]; +static audio_info_t info[5]; +static int freqs[5] = {SOUND_FREQ, MUSIC_FREQ, WT_FREQ, CD_FREQ, 0}; void closeal(void){ + int i; + for(i = 0; i < sizeof(audio) / sizeof(audio[0]); i++){ + if(audio[i] != -1){ + close(audio[i]); + } + audio[i] = -1; + } } void inital(void){ + int i; + for(i = 0; i < sizeof(audio) / sizeof(audio[0]); i++){ + audio[i] = open("/dev/audio", O_WRONLY); + if(audio[i] != -1){ + AUDIO_INITINFO(&info[i]); +#if defined(__NetBSD__) && (__NetBSD_Version__ >= 900000000) + ioctl(audio[i], AUDIO_GETFORMAT, &info[i]); +#else + ioctl(audio[i], AUDIO_GETINFO, &info[i]); +#endif + info[i].play.channels = 2; + info[i].play.precision = 16; + info[i].play.encoding = AUDIO_ENCODING_SLINEAR; + info[i].hiwat = 5; + info[i].lowat = 3; + ioctl(audio[i], AUDIO_SETINFO, &info[i]); + } + } +} + +void givealbuffer_common(const void *buf, const uint8_t src, const int size){ + const int freq = freqs[src]; + int16_t* output; + int output_size; + int16_t* conv; + int conv_size; + int i; + double gain; + if(audio[src] == -1) return; + + gain = sound_muted ? 0.0 : pow(10.0, (double) sound_gain / 20.0); + + if(sound_is_float){ + float* input = (float*)buf; + conv_size = sizeof(int16_t) * size; + conv = malloc(conv_size); + for(i = 0; i < conv_size / sizeof(int16_t); i++){ + conv[i] = 32767 * input[i]; + } + }else{ + conv_size = size * sizeof(int16_t); + conv = malloc(conv_size); + memcpy(conv, buf, conv_size); + } + + output_size = (double)conv_size * info[src].play.sample_rate / freq; + output = malloc(output_size); + + for(i = 0; i < output_size / sizeof(int16_t) / 2; i++){ + int ind = i * freq / info[src].play.sample_rate * 2; + output[i * 2 + 0] = conv[ind + 0] * gain; + output[i * 2 + 1] = conv[ind + 1] * gain; + } + + write(audio[src], output, output_size); + + free(conv); + free(output); } void givealbuffer(const void *buf){ + givealbuffer_common(buf, I_NORMAL, SOUNDBUFLEN << 1); } void givealbuffer_music(const void *buf){ + givealbuffer_common(buf, I_MUSIC, MUSICBUFLEN << 1); } void givealbuffer_wt(const void *buf){ + givealbuffer_common(buf, I_WT, WTBUFLEN << 1); } void givealbuffer_cd(const void *buf){ + givealbuffer_common(buf, I_CD, CD_BUFLEN << 1); } - void givealbuffer_midi(const void *buf, const uint32_t size){ + givealbuffer_common(buf, I_MIDI, (int) size); } -void al_set_midi(const int freq, const int buf_size){ - midi_freq = freq; - midi_buf_size = buf_size; +void al_set_midi(const int freq, UNUSED(const int buf_size)){ + freqs[I_MIDI] = freq; } From f287ee4fd0f96945c85feb0dd5085ef6129a223e Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 18:20:05 +0900 Subject: [PATCH 03/13] Check OpenBSD version and use newer API if needed --- src/sound/audio4.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index e7b7dcf33..ebea8a08f 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -29,6 +29,10 @@ #include <86box/sound.h> #include <86box/plat_unused.h> +#if defined(OpenBSD) && OpenBSD >= 201709 +#define USE_NEW_API +#endif + #define I_NORMAL 0 #define I_MUSIC 1 #define I_WT 2 @@ -36,8 +40,11 @@ #define I_MIDI 4 static int audio[5] = {-1, -1, -1, -1, -1}; -static audio_offset_t offset[5]; +#ifdef USE_NEW_API +static struct audio_swpar info[5]; +#else static audio_info_t info[5]; +#endif static int freqs[5] = {SOUND_FREQ, MUSIC_FREQ, WT_FREQ, CD_FREQ, 0}; void closeal(void){ @@ -55,6 +62,14 @@ void inital(void){ for(i = 0; i < sizeof(audio) / sizeof(audio[0]); i++){ audio[i] = open("/dev/audio", O_WRONLY); if(audio[i] != -1){ +#ifdef USE_NEW_API + AUDIO_INITPAR(&info[i]); + ioctl(audio[i], AUDIO_GETPAR, &info[i]); + info[i].pchan = 2; + info[i].bits = 16; + info[i].bps = 2; + ioctl(audio[i], AUDIO_SETPAR, &info[i]); +#else AUDIO_INITINFO(&info[i]); #if defined(__NetBSD__) && (__NetBSD_Version__ >= 900000000) ioctl(audio[i], AUDIO_GETFORMAT, &info[i]); @@ -67,6 +82,7 @@ void inital(void){ info[i].hiwat = 5; info[i].lowat = 3; ioctl(audio[i], AUDIO_SETINFO, &info[i]); +#endif } } } From ad655ab40c3b3d7115ae719cb985fa9333831341 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 18:55:37 +0900 Subject: [PATCH 04/13] Forgot to add newer API support in conversion part --- src/sound/audio4.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index ebea8a08f..18606f9ce 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -112,11 +112,19 @@ void givealbuffer_common(const void *buf, const uint8_t src, const int size){ memcpy(conv, buf, conv_size); } +#ifdef USE_NEW_API + output_size = (double)conv_size * info[src].rate / freq; +#else output_size = (double)conv_size * info[src].play.sample_rate / freq; +#endif output = malloc(output_size); for(i = 0; i < output_size / sizeof(int16_t) / 2; i++){ +#ifdef USE_NEW_API + int ind = i * freq / info[src].rate * 2; +#else int ind = i * freq / info[src].play.sample_rate * 2; +#endif output[i * 2 + 0] = conv[ind + 0] * gain; output[i * 2 + 1] = conv[ind + 1] * gain; } From 090b9d988a3efa0fa256a0c3b0bcb378dc9457f3 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 18:57:36 +0900 Subject: [PATCH 05/13] Include string.h for memory operations --- src/sound/audio4.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index 18606f9ce..fe1b8192d 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include From 8daed4c70c4c8274d1bb06231443c2c23a994a2a Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 19:03:36 +0900 Subject: [PATCH 06/13] OpenBSD needs stdarg.h --- src/include/86box/86box.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index e8c5fbac9..c58d595c5 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -20,8 +20,8 @@ #ifndef EMU_86BOX_H #define EMU_86BOX_H -#ifdef __NetBSD__ -/* Doesn't compile on NetBSD without this include */ +#if defined(__NetBSD__) || defined(__OpenBSD__) +/* Doesn't compile on NetBSD/OpenBSD without this include */ #include #endif From ef194e003e921edc2879317bbb22ecc662d0b3fc Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 19:29:37 +0900 Subject: [PATCH 07/13] Check /dev/audio0 too --- src/sound/audio4.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index fe1b8192d..2458f78c6 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -62,6 +62,7 @@ void inital(void){ int i; for(i = 0; i < sizeof(audio) / sizeof(audio[0]); i++){ audio[i] = open("/dev/audio", O_WRONLY); + if(audio[i] != -1) audio[i] = open("/dev/audio0", O_WRONLY); if(audio[i] != -1){ #ifdef USE_NEW_API AUDIO_INITPAR(&info[i]); From e023a046bb597f292ab761df2191802474160182 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 19:37:15 +0900 Subject: [PATCH 08/13] Wrong comparison --- src/sound/audio4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index 2458f78c6..fb98594e6 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -62,7 +62,7 @@ void inital(void){ int i; for(i = 0; i < sizeof(audio) / sizeof(audio[0]); i++){ audio[i] = open("/dev/audio", O_WRONLY); - if(audio[i] != -1) audio[i] = open("/dev/audio0", O_WRONLY); + if(audio[i] == -1) audio[i] = open("/dev/audio0", O_WRONLY); if(audio[i] != -1){ #ifdef USE_NEW_API AUDIO_INITPAR(&info[i]); From e4fb39d9441a127ae5fdcbdf571dcb31a06e91bc Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 19:38:49 +0900 Subject: [PATCH 09/13] Remove TODO message --- src/sound/audio4.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index fb98594e6..8428b3c93 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -7,7 +7,6 @@ * This file is part of the 86Box distribution. * * Interface to audio(4) for NetBSD/OpenBSD. - * TODO: Test on OpenBSD * * * Authors: Nishi From c135dddfa998c66cb71d6fff004b0f6730e94921 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 19:51:45 +0900 Subject: [PATCH 10/13] Use option instead of set in CMake --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 55cbec8b0..aafa46b1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -145,7 +145,9 @@ else() endif() if((CMAKE_SYSTEM_NAME STREQUAL "NetBSD") OR (CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")) - set(AUDIO4 ON) + option(AUDIO4 "Use audio(4) as sound backend" ON) +else() + set(AUDIO4 OFF) endif() if(WIN32) From 16a6ab3f95b187ca829dd21ffb17d698eaece1dc Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 20:35:41 +0900 Subject: [PATCH 11/13] Fix music frequency conversion bug --- src/sound/audio4.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index 8428b3c93..ad8b3ce82 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -96,6 +96,7 @@ void givealbuffer_common(const void *buf, const uint8_t src, const int size){ int conv_size; int i; double gain; + int target_rate; if(audio[src] == -1) return; gain = sound_muted ? 0.0 : pow(10.0, (double) sound_gain / 20.0); @@ -114,18 +115,18 @@ void givealbuffer_common(const void *buf, const uint8_t src, const int size){ } #ifdef USE_NEW_API - output_size = (double)conv_size * info[src].rate / freq; + target_rate = info[src].rate; #else - output_size = (double)conv_size * info[src].play.sample_rate / freq; + target_rate = info[src].play.sample_rate; #endif + + output_size = (double)conv_size * target_rate / freq; + output_size -= output_size % 2; output = malloc(output_size); for(i = 0; i < output_size / sizeof(int16_t) / 2; i++){ -#ifdef USE_NEW_API - int ind = i * freq / info[src].rate * 2; -#else - int ind = i * freq / info[src].play.sample_rate * 2; -#endif + int ind = i * freq / target_rate * 2; + ind -= ind % 2; output[i * 2 + 0] = conv[ind + 0] * gain; output[i * 2 + 1] = conv[ind + 1] * gain; } From fefcd530ab86dbb2143e01b8d0ae1117bccf6794 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 20:37:46 +0900 Subject: [PATCH 12/13] Remove the part that was not required --- src/sound/audio4.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index ad8b3ce82..2bad30144 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -126,7 +126,6 @@ void givealbuffer_common(const void *buf, const uint8_t src, const int size){ for(i = 0; i < output_size / sizeof(int16_t) / 2; i++){ int ind = i * freq / target_rate * 2; - ind -= ind % 2; output[i * 2 + 0] = conv[ind + 0] * gain; output[i * 2 + 1] = conv[ind + 1] * gain; } From c92d56261a38aed2e95c1445192763e540a7e244 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 20:44:29 +0900 Subject: [PATCH 13/13] Do mod4 instead of mod2, so it can keep the output channel correct --- src/sound/audio4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index 2bad30144..32989eecf 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -121,7 +121,7 @@ void givealbuffer_common(const void *buf, const uint8_t src, const int size){ #endif output_size = (double)conv_size * target_rate / freq; - output_size -= output_size % 2; + output_size -= output_size % 4; output = malloc(output_size); for(i = 0; i < output_size / sizeof(int16_t) / 2; i++){