- WildMidi also done.

This commit is contained in:
Christoph Oelckers 2019-09-28 00:10:39 +02:00
parent 890db1fbf9
commit 61bc25d781
9 changed files with 140 additions and 122 deletions

View file

@ -45,6 +45,7 @@
#include "timiditypp/timidity.h"
#include "timiditypp/instrum.h"
#include "v_text.h"
#include "c_console.h"
// do this without including windows.h for this one single prototype
#ifdef _WIN32
@ -65,6 +66,7 @@ OPLMidiConfig oplMidiConfig;
OpnConfig opnConfig;
GUSConfig gusConfig;
TimidityConfig timidityConfig;
WildMidiConfig wildMidiConfig;
//==========================================================================
//
@ -843,9 +845,6 @@ CUSTOM_CVAR(String, timidity_config, "gzdoom", CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CheckRestart(MDEV_TIMIDITY);
}
CVAR(Int, timidity_frequency, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
bool Timidity_SetupConfig(TimidityConfig* config, const char* args)
{
config->errorfunc = gus_printfunc;
@ -863,3 +862,56 @@ bool Timidity_SetupConfig(TimidityConfig* config, const char* args)
config->readerName = args;
return true;
}
//==========================================================================
//
// WildMidi
//
//==========================================================================
CUSTOM_CVAR(String, wildmidi_config, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
CheckRestart(MDEV_WILDMIDI);
}
CUSTOM_CVAR(Bool, wildmidi_reverb, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
if (currSong != NULL)
currSong->ChangeSettingInt("wildmidi.reverb", self ? WildMidi::WM_MO_REVERB : 0);
wildMidiConfig.reverb = self;
}
CUSTOM_CVAR(Bool, wildmidi_enhanced_resampling, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
if (currSong != NULL)
currSong->ChangeSettingInt("wildmidi.resampling", self ? WildMidi::WM_MO_ENHANCED_RESAMPLING : 0);
wildMidiConfig.enhanced_resampling = self;
}
static void wm_printfunc(const char* wmfmt, va_list args)
{
Printf(TEXTCOLOR_RED);
VPrintf(PRINT_HIGH, wmfmt, args);
}
bool WildMidi_SetupConfig(WildMidiConfig* config, const char* args)
{
config->errorfunc = wm_printfunc;
if (*args == 0) args = wildmidi_config;
if (stricmp(config->loadedConfig.c_str(), args) == 0) return false; // aleady loaded
auto reader = sfmanager.OpenSoundFont(args, SF_GUS);
if (reader == nullptr)
{
char error[80];
snprintf(error, 80, "WildMidi: %s: Unable to load sound font\n", args);
throw std::runtime_error(error);
}
config->reader = reader;
config->readerName = args;
config->reverb = wildmidi_reverb;
config->enhanced_resampling = wildmidi_enhanced_resampling;
return true;
}

View file

@ -54,7 +54,7 @@
// PUBLIC DATA DEFINITIONS -------------------------------------------------
CVAR(Bool, synth_watch, false, 0)
//CVAR(Bool, synth_watch, false, 0)
// CODE --------------------------------------------------------------------
@ -72,7 +72,7 @@ SoftSynthMIDIDevice::SoftSynthMIDIDevice(int samplerate, int minrate, int maxrat
Events = NULL;
Started = false;
SampleRate = samplerate;
if (SampleRate < minrate || SampleRate > maxrate) SampleRate = GSnd != NULL ? clamp((int)GSnd->GetOutputRate(), minrate, maxrate) : 44100;
if (SampleRate < minrate || SampleRate > maxrate) SampleRate = 44100;
}
//==========================================================================
@ -318,6 +318,7 @@ int SoftSynthMIDIDevice::PlayTick()
int parm2 = (event[2] >> 16) & 0x7f;
HandleEvent(status, parm1, parm2);
#if 0
if (synth_watch)
{
static const char *const commands[8] =
@ -339,6 +340,7 @@ int SoftSynthMIDIDevice::PlayTick()
fputs(buffer, stderr);
#endif
}
#endif
}
// Advance to next event.

View file

@ -105,7 +105,7 @@ void TimidityPPMIDIDevice::LoadInstruments(TimidityConfig* config)
//==========================================================================
TimidityPPMIDIDevice::TimidityPPMIDIDevice(TimidityConfig *config, int samplerate)
:SoftSynthMIDIDevice(samplerate <= 0? config->samplerate : samplerate, 4000, 65000)
:SoftSynthMIDIDevice(samplerate, 4000, 65000)
{
TimidityPlus::set_playback_rate(SampleRate);
LoadInstruments(config);

View file

@ -50,7 +50,7 @@
class WildMIDIDevice : public SoftSynthMIDIDevice
{
public:
WildMIDIDevice(const char *args, int samplerate);
WildMIDIDevice(WildMidiConfig* config, int samplerate);
~WildMIDIDevice();
int Open(MidiCallback, void *userdata);
@ -60,11 +60,14 @@ public:
protected:
WildMidi::Renderer *Renderer;
std::shared_ptr<WildMidi::Instruments> instruments;
void HandleEvent(int status, int parm1, int parm2);
void HandleLongEvent(const uint8_t *data, int len);
void ComputeOutput(float *buffer, int len);
void WildMidiSetOption(int opt, int set);
void ChangeSettingInt(const char *opt, int set);
void LoadInstruments(WildMidiConfig* config);
};
@ -80,44 +83,43 @@ protected:
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static FString CurrentConfig;
// PUBLIC DATA DEFINITIONS -------------------------------------------------
CUSTOM_CVAR(String, wildmidi_config, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (currSong != nullptr && currSong->GetDeviceType() == MDEV_WILDMIDI)
{
MIDIDeviceChanged(-1, true);
}
}
CVAR(Int, wildmidi_frequency, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CUSTOM_CVAR(Bool, wildmidi_reverb, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
if (currSong != NULL)
currSong->WildMidiSetOption(WildMidi::WM_MO_REVERB, *self? WildMidi::WM_MO_REVERB:0);
}
CUSTOM_CVAR(Bool, wildmidi_enhanced_resampling, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
if (currSong != NULL)
currSong->WildMidiSetOption(WildMidi::WM_MO_ENHANCED_RESAMPLING, *self? WildMidi::WM_MO_ENHANCED_RESAMPLING:0);
}
static WildMidi::Instruments *instruments;
void WildMidi_Shutdown()
{
if (instruments) delete instruments;
}
// CODE --------------------------------------------------------------------
static void gzdoom_error_func(const char* wmfmt, va_list args)
//==========================================================================
//
//
//
//==========================================================================
void WildMIDIDevice::LoadInstruments(WildMidiConfig* config)
{
Printf(TEXTCOLOR_RED);
VPrintf(PRINT_HIGH, wmfmt, args);
if (config->reader)
{
config->loadedConfig = config->readerName;
config->instruments.reset(new WildMidi::Instruments(config->reader, SampleRate));
bool success = config->instruments->LoadConfig(config->readerName.c_str());
config->reader = nullptr;
if (!success)
{
config->instruments.reset();
config->loadedConfig = "";
throw std::runtime_error("Unable to initialize instruments for WildMidi device");
}
}
else if (config->instruments == nullptr)
{
throw std::runtime_error("No instruments set for WildMidi device");
}
instruments = config->instruments;
if (instruments->LoadConfig(nullptr) < 0)
{
throw std::runtime_error("Unable to load instruments set for WildMidi device");
}
}
//==========================================================================
@ -126,45 +128,17 @@ static void gzdoom_error_func(const char* wmfmt, va_list args)
//
//==========================================================================
WildMIDIDevice::WildMIDIDevice(const char *args, int samplerate)
:SoftSynthMIDIDevice(samplerate <= 0? wildmidi_frequency : samplerate, 11025, 65535)
WildMIDIDevice::WildMIDIDevice(WildMidiConfig *config, int samplerate)
:SoftSynthMIDIDevice(samplerate, 11025, 65535)
{
Renderer = NULL;
WildMidi::wm_error_func = gzdoom_error_func;
LoadInstruments(config);
if (args == NULL || *args == 0) args = wildmidi_config;
if (instruments == nullptr || (CurrentConfig.CompareNoCase(args) != 0 || SampleRate != instruments->GetSampleRate()))
{
if (instruments) delete instruments;
instruments = nullptr;
CurrentConfig = "";
auto reader = sfmanager.OpenSoundFont(args, SF_GUS);
if (reader == nullptr)
{
I_Error("WildMidi: Unable to open sound font %s\n", args);
}
instruments = new WildMidi::Instruments(reader, SampleRate);
if (instruments->LoadConfig(nullptr) < 0)
{
I_Error("WildMidi: Unable to load instruments for sound font %s\n", args);
}
CurrentConfig = args;
}
if (CurrentConfig.IsNotEmpty())
{
Renderer = new WildMidi::Renderer(instruments);
int flags = 0;
if (wildmidi_enhanced_resampling) flags |= WildMidi::WM_MO_ENHANCED_RESAMPLING;
if (wildmidi_reverb) flags |= WildMidi::WM_MO_REVERB;
Renderer->SetOption(WildMidi::WM_MO_ENHANCED_RESAMPLING | WildMidi::WM_MO_REVERB, flags);
}
else
{
I_Error("Failed to load any MIDI patches");
}
Renderer = new WildMidi::Renderer(instruments.get());
int flags = 0;
if (config->enhanced_resampling) flags |= WildMidi::WM_MO_ENHANCED_RESAMPLING;
if (config->reverb) flags |= WildMidi::WM_MO_REVERB;
Renderer->SetOption(WildMidi::WM_MO_ENHANCED_RESAMPLING | WildMidi::WM_MO_REVERB, flags);
}
//==========================================================================
@ -180,7 +154,6 @@ WildMIDIDevice::~WildMIDIDevice()
{
delete Renderer;
}
// Do not shut down the device so that it can be reused for the next song being played.
}
//==========================================================================
@ -277,9 +250,14 @@ FString WildMIDIDevice::GetStats()
//
//==========================================================================
void WildMIDIDevice::WildMidiSetOption(int opt, int set)
void WildMIDIDevice::ChangeSettingInt(const char *opt, int set)
{
Renderer->SetOption(opt, set);
int option;
if (!stricmp(opt, "wildmidi.reverb")) option = WildMidi::WM_MO_REVERB;
else if (!stricmp(opt, "wildmidi.resampling")) option = WildMidi::WM_MO_ENHANCED_RESAMPLING;
else return;
int setit = option * int(set);
Renderer->SetOption(option, setit);
}
//==========================================================================
@ -288,8 +266,8 @@ void WildMIDIDevice::WildMidiSetOption(int opt, int set)
//
//==========================================================================
MIDIDevice *CreateWildMIDIDevice(const char *args, int samplerate)
MIDIDevice *CreateWildMIDIDevice(WildMidiConfig *config, int samplerate)
{
return new WildMIDIDevice(args, samplerate);
return new WildMIDIDevice(config, samplerate);
}

View file

@ -98,7 +98,6 @@ public:
//protected:
static void CALLBACK CallbackFunc(HMIDIOUT, UINT, DWORD_PTR, DWORD, DWORD);
MIDIStreamer *Streamer;
HMIDISTRM MidiOut;
UINT DeviceID;
DWORD SavedVolume;

View file

@ -160,7 +160,7 @@ void I_ShutdownMusic(bool onexit)
}
if (onexit)
{
WildMidi_Shutdown();
// free static data in the backends.
TimidityPP_Shutdown();
dumb_exit();
}
@ -256,10 +256,6 @@ void MusInfo::ChangeSettingString(const char *, const char *)
{
}
void MusInfo::WildMidiSetOption(int opt, int set)
{
}
FString MusInfo::GetStats()
{
return "No stats available for this song";

View file

@ -82,7 +82,6 @@ public:
virtual void ChangeSettingInt(const char *setting, int value); // FluidSynth settings
virtual void ChangeSettingNum(const char *setting, double value); // "
virtual void ChangeSettingString(const char *setting, const char *value); // "
virtual void WildMidiSetOption(int opt, int set);
virtual void GMEDepthChanged(float val);
void Start(bool loop, float rel_vol = -1.f, int subsong = 0);

View file

@ -121,7 +121,6 @@ namespace TimidityPlus
struct TimidityConfig
{
int samplerate = 0;
void (*errorfunc)(int type, int verbosity_level, const char* fmt, ...) = nullptr;
TimidityPlus::SoundFontReaderInterface* reader;
@ -137,6 +136,25 @@ struct TimidityConfig
extern TimidityConfig timidityConfig;
struct WildMidiConfig
{
bool reverb = false;
bool enhanced_resampling = true;
void (*errorfunc)(const char* wmfmt, va_list args) = nullptr;
WildMidi::SoundFontReaderInterface* reader;
std::string readerName;
// These next two fields are for caching the instruments for repeated use. The GUS device will work without them being cached in the config but it'd require reloading the instruments each time.
// Thus, this config should always be stored globally to avoid this.
// If the last loaded instrument set is to be reused or the caller wants to manage them itself, 'reader' should be left empty.
std::string loadedConfig;
std::shared_ptr<WildMidi::Instruments> instruments; // this is held both by the config and the device
};
extern WildMidiConfig wildMidiConfig;
class MIDIStreamer;
typedef void(*MidiCallback)(void *);
@ -166,7 +184,6 @@ public:
virtual void ChangeSettingInt(const char *setting, int value);
virtual void ChangeSettingNum(const char *setting, double value);
virtual void ChangeSettingString(const char *setting, const char *value);
virtual void WildMidiSetOption(int opt, int set);
virtual bool Preprocess(MIDIStreamer *song, bool looping);
virtual FString GetStats();
virtual int GetDeviceType() const { return MDEV_DEFAULT; }
@ -176,7 +193,6 @@ public:
void TimidityPP_Shutdown();
void WildMidi_Shutdown ();
// Base class for software synthesizer MIDI output devices ------------------
@ -280,7 +296,6 @@ public:
void ChangeSettingInt(const char *setting, int value) override;
void ChangeSettingNum(const char *setting, double value) override;
void ChangeSettingString(const char *setting, const char *value) override;
void WildMidiSetOption(int opt, int set) override;
int ServiceEvent();
void SetMIDISource(MIDISource *_source);
@ -419,8 +434,11 @@ MIDIDevice *CreateOPNMIDIDevice(const OpnConfig *args);
MIDIDevice *CreateOplMIDIDevice(const OPLMidiConfig* config);
MIDIDevice *CreateTimidityMIDIDevice(GUSConfig *config, int samplerate);
MIDIDevice *CreateTimidityPPMIDIDevice(TimidityConfig *config, int samplerate);
MIDIDevice *CreateWildMIDIDevice(WildMidiConfig *config, int samplerate);
MIDIDevice *CreateWildMIDIDevice(const char *args, int samplerate);
#ifdef _WIN32
MIDIDevice* CreateWinMIDIDevice(int mididevice);
#endif
// Data interface
@ -430,6 +448,7 @@ void OPL_SetupConfig(OPLMidiConfig *config, const char *args);
void OPN_SetupConfig(OpnConfig *config, const char *Args);
bool GUS_SetupConfig(GUSConfig *config, const char *args);
bool Timidity_SetupConfig(TimidityConfig* config, const char* args);
bool WildMidi_SetupConfig(WildMidiConfig* config, const char* args);
// Module played via foo_dumb -----------------------------------------------

View file

@ -47,9 +47,6 @@
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
#ifdef _WIN32
MIDIDevice *CreateWinMIDIDevice(int mididevice);
#endif
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
@ -239,7 +236,8 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype, int samplerate)
break;
case MDEV_WILDMIDI:
dev = CreateWildMIDIDevice(Args, samplerate);
WildMidi_SetupConfig(&wildMidiConfig, Args);
dev = CreateWildMIDIDevice(&wildMidiConfig, samplerate);
break;
default:
@ -303,7 +301,7 @@ void MIDIStreamer::Play(bool looping, int subsong)
m_Looping = looping;
source->SetMIDISubsong(subsong);
devtype = SelectMIDIDevice(DeviceType);
MIDI = CreateMIDIDevice(devtype, 0);
MIDI = CreateMIDIDevice(devtype, (int)GSnd->GetOutputRate());
InitPlayback();
}
@ -596,21 +594,6 @@ void MIDIStreamer::ChangeSettingString(const char *setting, const char *value)
}
//==========================================================================
//
// MIDIDeviceStreamer :: WildMidiSetOption
//
//==========================================================================
void MIDIStreamer::WildMidiSetOption(int opt, int set)
{
if (MIDI != NULL)
{
MIDI->WildMidiSetOption(opt, set);
}
}
//==========================================================================
//
// MIDIStreamer :: OutputVolume
@ -1070,16 +1053,6 @@ void MIDIDevice::ChangeSettingString(const char *setting, const char *value)
{
}
//==========================================================================
//
// MIDIDevice :: WildMidiSetOption
//
//==========================================================================
void MIDIDevice::WildMidiSetOption(int opt, int set)
{
}
//==========================================================================
//
// MIDIDevice :: GetStats