Merge branch 'feature/xaudio2'

This commit is contained in:
David Hrdlička
2022-02-20 01:27:48 +01:00
13 changed files with 439 additions and 280 deletions

View File

@@ -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.

View File

@@ -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

View File

@@ -114,8 +114,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(OPENAL "OpenAL" OFF)
option(FLUIDSYNTH "FluidSynth" ON)
option(MUNT "MUNT" ON)
option(DINPUT "DirectInput" OFF)

View File

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

View File

@@ -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,28 +86,6 @@ if(APPLE)
target_link_libraries(86Box Freetype::Freetype)
endif()
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)
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)

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

@@ -19,12 +19,46 @@ 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 OR FAUDIO)
target_compile_definitions(snd PRIVATE USE_OPENAL)
if (FAUDIO)
target_sources(snd PRIVATE faudio.cpp)
if(OPENAL)
if(VCPKG_TOOLCHAIN)
find_package(OpenAL CONFIG REQUIRED)
elseif(MINGW)
find_package(OpenAL MODULE REQUIRED)
else()
target_sources(snd PRIVATE openal.c)
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()

View File

@@ -1,219 +0,0 @@
/*
* 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 <math.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <FAudio.h>
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);
}
}

View File

@@ -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));

View File

@@ -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));

View File

@@ -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);

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

@@ -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) \