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 5f95e1309..4bc84e91c 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -35,10 +35,10 @@ jobs: fail-fast: true matrix: build: - - name: Regular ODR - slug: -ODR - preset: regular - target: install/strip +# - name: Regular ODR +# slug: -ODR +# preset: regular +# target: install/strip - name: Debug ODR slug: -ODR-Debug preset: debug @@ -47,10 +47,10 @@ jobs: slug: -ODR-Dev preset: experimental target: install - - name: Regular NDR - slug: -NDR - preset: regularndr - target: install/strip +# - name: Regular NDR +# slug: -NDR +# preset: regularndr +# target: install/strip - name: Debug NDR slug: -NDR-Debug preset: debugndr @@ -114,12 +114,12 @@ jobs: fail-fast: true matrix: build: - - name: Regular ODR - slug: -ODR - type: Release - dev-build: off - new-dynarec: off - strip: --strip +# - name: Regular ODR +# slug: -ODR +# type: Release +# dev-build: off +# new-dynarec: off +# strip: --strip - name: Debug ODR slug: -ODR-Debug type: Debug @@ -130,12 +130,12 @@ jobs: type: Debug dev-build: on new-dynarec: off - - name: Regular NDR - slug: -NDR - type: Release - strip: --strip - dev-build: off - new-dynarec: on +# - name: Regular NDR +# slug: -NDR +# type: Release +# strip: --strip +# dev-build: off +# new-dynarec: on - name: Debug NDR slug: -NDR-Debug type: Debug @@ -210,18 +210,18 @@ jobs: linux: name: "Linux GCC 11 (${{ matrix.build.name }} x86_64)" - runs-on: ubuntu-2004 + runs-on: ubuntu-20.04 strategy: fail-fast: true matrix: build: - - name: Regular ODR - slug: -ODR - type: Release - dev-build: off - new-dynarec: off - strip: --strip +# - name: Regular ODR +# slug: -ODR +# type: Release +# dev-build: off +# new-dynarec: off +# strip: --strip - name: Debug ODR slug: -ODR-Debug type: Debug @@ -232,12 +232,12 @@ jobs: type: Debug dev-build: on new-dynarec: off - - name: Regular NDR - slug: -NDR - type: Release - strip: --strip - dev-build: off - new-dynarec: on +# - name: Regular NDR +# slug: -NDR +# type: Release +# strip: --strip +# dev-build: off +# new-dynarec: on - name: Debug NDR slug: -NDR-Debug type: Debug @@ -280,12 +280,12 @@ jobs: fail-fast: true matrix: build: - - name: Regular ODR - slug: -ODR - type: Release - dev-build: off - new-dynarec: off - strip: --strip +# - name: Regular ODR +# slug: -ODR +# type: Release +# dev-build: off +# new-dynarec: off +# strip: --strip - name: Debug ODR slug: -ODR-Debug type: Debug @@ -296,12 +296,12 @@ jobs: type: Debug dev-build: on new-dynarec: off - - name: Regular NDR - slug: -NDR - type: Release - strip: --strip - dev-build: off - new-dynarec: on +# - name: Regular NDR +# slug: -NDR +# type: Release +# strip: --strip +# dev-build: off +# new-dynarec: on - name: Debug NDR slug: -NDR-Debug type: Debug diff --git a/CMakeLists.txt b/CMakeLists.txt index cb3bb8a5d..ff59cbc6b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,6 +115,7 @@ set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON) option(RELEASE "Release build" OFF) option(DYNAREC "Dynamic recompiler" ON) option(OPENAL "OpenAL" ON) +option(FAUDIO "FAudio" OFF) option(FLUIDSYNTH "FluidSynth" ON) option(MUNT "MUNT" ON) option(DINPUT "DirectInput" OFF) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 704024067..ba0cffc7d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -86,7 +86,12 @@ if(APPLE) target_link_libraries(86Box Freetype::Freetype) endif() -if(OPENAL) +if(FAUDIO) + find_package(FAudio REQUIRED) + target_link_libraries(86Box FAudio::FAudio) +endif() + +if(OPENAL AND NOT FAUDIO) if(VCPKG_TOOLCHAIN) find_package(OpenAL CONFIG REQUIRED) elseif(MINGW) 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 8879b0378..bddd1776e 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -19,9 +19,13 @@ add_library(snd OBJECT sound.c snd_opl.c snd_opl_nuked.c snd_resid.cc snd_azt2316a.c snd_cms.c snd_cs423x.c snd_gus.c snd_sb.c snd_sb_dsp.c snd_emu8k.c snd_mpu401.c snd_sn76489.c snd_ssi2001.c snd_wss.c snd_ym7128.c) -if(OPENAL) +if(OPENAL OR FAUDIO) target_compile_definitions(snd PRIVATE USE_OPENAL) - target_sources(snd PRIVATE openal.c) + if (FAUDIO) + target_sources(snd PRIVATE faudio.cpp) + else() + target_sources(snd PRIVATE openal.c) + endif() endif() if(FLUIDSYNTH) @@ -60,4 +64,4 @@ if(TANDY_ISA) endif() add_subdirectory(resid-fp) -target_link_libraries(86Box resid-fp) \ No newline at end of file +target_link_libraries(86Box resid-fp) diff --git a/src/sound/faudio.cpp b/src/sound/faudio.cpp new file mode 100644 index 000000000..246ec0b67 --- /dev/null +++ b/src/sound/faudio.cpp @@ -0,0 +1,219 @@ +/* + * 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 FAudio audio processing library. + * + * + * + * Authors: Cacodemon345 + * + * Copyright 2022 Cacodemon345. + */ +#include +#include +#include +#include +#include +#include +#include + +extern "C" +{ +#include <86box/86box.h> +#include <86box/sound.h> +#include <86box/midi.h> + +static int midi_freq = 44100; +static int midi_buf_size = 4410; +static int initialized = 0; +static FAudio* faudio = nullptr; +static FAudioMasteringVoice* mastervoice = nullptr; +static FAudioSourceVoice* srcvoice = nullptr; +static FAudioSourceVoice* srcvoicemidi = nullptr; +static FAudioSourceVoice* srcvoicecd = nullptr; + +#define FREQ 48000 +#define BUFLEN SOUNDBUFLEN + +static void FAUDIOCALL +onBufferFinished( + FAudioVoiceCallback *callback, + void *pBufferContext) +{ + if (sound_is_float) delete[] (float*)(pBufferContext); + else delete[] (int16_t*)(pBufferContext); + +} + +static FAudioVoiceCallback callbacks = +{ + onBufferFinished +}; + +void +inital() +{ + if (FAudioCreate(&faudio, 0, FAUDIO_DEFAULT_PROCESSOR)) + { + return; + } + + if (FAudio_CreateMasteringVoice(faudio, &mastervoice, 2, FREQ, 0, 0, nullptr)) + { + FAudio_Release(faudio); + faudio = nullptr; + return; + } + FAudioWaveFormatEx fmt; + fmt.nChannels = 2; + if (sound_is_float) + { + fmt.wFormatTag = FAUDIO_FORMAT_IEEE_FLOAT; + fmt.wBitsPerSample = 32; + } + else + { + fmt.wFormatTag = FAUDIO_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 (FAudio_CreateSourceVoice(faudio, &srcvoice, &fmt, 0, 2.0f, &callbacks, nullptr, nullptr)) + { + FAudioVoice_DestroyVoice(mastervoice); + FAudio_Release(faudio); + faudio = nullptr; + mastervoice = nullptr; + return; + } + fmt.nSamplesPerSec = CD_FREQ; + fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8; + fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign; + FAudio_CreateSourceVoice(faudio, &srcvoicecd, &fmt, 0, 2.0f, &callbacks, nullptr, nullptr); + FAudioVoice_SetVolume(srcvoice, 1, FAUDIO_COMMIT_NOW); + FAudioSourceVoice_Start(srcvoice, 0, FAUDIO_COMMIT_NOW); + FAudioSourceVoice_Start(srcvoicecd, 0, FAUDIO_COMMIT_NOW); + auto 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; + FAudio_CreateSourceVoice(faudio, &srcvoicemidi, &fmt, 0, 2.0f, &callbacks, nullptr, nullptr); + FAudioSourceVoice_Start(srcvoicemidi, 0, FAUDIO_COMMIT_NOW); + } + initialized = 1; +} + +void +closeal() +{ + if (!initialized) return; + initialized = 0; + FAudioSourceVoice_Stop(srcvoice, 0, FAUDIO_COMMIT_NOW); + FAudioSourceVoice_FlushSourceBuffers(srcvoice); + FAudioSourceVoice_Stop(srcvoicecd, 0, FAUDIO_COMMIT_NOW); + FAudioSourceVoice_FlushSourceBuffers(srcvoicecd); + if (srcvoicemidi) + { + FAudioSourceVoice_Stop(srcvoicemidi, 0, FAUDIO_COMMIT_NOW); + FAudioSourceVoice_FlushSourceBuffers(srcvoicemidi); + FAudioVoice_DestroyVoice(srcvoicemidi); + } + FAudioVoice_DestroyVoice(srcvoice); + FAudioVoice_DestroyVoice(srcvoicecd); + FAudioVoice_DestroyVoice(mastervoice); + FAudio_Release(faudio); + srcvoice = srcvoicecd = srcvoicemidi = nullptr; + mastervoice = nullptr; + faudio = nullptr; +} + +void +givealbuffer_common(void *buf, FAudioSourceVoice* sourcevoice, size_t buflen) +{ + if (!initialized) return; + + FAudioVoice_SetVolume(mastervoice, pow(10.0, (double)sound_gain / 20.0), FAUDIO_COMMIT_NOW); + FAudioBuffer buffer{}; + buffer.Flags = 0; + if (sound_is_float) + { + buffer.pAudioData = (uint8_t*)new float[buflen]; + buffer.AudioBytes = (buflen) * sizeof(float); + } + else + { + buffer.pAudioData = (uint8_t*)new int16_t[buflen]; + buffer.AudioBytes = (buflen) * sizeof(int16_t); + } + if (buffer.pAudioData == nullptr) + { + fatal("faudio: Out Of Memory!"); + } + memcpy((void*)buffer.pAudioData, buf, buffer.AudioBytes); + buffer.PlayBegin = buffer.PlayLength = 0; + buffer.PlayLength = buflen >> 1; + buffer.pContext = (void*)buffer.pAudioData; + FAudioSourceVoice_SubmitSourceBuffer(sourcevoice, &buffer, nullptr); +} + +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) + { + FAudioSourceVoice_Stop(srcvoicemidi, 0, FAUDIO_COMMIT_NOW); + FAudioSourceVoice_FlushSourceBuffers(srcvoicemidi); + FAudioVoice_DestroyVoice(srcvoicemidi); + srcvoicemidi = nullptr; + FAudioWaveFormatEx fmt; + fmt.nChannels = 2; + if (sound_is_float) + { + fmt.wFormatTag = FAUDIO_FORMAT_IEEE_FLOAT; + fmt.wBitsPerSample = 32; + } + else + { + fmt.wFormatTag = FAUDIO_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; + FAudio_CreateSourceVoice(faudio, &srcvoicemidi, &fmt, 0, 2.0f, &callbacks, nullptr, nullptr); + FAudioSourceVoice_Start(srcvoicemidi, 0, FAUDIO_COMMIT_NOW); + } +} + +void +givealbuffer_midi(void *buf, uint32_t size) +{ + givealbuffer_common(buf, srcvoicemidi, size); +} + +} \ No newline at end of file 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" + ] + } + } }