diff --git a/.ci/build.sh b/.ci/build.sh index a791521f5..493f42789 100644 --- a/.ci/build.sh +++ b/.ci/build.sh @@ -298,6 +298,9 @@ EOF # Link against the system libslirp instead of compiling ours. 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 # Clean workspace. diff --git a/.editorconfig b/.editorconfig index 047c9d67c..1cb9087ec 100644 --- a/.editorconfig +++ b/.editorconfig @@ -32,3 +32,7 @@ indent_size = 4 [*.cmake] indent_style = space indent_size = 4 + +[*.json] +indent_style = space +indent_size = 4 diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 4bc84e91c..2e4753927 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -252,7 +252,7 @@ jobs: steps: - uses: actions/checkout@v2 - 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 run: >- cmake -S . -B build @@ -316,7 +316,7 @@ jobs: steps: - uses: actions/checkout@v2 - 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 run: >- cmake -S . -B build diff --git a/CMakeLists.txt b/CMakeLists.txt index cb3bb8a5d..0aa4c7b56 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,7 +114,7 @@ set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON) # ------ ----------- ---- option(RELEASE "Release build" OFF) option(DYNAREC "Dynamic recompiler" ON) -option(OPENAL "OpenAL" ON) +option(OPENAL "OpenAL" OFF) option(FLUIDSYNTH "FluidSynth" ON) option(MUNT "MUNT" ON) option(DINPUT "DirectInput" OFF) diff --git a/src/86box.c b/src/86box.c index 9647a8a6e..2e49184ef 100644 --- a/src/86box.c +++ b/src/86box.c @@ -941,9 +941,7 @@ pc_reset_hard_close(void) scsi_disk_close(); -#ifdef USE_OPENAL closeal(); -#endif video_reset_close(); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 704024067..674346065 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -43,7 +43,7 @@ if(VNC) add_compile_definitions(USE_VNC) add_library(vnc OBJECT vnc.c vnc_keymap.c) target_link_libraries(86Box vnc vncserver) - if (WIN32) + if(WIN32) target_link_libraries(86Box ws2_32) endif() endif() @@ -86,23 +86,6 @@ if(APPLE) target_link_libraries(86Box Freetype::Freetype) 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) include_directories(${SDL2_INCLUDE_DIRS}) if(STATIC_BUILD AND TARGET SDL2::SDL2-static) diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index 0c9485461..b09207c14 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -204,6 +204,7 @@ extern void thread_destroy_event(event_t *arg); extern mutex_t *thread_create_mutex(void); 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_release_mutex(mutex_t *mutex); diff --git a/src/include/FAudio_compat.h b/src/include/FAudio_compat.h new file mode 100644 index 000000000..eb901a184 --- /dev/null +++ b/src/include/FAudio_compat.h @@ -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 \ No newline at end of file diff --git a/src/network/net_pcap.c b/src/network/net_pcap.c index 7008d1442..cfa4837dc 100644 --- a/src/network/net_pcap.c +++ b/src/network/net_pcap.c @@ -180,11 +180,15 @@ poll_thread(void *arg) /* Request ownership of the device. */ network_wait(1); +#if 0 /* Wait for a poll request. */ network_poll(); +#endif - if (pcap == NULL) + if (pcap == NULL) { + network_wait(0); 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))) data = NULL; @@ -213,12 +217,12 @@ poll_thread(void *arg) if (tx) network_do_tx(); + /* Release ownership of the device. */ + network_wait(0); + /* If we did not get anything, wait a while. */ if (!tx) thread_wait_event(evt, 10); - - /* Release ownership of the device. */ - network_wait(0); } /* No longer needed. */ diff --git a/src/network/net_slirp.c b/src/network/net_slirp.c index b4b46bbe7..aeb28ad37 100644 --- a/src/network/net_slirp.c +++ b/src/network/net_slirp.c @@ -362,11 +362,16 @@ poll_thread(void *arg) /* Request ownership of the queue. */ network_wait(1); +#if 0 /* Wait for a poll request. */ network_poll(); +#endif /* Stop processing if asked to. */ - if (slirp->stop) break; + if (slirp->stop) { + network_wait(0); + break; + } /* See if there is any work. */ slirp_tic(slirp); @@ -377,12 +382,12 @@ poll_thread(void *arg) if (tx) network_do_tx(); + /* Release ownership of the queue. */ + network_wait(0); + /* If we did not get anything, wait a while. */ if (!tx) thread_wait_event(evt, 10); - - /* Release ownership of the queue. */ - network_wait(0); } /* No longer needed. */ diff --git a/src/network/network.c b/src/network/network.c index fad9eacbc..7f4e83514 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -204,9 +204,13 @@ network_wait(uint8_t wait) void network_poll(void) { + network_wait(0); + while (poll_data.busy) thread_wait_event(poll_data.wake_poll_thread, -1); + network_wait(1); + thread_reset_event(poll_data.wake_poll_thread); } @@ -348,13 +352,13 @@ network_rx_queue(void *priv) { 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); return; } - netpkt_t *pkt = NULL; - network_busy(1); network_queue_get(0, &pkt); @@ -371,6 +375,8 @@ network_rx_queue(void *priv) network_queue_advance(0); network_busy(0); + + network_wait(0); } diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index d48f17115..94a7dadd9 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -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_type}" NAME) set(_qt_plugin_dest "${_prefix}/PlugIns/${_qt_plugin_type}") - install(FILES "${_qt_plugin_path}" - DESTINATION "${_qt_plugin_dest}") - list(APPEND ${_qt_plugins_var} "${_qt_plugin_dest}/${_qt_plugin_file}") + install(FILES "${_qt_plugin_path}" DESTINATION "${_qt_plugin_dest}") + list(APPEND ${_qt_plugins_var} "\${CMAKE_INSTALL_PREFIX_ABSOLUTE}/${_qt_plugin_dest}/${_qt_plugin_file}") else() message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found") endif() @@ -245,11 +244,7 @@ if (APPLE AND CMAKE_MACOSX_BUNDLE) install(CODE " include(BundleUtilities) get_filename_component(CMAKE_INSTALL_PREFIX_ABSOLUTE \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX} ABSOLUTE) - foreach(PLUGIN ${QT_PLUGINS}) - 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}\")") + fixup_bundle(\"\${CMAKE_INSTALL_PREFIX_ABSOLUTE}/86Box.app\" \"${QT_PLUGINS}\" \"${DIRS}\")") endif() if (UNIX AND NOT APPLE) diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index e8d6c6f20..ef753cd6f 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -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) 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) +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() if(FLUIDSYNTH) diff --git a/src/sound/midi_fluidsynth.c b/src/sound/midi_fluidsynth.c index ed3e2d535..14093efb4 100644 --- a/src/sound/midi_fluidsynth.c +++ b/src/sound/midi_fluidsynth.c @@ -40,10 +40,8 @@ enum fluid_interp { }; -#ifdef USE_OPENAL extern void givealbuffer_midi(void *buf, uint32_t size); extern void al_set_midi(int freq, int buf_size); -#endif static void *fluidsynth_handle; /* handle to FluidSynth DLL */ @@ -152,9 +150,7 @@ static void fluidsynth_thread(void *param) buf_pos += buf_size; if (buf_pos >= data->buf_size) { -#ifdef USE_OPENAL givealbuffer_midi(data->buffer, data->buf_size / sizeof(float)); -#endif buf_pos = 0; } } @@ -167,9 +163,7 @@ static void fluidsynth_thread(void *param) buf_pos += buf_size; if (buf_pos >= data->buf_size) { -#ifdef USE_OPENAL givealbuffer_midi(data->buffer_int16, data->buf_size / sizeof(int16_t)); -#endif buf_pos = 0; } } @@ -322,9 +316,7 @@ void* fluidsynth_init(const device_t *info) data->buffer_int16 = malloc(data->buf_size); } -#ifdef USE_OPENAL al_set_midi(data->samplerate, data->buf_size); -#endif dev = malloc(sizeof(midi_device_t)); memset(dev, 0, sizeof(midi_device_t)); diff --git a/src/sound/midi_mt32.c b/src/sound/midi_mt32.c index 00c26b392..e1812a733 100644 --- a/src/sound/midi_mt32.c +++ b/src/sound/midi_mt32.c @@ -14,10 +14,8 @@ #include <86box/midi.h> -#ifdef USE_OPENAL extern void givealbuffer_midi(void *buf, uint32_t size); extern void al_set_midi(int freq, int buf_size); -#endif static void display_mt32_message(void *instance_data, const char *message); @@ -193,9 +191,7 @@ static void mt32_thread(void *param) buf_pos += bsize; if (buf_pos >= buf_size) { -#ifdef USE_OPENAL givealbuffer_midi(buffer, buf_size / sizeof(float)); -#endif buf_pos = 0; } } @@ -207,9 +203,7 @@ static void mt32_thread(void *param) buf_pos += bsize; if (buf_pos >= buf_size) { -#ifdef USE_OPENAL givealbuffer_midi(buffer_int16, buf_size / sizeof(int16_t)); -#endif 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_nice_amp_ramp_enabled(context, device_get_config_int("nice_ramp")); -#ifdef USE_OPENAL al_set_midi(samplerate, buf_size); -#endif dev = malloc(sizeof(midi_device_t)); memset(dev, 0, sizeof(midi_device_t)); diff --git a/src/sound/sound.c b/src/sound/sound.c index e12b38bcb..4beab94ba 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -347,12 +347,10 @@ sound_cd_thread(void *param) } } -#ifdef USE_OPENAL if (sound_is_float) givealbuffer_cd(cd_out_buffer); else givealbuffer_cd(cd_out_buffer_int16); -#endif } } @@ -465,12 +463,10 @@ sound_poll(void *priv) } } -#ifdef USE_OPENAL if (sound_is_float) givealbuffer(outbuffer_ex); else givealbuffer(outbuffer_ex_int16); -#endif if (cd_thread_enable) { cd_buf_update--; @@ -499,9 +495,8 @@ sound_reset(void) midi_device_init(); midi_in_device_init(); -#ifdef USE_OPENAL + inital(); -#endif timer_add(&sound_poll_timer, sound_poll, NULL, 1); diff --git a/src/sound/xaudio2.c b/src/sound/xaudio2.c new file mode 100644 index 000000000..8f3329c3b --- /dev/null +++ b/src/sound/xaudio2.c @@ -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 +#include +#include +#include +#include +#include + +#if defined(_WIN32) && !defined(USE_FAUDIO) +#define COBJMACROS +#include +#else +#include +#include +#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); +} diff --git a/src/thread.cpp b/src/thread.cpp index 4134befba..1003dd871 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -37,6 +37,16 @@ thread_create_mutex(void) return mutex; } +int +thread_test_mutex(mutex_t *_mutex) +{ + if (_mutex == nullptr) + return 0; + + auto mutex = reinterpret_cast(_mutex); + return mutex->try_lock() ? 1 : 0; +} + int thread_wait_mutex(mutex_t *_mutex) { diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 3f0b3a3b6..380fa658d 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -173,7 +173,7 @@ ifndef DINPUT DINPUT := n endif ifndef OPENAL -OPENAL := y +OPENAL := n endif ifndef FLUIDSYNTH FLUIDSYNTH := y @@ -373,9 +373,6 @@ else endif endif -ifeq ($(OPENAL), y) -OPTS += -DUSE_OPENAL -endif ifeq ($(FLUIDSYNTH), y) OPTS += -DUSE_FLUIDSYNTH FSYNTHOBJ := midi_fluidsynth.o @@ -645,7 +642,6 @@ PRINTOBJ := png.o prt_cpmap.o \ prt_escp.o prt_text.o prt_ps.o SNDOBJ := sound.o \ - openal.o \ snd_opl.o snd_opl_nuked.o \ snd_resid.o \ convolve.o convolve-sse.o envelope.o extfilt.o \ @@ -736,6 +732,12 @@ else PLATOBJ += win_joystick_rawinput.o endif +ifeq ($(OPENAL), y) + SNDOBJ += openal.o +else + SNDOBJ += xaudio2.o +endif + OBJ := $(MAINOBJ) $(CPUOBJ) $(CHIPSETOBJ) $(MCHOBJ) $(DEVOBJ) $(MEMOBJ) \ $(FDDOBJ) $(GAMEOBJ) $(CDROMOBJ) $(ZIPOBJ) $(MOOBJ) $(HDDOBJ) $(MINIVHDOBJ) \ $(NETOBJ) $(PRINTOBJ) $(SCSIOBJ) $(SIOOBJ) $(SNDOBJ) $(VIDOBJ) $(VOODOOOBJ) \ @@ -744,13 +746,12 @@ ifdef EXOBJ OBJ += $(EXOBJ) endif -LIBS := -mwindows -lcomctl32 \ - -lopenal -lole32 +LIBS := -mwindows -lcomctl32 -lSDL2 -lrtmidi -limagehlp -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid ifeq ($(VNC), y) LIBS += $(VNCLIB) -lws2_32 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 ($(ARM64), y) LIBS += -Wl,--large-address-aware diff --git a/vcpkg.json b/vcpkg.json index 85295f1cf..2e01d1c1f 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,35 +1,35 @@ { - "name": "86box", - "version-string": "3.1", - "homepage": "https://86box.net/", - "documentation": "http://86box.readthedocs.io/", - "license": "GPL-2.0-or-later", - "dependencies": [ - "freetype", - "libpng", - "openal-soft", - "sdl2", - "rtmidi" - ], - "features": { - "qt-ui": { - "description": "Qt User Interface", - "dependencies": [ - "qt5-base", - "qt5-translations" - ] - }, - "munt": { - "description": "Roland MT-32 emulation", - "dependencies": [ - "libmt32emu" - ] - }, - "slirp": { - "description": "Slirp network support", - "dependencies": [ - "libslirp" - ] - } - } + "name": "86box", + "version-string": "3.1", + "homepage": "https://86box.net/", + "documentation": "http://86box.readthedocs.io/", + "license": "GPL-2.0-or-later", + "dependencies": [ + "freetype", + "libpng", + "openal-soft", + "sdl2", + "rtmidi" + ], + "features": { + "qt-ui": { + "description": "Qt User Interface", + "dependencies": [ + "qt5-base", + "qt5-translations" + ] + }, + "munt": { + "description": "Roland MT-32 emulation", + "dependencies": [ + "libmt32emu" + ] + }, + "slirp": { + "description": "Slirp network support", + "dependencies": [ + "libslirp" + ] + } + } }