mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-22 12:01:33 +00:00
- Added FluidSynth support as snd_mididevice -5. Only tested with Linux. I will have
to try compiling it myself on Windows to see if it's really that slow or if Ubuntu just ships an unoptimized version, because performance is pretty pathetic when compared to the other options. (I understand that it's a complete SoundFont2 renderer, so it is understandably slower than something like TiMidity++, but still. Does it really need to be around 10x slower? I played with the chorus, reverb, and interpolation settings, and none of them seemed to make much difference in performance.) SVN r2545 (trunk)
This commit is contained in:
parent
0657121847
commit
1fa4bbf69c
9 changed files with 239 additions and 18 deletions
23
FindFluidSynth.cmake
Normal file
23
FindFluidSynth.cmake
Normal file
|
@ -0,0 +1,23 @@
|
|||
# - Find fluidsynth
|
||||
# Find the native fluidsynth includes and library
|
||||
#
|
||||
# FLUIDSYNTH_INCLUDE_DIR - where to find fluidsynth.h
|
||||
# FLUIDSYNTH_LIBRARIES - List of libraries when using fluidsynth.
|
||||
# FLUIDSYNTH_FOUND - True if fluidsynth found.
|
||||
|
||||
|
||||
IF (FLUIDSYNTH_INCLUDE_DIR AND FLUIDSYNTH_LIBRARIES)
|
||||
# Already in cache, be silent
|
||||
SET(FluidSynth_FIND_QUIETLY TRUE)
|
||||
ENDIF (FLUIDSYNTH_INCLUDE_DIR AND FLUIDSYNTH_LIBRARIES)
|
||||
|
||||
FIND_PATH(FLUIDSYNTH_INCLUDE_DIR fluidsynth.h)
|
||||
|
||||
FIND_LIBRARY(FLUIDSYNTH_LIBRARIES NAMES fluidsynth )
|
||||
MARK_AS_ADVANCED( FLUIDSYNTH_LIBRARIES FLUIDSYNTH_INCLUDE_DIR )
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set FLUIDSYNTH_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(FluidSynth DEFAULT_MSG FLUIDSYNTH_LIBRARIES FLUIDSYNTH_INCLUDE_DIR)
|
||||
|
|
@ -31,6 +31,10 @@ endif( CMAKE_SIZEOF_VOID_P MATCHES "8" )
|
|||
# fmodapi<version>linux[64] -or simply- fmod
|
||||
# jpeg-6b
|
||||
# ...
|
||||
# The recommended method is to put it in the zdoom tree, since its
|
||||
# headers are unversioned. Especially now that we can't work properly
|
||||
# with anything newer than 4.26.xx, you probably don't want to use
|
||||
# a system-wide version.
|
||||
|
||||
# Construct version numbers for searching for the FMOD library on Linux.
|
||||
set( MINOR_VERSIONS "50" "49" "48" "47" "46" "45" "44" "43" "42" "41"
|
||||
|
@ -236,6 +240,10 @@ else( FMOD_LIBRARY )
|
|||
endif( FMOD_LIBRARY )
|
||||
|
||||
|
||||
# Search for FluidSynth
|
||||
|
||||
include( ../FindFluidSynth.cmake )
|
||||
|
||||
# Search for NASM
|
||||
|
||||
if( NOT NO_ASM )
|
||||
|
@ -370,7 +378,8 @@ endif( SSE_MATTERS )
|
|||
|
||||
if( CMAKE_COMPILER_IS_GNUCXX )
|
||||
if( PROFILE )
|
||||
set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -pg" )
|
||||
set( CMAKE_C_FLinclude( FindFluidSynth.cmake )
|
||||
AGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -pg" )
|
||||
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg" )
|
||||
set( CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -pg" )
|
||||
set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -pg" )
|
||||
|
@ -476,8 +485,10 @@ add_custom_target( revision_check ALL
|
|||
|
||||
# Libraries ZDoom needs
|
||||
|
||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${FMOD_LIBRARY}" )
|
||||
include_directories( "${ZLIB_INCLUDE_DIR}" "${FMOD_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" )
|
||||
|
||||
message( STATUS "Fluid synth libs: ${FLUIDSYNTH_LIBRARIES}" )
|
||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${FMOD_LIBRARY}" "${FLUIDSYNTH_LIBRARIES}" )
|
||||
include_directories( "${ZLIB_INCLUDE_DIR}" "${FMOD_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${FLUIDSYNTH_INCLUDE_DIR}" )
|
||||
|
||||
# Start defining source files for ZDoom
|
||||
|
||||
|
@ -572,6 +583,9 @@ else( SSE_MATTERS )
|
|||
set( X86_SOURCES )
|
||||
endif( SSE_MATTERS )
|
||||
|
||||
if( FLUIDSYNTH_FOUND )
|
||||
add_definitions( -DHAVE_FLUIDSYNTH )
|
||||
endif( FLUIDSYNTH_FOUND )
|
||||
|
||||
add_executable( zdoom WIN32
|
||||
autostart.cpp
|
||||
|
@ -793,6 +807,7 @@ add_executable( zdoom WIN32
|
|||
sound/music_mus_midiout.cpp
|
||||
sound/music_mus_opl.cpp
|
||||
sound/music_stream.cpp
|
||||
sound/music_fluidsynth_mididevice.cpp
|
||||
sound/music_timidity_mididevice.cpp
|
||||
sound/music_win_mididevice.cpp
|
||||
textures/automaptexture.cpp
|
||||
|
|
|
@ -101,6 +101,7 @@ EXTERN_CVAR (Int, snd_buffersize)
|
|||
EXTERN_CVAR (Int, snd_samplerate)
|
||||
EXTERN_CVAR (Bool, snd_pitched)
|
||||
EXTERN_CVAR (Int, snd_channels)
|
||||
EXTERN_CVAR (String, snd_midipatchset)
|
||||
|
||||
extern int sfx_empty;
|
||||
|
||||
|
@ -115,7 +116,6 @@ CVAR (Bool, snd_waterreverb, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|||
CVAR (String, snd_resampler, "Linear", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (String, snd_speakermode, "Auto", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (String, snd_output_format, "PCM-16", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (String, snd_midipatchset, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, snd_profile, false, 0)
|
||||
|
||||
// Underwater low-pass filter cutoff frequency. Set to 0 to disable the filter.
|
||||
|
@ -644,6 +644,7 @@ bool FMODSoundRenderer::Init()
|
|||
ChannelGroupTargetUnit = NULL;
|
||||
SfxReverbHooked = false;
|
||||
SfxReverbPlaceholder = NULL;
|
||||
SfxHeadMixer = NULL;
|
||||
OutputPlugin = 0;
|
||||
|
||||
Printf("I_InitSound: Initializing FMOD\n");
|
||||
|
@ -706,7 +707,8 @@ bool FMODSoundRenderer::Init()
|
|||
|
||||
if (!ShowedBanner)
|
||||
{
|
||||
Printf("FMOD Sound System, copyright © Firelight Technologies Pty, Ltd., 1994-2009.\n");
|
||||
// '\xa9' is the copyright symbol in the Windows-1252 code page.
|
||||
Printf("FMOD Sound System, copyright \xa9 Firelight Technologies Pty, Ltd., 1994-2009.\n");
|
||||
Printf("Loaded FMOD version %x.%02x.%02x\n", version >> 16, (version >> 8) & 255, version & 255);
|
||||
ShowedBanner = true;
|
||||
}
|
||||
|
@ -1014,6 +1016,12 @@ bool FMODSoundRenderer::Init()
|
|||
result = Sys->createDSPByType(FMOD_DSP_TYPE_MIXER, &SfxReverbPlaceholder);
|
||||
if (result == FMOD_OK)
|
||||
{
|
||||
result = Sys->createDSPByType(FMOD_DSP_TYPE_MIXER, &SfxHeadMixer);
|
||||
result = sfx_head->addInput(SfxHeadMixer, &SfxConnection);
|
||||
result = sfx_head->disconnectFrom(pausable_head);
|
||||
sfx_head = SfxHeadMixer;
|
||||
SfxHeadMixer->setActive(true);
|
||||
SfxHeadMixer->setBypass(false);
|
||||
// Replace the PausableSFX->SFX connection with
|
||||
// PausableSFX->ReverbPlaceholder->SFX.
|
||||
result = SfxReverbPlaceholder->addInput(pausable_head, NULL);
|
||||
|
@ -1023,13 +1031,13 @@ bool FMODSoundRenderer::Init()
|
|||
result = sfx_head->addInput(SfxReverbPlaceholder, &connection);
|
||||
if (result == FMOD_OK)
|
||||
{
|
||||
sfx_head->disconnectFrom(pausable_head);
|
||||
// sfx_head->disconnectFrom(pausable_head);
|
||||
SfxReverbPlaceholder->setActive(true);
|
||||
SfxReverbPlaceholder->setBypass(true);
|
||||
// The placeholder now takes the place of the pausable_head
|
||||
// for the following connections.
|
||||
pausable_head = SfxReverbPlaceholder;
|
||||
SfxConnection = connection;
|
||||
// SfxConnection = connection;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1038,6 +1046,7 @@ bool FMODSoundRenderer::Init()
|
|||
SfxReverbPlaceholder = NULL;
|
||||
}
|
||||
}
|
||||
#if 1
|
||||
result = WaterLP->addInput(pausable_head, NULL);
|
||||
WaterLP->setActive(false);
|
||||
WaterLP->setParameter(FMOD_DSP_LOWPASS_CUTOFF, snd_waterlp);
|
||||
|
@ -1069,6 +1078,7 @@ bool FMODSoundRenderer::Init()
|
|||
{
|
||||
result = sfx_head->addInput(WaterLP, NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1147,6 +1157,11 @@ void FMODSoundRenderer::Shutdown()
|
|||
SfxReverbPlaceholder->release();
|
||||
SfxReverbPlaceholder = NULL;
|
||||
}
|
||||
if (SfxHeadMixer != NULL)
|
||||
{
|
||||
SfxHeadMixer->release();
|
||||
SfxHeadMixer = NULL;
|
||||
}
|
||||
|
||||
Sys->close();
|
||||
if (OutputPlugin != 0)
|
||||
|
@ -1330,10 +1345,10 @@ FString FMODSoundRenderer::GatherStats()
|
|||
#endif
|
||||
|
||||
out.Format ("%d channels,"TEXTCOLOR_YELLOW"%5.2f"TEXTCOLOR_NORMAL"%% CPU "
|
||||
"(DSP:"TEXTCOLOR_YELLOW"%2.2f"TEXTCOLOR_NORMAL"%% "
|
||||
"Stream:"TEXTCOLOR_YELLOW"%2.2f"TEXTCOLOR_NORMAL"%% "
|
||||
"Geometry:"TEXTCOLOR_YELLOW"%2.2f"TEXTCOLOR_NORMAL"%% "
|
||||
"Update:"TEXTCOLOR_YELLOW"%2.2f"TEXTCOLOR_NORMAL"%%)",
|
||||
"(DSP:"TEXTCOLOR_YELLOW"%5.2f"TEXTCOLOR_NORMAL"%% "
|
||||
"Stream:"TEXTCOLOR_YELLOW"%5.2f"TEXTCOLOR_NORMAL"%% "
|
||||
"Geometry:"TEXTCOLOR_YELLOW"%5.2f"TEXTCOLOR_NORMAL"%% "
|
||||
"Update:"TEXTCOLOR_YELLOW"%5.2f"TEXTCOLOR_NORMAL"%%)",
|
||||
channels, total, dsp, stream, geometry, update);
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -104,6 +104,7 @@ private:
|
|||
FMOD::DSPConnection *SfxConnection;
|
||||
FMOD::DSP *ChannelGroupTargetUnit;
|
||||
FMOD::DSP *SfxReverbPlaceholder;
|
||||
FMOD::DSP *SfxHeadMixer;
|
||||
bool SfxReverbHooked;
|
||||
float LastWaterLP;
|
||||
unsigned int OutputPlugin;
|
||||
|
|
|
@ -162,6 +162,18 @@ void MusInfo::TimidityVolumeChanged()
|
|||
{
|
||||
}
|
||||
|
||||
void MusInfo::FluidSettingInt(const char *, int)
|
||||
{
|
||||
}
|
||||
|
||||
void MusInfo::FluidSettingNum(const char *, double)
|
||||
{
|
||||
}
|
||||
|
||||
void MusInfo::FluidSettingStr(const char *, const char *)
|
||||
{
|
||||
}
|
||||
|
||||
FString MusInfo::GetStats()
|
||||
{
|
||||
return "No stats available for this song";
|
||||
|
@ -428,6 +440,12 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
|
|||
{
|
||||
info = new MUSSong2(file, musiccache, len, MIDI_Timidity);
|
||||
}
|
||||
#ifdef HAVE_FLUIDSYNTH
|
||||
else if (snd_mididevice == -5 && device == MDEV_DEFAULT)
|
||||
{
|
||||
info = new MUSSong2(file, musiccache, len, MIDI_Fluid);
|
||||
}
|
||||
#endif
|
||||
if (info != NULL && !info->IsValid())
|
||||
{
|
||||
delete info;
|
||||
|
|
|
@ -98,6 +98,9 @@ public:
|
|||
virtual FString GetStats();
|
||||
virtual MusInfo *GetOPLDumper(const char *filename);
|
||||
virtual MusInfo *GetWaveDumper(const char *filename, int rate);
|
||||
virtual void FluidSettingInt(const char *setting, int value); // FluidSynth settings
|
||||
virtual void FluidSettingNum(const char *setting, double value); // "
|
||||
virtual void FluidSettingStr(const char *setting, const char *value); // "
|
||||
|
||||
enum EState
|
||||
{
|
||||
|
|
|
@ -95,6 +95,9 @@ public:
|
|||
virtual bool NeedThreadedCallback() = 0;
|
||||
virtual void PrecacheInstruments(const WORD *instruments, int count);
|
||||
virtual void TimidityVolumeChanged();
|
||||
virtual void FluidSettingInt(const char *setting, int value);
|
||||
virtual void FluidSettingNum(const char *setting, double value);
|
||||
virtual void FluidSettingStr(const char *setting, const char *value);
|
||||
virtual FString GetStats();
|
||||
};
|
||||
|
||||
|
@ -255,6 +258,64 @@ protected:
|
|||
FILE *File;
|
||||
};
|
||||
|
||||
// FluidSynth implementation of a MIDI device -------------------------------
|
||||
|
||||
#ifdef HAVE_FLUIDSYNTH
|
||||
#include <fluidsynth.h>
|
||||
|
||||
class FluidSynthMIDIDevice : public MIDIDevice
|
||||
{
|
||||
public:
|
||||
FluidSynthMIDIDevice();
|
||||
~FluidSynthMIDIDevice();
|
||||
|
||||
int Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata);
|
||||
void Close();
|
||||
bool IsOpen() const;
|
||||
int GetTechnology() const;
|
||||
int SetTempo(int tempo);
|
||||
int SetTimeDiv(int timediv);
|
||||
int StreamOut(MIDIHDR *data);
|
||||
int StreamOutSync(MIDIHDR *data);
|
||||
int Resume();
|
||||
void Stop();
|
||||
int PrepareHeader(MIDIHDR *data);
|
||||
int UnprepareHeader(MIDIHDR *data);
|
||||
bool FakeVolume();
|
||||
bool Pause(bool paused);
|
||||
bool NeedThreadedCallback();
|
||||
void PrecacheInstruments(const WORD *instruments, int count);
|
||||
FString GetStats();
|
||||
void FluidSettingInt(const char *setting, int value);
|
||||
void FluidSettingNum(const char *setting, double value);
|
||||
void FluidSettingStr(const char *setting, const char *value);
|
||||
|
||||
protected:
|
||||
static bool FillStream(SoundStream *stream, void *buff, int len, void *userdata);
|
||||
bool ServiceStream(void *buff, int numbytes);
|
||||
void HandleEvent(int status, int parm1, int parm2);
|
||||
int LoadPatchSets(const char *patches);
|
||||
|
||||
void (*Callback)(unsigned int, void *, DWORD, DWORD);
|
||||
void *CallbackData;
|
||||
|
||||
void CalcTickRate();
|
||||
int PlayTick();
|
||||
|
||||
FCriticalSection CritSec;
|
||||
SoundStream *Stream;
|
||||
fluid_settings_t *FluidSettings;
|
||||
fluid_synth_t *FluidSynth;
|
||||
double Tempo;
|
||||
double Division;
|
||||
double SamplesPerTick;
|
||||
double NextTickIn;
|
||||
MIDIHDR *Events;
|
||||
bool Started;
|
||||
DWORD Position;
|
||||
};
|
||||
#endif
|
||||
|
||||
// Base class for streaming MUS and MIDI files ------------------------------
|
||||
|
||||
// MIDI device selection.
|
||||
|
@ -262,7 +323,8 @@ enum EMIDIDevice
|
|||
{
|
||||
MIDI_Win,
|
||||
MIDI_OPL,
|
||||
MIDI_Timidity
|
||||
MIDI_Timidity,
|
||||
MIDI_Fluid
|
||||
};
|
||||
|
||||
class MIDIStreamer : public MusInfo
|
||||
|
@ -282,6 +344,9 @@ public:
|
|||
bool IsValid() const;
|
||||
void Update();
|
||||
FString GetStats();
|
||||
void FluidSettingInt(const char *setting, int value);
|
||||
void FluidSettingNum(const char *setting, double value);
|
||||
void FluidSettingStr(const char *setting, const char *value);
|
||||
|
||||
protected:
|
||||
MIDIStreamer(const char *dumpname, EMIDIDevice type);
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
|
||||
static DWORD nummididevices;
|
||||
static bool nummididevicesset;
|
||||
|
||||
CVAR (String, snd_midipatchset, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
|
||||
|
||||
#ifdef _WIN32
|
||||
UINT mididevice;
|
||||
|
||||
|
@ -19,7 +22,7 @@ CUSTOM_CVAR (Int, snd_mididevice, -1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|||
if (!nummididevicesset)
|
||||
return;
|
||||
|
||||
if ((self >= (signed)nummididevices) || (self < -4))
|
||||
if ((self >= (signed)nummididevices) || (self < -5))
|
||||
{
|
||||
Printf ("ID out of range. Using default device.\n");
|
||||
self = 0;
|
||||
|
@ -177,8 +180,8 @@ CCMD (snd_listmididevices)
|
|||
|
||||
CUSTOM_CVAR(Int, snd_mididevice, -1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
{
|
||||
if (self < -3)
|
||||
self = -3;
|
||||
if (self < -5)
|
||||
self = -5;
|
||||
else if (self > -1)
|
||||
self = -1;
|
||||
}
|
||||
|
|
|
@ -215,6 +215,12 @@ void MIDIStreamer::Play(bool looping, int subsong)
|
|||
assert(0);
|
||||
// Intentional fall-through for non-Windows systems.
|
||||
|
||||
#ifdef HAVE_FLUIDSYNTH
|
||||
case MIDI_Fluid:
|
||||
MIDI = new FluidSynthMIDIDevice;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case MIDI_Timidity:
|
||||
MIDI = new TimidityMIDIDevice;
|
||||
break;
|
||||
|
@ -225,10 +231,10 @@ void MIDIStreamer::Play(bool looping, int subsong)
|
|||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
assert(MIDI->NeedThreadedCallback() == false);
|
||||
assert(MIDI == NULL || MIDI->NeedThreadedCallback() == false);
|
||||
#endif
|
||||
|
||||
if (0 != MIDI->Open(Callback, this))
|
||||
if (MIDI == NULL || 0 != MIDI->Open(Callback, this))
|
||||
{
|
||||
Printf(PRINT_BOLD, "Could not open MIDI out device\n");
|
||||
return;
|
||||
|
@ -435,6 +441,48 @@ void MIDIStreamer::TimidityVolumeChanged()
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MIDIStreamer :: FluidSettingInt
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void MIDIStreamer::FluidSettingInt(const char *setting, int value)
|
||||
{
|
||||
if (MIDI != NULL)
|
||||
{
|
||||
MIDI->FluidSettingInt(setting, value);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MIDIStreamer :: FluidSettingNum
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void MIDIStreamer::FluidSettingNum(const char *setting, double value)
|
||||
{
|
||||
if (MIDI != NULL)
|
||||
{
|
||||
MIDI->FluidSettingNum(setting, value);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MIDIDeviceStreamer :: FluidSettingStr
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void MIDIStreamer::FluidSettingStr(const char *setting, const char *value)
|
||||
{
|
||||
if (MIDI != NULL)
|
||||
{
|
||||
MIDI->FluidSettingStr(setting, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -840,6 +888,36 @@ void MIDIDevice::TimidityVolumeChanged()
|
|||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MIDIDevice :: FluidSettingInt
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void MIDIDevice::FluidSettingInt(const char *setting, int value)
|
||||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MIDIDevice :: FluidSettingNum
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void MIDIDevice::FluidSettingNum(const char *setting, double value)
|
||||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MIDIDevice :: FluidSettingStr
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void MIDIDevice::FluidSettingStr(const char *setting, const char *value)
|
||||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MIDIDevice :: GetStats
|
||||
|
|
Loading…
Reference in a new issue