- Gave OPN device the same treatment

Also made some improvements to the interface.
This commit is contained in:
Christoph Oelckers 2019-09-27 01:51:05 +02:00
parent 315e15c7f0
commit b3b870d67e
7 changed files with 172 additions and 98 deletions

View file

@ -40,7 +40,9 @@
#include "doomerrors.h" #include "doomerrors.h"
// do this without including windows.h for this one single prototype // do this without including windows.h for this one single prototype
#ifdef _WIN32
extern "C" unsigned __stdcall GetSystemDirectoryA(char* lpBuffer, unsigned uSize); extern "C" unsigned __stdcall GetSystemDirectoryA(char* lpBuffer, unsigned uSize);
#endif
static void CheckRestart(int devtype) static void CheckRestart(int devtype)
{ {
@ -53,7 +55,7 @@ static void CheckRestart(int devtype)
ADLConfig adlConfig; ADLConfig adlConfig;
FluidConfig fluidConfig; FluidConfig fluidConfig;
OPLMidiConfig oplMidiConfig; OPLMidiConfig oplMidiConfig;
OpnConfig opnConfig;
CUSTOM_CVAR(Int, adl_chips_count, 6, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CUSTOM_CVAR(Int, adl_chips_count, 6, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{ {
@ -87,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) CUSTOM_CVAR(Bool, adl_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{ {
adlConfig.adl_use_custom_bank = self;
CheckRestart(MDEV_ADL); CheckRestart(MDEV_ADL);
} }
CUSTOM_CVAR(String, adl_custom_bank, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CUSTOM_CVAR(String, adl_custom_bank, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{ {
CheckRestart(MDEV_ADL); if (adl_use_custom_bank) 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;
} }
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) CUSTOM_CVAR(Int, adl_volume_model, ADLMIDI_VolumeModel_DMX, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{ {
adlConfig.adl_volume_model = self; adlConfig.adl_volume_model = self;
@ -469,3 +489,87 @@ int getOPLCore(const char* args)
if (args != NULL && *args >= '0' && *args < '4') current_opl_core = *args - '0'; if (args != NULL && *args >= '0' && *args < '4') current_opl_core = *args - '0';
return current_opl_core; 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; struct ADL_MIDIPlayer *Renderer;
public: public:
ADLMIDIDevice(const char *args, const ADLConfig *config); ADLMIDIDevice(const ADLConfig *config);
~ADLMIDIDevice(); ~ADLMIDIDevice();
int Open(MidiCallback, void *userdata); int Open(MidiCallback, void *userdata);
@ -54,7 +54,7 @@ protected:
void ComputeOutput(float *buffer, int len); void ComputeOutput(float *buffer, int len);
private: 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) :SoftSynthMIDIDevice(44100)
{ {
Renderer = adl_init(44100); // todo: make it configurable 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_switchEmulator(Renderer, config->adl_emulator_id);
adl_setRunAtPcmRate(Renderer, config->adl_run_at_pcm_rate); 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_setBank(Renderer, config->adl_bank);
adl_setNumChips(Renderer, config->adl_chips_count); adl_setNumChips(Renderer, config->adl_chips_count);
adl_setVolumeRangeModel(Renderer, config->adl_volume_model); 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 0;
return (adl_openBankFile(Renderer, bankfile) == 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 class FluidSynthMIDIDevice : public SoftSynthMIDIDevice
{ {
public: public:
FluidSynthMIDIDevice(int samplerate, FluidConfig *config, int (*printfunc_)(const char *, ...)); FluidSynthMIDIDevice(int samplerate, const FluidConfig *config, int (*printfunc_)(const char *, ...));
~FluidSynthMIDIDevice(); ~FluidSynthMIDIDevice();
int Open(MidiCallback, void *userdata); 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) : 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. // 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; FluidSynth = NULL;
FluidSettings = NULL; FluidSettings = NULL;
#ifdef DYN_FLUIDSYNTH #ifdef DYN_FLUIDSYNTH
if (!LoadFluidSynth(config->fluid_lib)) if (!LoadFluidSynth(config->fluid_lib.c_str()))
{ {
throw std::runtime_error("Failed to load FluidSynth.\n"); 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); return new FluidSynthMIDIDevice(samplerate, config, printfunc);
} }

View file

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

View file

@ -44,7 +44,7 @@ class OPNMIDIDevice : public SoftSynthMIDIDevice
{ {
struct OPN2_MIDIPlayer *Renderer; struct OPN2_MIDIPlayer *Renderer;
public: public:
OPNMIDIDevice(const char *args); OPNMIDIDevice(const OpnConfig *config);
~OPNMIDIDevice(); ~OPNMIDIDevice();
@ -72,53 +72,6 @@ enum
ME_PITCHWHEEL = 0xE0 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) :SoftSynthMIDIDevice(44100)
{ {
Renderer = opn2_init(44100); // todo: make it configurable Renderer = opn2_init(44100); // todo: make it configurable
if (Renderer != nullptr) if (Renderer != nullptr)
{ {
if (!LoadCustomBank(opn_custom_bank)) if (!LoadCustomBank(config->opn_custom_bank.c_str()))
{ {
int lump = Wads.CheckNumForFullName("xg.wopn"); if(config->default_bank.size() == 0)
if (lump < 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, config->default_bank.data(), (long)config->default_bank.size());
opn2_openBankData(Renderer, data.GetMem(), (long)data.GetSize());
} }
opn2_switchEmulator(Renderer, (int)opn_emulator_id); opn2_switchEmulator(Renderer, (int)config->opn_emulator_id);
opn2_setRunAtPcmRate(Renderer, (int)opn_run_at_pcm_rate); opn2_setRunAtPcmRate(Renderer, (int)config->opn_run_at_pcm_rate);
opn2_setNumChips(Renderer, opn_chips_count); opn2_setNumChips(Renderer, config->opn_chips_count);
opn2_setSoftPanEnabled(Renderer, (int)opn_fullpan); 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) int OPNMIDIDevice::LoadCustomBank(const char *bankfile)
{ {
if(!opn_use_custom_bank) if(!bankfile || !*bankfile)
return 0; return 0;
auto info = sfmanager.FindSoundFont(bankfile, SF_WOPN);
if(info == nullptr)
return 0;
bankfile = info->mFilename.GetChars();
return (opn2_openBankFile(Renderer, bankfile) == 0); 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 int adl_volume_model = 3; // DMX
bool adl_run_at_pcm_rate = 0; bool adl_run_at_pcm_rate = 0;
bool adl_fullpan = 1; bool adl_fullpan = 1;
bool adl_use_custom_bank = 0; std::string adl_custom_bank;
const char *adl_custom_bank = nullptr;
}; };
extern ADLConfig adlConfig; extern ADLConfig adlConfig;
struct FluidConfig struct FluidConfig
{ {
const char* fluid_lib = nullptr; std::string fluid_lib;
std::vector<std::string> fluid_patchset; std::vector<std::string> fluid_patchset;
bool fluid_reverb = false; bool fluid_reverb = false;
bool fluid_chorus = false; bool fluid_chorus = false;
@ -73,6 +72,18 @@ struct OPLMidiConfig
struct GenMidiInstrument OPLinstruments[GENMIDI_NUM_TOTAL]; 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; extern OPLMidiConfig oplMidiConfig;
@ -351,11 +362,20 @@ public:
CDDAFile (FileReader &reader); 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 // Data interface
int BuildFluidPatchSetList(const char* patches, bool systemfallback); int BuildFluidPatchSetList(const char* patches, bool systemfallback);
void SetAdlCustomBank(const char *Args);
void LoadGenMidi(); void LoadGenMidi();
int getOPLCore(const char* args); int getOPLCore(const char* args);
void SetOpnCustomBank(const char *Args);
// Module played via foo_dumb ----------------------------------------------- // Module played via foo_dumb -----------------------------------------------

View file

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