Merge branch 'master' into more-updates

This commit is contained in:
Jasmine Iwanek
2022-02-19 23:39:55 -05:00
20 changed files with 518 additions and 106 deletions

View File

@@ -298,6 +298,9 @@ EOF
# Link against the system libslirp instead of compiling ours. # Link against the system libslirp instead of compiling ours.
cmake_flags_extra="$cmake_flags_extra -D SLIRP_EXTERNAL=ON" cmake_flags_extra="$cmake_flags_extra -D SLIRP_EXTERNAL=ON"
# Use OpenAL for Linux builds before FAudio builds are set up.
cmake_flags_extra="$cmake_flags_extra -D OPENAL=ON"
fi fi
# Clean workspace. # Clean workspace.

View File

@@ -32,3 +32,7 @@ indent_size = 4
[*.cmake] [*.cmake]
indent_style = space indent_style = space
indent_size = 4 indent_size = 4
[*.json]
indent_style = space
indent_size = 4

View File

@@ -252,7 +252,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Install dependencies - name: Install dependencies
run: sudo apt update && sudo apt install gcc-11 g++-11 libfreetype-dev libsdl2-dev libpng-dev libopenal-dev libc6-dev librtmidi-dev qtbase5-dev qttools5-dev run: sudo apt update && sudo apt install gcc-11 g++-11 libfreetype-dev libsdl2-dev libpng-dev libopenal-dev libc6-dev librtmidi-dev qtbase5-dev qttools5-dev libfaudio-dev
- name: Configure CMake - name: Configure CMake
run: >- run: >-
cmake -S . -B build cmake -S . -B build
@@ -316,7 +316,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Install dependencies - name: Install dependencies
run: brew install freetype sdl2 libpng openal-soft rtmidi qt@5 run: brew install freetype sdl2 libpng openal-soft rtmidi qt@5 faudio
- name: Configure CMake - name: Configure CMake
run: >- run: >-
cmake -S . -B build cmake -S . -B build

View File

@@ -114,7 +114,7 @@ set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
# ------ ----------- ---- # ------ ----------- ----
option(RELEASE "Release build" OFF) option(RELEASE "Release build" OFF)
option(DYNAREC "Dynamic recompiler" ON) option(DYNAREC "Dynamic recompiler" ON)
option(OPENAL "OpenAL" ON) option(OPENAL "OpenAL" OFF)
option(FLUIDSYNTH "FluidSynth" ON) option(FLUIDSYNTH "FluidSynth" ON)
option(MUNT "MUNT" ON) option(MUNT "MUNT" ON)
option(DINPUT "DirectInput" OFF) option(DINPUT "DirectInput" OFF)

View File

@@ -941,9 +941,7 @@ pc_reset_hard_close(void)
scsi_disk_close(); scsi_disk_close();
#ifdef USE_OPENAL
closeal(); closeal();
#endif
video_reset_close(); video_reset_close();

View File

@@ -43,7 +43,7 @@ if(VNC)
add_compile_definitions(USE_VNC) add_compile_definitions(USE_VNC)
add_library(vnc OBJECT vnc.c vnc_keymap.c) add_library(vnc OBJECT vnc.c vnc_keymap.c)
target_link_libraries(86Box vnc vncserver) target_link_libraries(86Box vnc vncserver)
if (WIN32) if(WIN32)
target_link_libraries(86Box ws2_32) target_link_libraries(86Box ws2_32)
endif() endif()
endif() endif()
@@ -86,23 +86,6 @@ if(APPLE)
target_link_libraries(86Box Freetype::Freetype) target_link_libraries(86Box Freetype::Freetype)
endif() endif()
if(OPENAL)
if(VCPKG_TOOLCHAIN)
find_package(OpenAL CONFIG REQUIRED)
elseif(MINGW)
find_package(OpenAL MODULE REQUIRED)
else()
find_package(OpenAL REQUIRED)
endif()
if(TARGET OpenAL::OpenAL)
target_link_libraries(86Box OpenAL::OpenAL)
else()
include_directories(${OPENAL_INCLUDE_DIR})
target_link_libraries(86Box ${OPENAL_LIBRARY})
endif()
endif()
find_package(SDL2 REQUIRED) find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS}) include_directories(${SDL2_INCLUDE_DIRS})
if(STATIC_BUILD AND TARGET SDL2::SDL2-static) if(STATIC_BUILD AND TARGET SDL2::SDL2-static)

View File

@@ -204,6 +204,7 @@ extern void thread_destroy_event(event_t *arg);
extern mutex_t *thread_create_mutex(void); extern mutex_t *thread_create_mutex(void);
extern void thread_close_mutex(mutex_t *arg); extern void thread_close_mutex(mutex_t *arg);
extern int thread_test_mutex(mutex_t *arg);
extern int thread_wait_mutex(mutex_t *arg); extern int thread_wait_mutex(mutex_t *arg);
extern int thread_release_mutex(mutex_t *mutex); extern int thread_release_mutex(mutex_t *mutex);

106
src/include/FAudio_compat.h Normal file
View File

@@ -0,0 +1,106 @@
/* map xaudio2 API to faudio API */
typedef uint32_t HRESULT;
typedef uint32_t UINT32;
typedef uint32_t DWORD;
typedef uint8_t BOOL;
#define WINAPI FAUDIOCALL
#define TRUE 1
#define FALSE 0
#define S_OK 0
#define XAUDIO2_E_INVALID_CALL FAUDIO_E_INVALID_CALL
#define XAUDIO2_DEFAULT_PROCESSOR FAUDIO_DEFAULT_PROCESSOR
#define XAUDIO2_COMMIT_NOW FAUDIO_COMMIT_NOW
#define XAUDIO2_END_OF_STREAM FAUDIO_END_OF_STREAM
#define WAVE_FORMAT_PCM FAUDIO_FORMAT_PCM
#define WAVE_FORMAT_IEEE_FLOAT FAUDIO_FORMAT_IEEE_FLOAT
#define AudioCategory_GameEffects FAudioStreamCategory_GameEffects
#define GlobalDefaultDevice FAudioGlobalDefaultDevice
#define NotDefaultDevice FAudioNotDefaultDevice
#define XAudio2Create FAudioCreate
typedef FAudioBuffer XAUDIO2_BUFFER;
typedef FAudioDeviceDetails XAUDIO2_DEVICE_DETAILS;
typedef FAudioEffectChain XAUDIO2_EFFECT_CHAIN;
typedef FAudioEffectDescriptor XAUDIO2_EFFECT_DESCRIPTOR;
typedef FAudioVoiceDetails XAUDIO2_VOICE_DETAILS;
typedef FAudioVoiceDetails XAUDIO27_VOICE_DETAILS;
typedef FAudioVoiceState XAUDIO2_VOICE_STATE;
typedef FAudioWaveFormatEx WAVEFORMATEX;
typedef FAudioPerformanceData XAUDIO2_PERFORMANCE_DATA;
typedef FAudioEngineCallback IXAudio2EngineCallback;
typedef FAudioVoiceCallback IXAudio2VoiceCallback;
typedef FAPO IXAPO;
typedef FAudio IXAudio27;
#define IXAudio27_CreateMasteringVoice FAudio_CreateMasteringVoice
#define IXAudio27_CreateSourceVoice FAudio_CreateSourceVoice
#define IXAudio27_CreateSubmixVoice FAudio_CreateSubmixVoice
#define IXAudio27_GetDeviceCount FAudio_GetDeviceCount
#define IXAudio27_GetDeviceDetails FAudio_GetDeviceDetails
#define IXAudio27_GetPerformanceData FAudio_GetPerformanceData
#define IXAudio27_Initialize FAudio_Initialize
#define IXAudio27_RegisterForCallbacks FAudio_RegisterForCallbacks
#define IXAudio27_Release FAudio_Release
#define IXAudio27_StartEngine FAudio_StartEngine
#define IXAudio27_StopEngine FAudio_StopEngine
#define IXAudio27_UnregisterForCallbacks FAudio_UnregisterForCallbacks
typedef FAudio IXAudio2;
#define IXAudio2_CreateMasteringVoice FAudio_CreateMasteringVoice8
#define IXAudio2_CreateSourceVoice FAudio_CreateSourceVoice
#define IXAudio2_CreateSubmixVoice FAudio_CreateSubmixVoice
#define IXAudio2_GetPerformanceData FAudio_GetPerformanceData
#define IXAudio2_RegisterForCallbacks FAudio_RegisterForCallbacks
#define IXAudio2_Release FAudio_Release
#define IXAudio2_StartEngine FAudio_StartEngine
#define IXAudio2_StopEngine FAudio_StopEngine
#define IXAudio2_UnregisterForCallbacks FAudio_UnregisterForCallbacks
typedef FAudioMasteringVoice IXAudio2MasteringVoice;
#define IXAudio2MasteringVoice_DestroyVoice FAudioVoice_DestroyVoice
#define IXAudio2MasteringVoice_GetChannelMask FAudioMasteringVoice_GetChannelMask
#define IXAudio2MasteringVoice_SetEffectChain FAudioVoice_SetEffectChain
#define IXAudio2MasteringVoice_SetVolume FAudioVoice_SetVolume
typedef FAudioSourceVoice IXAudio27SourceVoice;
#define IXAudio27SourceVoice_DestroyVoice FAudioVoice_DestroyVoice
#define IXAudio27SourceVoice_ExitLoop FAudioSourceVoice_ExitLoop
#define IXAudio27SourceVoice_FlushSourceBuffers FAudioSourceVoice_FlushSourceBuffers
#define IXAudio27SourceVoice_GetState(a,b) FAudioSourceVoice_GetState(a,b,0)
#define IXAudio27SourceVoice_GetVoiceDetails FAudioVoice_GetVoiceDetails
#define IXAudio27SourceVoice_SetChannelVolumes FAudioVoice_SetChannelVolumes
#define IXAudio27SourceVoice_SetSourceSampleRate FAudioSourceVoice_SetSourceSampleRate
#define IXAudio27SourceVoice_Start FAudioSourceVoice_Start
#define IXAudio27SourceVoice_Stop FAudioSourceVoice_Stop
#define IXAudio27SourceVoice_SubmitSourceBuffer FAudioSourceVoice_SubmitSourceBuffer
typedef FAudioSourceVoice IXAudio2SourceVoice;
#define IXAudio2SourceVoice_DestroyVoice FAudioVoice_DestroyVoice
#define IXAudio2SourceVoice_ExitLoop FAudioSourceVoice_ExitLoop
#define IXAudio2SourceVoice_FlushSourceBuffers FAudioSourceVoice_FlushSourceBuffers
#define IXAudio2SourceVoice_GetState FAudioSourceVoice_GetState
#define IXAudio2SourceVoice_GetVoiceDetails FAudioVoice_GetVoiceDetails
#define IXAudio2SourceVoice_SetChannelVolumes FAudioVoice_SetChannelVolumes
#define IXAudio2SourceVoice_SetSourceSampleRate FAudioSourceVoice_SetSourceSampleRate
#define IXAudio2SourceVoice_SetVolume FAudioVoice_SetVolume
#define IXAudio2SourceVoice_Start FAudioSourceVoice_Start
#define IXAudio2SourceVoice_Stop FAudioSourceVoice_Stop
#define IXAudio2SourceVoice_SubmitSourceBuffer FAudioSourceVoice_SubmitSourceBuffer
typedef FAudioSubmixVoice IXAudio27SubmixVoice;
#define IXAudio27SubmixVoice_GetVoiceDetails FAudioVoice_GetVoiceDetails
#define IXAudio27SubmixVoice_DestroyVoice FAudioVoice_DestroyVoice
typedef FAudioSubmixVoice IXAudio2SubmixVoice;
#define IXAudio2SubmixVoice_GetVoiceDetails FAudioVoice_GetVoiceDetails
#define IXAudio2SubmixVoice_DestroyVoice FAudioVoice_DestroyVoice

View File

@@ -180,11 +180,15 @@ poll_thread(void *arg)
/* Request ownership of the device. */ /* Request ownership of the device. */
network_wait(1); network_wait(1);
#if 0
/* Wait for a poll request. */ /* Wait for a poll request. */
network_poll(); network_poll();
#endif
if (pcap == NULL) if (pcap == NULL) {
network_wait(0);
break; break;
}
if (network_get_wait() || (poll_card->set_link_state && poll_card->set_link_state(poll_card->priv)) || (poll_card->wait && poll_card->wait(poll_card->priv))) if (network_get_wait() || (poll_card->set_link_state && poll_card->set_link_state(poll_card->priv)) || (poll_card->wait && poll_card->wait(poll_card->priv)))
data = NULL; data = NULL;
@@ -213,12 +217,12 @@ poll_thread(void *arg)
if (tx) if (tx)
network_do_tx(); network_do_tx();
/* Release ownership of the device. */
network_wait(0);
/* If we did not get anything, wait a while. */ /* If we did not get anything, wait a while. */
if (!tx) if (!tx)
thread_wait_event(evt, 10); thread_wait_event(evt, 10);
/* Release ownership of the device. */
network_wait(0);
} }
/* No longer needed. */ /* No longer needed. */

View File

@@ -362,11 +362,16 @@ poll_thread(void *arg)
/* Request ownership of the queue. */ /* Request ownership of the queue. */
network_wait(1); network_wait(1);
#if 0
/* Wait for a poll request. */ /* Wait for a poll request. */
network_poll(); network_poll();
#endif
/* Stop processing if asked to. */ /* Stop processing if asked to. */
if (slirp->stop) break; if (slirp->stop) {
network_wait(0);
break;
}
/* See if there is any work. */ /* See if there is any work. */
slirp_tic(slirp); slirp_tic(slirp);
@@ -377,12 +382,12 @@ poll_thread(void *arg)
if (tx) if (tx)
network_do_tx(); network_do_tx();
/* Release ownership of the queue. */
network_wait(0);
/* If we did not get anything, wait a while. */ /* If we did not get anything, wait a while. */
if (!tx) if (!tx)
thread_wait_event(evt, 10); thread_wait_event(evt, 10);
/* Release ownership of the queue. */
network_wait(0);
} }
/* No longer needed. */ /* No longer needed. */

View File

@@ -204,9 +204,13 @@ network_wait(uint8_t wait)
void void
network_poll(void) network_poll(void)
{ {
network_wait(0);
while (poll_data.busy) while (poll_data.busy)
thread_wait_event(poll_data.wake_poll_thread, -1); thread_wait_event(poll_data.wake_poll_thread, -1);
network_wait(1);
thread_reset_event(poll_data.wake_poll_thread); thread_reset_event(poll_data.wake_poll_thread);
} }
@@ -348,13 +352,13 @@ network_rx_queue(void *priv)
{ {
int ret = 1; int ret = 1;
if (network_rx_pause) { netpkt_t *pkt = NULL;
if (network_rx_pause || !thread_test_mutex(network_mutex)) {
timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * 128.0); timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * 128.0);
return; return;
} }
netpkt_t *pkt = NULL;
network_busy(1); network_busy(1);
network_queue_get(0, &pkt); network_queue_get(0, &pkt);
@@ -371,6 +375,8 @@ network_rx_queue(void *priv)
network_queue_advance(0); network_queue_advance(0);
network_busy(0); network_busy(0);
network_wait(0);
} }

View File

@@ -202,9 +202,8 @@ macro(install_qt5_plugin _qt_plugin_name _qt_plugins_var _prefix)
get_filename_component(_qt_plugin_type "${_qt_plugin_path}" PATH) get_filename_component(_qt_plugin_type "${_qt_plugin_path}" PATH)
get_filename_component(_qt_plugin_type "${_qt_plugin_type}" NAME) get_filename_component(_qt_plugin_type "${_qt_plugin_type}" NAME)
set(_qt_plugin_dest "${_prefix}/PlugIns/${_qt_plugin_type}") set(_qt_plugin_dest "${_prefix}/PlugIns/${_qt_plugin_type}")
install(FILES "${_qt_plugin_path}" install(FILES "${_qt_plugin_path}" DESTINATION "${_qt_plugin_dest}")
DESTINATION "${_qt_plugin_dest}") list(APPEND ${_qt_plugins_var} "\${CMAKE_INSTALL_PREFIX_ABSOLUTE}/${_qt_plugin_dest}/${_qt_plugin_file}")
list(APPEND ${_qt_plugins_var} "${_qt_plugin_dest}/${_qt_plugin_file}")
else() else()
message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found") message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found")
endif() endif()
@@ -245,11 +244,7 @@ if (APPLE AND CMAKE_MACOSX_BUNDLE)
install(CODE " install(CODE "
include(BundleUtilities) include(BundleUtilities)
get_filename_component(CMAKE_INSTALL_PREFIX_ABSOLUTE \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX} ABSOLUTE) get_filename_component(CMAKE_INSTALL_PREFIX_ABSOLUTE \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX} ABSOLUTE)
foreach(PLUGIN ${QT_PLUGINS}) fixup_bundle(\"\${CMAKE_INSTALL_PREFIX_ABSOLUTE}/86Box.app\" \"${QT_PLUGINS}\" \"${DIRS}\")")
get_filename_component(PLUGIN_ABSOLUTE \${PLUGIN} ABSOLUTE BASE_DIR \${CMAKE_INSTALL_PREFIX_ABSOLUTE})
list(APPEND QT_PLUGINS_ABSOLUTE \${PLUGIN_ABSOLUTE})
endforeach()
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX_ABSOLUTE}/86Box.app\" \"${QT_PLUGINS_ABSOLUTE}\" \"${DIRS}\")")
endif() endif()
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)

View File

@@ -20,8 +20,46 @@ add_library(snd OBJECT sound.c snd_opl.c snd_opl_nuked.c snd_resid.cc
snd_emu8k.c snd_mpu401.c snd_sn76489.c snd_ssi2001.c snd_wss.c snd_ym7128.c) snd_emu8k.c snd_mpu401.c snd_sn76489.c snd_ssi2001.c snd_wss.c snd_ym7128.c)
if(OPENAL) if(OPENAL)
target_compile_definitions(snd PRIVATE USE_OPENAL) if(VCPKG_TOOLCHAIN)
find_package(OpenAL CONFIG REQUIRED)
elseif(MINGW)
find_package(OpenAL MODULE REQUIRED)
else()
find_package(OpenAL REQUIRED)
endif()
if(TARGET OpenAL::OpenAL)
target_link_libraries(86Box OpenAL::OpenAL)
else()
include_directories(${OPENAL_INCLUDE_DIR})
target_link_libraries(86Box ${OPENAL_LIBRARY})
endif()
target_sources(snd PRIVATE openal.c) target_sources(snd PRIVATE openal.c)
else()
if(WIN32)
option(FAUDIO "Use FAudio instead of XAudio2" OFF)
endif()
target_sources(snd PRIVATE xaudio2.c)
if(NOT WIN32 OR FAUDIO)
find_package(PkgConfig REQUIRED)
# Use FAudio, a reimplementation of XAudio2
pkg_check_modules(FAUDIO IMPORTED_TARGET FAudio)
if(FAUDIO_FOUND)
target_link_libraries(86Box PkgConfig::FAUDIO)
else()
find_path(FAUDIO_INCLUDE_DIR NAMES "FAudio.h")
find_library(FAUDIO_LIBRARY FAudio)
include_directories(${FAUDIO_INCLUDE_DIR})
target_link_libraries(86Box ${FAUDIO_LIBRARY})
endif()
set_property(SOURCE xaudio2.c PROPERTY COMPILE_DEFINITIONS USE_FAUDIO)
endif()
endif() endif()
if(FLUIDSYNTH) if(FLUIDSYNTH)

View File

@@ -40,10 +40,8 @@ enum fluid_interp {
}; };
#ifdef USE_OPENAL
extern void givealbuffer_midi(void *buf, uint32_t size); extern void givealbuffer_midi(void *buf, uint32_t size);
extern void al_set_midi(int freq, int buf_size); extern void al_set_midi(int freq, int buf_size);
#endif
static void *fluidsynth_handle; /* handle to FluidSynth DLL */ static void *fluidsynth_handle; /* handle to FluidSynth DLL */
@@ -152,9 +150,7 @@ static void fluidsynth_thread(void *param)
buf_pos += buf_size; buf_pos += buf_size;
if (buf_pos >= data->buf_size) if (buf_pos >= data->buf_size)
{ {
#ifdef USE_OPENAL
givealbuffer_midi(data->buffer, data->buf_size / sizeof(float)); givealbuffer_midi(data->buffer, data->buf_size / sizeof(float));
#endif
buf_pos = 0; buf_pos = 0;
} }
} }
@@ -167,9 +163,7 @@ static void fluidsynth_thread(void *param)
buf_pos += buf_size; buf_pos += buf_size;
if (buf_pos >= data->buf_size) if (buf_pos >= data->buf_size)
{ {
#ifdef USE_OPENAL
givealbuffer_midi(data->buffer_int16, data->buf_size / sizeof(int16_t)); givealbuffer_midi(data->buffer_int16, data->buf_size / sizeof(int16_t));
#endif
buf_pos = 0; buf_pos = 0;
} }
} }
@@ -322,9 +316,7 @@ void* fluidsynth_init(const device_t *info)
data->buffer_int16 = malloc(data->buf_size); data->buffer_int16 = malloc(data->buf_size);
} }
#ifdef USE_OPENAL
al_set_midi(data->samplerate, data->buf_size); al_set_midi(data->samplerate, data->buf_size);
#endif
dev = malloc(sizeof(midi_device_t)); dev = malloc(sizeof(midi_device_t));
memset(dev, 0, sizeof(midi_device_t)); memset(dev, 0, sizeof(midi_device_t));

View File

@@ -14,10 +14,8 @@
#include <86box/midi.h> #include <86box/midi.h>
#ifdef USE_OPENAL
extern void givealbuffer_midi(void *buf, uint32_t size); extern void givealbuffer_midi(void *buf, uint32_t size);
extern void al_set_midi(int freq, int buf_size); extern void al_set_midi(int freq, int buf_size);
#endif
static void display_mt32_message(void *instance_data, const char *message); static void display_mt32_message(void *instance_data, const char *message);
@@ -193,9 +191,7 @@ static void mt32_thread(void *param)
buf_pos += bsize; buf_pos += bsize;
if (buf_pos >= buf_size) if (buf_pos >= buf_size)
{ {
#ifdef USE_OPENAL
givealbuffer_midi(buffer, buf_size / sizeof(float)); givealbuffer_midi(buffer, buf_size / sizeof(float));
#endif
buf_pos = 0; buf_pos = 0;
} }
} }
@@ -207,9 +203,7 @@ static void mt32_thread(void *param)
buf_pos += bsize; buf_pos += bsize;
if (buf_pos >= buf_size) if (buf_pos >= buf_size)
{ {
#ifdef USE_OPENAL
givealbuffer_midi(buffer_int16, buf_size / sizeof(int16_t)); givealbuffer_midi(buffer_int16, buf_size / sizeof(int16_t));
#endif
buf_pos = 0; buf_pos = 0;
} }
} }
@@ -261,9 +255,7 @@ void* mt32emu_init(char *control_rom, char *pcm_rom)
mt32emu_set_reversed_stereo_enabled(context, device_get_config_int("reversed_stereo")); mt32emu_set_reversed_stereo_enabled(context, device_get_config_int("reversed_stereo"));
mt32emu_set_nice_amp_ramp_enabled(context, device_get_config_int("nice_ramp")); mt32emu_set_nice_amp_ramp_enabled(context, device_get_config_int("nice_ramp"));
#ifdef USE_OPENAL
al_set_midi(samplerate, buf_size); al_set_midi(samplerate, buf_size);
#endif
dev = malloc(sizeof(midi_device_t)); dev = malloc(sizeof(midi_device_t));
memset(dev, 0, sizeof(midi_device_t)); memset(dev, 0, sizeof(midi_device_t));

View File

@@ -347,12 +347,10 @@ sound_cd_thread(void *param)
} }
} }
#ifdef USE_OPENAL
if (sound_is_float) if (sound_is_float)
givealbuffer_cd(cd_out_buffer); givealbuffer_cd(cd_out_buffer);
else else
givealbuffer_cd(cd_out_buffer_int16); givealbuffer_cd(cd_out_buffer_int16);
#endif
} }
} }
@@ -465,12 +463,10 @@ sound_poll(void *priv)
} }
} }
#ifdef USE_OPENAL
if (sound_is_float) if (sound_is_float)
givealbuffer(outbuffer_ex); givealbuffer(outbuffer_ex);
else else
givealbuffer(outbuffer_ex_int16); givealbuffer(outbuffer_ex_int16);
#endif
if (cd_thread_enable) { if (cd_thread_enable) {
cd_buf_update--; cd_buf_update--;
@@ -499,9 +495,8 @@ sound_reset(void)
midi_device_init(); midi_device_init();
midi_in_device_init(); midi_in_device_init();
#ifdef USE_OPENAL
inital(); inital();
#endif
timer_add(&sound_poll_timer, sound_poll, NULL, 1); timer_add(&sound_poll_timer, sound_poll, NULL, 1);

279
src/sound/xaudio2.c Normal file
View File

@@ -0,0 +1,279 @@
/*
* 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 the XAudio2 audio processing library.
*
*
*
* Authors: Cacodemon345
*
* Copyright 2022 Cacodemon345.
*/
#include <math.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#if defined(_WIN32) && !defined(USE_FAUDIO)
#define COBJMACROS
#include <xaudio2.h>
#else
#include <FAudio.h>
#include <FAudio_compat.h>
#endif
#include <86box/86box.h>
#include <86box/sound.h>
#include <86box/midi.h>
#include <86box/plat_dynld.h>
#if defined(_WIN32) && !defined(USE_FAUDIO)
static void *xaudio2_handle = NULL;
static HRESULT (WINAPI *pXAudio2Create)(IXAudio2** ppXAudio2, uint32_t Flags, XAUDIO2_PROCESSOR XAudio2Processor);
static dllimp_t xaudio2_imports[] = {
{ "XAudio2Create", &pXAudio2Create },
{ NULL, NULL },
};
#define XAudio2Create pXAudio2Create
#endif
static int midi_freq = 44100;
static int midi_buf_size = 4410;
static int initialized = 0;
static IXAudio2 *xaudio2 = NULL;
static IXAudio2MasteringVoice *mastervoice = NULL;
static IXAudio2SourceVoice *srcvoice = NULL;
static IXAudio2SourceVoice *srcvoicemidi = NULL;
static IXAudio2SourceVoice *srcvoicecd = NULL;
#define FREQ 48000
#define BUFLEN SOUNDBUFLEN
static void WINAPI OnVoiceProcessingPassStart(IXAudio2VoiceCallback *callback, uint32_t bytesRequired) {}
static void WINAPI OnVoiceProcessingPassEnd(IXAudio2VoiceCallback *callback) {}
static void WINAPI OnStreamEnd(IXAudio2VoiceCallback *callback) {}
static void WINAPI OnBufferStart(IXAudio2VoiceCallback *callback, void *pBufferContext) {}
static void WINAPI OnLoopEnd(IXAudio2VoiceCallback *callback, void *pBufferContext) {}
static void WINAPI OnVoiceError(IXAudio2VoiceCallback *callback, void *pBufferContext, HRESULT error) {}
static void WINAPI
OnBufferEnd(IXAudio2VoiceCallback *callback, void *pBufferContext)
{
free(pBufferContext);
}
#if defined(_WIN32) && !defined(USE_FAUDIO)
static IXAudio2VoiceCallbackVtbl callbacksVtbl =
#else
static FAudioVoiceCallback callbacks =
#endif
{
.OnVoiceProcessingPassStart = OnVoiceProcessingPassStart,
.OnVoiceProcessingPassEnd = OnVoiceProcessingPassEnd,
.OnStreamEnd = OnStreamEnd,
.OnBufferStart = OnBufferStart,
.OnBufferEnd = OnBufferEnd,
.OnLoopEnd = OnLoopEnd,
.OnVoiceError = OnVoiceError
};
#if defined(_WIN32) && !defined(USE_FAUDIO)
static IXAudio2VoiceCallback callbacks = { &callbacksVtbl };
#endif
void
inital()
{
#if defined(_WIN32) && !defined(USE_FAUDIO)
if (xaudio2_handle == NULL) {
xaudio2_handle = dynld_module("xaudio2_9.dll", xaudio2_imports);
}
if (xaudio2_handle == NULL) {
xaudio2_handle = dynld_module("xaudio2_9redist.dll", xaudio2_imports);
}
if (xaudio2_handle == NULL) {
return;
}
#endif
if (XAudio2Create(&xaudio2, 0, XAUDIO2_DEFAULT_PROCESSOR))
{
return;
}
if (IXAudio2_CreateMasteringVoice(xaudio2, &mastervoice, 2, FREQ, 0, 0, NULL, 0))
{
IXAudio2_Release(xaudio2);
xaudio2 = NULL;
return;
}
WAVEFORMATEX fmt;
fmt.nChannels = 2;
if (sound_is_float)
{
fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
fmt.wBitsPerSample = 32;
}
else
{
fmt.wFormatTag = WAVE_FORMAT_PCM;
fmt.wBitsPerSample = 16;
}
fmt.nSamplesPerSec = FREQ;
fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
fmt.cbSize = 0;
if (IXAudio2_CreateSourceVoice(xaudio2, &srcvoice, &fmt, 0, 2.0f, &callbacks, NULL, NULL))
{
IXAudio2MasteringVoice_DestroyVoice(mastervoice);
IXAudio2_Release(xaudio2);
xaudio2 = NULL;
mastervoice = NULL;
return;
}
fmt.nSamplesPerSec = CD_FREQ;
fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
IXAudio2_CreateSourceVoice(xaudio2, &srcvoicecd, &fmt, 0, 2.0f, &callbacks, NULL, NULL);
IXAudio2SourceVoice_SetVolume(srcvoice, 1, XAUDIO2_COMMIT_NOW);
IXAudio2SourceVoice_Start(srcvoice, 0, XAUDIO2_COMMIT_NOW);
IXAudio2SourceVoice_Start(srcvoicecd, 0, XAUDIO2_COMMIT_NOW);
char *mdn = midi_device_get_internal_name(midi_device_current);
if (strcmp(mdn, "none") && strcmp(mdn, SYSTEM_MIDI_INTERNAL_NAME))
{
fmt.nSamplesPerSec = midi_freq;
fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
IXAudio2_CreateSourceVoice(xaudio2, &srcvoicemidi, &fmt, 0, 2.0f, &callbacks, NULL, NULL);
IXAudio2SourceVoice_Start(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW);
}
initialized = 1;
}
void
closeal()
{
if (!initialized) return;
initialized = 0;
IXAudio2SourceVoice_Stop(srcvoice, 0, XAUDIO2_COMMIT_NOW);
IXAudio2SourceVoice_FlushSourceBuffers(srcvoice);
IXAudio2SourceVoice_Stop(srcvoicecd, 0, XAUDIO2_COMMIT_NOW);
IXAudio2SourceVoice_FlushSourceBuffers(srcvoicecd);
if (srcvoicemidi)
{
IXAudio2SourceVoice_Stop(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW);
IXAudio2SourceVoice_FlushSourceBuffers(srcvoicemidi);
IXAudio2SourceVoice_DestroyVoice(srcvoicemidi);
}
IXAudio2SourceVoice_DestroyVoice(srcvoice);
IXAudio2SourceVoice_DestroyVoice(srcvoicecd);
IXAudio2MasteringVoice_DestroyVoice(mastervoice);
IXAudio2_Release(xaudio2);
srcvoice = srcvoicecd = srcvoicemidi = NULL;
mastervoice = NULL;
xaudio2 = NULL;
#if defined(_WIN32) && !defined(USE_FAUDIO)
dynld_close(xaudio2_handle);
xaudio2_handle = NULL;
#endif
}
void
givealbuffer_common(void *buf, IXAudio2SourceVoice* sourcevoice, size_t buflen)
{
if (!initialized) return;
IXAudio2MasteringVoice_SetVolume(mastervoice, pow(10.0, (double)sound_gain / 20.0), XAUDIO2_COMMIT_NOW);
XAUDIO2_BUFFER buffer = {0};
buffer.Flags = 0;
if (sound_is_float)
{
buffer.pAudioData = calloc(buflen, sizeof(float));
buffer.AudioBytes = (buflen) * sizeof(float);
}
else
{
buffer.pAudioData = calloc(buflen, sizeof(int16_t));
buffer.AudioBytes = (buflen) * sizeof(int16_t);
}
if (buffer.pAudioData == NULL)
{
fatal("xaudio2: Out Of Memory!");
}
memcpy((void*)buffer.pAudioData, buf, buffer.AudioBytes);
buffer.PlayBegin = buffer.PlayLength = 0;
buffer.PlayLength = buflen >> 1;
buffer.pContext = (void*)buffer.pAudioData;
IXAudio2SourceVoice_SubmitSourceBuffer(sourcevoice, &buffer, NULL);
}
void
givealbuffer(void *buf)
{
givealbuffer_common(buf, srcvoice, BUFLEN << 1);
}
void
givealbuffer_cd(void *buf)
{
if (srcvoicecd) givealbuffer_common(buf, srcvoicecd, CD_BUFLEN << 1);
}
void
al_set_midi(int freq, int buf_size)
{
midi_freq = freq;
midi_buf_size = buf_size;
if (initialized && srcvoicemidi)
{
IXAudio2SourceVoice_Stop(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW);
IXAudio2SourceVoice_FlushSourceBuffers(srcvoicemidi);
IXAudio2SourceVoice_DestroyVoice(srcvoicemidi);
srcvoicemidi = NULL;
WAVEFORMATEX fmt;
fmt.nChannels = 2;
if (sound_is_float)
{
fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
fmt.wBitsPerSample = 32;
}
else
{
fmt.wFormatTag = WAVE_FORMAT_PCM;
fmt.wBitsPerSample = 16;
}
fmt.nSamplesPerSec = midi_freq;
fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
fmt.cbSize = 0;
IXAudio2_CreateSourceVoice(xaudio2, &srcvoicemidi, &fmt, 0, 2.0f, &callbacks, NULL, NULL);
IXAudio2SourceVoice_Start(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW);
}
}
void
givealbuffer_midi(void *buf, uint32_t size)
{
givealbuffer_common(buf, srcvoicemidi, size);
}

View File

@@ -37,6 +37,16 @@ thread_create_mutex(void)
return mutex; return mutex;
} }
int
thread_test_mutex(mutex_t *_mutex)
{
if (_mutex == nullptr)
return 0;
auto mutex = reinterpret_cast<std::mutex*>(_mutex);
return mutex->try_lock() ? 1 : 0;
}
int int
thread_wait_mutex(mutex_t *_mutex) thread_wait_mutex(mutex_t *_mutex)
{ {

View File

@@ -173,7 +173,7 @@ ifndef DINPUT
DINPUT := n DINPUT := n
endif endif
ifndef OPENAL ifndef OPENAL
OPENAL := y OPENAL := n
endif endif
ifndef FLUIDSYNTH ifndef FLUIDSYNTH
FLUIDSYNTH := y FLUIDSYNTH := y
@@ -373,9 +373,6 @@ else
endif endif
endif endif
ifeq ($(OPENAL), y)
OPTS += -DUSE_OPENAL
endif
ifeq ($(FLUIDSYNTH), y) ifeq ($(FLUIDSYNTH), y)
OPTS += -DUSE_FLUIDSYNTH OPTS += -DUSE_FLUIDSYNTH
FSYNTHOBJ := midi_fluidsynth.o FSYNTHOBJ := midi_fluidsynth.o
@@ -645,7 +642,6 @@ PRINTOBJ := png.o prt_cpmap.o \
prt_escp.o prt_text.o prt_ps.o prt_escp.o prt_text.o prt_ps.o
SNDOBJ := sound.o \ SNDOBJ := sound.o \
openal.o \
snd_opl.o snd_opl_nuked.o \ snd_opl.o snd_opl_nuked.o \
snd_resid.o \ snd_resid.o \
convolve.o convolve-sse.o envelope.o extfilt.o \ convolve.o convolve-sse.o envelope.o extfilt.o \
@@ -736,6 +732,12 @@ else
PLATOBJ += win_joystick_rawinput.o PLATOBJ += win_joystick_rawinput.o
endif endif
ifeq ($(OPENAL), y)
SNDOBJ += openal.o
else
SNDOBJ += xaudio2.o
endif
OBJ := $(MAINOBJ) $(CPUOBJ) $(CHIPSETOBJ) $(MCHOBJ) $(DEVOBJ) $(MEMOBJ) \ OBJ := $(MAINOBJ) $(CPUOBJ) $(CHIPSETOBJ) $(MCHOBJ) $(DEVOBJ) $(MEMOBJ) \
$(FDDOBJ) $(GAMEOBJ) $(CDROMOBJ) $(ZIPOBJ) $(MOOBJ) $(HDDOBJ) $(MINIVHDOBJ) \ $(FDDOBJ) $(GAMEOBJ) $(CDROMOBJ) $(ZIPOBJ) $(MOOBJ) $(HDDOBJ) $(MINIVHDOBJ) \
$(NETOBJ) $(PRINTOBJ) $(SCSIOBJ) $(SIOOBJ) $(SNDOBJ) $(VIDOBJ) $(VOODOOOBJ) \ $(NETOBJ) $(PRINTOBJ) $(SCSIOBJ) $(SIOOBJ) $(SNDOBJ) $(VIDOBJ) $(VOODOOOBJ) \
@@ -744,13 +746,12 @@ ifdef EXOBJ
OBJ += $(EXOBJ) OBJ += $(EXOBJ)
endif endif
LIBS := -mwindows -lcomctl32 \ LIBS := -mwindows -lcomctl32 -lSDL2 -lrtmidi -limagehlp -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid
-lopenal -lole32
ifeq ($(VNC), y) ifeq ($(VNC), y)
LIBS += $(VNCLIB) -lws2_32 LIBS += $(VNCLIB) -lws2_32
endif endif
LIBS += -lpng -lz -lwsock32 -lshell32 -liphlpapi -lpsapi -lSDL2 -limm32 -lhid -lsetupapi -loleaut32 -luxtheme -lversion -lrtmidi -lwinmm -static -lstdc++ LIBS += -lpng -lz -lwsock32 -liphlpapi -lpsapi -lhid -lsetupapi -luxtheme -static -lstdc++
ifneq ($(X64), y) ifneq ($(X64), y)
ifneq ($(ARM64), y) ifneq ($(ARM64), y)
LIBS += -Wl,--large-address-aware LIBS += -Wl,--large-address-aware