- Gave OPN device the same treatment

Also made some improvements to the interface.

# Conflicts:
#	src/sound/mididevices/midi_cvars.cpp
This commit is contained in:
Christoph Oelckers 2019-09-27 01:51:05 +02:00 committed by drfrag
parent 850975cbc4
commit 309a45ed48
7 changed files with 171 additions and 99 deletions

View file

@ -39,8 +39,8 @@
#include "cmdlib.h"
#include "doomerrors.h"
#ifdef _WIN32
// do this without including windows.h for this one single prototype
#ifdef _WIN32
extern "C" unsigned __stdcall GetSystemDirectoryA(char* lpBuffer, unsigned uSize);
#endif // _WIN32
@ -55,7 +55,7 @@ static void CheckRestart(int devtype)
ADLConfig adlConfig;
FluidConfig fluidConfig;
OPLMidiConfig oplMidiConfig;
OpnConfig opnConfig;
CUSTOM_CVAR(Int, adl_chips_count, 6, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
@ -89,20 +89,38 @@ CUSTOM_CVAR(Int, adl_bank, 14, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CUSTOM_CVAR(Bool, adl_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
adlConfig.adl_use_custom_bank = self;
CheckRestart(MDEV_ADL);
}
CUSTOM_CVAR(String, adl_custom_bank, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
CheckRestart(MDEV_ADL);
//Resolve the path here, so that the renderer does not have to do the work itself and only needs to process final names.
auto info = sfmanager.FindSoundFont(self, SF_WOPL);
if (info == nullptr) adlConfig.adl_custom_bank = nullptr;
else adlConfig.adl_custom_bank = info->mFilename;
if (adl_use_custom_bank) CheckRestart(MDEV_ADL);
}
void SetAdlCustomBank(const char *Args)
{
//Resolve the path here, so that the renderer does not have to do the work itself and only needs to process final names.
const char *bank = Args && *Args? Args : adl_use_custom_bank? *adl_custom_bank : nullptr;
adlConfig.adl_bank = adl_bank;
if (bank && *bank)
{
auto info = sfmanager.FindSoundFont(bank, SF_WOPL);
if (info == nullptr)
{
if (*bank >= '0' && *bank <= '9')
{
adlConfig.adl_bank = (int)strtoll(bank, nullptr, 10);
}
adlConfig.adl_custom_bank = nullptr;
}
else
{
adlConfig.adl_custom_bank = info->mFilename;
}
}
}
CUSTOM_CVAR(Int, adl_volume_model, ADLMIDI_VolumeModel_DMX, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
adlConfig.adl_volume_model = self;
@ -471,3 +489,87 @@ int getOPLCore(const char* args)
if (args != NULL && *args >= '0' && *args < '4') current_opl_core = *args - '0';
return current_opl_core;
}
CUSTOM_CVAR(Int, opn_chips_count, 8, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
opnConfig.opn_chips_count = self;
if (currSong != nullptr && currSong->GetDeviceType() == MDEV_OPN)
{
MIDIDeviceChanged(-1, true);
}
}
CUSTOM_CVAR(Int, opn_emulator_id, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
opnConfig.opn_emulator_id = self;
if (currSong != nullptr && currSong->GetDeviceType() == MDEV_OPN)
{
MIDIDeviceChanged(-1, true);
}
}
CUSTOM_CVAR(Bool, opn_run_at_pcm_rate, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
opnConfig.opn_run_at_pcm_rate = self;
if (currSong != nullptr && currSong->GetDeviceType() == MDEV_OPN)
{
MIDIDeviceChanged(-1, true);
}
}
CUSTOM_CVAR(Bool, opn_fullpan, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
opnConfig.opn_fullpan = self;
if (currSong != nullptr && currSong->GetDeviceType() == MDEV_OPN)
{
MIDIDeviceChanged(-1, true);
}
}
CUSTOM_CVAR(Bool, opn_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (currSong != nullptr && currSong->GetDeviceType() == MDEV_OPN)
{
MIDIDeviceChanged(-1, true);
}
}
CUSTOM_CVAR(String, opn_custom_bank, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (opn_use_custom_bank && currSong != nullptr && currSong->GetDeviceType() == MDEV_OPN)
{
MIDIDeviceChanged(-1, true);
}
}
void SetOpnCustomBank(const char *Args)
{
//Resolve the path here, so that the renderer does not have to do the work itself and only needs to process final names.
const char *bank = Args && *Args? Args : opn_use_custom_bank? *opn_custom_bank : nullptr;
if (bank && *bank)
{
auto info = sfmanager.FindSoundFont(bank, SF_WOPN);
if (info == nullptr)
{
opnConfig.opn_custom_bank = "";
}
else
{
opnConfig.opn_custom_bank = info->mFilename;
}
}
int lump = Wads.CheckNumForFullName("xg.wopn");
if (lump < 0)
{
opnConfig.default_bank.resize(0);
return;
}
FMemLump data = Wads.ReadLump(lump);
opnConfig.default_bank.resize(data.GetSize());
memcpy(opnConfig.default_bank.data(), data.GetMem(), data.GetSize());
}

View file

@ -41,7 +41,7 @@ class ADLMIDIDevice : public SoftSynthMIDIDevice
{
struct ADL_MIDIPlayer *Renderer;
public:
ADLMIDIDevice(const char *args, const ADLConfig *config);
ADLMIDIDevice(const ADLConfig *config);
~ADLMIDIDevice();
int Open(MidiCallback, void *userdata);
@ -54,7 +54,7 @@ protected:
void ComputeOutput(float *buffer, int len);
private:
int LoadCustomBank(const char *bankfile, const ADLConfig *config);
int LoadCustomBank(const ADLConfig *config);
};
@ -75,7 +75,7 @@ enum
//
//==========================================================================
ADLMIDIDevice::ADLMIDIDevice(const char *args, const ADLConfig *config)
ADLMIDIDevice::ADLMIDIDevice(const ADLConfig *config)
:SoftSynthMIDIDevice(44100)
{
Renderer = adl_init(44100); // todo: make it configurable
@ -83,7 +83,7 @@ ADLMIDIDevice::ADLMIDIDevice(const char *args, const ADLConfig *config)
{
adl_switchEmulator(Renderer, config->adl_emulator_id);
adl_setRunAtPcmRate(Renderer, config->adl_run_at_pcm_rate);
if (!LoadCustomBank(config->adl_custom_bank, config))
if (!LoadCustomBank(config))
adl_setBank(Renderer, config->adl_bank);
adl_setNumChips(Renderer, config->adl_chips_count);
adl_setVolumeRangeModel(Renderer, config->adl_volume_model);
@ -116,9 +116,10 @@ ADLMIDIDevice::~ADLMIDIDevice()
//
//==========================================================================
int ADLMIDIDevice::LoadCustomBank(const char *bankfile, const ADLConfig *config)
int ADLMIDIDevice::LoadCustomBank(const ADLConfig *config)
{
if(!config->adl_use_custom_bank || !bankfile || !*bankfile)
const char *bankfile = config->adl_custom_bank.c_str();
if(!*bankfile)
return 0;
return (adl_openBankFile(Renderer, bankfile) == 0);
}
@ -225,9 +226,9 @@ void ADLMIDIDevice::ComputeOutput(float *buffer, int len)
//
//==========================================================================
MIDIDevice *CreateADLMIDIDevice(const char *args, const ADLConfig *config)
MIDIDevice *CreateADLMIDIDevice(const ADLConfig *config)
{
return new ADLMIDIDevice(args, config);
return new ADLMIDIDevice(config);
}

View file

@ -51,7 +51,7 @@ struct fluid_synth_t;
class FluidSynthMIDIDevice : public SoftSynthMIDIDevice
{
public:
FluidSynthMIDIDevice(int samplerate, FluidConfig *config, int (*printfunc_)(const char *, ...));
FluidSynthMIDIDevice(int samplerate, const FluidConfig *config, int (*printfunc_)(const char *, ...));
~FluidSynthMIDIDevice();
int Open(MidiCallback, void *userdata);
@ -162,7 +162,7 @@ const char *BaseFileSearch(const char *file, const char *ext, bool lookfirstinpr
//
//==========================================================================
FluidSynthMIDIDevice::FluidSynthMIDIDevice(int samplerate, FluidConfig *config, int (*printfunc_)(const char*, ...) = nullptr)
FluidSynthMIDIDevice::FluidSynthMIDIDevice(int samplerate, const FluidConfig *config, int (*printfunc_)(const char*, ...) = nullptr)
: SoftSynthMIDIDevice(samplerate <= 0? config->fluid_samplerate : samplerate, 22050, 96000)
{
// These are needed for changing the settings. If something posts a transient config in here we got no way to retrieve the values afterward.
@ -180,7 +180,7 @@ FluidSynthMIDIDevice::FluidSynthMIDIDevice(int samplerate, FluidConfig *config,
FluidSynth = NULL;
FluidSettings = NULL;
#ifdef DYN_FLUIDSYNTH
if (!LoadFluidSynth(config->fluid_lib))
if (!LoadFluidSynth(config->fluid_lib.c_str()))
{
throw std::runtime_error("Failed to load FluidSynth.\n");
}
@ -621,7 +621,7 @@ void FluidSynthMIDIDevice::UnloadFluidSynth()
//
//==========================================================================
MIDIDevice *CreateFluidSynthMIDIDevice(int samplerate, FluidConfig *config, int (*printfunc)(const char*, ...))
MIDIDevice *CreateFluidSynthMIDIDevice(int samplerate, const FluidConfig *config, int (*printfunc)(const char*, ...))
{
return new FluidSynthMIDIDevice(samplerate, config, printfunc);
}

View file

@ -55,7 +55,7 @@
class OPLMIDIDevice : public SoftSynthMIDIDevice, protected OPLmusicBlock
{
public:
OPLMIDIDevice(OPLMidiConfig *config);
OPLMIDIDevice(const OPLMidiConfig *config);
int Open(MidiCallback, void *userdata);
void Close();
int GetTechnology() const;
@ -82,7 +82,7 @@ protected:
//
//==========================================================================
OPLMIDIDevice::OPLMIDIDevice(OPLMidiConfig *config)
OPLMIDIDevice::OPLMIDIDevice(const OPLMidiConfig *config)
: SoftSynthMIDIDevice((int)OPL_SAMPLE_RATE), OPLmusicBlock(config->core, config->numchips)
{
FullPan = config->fullpan;
@ -314,7 +314,7 @@ FString OPLMIDIDevice::GetStats()
return out;
}
MIDIDevice* CreateOplMIDIDevice(OPLMidiConfig* config)
MIDIDevice* CreateOplMIDIDevice(const OPLMidiConfig* config)
{
return new OPLMIDIDevice(config);
}

View file

@ -44,7 +44,7 @@ class OPNMIDIDevice : public SoftSynthMIDIDevice
{
struct OPN2_MIDIPlayer *Renderer;
public:
OPNMIDIDevice(const char *args);
OPNMIDIDevice(const OpnConfig *config);
~OPNMIDIDevice();
@ -72,53 +72,6 @@ enum
ME_PITCHWHEEL = 0xE0
};
CUSTOM_CVAR(Int, opn_chips_count, 8, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (currSong != nullptr && currSong->GetDeviceType() == MDEV_OPN)
{
MIDIDeviceChanged(-1, true);
}
}
CUSTOM_CVAR(Int, opn_emulator_id, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (currSong != nullptr && currSong->GetDeviceType() == MDEV_OPN)
{
MIDIDeviceChanged(-1, true);
}
}
CUSTOM_CVAR(Bool, opn_run_at_pcm_rate, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (currSong != nullptr && currSong->GetDeviceType() == MDEV_OPN)
{
MIDIDeviceChanged(-1, true);
}
}
CUSTOM_CVAR(Bool, opn_fullpan, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (currSong != nullptr && currSong->GetDeviceType() == MDEV_OPN)
{
MIDIDeviceChanged(-1, true);
}
}
CUSTOM_CVAR(Bool, opn_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (currSong != nullptr && currSong->GetDeviceType() == MDEV_OPN)
{
MIDIDeviceChanged(-1, true);
}
}
CUSTOM_CVAR(String, opn_custom_bank, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (opn_use_custom_bank && currSong != nullptr && currSong->GetDeviceType() == MDEV_OPN)
{
MIDIDeviceChanged(-1, true);
}
}
//==========================================================================
//
@ -126,27 +79,30 @@ CUSTOM_CVAR(String, opn_custom_bank, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
//
//==========================================================================
OPNMIDIDevice::OPNMIDIDevice(const char *args)
OPNMIDIDevice::OPNMIDIDevice(const OpnConfig *config)
:SoftSynthMIDIDevice(44100)
{
Renderer = opn2_init(44100); // todo: make it configurable
if (Renderer != nullptr)
{
if (!LoadCustomBank(opn_custom_bank))
if (!LoadCustomBank(config->opn_custom_bank.c_str()))
{
int lump = Wads.CheckNumForFullName("xg.wopn");
if (lump < 0)
if(config->default_bank.size() == 0)
{
I_Error("No OPN bank found");
opn2_close(Renderer);
throw std::runtime_error("No OPN bank found");
}
FMemLump data = Wads.ReadLump(lump);
opn2_openBankData(Renderer, data.GetMem(), (long)data.GetSize());
opn2_openBankData(Renderer, config->default_bank.data(), (long)config->default_bank.size());
}
opn2_switchEmulator(Renderer, (int)opn_emulator_id);
opn2_setRunAtPcmRate(Renderer, (int)opn_run_at_pcm_rate);
opn2_setNumChips(Renderer, opn_chips_count);
opn2_setSoftPanEnabled(Renderer, (int)opn_fullpan);
opn2_switchEmulator(Renderer, (int)config->opn_emulator_id);
opn2_setRunAtPcmRate(Renderer, (int)config->opn_run_at_pcm_rate);
opn2_setNumChips(Renderer, config->opn_chips_count);
opn2_setSoftPanEnabled(Renderer, (int)config->opn_fullpan);
}
else
{
throw std::runtime_error("Unable to create OPN renderer.");
}
}
@ -177,12 +133,8 @@ OPNMIDIDevice::~OPNMIDIDevice()
int OPNMIDIDevice::LoadCustomBank(const char *bankfile)
{
if(!opn_use_custom_bank)
if(!bankfile || !*bankfile)
return 0;
auto info = sfmanager.FindSoundFont(bankfile, SF_WOPN);
if(info == nullptr)
return 0;
bankfile = info->mFilename.GetChars();
return (opn2_openBankFile(Renderer, bankfile) == 0);
}
@ -283,9 +235,9 @@ void OPNMIDIDevice::ComputeOutput(float *buffer, int len)
//
//==========================================================================
MIDIDevice *CreateOPNMIDIDevice(const char *args)
MIDIDevice *CreateOPNMIDIDevice(const OpnConfig *config)
{
return new OPNMIDIDevice(args);
return new OPNMIDIDevice(config);
}

View file

@ -35,15 +35,14 @@ struct ADLConfig
int adl_volume_model = 3; // DMX
bool adl_run_at_pcm_rate = 0;
bool adl_fullpan = 1;
bool adl_use_custom_bank = 0;
const char *adl_custom_bank = nullptr;
std::string adl_custom_bank;
};
extern ADLConfig adlConfig;
struct FluidConfig
{
const char* fluid_lib = nullptr;
std::string fluid_lib;
std::vector<std::string> fluid_patchset;
bool fluid_reverb = false;
bool fluid_chorus = false;
@ -73,6 +72,18 @@ struct OPLMidiConfig
struct GenMidiInstrument OPLinstruments[GENMIDI_NUM_TOTAL];
};
struct OpnConfig
{
int opn_chips_count = 8;
int opn_emulator_id = 0;
bool opn_run_at_pcm_rate = false;
bool opn_fullpan = 1;
std::string opn_custom_bank;
std::vector<uint8_t> default_bank;
};
extern OPLMidiConfig oplMidiConfig;
@ -351,11 +362,20 @@ public:
CDDAFile (FileReader &reader);
};
// MIDI devices
MIDIDevice *CreateFluidSynthMIDIDevice(int samplerate, const FluidConfig* config, int (*printfunc)(const char*, ...));
MIDIDevice *CreateADLMIDIDevice(const ADLConfig* config);
MIDIDevice *CreateOPNMIDIDevice(const OpnConfig *args);
MIDIDevice *CreateOplMIDIDevice(const OPLMidiConfig* config);
// Data interface
int BuildFluidPatchSetList(const char* patches, bool systemfallback);
void SetAdlCustomBank(const char *Args);
void LoadGenMidi();
int getOPLCore(const char* args);
void SetOpnCustomBank(const char *Args);
// Module played via foo_dumb -----------------------------------------------

View file

@ -52,14 +52,9 @@
#ifdef _WIN32
MIDIDevice *CreateWinMIDIDevice(int mididevice);
#endif
MIDIDevice* CreateFluidSynthMIDIDevice(int samplerate, FluidConfig* config, int (*printfunc)(const char*, ...));
MIDIDevice *CreateTimidityMIDIDevice(const char *args, int samplerate);
MIDIDevice *CreateTimidityPPMIDIDevice(const char *args, int samplerate);
MIDIDevice *CreateADLMIDIDevice(const char *args, const ADLConfig* config);
MIDIDevice *CreateOPNMIDIDevice(const char *args);
MIDIDevice *CreateWildMIDIDevice(const char *args, int samplerate);
MIDIDevice* CreateOplMIDIDevice(OPLMidiConfig* config);
int BuildFluidPatchSetList(const char* patches, bool systemfallback);
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
@ -215,10 +210,12 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype, int samplerate)
break;
case MDEV_ADL:
dev = CreateADLMIDIDevice(Args, &adlConfig);
SetAdlCustomBank(Args);
dev = CreateADLMIDIDevice(&adlConfig);
break;
case MDEV_OPN:
SetOpnCustomBank(Args);
dev = CreateOPNMIDIDevice(Args);
break;