- made the sound font loading a bit more error resistant.

- implemented a fallback both for sound font lookup and for MIDI device selection so that if some non-working combination is set up, the player will fall back to something that works.
This commit is contained in:
Christoph Oelckers 2018-02-26 16:34:58 +01:00
parent d45a50b0db
commit eb124f6160
10 changed files with 79 additions and 37 deletions

View file

@ -390,6 +390,14 @@ const FSoundFontInfo *FSoundFontManager::FindSoundFont(const char *name, int all
return &sfi; return &sfi;
} }
} }
// We did not find what we were looking for. Let's just return the first valid item that works with the given device.
for (auto &sfi : soundfonts)
{
if (allowed & sfi.type)
{
return &sfi;
}
}
return nullptr; return nullptr;
} }

View file

@ -162,6 +162,8 @@ enum EMidiDevice
MDEV_FLUIDSYNTH = 4, MDEV_FLUIDSYNTH = 4,
MDEV_GUS = 5, MDEV_GUS = 5,
MDEV_WILDMIDI = 6, MDEV_WILDMIDI = 6,
MDEV_COUNT
}; };
class MusInfo; class MusInfo;

View file

@ -357,9 +357,9 @@ FluidSynthMIDIDevice::FluidSynthMIDIDevice(const char *args)
#endif #endif
Printf("Failed to load any MIDI patches.\n");
delete_fluid_synth(FluidSynth); delete_fluid_synth(FluidSynth);
FluidSynth = NULL; FluidSynth = NULL;
I_Error("Failed to load any MIDI patches.\n");
} }

View file

@ -32,8 +32,6 @@
** **
*/ */
#include "i_midi_win32.h"
#include <string> #include <string>
#include <vector> #include <vector>
@ -130,6 +128,10 @@ TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args)
{ {
Renderer = new TimidityPlus::Player(timidity_frequency, instruments); Renderer = new TimidityPlus::Player(timidity_frequency, instruments);
} }
else
{
I_Error("Failed to load any MIDI patches");
}
sampletime = 0; sampletime = 0;
} }

View file

@ -40,6 +40,7 @@
#include "m_swap.h" #include "m_swap.h"
#include "w_wad.h" #include "w_wad.h"
#include "v_text.h" #include "v_text.h"
#include "i_system.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
@ -123,6 +124,10 @@ WildMIDIDevice::WildMIDIDevice(const char *args)
if (wildmidi_reverb) flags |= WM_MO_REVERB; if (wildmidi_reverb) flags |= WM_MO_REVERB;
Renderer->SetOption(WM_MO_ENHANCED_RESAMPLING | WM_MO_REVERB, flags); Renderer->SetOption(WM_MO_ENHANCED_RESAMPLING | WM_MO_REVERB, flags);
} }
else
{
I_Error("Failed to load any MIDI patches");
}
} }
//========================================================================== //==========================================================================

View file

@ -42,6 +42,7 @@
#include "templates.h" #include "templates.h"
#include "doomdef.h" #include "doomdef.h"
#include "m_swap.h" #include "m_swap.h"
#include "i_system.h"
#ifndef __GNUC__ #ifndef __GNUC__
#include <mmdeviceapi.h> #include <mmdeviceapi.h>
@ -682,7 +683,7 @@ MIDIDevice *CreateWinMIDIDevice(int mididevice)
if (d->BufferDoneEvent == nullptr || d->ExitEvent == nullptr) if (d->BufferDoneEvent == nullptr || d->ExitEvent == nullptr)
{ {
delete d; delete d;
return nullptr; I_Error("failed to create MIDI events");
} }
return d; return d;
} }

View file

@ -126,7 +126,7 @@ CUSTOM_CVAR (Int, snd_mididevice, DEF_MIDIDEV, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
return; return;
} }
else if (self == -1) self = DEF_MIDIDEV; else if (self == -1) self = DEF_MIDIDEV;
mididevice = MAX<UINT>(0, self); mididevice = MAX<int>(0, self);
MIDIDeviceChanged(self); MIDIDeviceChanged(self);
} }

View file

@ -183,42 +183,60 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype)
{ {
// fixme: This should check up front if the device can be started. // fixme: This should check up front if the device can be started.
// Checks to ensure that a device finds a compatible sound font are entirely missing here. // Checks to ensure that a device finds a compatible sound font are entirely missing here.
bool checked[MDEV_COUNT] = { false };
switch (devtype) if (devtype == MDEV_SNDSYS) devtype = MDEV_FLUIDSYNTH;
while (true)
{ {
case MDEV_GUS:
return new TimidityMIDIDevice(Args);
case MDEV_MMAPI:
#ifdef _WIN32
return CreateWinMIDIDevice(mididevice);
#endif
// Intentional fall-through for non-Windows systems.
case MDEV_FLUIDSYNTH:
case MDEV_SNDSYS:
return new FluidSynthMIDIDevice(Args);
case MDEV_OPL:
try try
{ {
return new OPLMIDIDevice(Args); switch (devtype)
{
case MDEV_GUS:
return new TimidityMIDIDevice(Args);
case MDEV_MMAPI:
#ifdef _WIN32
return CreateWinMIDIDevice(mididevice);
#endif
// Intentional fall-through for non-Windows systems.
case MDEV_FLUIDSYNTH:
return new FluidSynthMIDIDevice(Args);
case MDEV_OPL:
return new OPLMIDIDevice(Args);
case MDEV_TIMIDITY:
return CreateTimidityPPMIDIDevice(Args);
case MDEV_WILDMIDI:
return new WildMIDIDevice(Args);
default:
break;
}
} }
catch (CRecoverableError &err) catch (CRecoverableError &err)
{ {
// The creation of an OPL MIDI device can abort with an error if no GENMIDI lump can be found. checked[devtype] = true;
Printf("Unable to create OPL MIDI device: %s\nFalling back to default playback", err.GetMessage()); devtype = MDEV_DEFAULT;
return new FluidSynthMIDIDevice(nullptr); // Opening the requested device did not work out so choose another one.
if (!checked[MDEV_FLUIDSYNTH]) devtype = MDEV_FLUIDSYNTH;
else if (!checked[MDEV_TIMIDITY]) devtype = MDEV_TIMIDITY;
else if (!checked[MDEV_WILDMIDI]) devtype = MDEV_WILDMIDI;
else if (!checked[MDEV_GUS]) devtype = MDEV_GUS;
#ifdef _WIN32
else if (!checked[MDEV_MMAPI]) devtype = MDEV_MMAPI;
#endif
else if (!checked[MDEV_OPL]) devtype = MDEV_OPL;
if (devtype == MDEV_DEFAULT)
{
Printf("Failed to play music: Unable to open any MIDI Device.");
return nullptr;
}
} }
case MDEV_TIMIDITY:
return CreateTimidityPPMIDIDevice(Args);
case MDEV_WILDMIDI:
return new WildMIDIDevice(Args);
default:
return NULL;
} }
} }

View file

@ -161,7 +161,7 @@ static Instrument *load_instrument(Renderer *song, const char *name, int percuss
int i, j; int i, j;
bool noluck = false; bool noluck = false;
if (!name) return 0; if (!name || gus_sfreader == nullptr) return nullptr;
/* Open patch file */ /* Open patch file */
fp = gus_sfreader->LookupFile(name).first; fp = gus_sfreader->LookupFile(name).first;

View file

@ -720,15 +720,21 @@ void FreeDLS(DLS_Data *data);
Renderer::Renderer(float sample_rate, const char *args) Renderer::Renderer(float sample_rate, const char *args)
{ {
int res = 0;
// Load explicitly stated sound font if so desired. // Load explicitly stated sound font if so desired.
if (args != nullptr && *args != 0) if (args != nullptr && *args != 0)
{ {
if (!stricmp(args, "DMXGUS")) LoadDMXGUS(); if (!stricmp(args, "DMXGUS")) res = LoadDMXGUS();
LoadConfig(args); res = LoadConfig(args);
} }
else if (tonebank[0] == nullptr) else if (tonebank[0] == nullptr)
{ {
LoadConfig(); res = LoadConfig();
}
if (res < 0)
{
I_Error("Failed to load any MIDI patches");
} }
// These can be left empty here if an error occured during sound font initialization. // These can be left empty here if an error occured during sound font initialization.