Load fluidsynth entrypoints dynamically (and make them optional)
This removes the static dependency on fluidsynth being present at buildtime (even headers aren't needed anymore). Even though midi is a default format for the RPG XP/VX series, it has fallen more and more out of use, with VX Ace completely abandoning it from the RTP and making ogg vorbis the de facto standard. Midi support is kept for legacy reasons, but isn't encouraged. On top of all this, fluidsynth together with glib is a heavy dependency that often times won't even be used. Making it optional at build time is an attempt to unify and keep build config fragmentation low. In RGSS3, fluidsynth / midi is not initialized at all by default, but rather on demand when either a midi track is played back or Audio.setup_midi is called.
This commit is contained in:
parent
673a25f811
commit
757a1d5e39
|
@ -3,7 +3,7 @@ Project(mkxp)
|
||||||
|
|
||||||
## Setup options ##
|
## Setup options ##
|
||||||
|
|
||||||
option(MIDI "Enable midi support" ON)
|
option(SHARED_FLUID "Dynamically link fluidsynth at build time" OFF)
|
||||||
option(WORKDIR_CURRENT "Keep current directory on startup" OFF)
|
option(WORKDIR_CURRENT "Keep current directory on startup" OFF)
|
||||||
option(FORCE32 "Force 32bit compile on 64bit OS" OFF)
|
option(FORCE32 "Force 32bit compile on 64bit OS" OFF)
|
||||||
set(BINDING "MRI" CACHE STRING "The Binding Type (MRI, MRUBY, NULL)")
|
set(BINDING "MRI" CACHE STRING "The Binding Type (MRI, MRUBY, NULL)")
|
||||||
|
@ -151,6 +151,8 @@ set(MAIN_HEADERS
|
||||||
src/windowvx.h
|
src/windowvx.h
|
||||||
src/tilemapvx.h
|
src/tilemapvx.h
|
||||||
src/tileatlasvx.h
|
src/tileatlasvx.h
|
||||||
|
src/sharedmidistate.h
|
||||||
|
src/fluid-fun.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(MAIN_SOURCE
|
set(MAIN_SOURCE
|
||||||
|
@ -193,6 +195,8 @@ set(MAIN_SOURCE
|
||||||
src/tilemapvx.cpp
|
src/tilemapvx.cpp
|
||||||
src/tileatlasvx.cpp
|
src/tileatlasvx.cpp
|
||||||
src/autotilesvx.cpp
|
src/autotilesvx.cpp
|
||||||
|
src/midisource.cpp
|
||||||
|
src/fluid-fun.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
source_group("MKXP Source" FILES ${MAIN_SOURCE} ${MAIN_HEADERS})
|
source_group("MKXP Source" FILES ${MAIN_SOURCE} ${MAIN_HEADERS})
|
||||||
|
@ -227,16 +231,10 @@ if (RGSS2)
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (MIDI)
|
if (SHARED_FLUID)
|
||||||
pkg_check_modules(MIDI REQUIRED fluidsynth)
|
pkg_check_modules(FLUID REQUIRED fluidsynth)
|
||||||
list(APPEND DEFINES
|
list(APPEND DEFINES
|
||||||
MIDI
|
SHARED_FLUID
|
||||||
)
|
|
||||||
list(APPEND MAIN_HEADERS
|
|
||||||
src/sharedmidistate.h
|
|
||||||
)
|
|
||||||
list(APPEND MAIN_SOURCE
|
|
||||||
src/midisource.cpp
|
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -400,7 +398,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE
|
||||||
${Boost_INCLUDE_DIR}
|
${Boost_INCLUDE_DIR}
|
||||||
${MRI_INCLUDE_DIRS}
|
${MRI_INCLUDE_DIRS}
|
||||||
${VORBISFILE_INCLUDE_DIRS}
|
${VORBISFILE_INCLUDE_DIRS}
|
||||||
${MIDI_INCLUDE_DIRS}
|
${FLUID_INCLUDE_DIRS}
|
||||||
${OPENAL_INCLUDE_DIR}
|
${OPENAL_INCLUDE_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -415,7 +413,7 @@ target_link_libraries(${PROJECT_NAME}
|
||||||
${Boost_LIBRARIES}
|
${Boost_LIBRARIES}
|
||||||
${MRI_LIBRARIES}
|
${MRI_LIBRARIES}
|
||||||
${VORBISFILE_LIBRARIES}
|
${VORBISFILE_LIBRARIES}
|
||||||
${MIDI_LIBRARIES}
|
${FLUID_LIBRARIES}
|
||||||
${OPENAL_LIBRARY}
|
${OPENAL_LIBRARY}
|
||||||
${ZLIB_LIBRARY}
|
${ZLIB_LIBRARY}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,6 @@ This binding only exists for testing purposes and does nothing (the engine quits
|
||||||
* SDL_sound (latest hg, apply provided patches!)
|
* SDL_sound (latest hg, apply provided patches!)
|
||||||
* vorbisfile
|
* vorbisfile
|
||||||
* pixman
|
* pixman
|
||||||
* fluidsynth (if midi enabled)
|
|
||||||
* zlib (only ruby bindings)
|
* zlib (only ruby bindings)
|
||||||
* OpenGL header (alternatively GLES2 with `DEFINES+=GLES2_HEADER`)
|
* OpenGL header (alternatively GLES2 with `DEFINES+=GLES2_HEADER`)
|
||||||
* libiconv (on Windows, optional with INI_ENCODING)
|
* libiconv (on Windows, optional with INI_ENCODING)
|
||||||
|
@ -72,7 +71,7 @@ qmake will use pkg-config to locate the respective include/library paths. If you
|
||||||
|
|
||||||
The exception is boost, which is weird in that it still hasn't managed to pull off pkg-config support (seriously?). *If you installed boost in a non-standard prefix*, you will need to pass its include path via `BOOST_I` and library path via `BOOST_L`, either as direct arguments to qmake (`qmake BOOST_I="/usr/include" ...`) or via environment variables. You can specify a library suffix (eg. "-mt") via `BOOST_LIB_SUFFIX` if needed.
|
The exception is boost, which is weird in that it still hasn't managed to pull off pkg-config support (seriously?). *If you installed boost in a non-standard prefix*, you will need to pass its include path via `BOOST_I` and library path via `BOOST_L`, either as direct arguments to qmake (`qmake BOOST_I="/usr/include" ...`) or via environment variables. You can specify a library suffix (eg. "-mt") via `BOOST_LIB_SUFFIX` if needed.
|
||||||
|
|
||||||
Midi support is enabled by default; you can disable it via `qmake CONFIG+=DISABLE_MIDI`, in which case the fluidsynth dependency is dropped. When building fluidsynth yourself, you can disable almost all options (audio drivers etc.) as they are not used. Note that upstream fluidsynth has support for sharing soundfont data between synthesizers (mkxp uses multiple synths), so if your memory usage is very high, you might want to try compiling fluidsynth from git master.
|
Midi support is enabled by default and requires fluidsynth to be present at runtime (not needed for building); if mkxp can't find it at runtime, midi playback is disabled. It looks for `libfluidsynth.so.1` on Linux, `libfluidsynth.dylib.1` on OSX and `fluidsynth.dll` on Windows, so make sure to have one of these in your link path. If you still need fluidsynth to be hard linked at buildtime, use `CONFIG+=SHARED_FLUID`. When building fluidsynth yourself, you can disable almost all options (audio drivers etc.) as they are not used. Note that upstream fluidsynth has support for sharing soundfont data between synthesizers (mkxp uses multiple synths), so if your memory usage is very high, you might want to try compiling fluidsynth from git master.
|
||||||
|
|
||||||
By default, mkxp switches into the directory where its binary is contained and then starts reading the configuration and resolving relative paths. In case this is undesired (eg. when the binary is to be installed to a system global, read-only location), it can be turned off by adding `DEFINES+=WORKDIR_CURRENT` to qmake's arguments.
|
By default, mkxp switches into the directory where its binary is contained and then starts reading the configuration and resolving relative paths. In case this is undesired (eg. when the binary is to be installed to a system global, read-only location), it can be turned off by adding `DEFINES+=WORKDIR_CURRENT` to qmake's arguments.
|
||||||
|
|
||||||
|
|
26
mkxp.pro
26
mkxp.pro
|
@ -8,12 +8,6 @@ INCLUDEPATH += . src
|
||||||
|
|
||||||
CONFIG(release, debug|release): DEFINES += NDEBUG
|
CONFIG(release, debug|release): DEFINES += NDEBUG
|
||||||
|
|
||||||
CONFIG += MIDI
|
|
||||||
|
|
||||||
DISABLE_MIDI {
|
|
||||||
CONFIG -= MIDI
|
|
||||||
}
|
|
||||||
|
|
||||||
isEmpty(BINDING) {
|
isEmpty(BINDING) {
|
||||||
BINDING = MRI
|
BINDING = MRI
|
||||||
}
|
}
|
||||||
|
@ -50,7 +44,7 @@ unix {
|
||||||
PKGCONFIG += sigc++-2.0 pixman-1 zlib physfs vorbisfile \
|
PKGCONFIG += sigc++-2.0 pixman-1 zlib physfs vorbisfile \
|
||||||
sdl2 SDL2_image SDL2_ttf SDL_sound openal
|
sdl2 SDL2_image SDL2_ttf SDL_sound openal
|
||||||
|
|
||||||
MIDI {
|
SHARED_FLUID {
|
||||||
PKGCONFIG += fluidsynth
|
PKGCONFIG += fluidsynth
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +129,9 @@ HEADERS += \
|
||||||
src/rgssad.h \
|
src/rgssad.h \
|
||||||
src/windowvx.h \
|
src/windowvx.h \
|
||||||
src/tilemapvx.h \
|
src/tilemapvx.h \
|
||||||
src/tileatlasvx.h
|
src/tileatlasvx.h \
|
||||||
|
src/sharedmidistate.h \
|
||||||
|
src/fluid-fun.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
src/main.cpp \
|
src/main.cpp \
|
||||||
|
@ -176,7 +172,9 @@ SOURCES += \
|
||||||
src/windowvx.cpp \
|
src/windowvx.cpp \
|
||||||
src/tilemapvx.cpp \
|
src/tilemapvx.cpp \
|
||||||
src/tileatlasvx.cpp \
|
src/tileatlasvx.cpp \
|
||||||
src/autotilesvx.cpp
|
src/autotilesvx.cpp \
|
||||||
|
src/midisource.cpp \
|
||||||
|
src/fluid-fun.cpp
|
||||||
|
|
||||||
EMBED = \
|
EMBED = \
|
||||||
shader/transSimple.frag \
|
shader/transSimple.frag \
|
||||||
|
@ -200,14 +198,8 @@ EMBED = \
|
||||||
shader/tilemapvx.vert \
|
shader/tilemapvx.vert \
|
||||||
assets/liberation.ttf
|
assets/liberation.ttf
|
||||||
|
|
||||||
MIDI {
|
SHARED_FLUID {
|
||||||
HEADERS += \
|
DEFINES += SHARED_FLUID
|
||||||
src/sharedmidistate.h
|
|
||||||
|
|
||||||
SOURCES += \
|
|
||||||
src/midisource.cpp
|
|
||||||
|
|
||||||
DEFINES += MIDI
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INI_ENCODING {
|
INI_ENCODING {
|
||||||
|
|
|
@ -61,9 +61,7 @@ ALDataSource *createSDLSource(SDL_RWops &ops,
|
||||||
ALDataSource *createVorbisSource(SDL_RWops &ops,
|
ALDataSource *createVorbisSource(SDL_RWops &ops,
|
||||||
bool looped);
|
bool looped);
|
||||||
|
|
||||||
#ifdef MIDI
|
|
||||||
ALDataSource *createMidiSource(SDL_RWops &ops,
|
ALDataSource *createMidiSource(SDL_RWops &ops,
|
||||||
bool looped);
|
bool looped);
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // ALDATASOURCE_H
|
#endif // ALDATASOURCE_H
|
||||||
|
|
|
@ -22,8 +22,10 @@
|
||||||
#include "alstream.h"
|
#include "alstream.h"
|
||||||
|
|
||||||
#include "sharedstate.h"
|
#include "sharedstate.h"
|
||||||
|
#include "sharedmidistate.h"
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
#include "aldatasource.h"
|
#include "aldatasource.h"
|
||||||
|
#include "fluid-fun.h"
|
||||||
|
|
||||||
#include <SDL_mutex.h>
|
#include <SDL_mutex.h>
|
||||||
#include <SDL_thread.h>
|
#include <SDL_thread.h>
|
||||||
|
@ -198,32 +200,26 @@ void ALStream::openSource(const std::string &filename)
|
||||||
shState->fileSystem().openRead(srcOps, filename.c_str(), FileSystem::Audio, false, &ext);
|
shState->fileSystem().openRead(srcOps, filename.c_str(), FileSystem::Audio, false, &ext);
|
||||||
needsRewind = false;
|
needsRewind = false;
|
||||||
|
|
||||||
bool readSig = rgssVer >= 2;
|
/* Try to read ogg file signature */
|
||||||
|
char sig[5] = { 0 };
|
||||||
|
SDL_RWread(&srcOps, sig, 1, 4);
|
||||||
|
SDL_RWseek(&srcOps, 0, RW_SEEK_SET);
|
||||||
|
|
||||||
#ifdef MIDI
|
if (!strcmp(sig, "OggS"))
|
||||||
readSig = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (readSig)
|
|
||||||
{
|
{
|
||||||
/* Try to read ogg file signature */
|
source = createVorbisSource(srcOps, looped);
|
||||||
char sig[5] = { 0 };
|
return;
|
||||||
SDL_RWread(&srcOps, sig, 1, 4);
|
}
|
||||||
SDL_RWseek(&srcOps, 0, RW_SEEK_SET);
|
|
||||||
|
|
||||||
if (!strcmp(sig, "OggS"))
|
if (!strcmp(sig, "MThd"))
|
||||||
{
|
{
|
||||||
source = createVorbisSource(srcOps, looped);
|
shState->midiState().initIfNeeded(shState->config());
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MIDI
|
if (HAVE_FLUID)
|
||||||
if (!strcmp(sig, "MThd"))
|
|
||||||
{
|
{
|
||||||
source = createMidiSource(srcOps, looped);
|
source = createMidiSource(srcOps, looped);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
source = createSDLSource(srcOps, ext, STREAM_BUF_SIZE, looped);
|
source = createSDLSource(srcOps, ext, STREAM_BUF_SIZE, looped);
|
||||||
|
|
|
@ -24,10 +24,7 @@
|
||||||
#include "audiostream.h"
|
#include "audiostream.h"
|
||||||
#include "soundemitter.h"
|
#include "soundemitter.h"
|
||||||
#include "sharedstate.h"
|
#include "sharedstate.h"
|
||||||
|
|
||||||
#ifdef MIDI
|
|
||||||
#include "sharedmidistate.h"
|
#include "sharedmidistate.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -317,9 +314,7 @@ void Audio::seStop()
|
||||||
|
|
||||||
void Audio::setupMidi()
|
void Audio::setupMidi()
|
||||||
{
|
{
|
||||||
#ifdef MIDI
|
shState->midiState().initIfNeeded(shState->config());
|
||||||
shState->midiState().initDefaultSynths();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float Audio::bgmPos()
|
float Audio::bgmPos()
|
||||||
|
|
|
@ -340,10 +340,8 @@ FileSystem::FileSystem(const char *argv0,
|
||||||
if (rgssVer >= 2 && !contains(p->extensions[Audio], std::string("ogg")))
|
if (rgssVer >= 2 && !contains(p->extensions[Audio], std::string("ogg")))
|
||||||
p->extensions[Audio].push_back("ogg");
|
p->extensions[Audio].push_back("ogg");
|
||||||
|
|
||||||
#if MIDI
|
|
||||||
p->extensions[Audio].push_back("mid");
|
p->extensions[Audio].push_back("mid");
|
||||||
p->extensions[Audio].push_back("midi");
|
p->extensions[Audio].push_back("midi");
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Font extensions */
|
/* Font extensions */
|
||||||
p->extensions[Font].push_back("ttf");
|
p->extensions[Font].push_back("ttf");
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
#include "fluid-fun.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <SDL_loadso.h>
|
||||||
|
#include <SDL_platform.h>
|
||||||
|
|
||||||
|
#include "debugwriter.h"
|
||||||
|
|
||||||
|
#ifdef SHARED_FLUID
|
||||||
|
#include <fluidsynth.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __LINUX__
|
||||||
|
#define FLUID_LIB "libfluidsynth.so.1"
|
||||||
|
#elif __MACOSX__
|
||||||
|
#define FLUID_LIB "libfluidsynth.dylib.1"
|
||||||
|
#elif __WINDOWS__
|
||||||
|
#define FLUID_LIB "fluidsynth.dll"
|
||||||
|
#else
|
||||||
|
#error "platform not recognized"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct FluidFunctions fluid;
|
||||||
|
|
||||||
|
static void *so;
|
||||||
|
|
||||||
|
void initFluidFunctions()
|
||||||
|
{
|
||||||
|
#ifdef SHARED_FLUID
|
||||||
|
|
||||||
|
#define FLUID_FUN(name, type) \
|
||||||
|
fluid.name = fluid_##name;
|
||||||
|
|
||||||
|
#define FLUID_FUN2(name, type, real_name) \
|
||||||
|
fluid.name = real_name;
|
||||||
|
|
||||||
|
#else
|
||||||
|
so = SDL_LoadObject(FLUID_LIB);
|
||||||
|
|
||||||
|
if (!so)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
#define FLUID_FUN(name, type) \
|
||||||
|
fluid.name = (type) SDL_LoadFunction(so, "fluid_" #name); \
|
||||||
|
if (!fluid.name) \
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
#define FLUID_FUN2(name, type, real_name) \
|
||||||
|
fluid.name = (type) SDL_LoadFunction(so, #real_name); \
|
||||||
|
if (!fluid.name) \
|
||||||
|
goto fail;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FLUID_FUNCS
|
||||||
|
FLUID_FUNCS2
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifndef SHARED_FLUID
|
||||||
|
fail:
|
||||||
|
Debug() << "Failed to load " FLUID_LIB ". Midi playback is disabled.";
|
||||||
|
|
||||||
|
memset(&fluid, 0, sizeof(fluid));
|
||||||
|
finiFluidFunctions();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void finiFluidFunctions()
|
||||||
|
{
|
||||||
|
#ifndef SHARED_FLUID
|
||||||
|
SDL_UnloadObject(so);
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
#ifndef FLUIDFUN_H
|
||||||
|
#define FLUIDFUN_H
|
||||||
|
|
||||||
|
typedef struct _fluid_hashtable_t fluid_settings_t;
|
||||||
|
typedef struct _fluid_synth_t fluid_synth_t;
|
||||||
|
|
||||||
|
typedef fluid_settings_t* (*NEWFLUIDSETTINGSPROC)(void);
|
||||||
|
typedef int (*FLUIDSETTINGSSETNUMPROC)(fluid_settings_t* settings, const char *name, double val);
|
||||||
|
typedef int (*FLUIDSETTINGSSETSTRPROC)(fluid_settings_t* settings, const char *name, const char *str);
|
||||||
|
typedef void (*DELETEFLUIDSETTINGSPROC)(fluid_settings_t* settings);
|
||||||
|
typedef fluid_synth_t* (*NEWFLUIDSYNTHPROC)(fluid_settings_t* settings);
|
||||||
|
typedef int (*DELETEFLUIDSYNTHPROC)(fluid_synth_t* synth);
|
||||||
|
typedef int (*FLUIDSYNTHSFLOADPROC)(fluid_synth_t* synth, const char* filename, int reset_presets);
|
||||||
|
typedef int (*FLUIDSYNTHSYSTEMRESETPROC)(fluid_synth_t* synth);
|
||||||
|
typedef int (*FLUIDSYNTHWRITES16PROC)(fluid_synth_t* synth, int len, void* lout, int loff, int lincr, void* rout, int roff, int rincr);
|
||||||
|
typedef int (*FLUIDSYNTHNOTEONPROC)(fluid_synth_t* synth, int chan, int key, int vel);
|
||||||
|
typedef int (*FLUIDSYNTHNOTEOFFPROC)(fluid_synth_t* synth, int chan, int key);
|
||||||
|
typedef int (*FLUIDSYNTHCHANNELPRESSUREPROC)(fluid_synth_t* synth, int chan, int val);
|
||||||
|
typedef int (*FLUIDSYNTHPITCHBENDPROC)(fluid_synth_t* synth, int chan, int val);
|
||||||
|
typedef int (*FLUIDSYNTHCCPROC)(fluid_synth_t* synth, int chan, int ctrl, int val);
|
||||||
|
typedef int (*FLUIDSYNTHPROGRAMCHANGEPROC)(fluid_synth_t* synth, int chan, int program);
|
||||||
|
|
||||||
|
#define FLUID_FUNCS \
|
||||||
|
FLUID_FUN(settings_setnum, FLUIDSETTINGSSETNUMPROC) \
|
||||||
|
FLUID_FUN(settings_setstr, FLUIDSETTINGSSETSTRPROC) \
|
||||||
|
FLUID_FUN(synth_sfload, FLUIDSYNTHSFLOADPROC) \
|
||||||
|
FLUID_FUN(synth_system_reset, FLUIDSYNTHSYSTEMRESETPROC) \
|
||||||
|
FLUID_FUN(synth_write_s16, FLUIDSYNTHWRITES16PROC) \
|
||||||
|
FLUID_FUN(synth_noteon, FLUIDSYNTHNOTEONPROC) \
|
||||||
|
FLUID_FUN(synth_noteoff, FLUIDSYNTHNOTEOFFPROC) \
|
||||||
|
FLUID_FUN(synth_channel_pressure, FLUIDSYNTHCHANNELPRESSUREPROC) \
|
||||||
|
FLUID_FUN(synth_pitch_bend, FLUIDSYNTHPITCHBENDPROC) \
|
||||||
|
FLUID_FUN(synth_cc, FLUIDSYNTHCCPROC) \
|
||||||
|
FLUID_FUN(synth_program_change, FLUIDSYNTHPROGRAMCHANGEPROC)
|
||||||
|
|
||||||
|
/* Functions that don't fit into the default prefix naming scheme */
|
||||||
|
#define FLUID_FUNCS2 \
|
||||||
|
FLUID_FUN2(new_settings, NEWFLUIDSETTINGSPROC, new_fluid_settings) \
|
||||||
|
FLUID_FUN2(new_synth, NEWFLUIDSYNTHPROC, new_fluid_synth) \
|
||||||
|
FLUID_FUN2(delete_settings, DELETEFLUIDSETTINGSPROC, delete_fluid_settings) \
|
||||||
|
FLUID_FUN2(delete_synth, DELETEFLUIDSYNTHPROC, delete_fluid_synth)
|
||||||
|
|
||||||
|
struct FluidFunctions
|
||||||
|
{
|
||||||
|
#define FLUID_FUN(name, type) type name;
|
||||||
|
#define FLUID_FUN2(name, type, rn) type name;
|
||||||
|
FLUID_FUNCS
|
||||||
|
FLUID_FUNCS2
|
||||||
|
#undef FLUID_FUN
|
||||||
|
#undef FLUID_FUN2
|
||||||
|
};
|
||||||
|
|
||||||
|
#define HAVE_FLUID fluid.new_synth
|
||||||
|
|
||||||
|
extern FluidFunctions fluid;
|
||||||
|
|
||||||
|
void initFluidFunctions();
|
||||||
|
void finiFluidFunctions();
|
||||||
|
|
||||||
|
#endif // FLUIDFUN_H
|
|
@ -27,8 +27,8 @@
|
||||||
#include "sharedmidistate.h"
|
#include "sharedmidistate.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "debugwriter.h"
|
#include "debugwriter.h"
|
||||||
|
#include "fluid-fun.h"
|
||||||
|
|
||||||
#include <fluidsynth.h>
|
|
||||||
#include <SDL_rwops.h>
|
#include <SDL_rwops.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -648,22 +648,22 @@ struct MidiSource : ALDataSource, MidiReadHandler
|
||||||
switch (e.type)
|
switch (e.type)
|
||||||
{
|
{
|
||||||
case NoteOn:
|
case NoteOn:
|
||||||
fluid_synth_noteon(synth, e.e.note.chan, key, e.e.note.vel);
|
fluid.synth_noteon(synth, e.e.note.chan, key, e.e.note.vel);
|
||||||
break;
|
break;
|
||||||
case NoteOff:
|
case NoteOff:
|
||||||
fluid_synth_noteoff(synth, e.e.note.chan, key);
|
fluid.synth_noteoff(synth, e.e.note.chan, key);
|
||||||
break;
|
break;
|
||||||
case ChanTouch:
|
case ChanTouch:
|
||||||
fluid_synth_channel_pressure(synth, e.e.chanTouch.chan, e.e.chanTouch.val);
|
fluid.synth_channel_pressure(synth, e.e.chanTouch.chan, e.e.chanTouch.val);
|
||||||
break;
|
break;
|
||||||
case PitchBend:
|
case PitchBend:
|
||||||
fluid_synth_pitch_bend(synth, e.e.pitchBend.chan, e.e.pitchBend.val);
|
fluid.synth_pitch_bend(synth, e.e.pitchBend.chan, e.e.pitchBend.val);
|
||||||
break;
|
break;
|
||||||
case CC:
|
case CC:
|
||||||
fluid_synth_cc(synth, e.e.cc.chan, e.e.cc.ctrl, e.e.cc.val);
|
fluid.synth_cc(synth, e.e.cc.chan, e.e.cc.ctrl, e.e.cc.val);
|
||||||
break;
|
break;
|
||||||
case PC:
|
case PC:
|
||||||
fluid_synth_program_change(synth, e.e.pc.chan, e.e.pc.prog);
|
fluid.synth_program_change(synth, e.e.pc.chan, e.e.pc.prog);
|
||||||
break;
|
break;
|
||||||
case Tempo:
|
case Tempo:
|
||||||
updatePlaybackSpeed(e.e.tempo.bpm);
|
updatePlaybackSpeed(e.e.tempo.bpm);
|
||||||
|
@ -679,7 +679,7 @@ struct MidiSource : ALDataSource, MidiReadHandler
|
||||||
int len = count * TICK_FRAMES;
|
int len = count * TICK_FRAMES;
|
||||||
void *buffer = &synthBuf[bufOffset];
|
void *buffer = &synthBuf[bufOffset];
|
||||||
|
|
||||||
fluid_synth_write_s16(synth, len, buffer, 0, 2, buffer, 1, 2);
|
fluid.synth_write_s16(synth, len, buffer, 0, 2, buffer, 1, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MidiReadHandler */
|
/* MidiReadHandler */
|
||||||
|
@ -817,7 +817,7 @@ struct MidiSource : ALDataSource, MidiReadHandler
|
||||||
void seekToOffset(float)
|
void seekToOffset(float)
|
||||||
{
|
{
|
||||||
/* Reset synth */
|
/* Reset synth */
|
||||||
fluid_synth_system_reset(synth);
|
fluid.synth_system_reset(synth);
|
||||||
|
|
||||||
/* Reset runtime variables */
|
/* Reset runtime variables */
|
||||||
genDeltasCarry = 0;
|
genDeltasCarry = 0;
|
||||||
|
|
|
@ -24,8 +24,7 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "debugwriter.h"
|
#include "debugwriter.h"
|
||||||
|
#include "fluid-fun.h"
|
||||||
#include <fluidsynth.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -50,58 +49,52 @@ struct SharedMidiState
|
||||||
SharedMidiState(const Config &conf)
|
SharedMidiState(const Config &conf)
|
||||||
: inited(false),
|
: inited(false),
|
||||||
soundFont(conf.midi.soundFont)
|
soundFont(conf.midi.soundFont)
|
||||||
{
|
{}
|
||||||
flSettings = new_fluid_settings();
|
|
||||||
fluid_settings_setnum(flSettings, "synth.gain", 1.0);
|
|
||||||
fluid_settings_setnum(flSettings, "synth.sample-rate", SYNTH_SAMPLERATE);
|
|
||||||
fluid_settings_setstr(flSettings, "synth.chorus.active", conf.midi.chorus ? "yes" : "no");
|
|
||||||
fluid_settings_setstr(flSettings, "synth.reverb.active", conf.midi.reverb ? "yes" : "no");
|
|
||||||
}
|
|
||||||
|
|
||||||
~SharedMidiState()
|
~SharedMidiState()
|
||||||
{
|
{
|
||||||
delete_fluid_settings(flSettings);
|
if (!HAVE_FLUID || !inited)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fluid.delete_settings(flSettings);
|
||||||
|
|
||||||
for (size_t i = 0; i < synths.size(); ++i)
|
for (size_t i = 0; i < synths.size(); ++i)
|
||||||
{
|
{
|
||||||
assert(!synths[i].inUse);
|
assert(!synths[i].inUse);
|
||||||
delete_fluid_synth(synths[i].synth);
|
fluid.delete_synth(synths[i].synth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
finiFluidFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_synth_t *addSynth(bool usedNow)
|
void initIfNeeded(const Config &conf)
|
||||||
{
|
|
||||||
fluid_synth_t *syn = new_fluid_synth(flSettings);
|
|
||||||
|
|
||||||
if (!soundFont.empty())
|
|
||||||
fluid_synth_sfload(syn, soundFont.c_str(), 1);
|
|
||||||
else
|
|
||||||
Debug() << "Warning: No soundfont specified, sound might be mute";
|
|
||||||
|
|
||||||
Synth synth;
|
|
||||||
synth.inUse = usedNow;
|
|
||||||
synth.synth = syn;
|
|
||||||
synths.push_back(synth);
|
|
||||||
|
|
||||||
return syn;
|
|
||||||
}
|
|
||||||
|
|
||||||
void initDefaultSynths()
|
|
||||||
{
|
{
|
||||||
if (inited)
|
if (inited)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
inited = true;
|
||||||
|
|
||||||
|
initFluidFunctions();
|
||||||
|
|
||||||
|
if (!HAVE_FLUID)
|
||||||
|
return;
|
||||||
|
|
||||||
|
flSettings = fluid.new_settings();
|
||||||
|
fluid.settings_setnum(flSettings, "synth.gain", 1.0);
|
||||||
|
fluid.settings_setnum(flSettings, "synth.sample-rate", SYNTH_SAMPLERATE);
|
||||||
|
fluid.settings_setstr(flSettings, "synth.chorus.active", conf.midi.chorus ? "yes" : "no");
|
||||||
|
fluid.settings_setstr(flSettings, "synth.reverb.active", conf.midi.reverb ? "yes" : "no");
|
||||||
|
|
||||||
for (size_t i = 0; i < SYNTH_INIT_COUNT; ++i)
|
for (size_t i = 0; i < SYNTH_INIT_COUNT; ++i)
|
||||||
addSynth(false);
|
addSynth(false);
|
||||||
|
|
||||||
inited = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fluid_synth_t *allocateSynth()
|
fluid_synth_t *allocateSynth()
|
||||||
{
|
{
|
||||||
size_t i;
|
assert(HAVE_FLUID);
|
||||||
|
assert(inited);
|
||||||
|
|
||||||
initDefaultSynths();
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < synths.size(); ++i)
|
for (i = 0; i < synths.size(); ++i)
|
||||||
if (!synths[i].inUse)
|
if (!synths[i].inUse)
|
||||||
|
@ -110,7 +103,7 @@ struct SharedMidiState
|
||||||
if (i < synths.size())
|
if (i < synths.size())
|
||||||
{
|
{
|
||||||
fluid_synth_t *syn = synths[i].synth;
|
fluid_synth_t *syn = synths[i].synth;
|
||||||
fluid_synth_system_reset(syn);
|
fluid.synth_system_reset(syn);
|
||||||
synths[i].inUse = true;
|
synths[i].inUse = true;
|
||||||
|
|
||||||
return syn;
|
return syn;
|
||||||
|
@ -133,6 +126,24 @@ struct SharedMidiState
|
||||||
|
|
||||||
synths[i].inUse = false;
|
synths[i].inUse = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
fluid_synth_t *addSynth(bool usedNow)
|
||||||
|
{
|
||||||
|
fluid_synth_t *syn = fluid.new_synth(flSettings);
|
||||||
|
|
||||||
|
if (!soundFont.empty())
|
||||||
|
fluid.synth_sfload(syn, soundFont.c_str(), 1);
|
||||||
|
else
|
||||||
|
Debug() << "Warning: No soundfont specified, sound might be mute";
|
||||||
|
|
||||||
|
Synth synth;
|
||||||
|
synth.inUse = usedNow;
|
||||||
|
synth.synth = syn;
|
||||||
|
synths.push_back(synth);
|
||||||
|
|
||||||
|
return syn;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHAREDMIDISTATE_H
|
#endif // SHAREDMIDISTATE_H
|
||||||
|
|
|
@ -36,10 +36,7 @@
|
||||||
#include "quad.h"
|
#include "quad.h"
|
||||||
#include "binding.h"
|
#include "binding.h"
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
|
|
||||||
#ifdef MIDI
|
|
||||||
#include "sharedmidistate.h"
|
#include "sharedmidistate.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -74,9 +71,7 @@ struct SharedStatePrivate
|
||||||
RGSSThreadData &rtData;
|
RGSSThreadData &rtData;
|
||||||
Config &config;
|
Config &config;
|
||||||
|
|
||||||
#ifdef MIDI
|
|
||||||
SharedMidiState midiState;
|
SharedMidiState midiState;
|
||||||
#endif
|
|
||||||
|
|
||||||
Graphics graphics;
|
Graphics graphics;
|
||||||
Input input;
|
Input input;
|
||||||
|
@ -109,9 +104,7 @@ struct SharedStatePrivate
|
||||||
eThread(*threadData->ethread),
|
eThread(*threadData->ethread),
|
||||||
rtData(*threadData),
|
rtData(*threadData),
|
||||||
config(threadData->config),
|
config(threadData->config),
|
||||||
#ifdef MIDI
|
|
||||||
midiState(threadData->config),
|
midiState(threadData->config),
|
||||||
#endif
|
|
||||||
graphics(threadData),
|
graphics(threadData),
|
||||||
audio(threadData->config),
|
audio(threadData->config),
|
||||||
fontState(threadData->config),
|
fontState(threadData->config),
|
||||||
|
@ -164,10 +157,8 @@ struct SharedStatePrivate
|
||||||
|
|
||||||
/* RGSS3 games will call setup_midi, so there's
|
/* RGSS3 games will call setup_midi, so there's
|
||||||
* no need to do it on startup */
|
* no need to do it on startup */
|
||||||
#if MIDI
|
|
||||||
if (rgssVer <= 2)
|
if (rgssVer <= 2)
|
||||||
midiState.initDefaultSynths();
|
midiState.initIfNeeded(threadData->config);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~SharedStatePrivate()
|
~SharedStatePrivate()
|
||||||
|
@ -245,10 +236,7 @@ GSATT(ShaderSet&, shaders)
|
||||||
GSATT(TexPool&, texPool)
|
GSATT(TexPool&, texPool)
|
||||||
GSATT(Quad&, gpQuad)
|
GSATT(Quad&, gpQuad)
|
||||||
GSATT(SharedFontState&, fontState)
|
GSATT(SharedFontState&, fontState)
|
||||||
|
|
||||||
#ifdef MIDI
|
|
||||||
GSATT(SharedMidiState&, midiState)
|
GSATT(SharedMidiState&, midiState)
|
||||||
#endif
|
|
||||||
|
|
||||||
void SharedState::setBindingData(void *data)
|
void SharedState::setBindingData(void *data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -49,10 +49,7 @@ class SharedFontState;
|
||||||
struct GlobalIBO;
|
struct GlobalIBO;
|
||||||
struct Config;
|
struct Config;
|
||||||
struct Vec2i;
|
struct Vec2i;
|
||||||
|
|
||||||
#ifdef MIDI
|
|
||||||
struct SharedMidiState;
|
struct SharedMidiState;
|
||||||
#endif
|
|
||||||
|
|
||||||
struct SharedState
|
struct SharedState
|
||||||
{
|
{
|
||||||
|
@ -83,9 +80,7 @@ struct SharedState
|
||||||
SharedFontState &fontState() const;
|
SharedFontState &fontState() const;
|
||||||
Font &defaultFont() const;
|
Font &defaultFont() const;
|
||||||
|
|
||||||
#ifdef MIDI
|
|
||||||
SharedMidiState &midiState() const;
|
SharedMidiState &midiState() const;
|
||||||
#endif
|
|
||||||
|
|
||||||
sigc::signal<void> prepareDraw;
|
sigc::signal<void> prepareDraw;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue