diff --git a/src/sound/i_soundfont.cpp b/src/sound/i_soundfont.cpp index fbd6ae8b0..bb3520435 100644 --- a/src/sound/i_soundfont.cpp +++ b/src/sound/i_soundfont.cpp @@ -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; diff --git a/src/sound/i_soundfont.h b/src/sound/i_soundfont.h index 7e1aabbe0..3b161621a 100644 --- a/src/sound/i_soundfont.h +++ b/src/sound/i_soundfont.h @@ -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 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; + } }; //========================================================================== diff --git a/src/sound/mididevices/music_wildmidi_mididevice.cpp b/src/sound/mididevices/music_wildmidi_mididevice.cpp index b3599d1e8..a14af5149 100644 --- a/src/sound/mididevices/music_wildmidi_mididevice.cpp +++ b/src/sound/mididevices/music_wildmidi_mididevice.cpp @@ -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; diff --git a/src/sound/timidity/timidity.cpp b/src/sound/timidity/timidity.cpp index 9fc94a496..d37c0e1a7 100644 --- a/src/sound/timidity/timidity.cpp +++ b/src/sound/timidity/timidity.cpp @@ -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; diff --git a/src/sound/wildmidi/file_io.cpp b/src/sound/wildmidi/file_io.cpp index 7dffff387..c2baafd17 100644 --- a/src/sound/wildmidi/file_io.cpp +++ b/src/sound/wildmidi/file_io.cpp @@ -40,47 +40,38 @@ #include "file_io.h" #include "pathexpander.h" #include "cmdlib.h" +#include "i_soundfont.h" -static PathExpander wmPathExpander; +std::unique_ptr 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); diff --git a/src/sound/wildmidi/file_io.h b/src/sound/wildmidi/file_io.h index 550a8a4b2..2b33042ac 100644 --- a/src/sound/wildmidi/file_io.h +++ b/src/sound/wildmidi/file_io.h @@ -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 */ diff --git a/src/sound/wildmidi/wildmidi_lib.cpp b/src/sound/wildmidi/wildmidi_lib.cpp index 5f711bf35..547b7dd9c 100644 --- a/src/sound/wildmidi/wildmidi_lib.cpp +++ b/src/sound/wildmidi/wildmidi_lib.cpp @@ -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 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. } }