- WildMidi now uses the soundfont manager.

- added the missing handler for reading Timidity configs from the lump directory.
- fixed incomplete init of the GUS synth when no soundfont can be located.
- fixed bad initialization of WildMidi sampling frequency. It would default to 11.025 kHz if no valid rate was set. Now it will use the sound device's native frequency.
This commit is contained in:
Christoph Oelckers 2018-02-22 22:35:49 +01:00
parent 1361956072
commit c12c068355
7 changed files with 185 additions and 65 deletions

View file

@ -106,13 +106,10 @@ FileReader *FSoundFontReader::OpenFile(const char *name)
auto lump = collection->CheckNumForFullName(name, mFindInfile);
if (lump >= 0)
{
// For SF2 files return the backing file reader to avoid reopening the file.
// Note that there is no possibility of a non-SF2 resource file having only one lump due to the check in the init code.
// For SF2 files return a streaming reader to avoid loading the entire file into memory.
if (collection->GetLumpCount(mFindInfile) == 1)
{
auto fr = collection->GetFileReader(mFindInfile);
fr->Seek(0, SEEK_SET);
return fr;
return collection->ReopenLumpNumNewFile(lump);
}
return collection->ReopenLumpNum(lump);
}
@ -216,6 +213,11 @@ FZipPatReader::~FZipPatReader()
if (resf != nullptr) delete resf;
}
FileReader *FZipPatReader::OpenMainConfigFile()
{
return OpenFile("timidity.cfg");
}
FileReader *FZipPatReader::OpenFile(const char *name)
{
if (resf != nullptr)
@ -279,7 +281,7 @@ FPatchSetReader::FPatchSetReader(const char *filename)
FileReader *FPatchSetReader::OpenMainConfigFile()
{
auto fr = new FileReader;
if (fr->Open(mBasePath)) return fr;
if (fr->Open(mFullPathToConfig)) return fr;
delete fr;
return nullptr;
}
@ -295,6 +297,38 @@ FileReader *FPatchSetReader::OpenFile(const char *name)
return nullptr;
}
//==========================================================================
//
//
//
//==========================================================================
FLumpPatchSetReader::FLumpPatchSetReader(const char *filename)
{
mLumpIndex = Wads.CheckNumForFullName(filename);
FileReader *fr = new FileReader;
mBasePath = filename;
FixPathSeperator(mBasePath);
mBasePath = ExtractFilePath(mBasePath);
if (mBasePath.Len() > 0 && mBasePath.Back() != '/') mBasePath += '/';
}
FileReader *FLumpPatchSetReader::OpenMainConfigFile()
{
return Wads.ReopenLumpNum(mLumpIndex);
}
FileReader *FLumpPatchSetReader::OpenFile(const char *name)
{
FString path;
if (IsAbsPath(name)) return nullptr; // no absolute paths in the lump directory.
path = mBasePath + name;
auto index = Wads.CheckNumForFullName(path);
if (index < 0) return nullptr;
return Wads.ReopenLumpNum(index);
}
//==========================================================================
//
// collects everything out of the soundfonts directory.
@ -428,6 +462,19 @@ const FSoundFontInfo *FSoundFontManager::FindSoundFont(const char *name, int all
FSoundFontReader *FSoundFontManager::OpenSoundFont(const char *name, int allowed)
{
// First check if the given name is inside the loaded resources.
// To avoid clashes this will only be done if the name has the '.cfg' extension.
// Sound fonts cannot be loaded this way.
if (name != nullptr)
{
const char *p = name + strlen(name) - 4;
if (p > name && !stricmp(p, ".cfg") && Wads.CheckNumForFullName(name) >= 0)
{
return new FLumpPatchSetReader(name);
}
}
auto sfi = FindSoundFont(name, allowed);
if (sfi != nullptr)
{
@ -442,13 +489,34 @@ FSoundFontReader *FSoundFontManager::OpenSoundFont(const char *name, int allowed
{
char head[16] = { 0};
fr.Read(head, 16);
fr.Close();
if (!memcmp(head, "RIFF", 4) && !memcmp(head+8, "sfbkLIST", 8))
{
FString fname = name;
FSoundFontInfo sft = { fname, fname, fname, SF_SF2 };
soundfonts.Push(sft);
return new FSF2Reader(name);
}
}
}
if (allowed & SF_GUS)
{
FileReader fr;
if (fr.Open(name))
{
char head[16] = { 0 };
fr.Read(head, 2);
fr.Close();
if (!memcmp(head, "PK", 2)) // The only reason for this check is to block non-Zips. The actual validation will be done by FZipFile.
{
auto r = new FZipPatReader(name);
if (r->isOk()) return r;
delete r;
}
}
// Config files are only accepted if they are named '.cfg', because they are impossible to validate.
const char *p = name + strlen(name) - 4;
if (p > name && !stricmp(p, ".cfg") && FileExists(name))
{
return new FPatchSetReader(name);
}
}
return nullptr;

View file

@ -45,7 +45,7 @@ protected:
}
int pathcmp(const char *p1, const char *p2);
public:
@ -54,6 +54,10 @@ public:
virtual FileReader *OpenFile(const char *name);
std::pair<FileReader *, FString> LookupFile(const char *name);
void AddPath(const char *str);
virtual FString basePath() const
{
return ""; // archived patch sets do not use paths
}
};
//==========================================================================
@ -62,7 +66,7 @@ public:
//
//==========================================================================
class FSF2Reader : FSoundFontReader
class FSF2Reader : public FSoundFontReader
{
FString mFilename;
public:
@ -76,13 +80,38 @@ public:
//
//==========================================================================
class FZipPatReader : FSoundFontReader
class FZipPatReader : public FSoundFontReader
{
FResourceFile *resf;
public:
FZipPatReader(const char *filename);
~FZipPatReader();
virtual FileReader *OpenMainConfigFile() override;
virtual FileReader *OpenFile(const char *name) override;
bool isOk() { return resf != nullptr; }
};
//==========================================================================
//
//
//
//==========================================================================
class FLumpPatchSetReader : public FSoundFontReader
{
int mLumpIndex;;
FString mBasePath;
public:
FLumpPatchSetReader(const char *filename);
~FLumpPatchSetReader();
virtual FileReader *OpenMainConfigFile() override;
virtual FileReader *OpenFile(const char *name) override;
virtual FString basePath() const override
{
return mBasePath;
}
};
//==========================================================================
@ -91,16 +120,20 @@ public:
//
//==========================================================================
class FPatchSetReader : FSoundFontReader
class FPatchSetReader : public FSoundFontReader
{
FString mBasePath;
FString mFullPathToConfig;
FString mBasePath;
FString mFullPathToConfig;
public:
FPatchSetReader(const char *filename);
~FPatchSetReader();
virtual FileReader *OpenMainConfigFile() override;
virtual FileReader *OpenFile(const char *name) override;
FPatchSetReader(const char *filename);
~FPatchSetReader();
virtual FileReader *OpenMainConfigFile() override;
virtual FileReader *OpenFile(const char *name) override;
virtual FString basePath() const override
{
return mBasePath;
}
};
//==========================================================================

View file

@ -92,13 +92,13 @@ WildMIDIDevice::WildMIDIDevice(const char *args)
{
Renderer = NULL;
if (wildmidi_frequency >= 11025 && wildmidi_frequency < 65536)
{ // Use our own sample rate instead of the global one
SampleRate = wildmidi_frequency;
if (wildmidi_frequency > 0)
{
SampleRate = clamp(*wildmidi_frequency, 11025, 65535);
}
else
{ // Else make sure we're not outside of WildMidi's range
SampleRate = clamp(SampleRate, 11025, 65535);
{ // If nothing is set, use the active device's output rate.
SampleRate = (int)GSnd->GetOutputRate();
}
if (args == NULL || *args == 0) args = wildmidi_config;

View file

@ -664,6 +664,7 @@ int LoadDMXGUS()
readbuffer[i-1] = 0;
}
/* Some functions get aggravated if not even the standard banks are available. */
if (tonebank[0] == NULL)
{
tonebank[0] = new ToneBank;
@ -697,12 +698,25 @@ void FreeDLS(DLS_Data *data);
Renderer::Renderer(float sample_rate, const char *args)
{
// Load explicitly stated sound font if so desired.
if (args != nullptr)
if (args != nullptr && *args != 0)
{
if (!stricmp(args, "DMXGUS")) LoadDMXGUS();
LoadConfig(args);
int ret;
FreeAll();
if (!stricmp(args, "DMXGUS")) ret = LoadDMXGUS();
ret = LoadConfig(args);
if (ret != 0)
{
}
}
//
if (tonebank[0] == NULL)
{
tonebank[0] = new ToneBank;
drumset[0] = new ToneBank;
}
rate = sample_rate;
patches = NULL;
resample_buffer_size = 0;

View file

@ -40,47 +40,38 @@
#include "file_io.h"
#include "pathexpander.h"
#include "cmdlib.h"
#include "i_soundfont.h"
static PathExpander wmPathExpander;
std::unique_ptr<FSoundFontReader> wm_sfreader;
static FString config_name;
unsigned char *_WM_BufferFile(const char *filename, unsigned long int *size, bool ismain)
bool _WM_InitReader(const char *config_file)
{
auto reader = sfmanager.OpenSoundFont(config_file, SF_GUS);
if (reader == nullptr)
{
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, errno);
return false; // No sound font could be opened.
}
wm_sfreader.reset(reader);
config_name = config_file;
return true;
}
unsigned char *_WM_BufferFile(const char *filename, unsigned long int *size)
{
FileReader *fp;
int lumpnum;
if (ismain)
if (filename == nullptr)
{
wmPathExpander.openmode = PathExpander::OM_FILEORLUMP;
wmPathExpander.clearPathlist();
#ifdef _WIN32
wmPathExpander.addToPathlist("C:\\TIMIDITY");
wmPathExpander.addToPathlist("\\TIMIDITY");
wmPathExpander.addToPathlist(progdir);
#else
wmPathExpander.addToPathlist("/usr/local/lib/timidity");
wmPathExpander.addToPathlist("/etc/timidity");
wmPathExpander.addToPathlist("/etc");
#endif
fp = wm_sfreader->OpenMainConfigFile();
filename = config_name;
}
if (!(fp = wmPathExpander.openFileReader(filename, &lumpnum)))
return NULL;
if (ismain)
else
{
if (lumpnum > 0)
{
wmPathExpander.openmode = PathExpander::OM_LUMP;
wmPathExpander.clearPathlist(); // when reading from a PK3 we don't want to use any external path
}
else
{
wmPathExpander.openmode = PathExpander::OM_FILE;
}
fp = wm_sfreader->OpenFile(filename);
}
if (fp == NULL)
{
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, errno);

View file

@ -28,6 +28,7 @@
#define __FILE_IO_H
#define WM_MAXFILESIZE 0x1fffffff
extern unsigned char *_WM_BufferFile (const char *filename, unsigned long int *size, bool mainfile = false);
extern unsigned char *_WM_BufferFile (const char *filename, unsigned long int *size);
extern bool _WM_InitReader(const char *config_name);
#endif /* __FILE_IO_H */

View file

@ -50,6 +50,8 @@
#include "gus_pat.h"
#include "wildmidi_lib.h"
#include "critsec.h"
#include "files.h"
#include "i_soundfont.h"
#define IS_DIR_SEPARATOR(c) ((c) == '/' || (c) == '\\')
#ifdef _WIN32
@ -89,6 +91,7 @@ static int auto_amp = 0;
static int auto_amp_with_amp = 0;
static FCriticalSection patch_lock;
extern std::unique_ptr<FSoundFontReader> wm_sfreader;
struct _channel {
unsigned char bank;
@ -659,7 +662,7 @@ static char** WM_LC_Tokenize_Line(char *line_data)
return token_data;
}
static int WM_LoadConfig(const char *config_file) {
static int WM_LoadConfig(const char *config_file, bool main) {
unsigned long int config_size = 0;
char *config_buffer = NULL;
const char *dir_end = NULL;
@ -670,13 +673,23 @@ static int WM_LoadConfig(const char *config_file) {
struct _patch * tmp_patch;
char **line_tokens = NULL;
int token_count = 0;
auto config_parm = config_file;
config_buffer = (char *) _WM_BufferFile(config_file, &config_size, true);
FileReader *fr = nullptr;
if (main)
{
if (!_WM_InitReader(config_file)) return -1; // unable to open this as a config file.
config_parm = nullptr;
}
config_buffer = (char *)_WM_BufferFile(config_parm, &config_size);
if (!config_buffer) {
WM_FreePatches();
return -1;
}
FString bp = wm_sfreader->basePath();
if (config_parm == nullptr) config_file = bp.GetChars(); // Re-get the base path because for archives this is empty.
// This part was rewritten because the original depended on a header that was GPL'd.
dir_end = strrchr(config_file, '/');
@ -780,7 +793,7 @@ static int WM_LoadConfig(const char *config_file) {
return -1;
}
}
if (WM_LoadConfig(new_config) == -1) {
if (WM_LoadConfig(new_config, false) == -1) {
free(new_config);
free(line_tokens);
free(config_buffer);
@ -2558,7 +2571,7 @@ WM_SYMBOL int WildMidi_Init(const char * config_file, unsigned short int rate,
return -1;
}
WM_InitPatches();
if (WM_LoadConfig(config_file) == -1) {
if (WM_LoadConfig(config_file, true) == -1) {
return -1;
}
@ -2929,7 +2942,7 @@ void WildMidi_Renderer::ComputeOutput(float *fbuffer, int len)
}
for (; buffer < newbuf; ++buffer)
{
*(float *)buffer = (float)*buffer / 32768.f;
*(float *)buffer = (float)*buffer * (2. / 32768.f); // boost the volume because Wildmidi is far more quiet than the other synths and therefore hard to balance.
}
}