From 61bc25d7817fa96e1dc908a041d39222111d4de4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 28 Sep 2019 00:10:39 +0200 Subject: [PATCH] - WildMidi also done. --- src/sound/mididevices/midi_cvars.cpp | 58 +++++++- .../music_softsynth_mididevice.cpp | 6 +- .../music_timiditypp_mididevice.cpp | 2 +- .../mididevices/music_wildmidi_mididevice.cpp | 126 ++++++++---------- .../mididevices/music_win_mididevice.cpp | 1 - src/sound/music/i_music.cpp | 6 +- src/sound/music/i_music.h | 1 - src/sound/music/i_musicinterns.h | 29 +++- src/sound/musicformats/music_midistream.cpp | 33 +---- 9 files changed, 140 insertions(+), 122 deletions(-) diff --git a/src/sound/mididevices/midi_cvars.cpp b/src/sound/mididevices/midi_cvars.cpp index 38069ffa6..4170fdc06 100644 --- a/src/sound/mididevices/midi_cvars.cpp +++ b/src/sound/mididevices/midi_cvars.cpp @@ -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; +} + diff --git a/src/sound/mididevices/music_softsynth_mididevice.cpp b/src/sound/mididevices/music_softsynth_mididevice.cpp index af1f1251c..b1b3a22af 100644 --- a/src/sound/mididevices/music_softsynth_mididevice.cpp +++ b/src/sound/mididevices/music_softsynth_mididevice.cpp @@ -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. diff --git a/src/sound/mididevices/music_timiditypp_mididevice.cpp b/src/sound/mididevices/music_timiditypp_mididevice.cpp index 8ae874f45..1f9eb82fd 100644 --- a/src/sound/mididevices/music_timiditypp_mididevice.cpp +++ b/src/sound/mididevices/music_timiditypp_mididevice.cpp @@ -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); diff --git a/src/sound/mididevices/music_wildmidi_mididevice.cpp b/src/sound/mididevices/music_wildmidi_mididevice.cpp index ab88d2b9f..5cd261812 100644 --- a/src/sound/mididevices/music_wildmidi_mididevice.cpp +++ b/src/sound/mididevices/music_wildmidi_mididevice.cpp @@ -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 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); } diff --git a/src/sound/mididevices/music_win_mididevice.cpp b/src/sound/mididevices/music_win_mididevice.cpp index 94c8a0b36..17ae00341 100644 --- a/src/sound/mididevices/music_win_mididevice.cpp +++ b/src/sound/mididevices/music_win_mididevice.cpp @@ -98,7 +98,6 @@ public: //protected: static void CALLBACK CallbackFunc(HMIDIOUT, UINT, DWORD_PTR, DWORD, DWORD); - MIDIStreamer *Streamer; HMIDISTRM MidiOut; UINT DeviceID; DWORD SavedVolume; diff --git a/src/sound/music/i_music.cpp b/src/sound/music/i_music.cpp index f01724db1..1043c2d4b 100644 --- a/src/sound/music/i_music.cpp +++ b/src/sound/music/i_music.cpp @@ -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"; diff --git a/src/sound/music/i_music.h b/src/sound/music/i_music.h index 2d264e6d0..c78af7ec9 100644 --- a/src/sound/music/i_music.h +++ b/src/sound/music/i_music.h @@ -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); diff --git a/src/sound/music/i_musicinterns.h b/src/sound/music/i_musicinterns.h index 4b88d320b..3231f1704 100644 --- a/src/sound/music/i_musicinterns.h +++ b/src/sound/music/i_musicinterns.h @@ -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 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 ----------------------------------------------- diff --git a/src/sound/musicformats/music_midistream.cpp b/src/sound/musicformats/music_midistream.cpp index d21238dd0..49f16643d 100644 --- a/src/sound/musicformats/music_midistream.cpp +++ b/src/sound/musicformats/music_midistream.cpp @@ -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