From 4369220335be5e41d3948fd63d732b17e4be2b2e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 25 Sep 2019 17:27:10 +0200 Subject: [PATCH] - refactoring of WildMidi to have proper instrument management Not tested yet, it compiles but may not work as-is. --- .../mididevices/music_wildmidi_mididevice.cpp | 41 +- src/sound/music/i_musicinterns.h | 2 + src/sound/music/i_soundfont.cpp | 44 +- src/sound/music/i_soundfont.h | 14 +- src/sound/wildmidi/common.h | 29 +- src/sound/wildmidi/file_io.cpp | 32 +- src/sound/wildmidi/file_io.h | 9 +- src/sound/wildmidi/gus_pat.cpp | 66 ++- src/sound/wildmidi/gus_pat.h | 49 +-- src/sound/wildmidi/reverb.cpp | 3 + src/sound/wildmidi/reverb.h | 5 + src/sound/wildmidi/wildmidi_file.h | 146 +++++++ src/sound/wildmidi/wildmidi_lib.cpp | 407 ++++++------------ src/sound/wildmidi/wildmidi_lib.h | 117 +++-- src/sound/wildmidi/wm_error.cpp | 29 +- src/sound/wildmidi/wm_error.h | 4 + 16 files changed, 567 insertions(+), 430 deletions(-) create mode 100644 src/sound/wildmidi/wildmidi_file.h diff --git a/src/sound/mididevices/music_wildmidi_mididevice.cpp b/src/sound/mididevices/music_wildmidi_mididevice.cpp index 5fa57b9bd6..ffa569dc87 100644 --- a/src/sound/mididevices/music_wildmidi_mididevice.cpp +++ b/src/sound/mididevices/music_wildmidi_mididevice.cpp @@ -56,7 +56,7 @@ public: int GetDeviceType() const override { return MDEV_WILDMIDI; } protected: - WildMidi_Renderer *Renderer; + WildMidi::Renderer *Renderer; void HandleEvent(int status, int parm1, int parm2); void HandleLongEvent(const uint8_t *data, int len); @@ -93,13 +93,20 @@ CVAR(Int, wildmidi_frequency, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CUSTOM_CVAR(Bool, wildmidi_reverb, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) { if (currSong != NULL) - currSong->WildMidiSetOption(WM_MO_REVERB, *self? WM_MO_REVERB:0); + currSong->WildMidiSetOption(WildMidi::WM_MO_REVERB, *self? WildMidi::WM_MO_REVERB:0); } CUSTOM_CVAR(Bool, wildmidi_enhanced_resampling, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) { if (currSong != NULL) - currSong->WildMidiSetOption(WM_MO_ENHANCED_RESAMPLING, *self? WM_MO_ENHANCED_RESAMPLING:0); + currSong->WildMidiSetOption(WildMidi::WM_MO_ENHANCED_RESAMPLING, *self? WildMidi::WM_MO_ENHANCED_RESAMPLING:0); +} + +static WildMidi::Instruments *instruments; + +void WildMidi_Shutdown() +{ + if (instruments) delete instruments; } // CODE -------------------------------------------------------------------- @@ -117,32 +124,32 @@ WildMIDIDevice::WildMIDIDevice(const char *args, int samplerate) if (args == NULL || *args == 0) args = wildmidi_config; - if (CurrentConfig.CompareNoCase(args) != 0 || SampleRate != WildMidi_GetSampleRate()) + if (instruments == nullptr || (CurrentConfig.CompareNoCase(args) != 0 || SampleRate != instruments->GetSampleRate())) { - if (CurrentConfig.IsNotEmpty()) - { - WildMidi_Shutdown(); - CurrentConfig = ""; - } + if (instruments) delete instruments; + instruments = nullptr; + CurrentConfig = ""; - auto reader = sfmanager.OpenSoundFont(CurrentConfig, SF_GUS); + auto reader = sfmanager.OpenSoundFont(args, SF_GUS); if (reader == nullptr) { - I_Error("WildMidi: Unable to open sound font %s\n", CurrentConfig.GetChars()); + I_Error("WildMidi: Unable to open sound font %s\n", args); } - if (!WildMidi_Init(args, SampleRate, 0)) + instruments = new WildMidi::Instruments(reader, SampleRate); + if (instruments->LoadConfig(nullptr) < 0) { - CurrentConfig = args; + I_Error("WildMidi: Unable to load instruments for sound font %s\n", args); } + CurrentConfig = args; } if (CurrentConfig.IsNotEmpty()) { - Renderer = new WildMidi_Renderer(); + Renderer = new WildMidi::Renderer(instruments); int flags = 0; - if (wildmidi_enhanced_resampling) flags |= WM_MO_ENHANCED_RESAMPLING; - if (wildmidi_reverb) flags |= WM_MO_REVERB; - Renderer->SetOption(WM_MO_ENHANCED_RESAMPLING | WM_MO_REVERB, flags); + if (wildmidi_enhanced_resampling) flags |= WildMidi::WM_MO_ENHANCED_RESAMPLING; + if (wildmidi_reverb) flags |= WildMidi::WM_MO_REVERB; + Renderer->SetOption(WildMidi::WM_MO_ENHANCED_RESAMPLING | WildMidi::WM_MO_REVERB, flags); } else { diff --git a/src/sound/music/i_musicinterns.h b/src/sound/music/i_musicinterns.h index ce68f4b9d6..37a0f2a9ab 100644 --- a/src/sound/music/i_musicinterns.h +++ b/src/sound/music/i_musicinterns.h @@ -90,6 +90,8 @@ public: void Timidity_Shutdown(); void TimidityPP_Shutdown(); +void WildMidi_Shutdown (); + // Base class for software synthesizer MIDI output devices ------------------ diff --git a/src/sound/music/i_soundfont.cpp b/src/sound/music/i_soundfont.cpp index d7d0d9c7ce..40e3b003d2 100644 --- a/src/sound/music/i_soundfont.cpp +++ b/src/sound/music/i_soundfont.cpp @@ -42,6 +42,12 @@ #include "resourcefiles/resourcefile.h" #include "timiditypp/common.h" +//========================================================================== +// +// +// +//========================================================================== + FSoundFontManager sfmanager; template @@ -131,6 +137,11 @@ int FSoundFontReader::pathcmp(const char *p1, const char *p2) return mCaseSensitivePaths? strcmp(p1, p2) : stricmp(p1, p2); } +//========================================================================== +// +// +// +//========================================================================== FileReader FSoundFontReader::Open(const char *name, std::string& filename) { @@ -151,40 +162,45 @@ FileReader FSoundFontReader::Open(const char *name, std::string& filename) //========================================================================== // -// This is the interface function for Timidity++ +// // //========================================================================== -struct TimidityPlus::timidity_file* FSoundFontReader::open_timidityplus_file(const char* name) +template +interface* FSoundFontReader::open_interface(const char* name) { std::string filename; - + FileReader fr = Open(name, filename); if (!fr.isOpen()) return nullptr; - - auto tf = new file_interface; + + auto tf = new file_interface; tf->fr = std::move(fr); tf->filename = std::move(filename); return tf; } + //========================================================================== // -// This is the interface function for Timidity(GUS) +// The file interfaces for the different MIDI renderers +// They are all the same except for the class names. // //========================================================================== +struct TimidityPlus::timidity_file* FSoundFontReader::open_timidityplus_file(const char* name) +{ + return open_interface(name); +} + struct Timidity::timidity_file* FSoundFontReader::open_timidity_file(const char* name) { - std::string filename; + return open_interface(name); +} - FileReader fr = Open(name, filename); - if (!fr.isOpen()) return nullptr; - - auto tf = new file_interface; - tf->fr = std::move(fr); - tf->filename = std::move(filename); - return tf; +struct WildMidi::wildmidi_file* FSoundFontReader::open_wildmidi_file(const char* name) +{ + return open_interface(name); } //========================================================================== diff --git a/src/sound/music/i_soundfont.h b/src/sound/music/i_soundfont.h index e29c1147a3..92472f0046 100644 --- a/src/sound/music/i_soundfont.h +++ b/src/sound/music/i_soundfont.h @@ -5,6 +5,7 @@ #include "files.h" #include "timiditypp/timidity_file.h" #include "timidity/timidity_file.h" +#include "wildmidi_file.h" enum { @@ -28,7 +29,8 @@ struct FSoundFontInfo // //========================================================================== -class FSoundFontReader : public TimidityPlus::SoundFontReaderInterface, public Timidity::SoundFontReaderInterface +class FSoundFontReader : public TimidityPlus::SoundFontReaderInterface, public Timidity::SoundFontReaderInterface, public WildMidi::SoundFontReaderInterface +// Yes, it's 3 copies of essentially the same interface, but since we want to keep the 3 renderers as isolated modules we have to pull in their own implementations here. { protected: // This is only doable for loose config files that get set as sound fonts. All other cases read from a contained environment where this does not apply. @@ -75,6 +77,16 @@ public: return AddPath(name); } + // WildMidi interface - essentially the same again but yet another namespace + virtual struct WildMidi::wildmidi_file* open_wildmidi_file(const char* name) override; + virtual void wildmidi_add_path(const char* name) override + { + return AddPath(name); + } + + template + interface* open_interface(const char* name); + }; //========================================================================== diff --git a/src/sound/wildmidi/common.h b/src/sound/wildmidi/common.h index a089329e0c..e80a9a7d88 100644 --- a/src/sound/wildmidi/common.h +++ b/src/sound/wildmidi/common.h @@ -27,22 +27,21 @@ #ifndef __COMMON_H #define __COMMON_H -#define SAMPLE_16BIT 0x01 -#define SAMPLE_UNSIGNED 0x02 -#define SAMPLE_LOOP 0x04 -#define SAMPLE_PINGPONG 0x08 -#define SAMPLE_REVERSE 0x10 -#define SAMPLE_SUSTAIN 0x20 -#define SAMPLE_ENVELOPE 0x40 -#define SAMPLE_CLAMPED 0x80 +namespace WildMidi +{ -#ifdef DEBUG_SAMPLES -#define SAMPLE_CONVERT_DEBUG(dx) printf("\r%s\n",dx) -#else -#define SAMPLE_CONVERT_DEBUG(dx) -#endif +enum +{ + SAMPLE_16BIT = 0x01, + SAMPLE_UNSIGNED = 0x02, + SAMPLE_LOOP = 0x04, + SAMPLE_PINGPONG = 0x08, + SAMPLE_REVERSE = 0x10, + SAMPLE_SUSTAIN = 0x20, + SAMPLE_ENVELOPE = 0x40, + SAMPLE_CLAMPED = 0x80, +}; -extern unsigned short int _WM_SampleRate; struct _sample { unsigned int data_length; @@ -90,5 +89,7 @@ struct _patch { #ifndef M_LN2 #define M_LN2 0.69314718055994530942 #endif + +} #endif /* __COMMON_H */ diff --git a/src/sound/wildmidi/file_io.cpp b/src/sound/wildmidi/file_io.cpp index 0cdca4c79d..a7817c608f 100644 --- a/src/sound/wildmidi/file_io.cpp +++ b/src/sound/wildmidi/file_io.cpp @@ -36,35 +36,27 @@ #include #include -#include "files.h" #include "wm_error.h" #include "file_io.h" -#include "i_soundfont.h" - -std::unique_ptr wm_sfreader; +#include "wildmidi_file.h" -unsigned char *_WM_BufferFile(const char *filename, unsigned long int *size) +namespace WildMidi { - FileReader fp; - if (filename == nullptr) - { - fp = wm_sfreader->OpenMainConfigFile(); - filename = wm_sfreader->MainConfigFileName(); - } - else - { - fp = wm_sfreader->OpenFile(filename); - } +static const int WM_MAXFILESIZE = 0x1fffffff; + +unsigned char *_WM_BufferFile(SoundFontReaderInterface *reader, const char *filename, unsigned long int *size, std::string *fullname) +{ + auto fp = reader->open_wildmidi_file(filename); - if (!fp.isOpen()) + if (!fp) { _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, errno); return NULL; } - auto fsize = fp.GetLength(); + auto fsize = (fp->seek(0, SEEK_END), fp->tell()); if (fsize > WM_MAXFILESIZE) { @@ -81,8 +73,12 @@ unsigned char *_WM_BufferFile(const char *filename, unsigned long int *size) return NULL; } - fp.Read(data, fsize); + fp->seek(0, SEEK_SET); + fp->read(data, fsize); + fp->close(); data[fsize] = 0; *size = (long)fsize; + if (fullname) *fullname = fp->filename; return data; } +} diff --git a/src/sound/wildmidi/file_io.h b/src/sound/wildmidi/file_io.h index 2b33042ac8..01fb6260ec 100644 --- a/src/sound/wildmidi/file_io.h +++ b/src/sound/wildmidi/file_io.h @@ -27,8 +27,11 @@ #ifndef __FILE_IO_H #define __FILE_IO_H -#define WM_MAXFILESIZE 0x1fffffff -extern unsigned char *_WM_BufferFile (const char *filename, unsigned long int *size); -extern bool _WM_InitReader(const char *config_name); +#include "wildmidi_file.h" + +namespace WildMidi +{ + unsigned char *_WM_BufferFile(SoundFontReaderInterface *reader, const char *filename, unsigned long int *size, std::string *fullname = nullptr); +} #endif /* __FILE_IO_H */ diff --git a/src/sound/wildmidi/gus_pat.cpp b/src/sound/wildmidi/gus_pat.cpp index 8f4824dc53..e2080e24d5 100644 --- a/src/sound/wildmidi/gus_pat.cpp +++ b/src/sound/wildmidi/gus_pat.cpp @@ -30,7 +30,54 @@ #include "common.h" #include "wm_error.h" #include "file_io.h" +#include "wildmidi_lib.h" +namespace WildMidi +{ + + /* Guspat Envelope Rate Timings */ + + float env_time_table[] = { + /* Row 1 = (4095.0 / (x * ( 1.0 / (1.6 * 14.0) ))) / 1000000.0 */ + 0.0f, 0.091728000f, 0.045864000f, 0.030576000f, 0.022932000f, 0.018345600f, 0.015288000f, 0.013104000f, + 0.011466000f, 0.010192000f, 0.009172800f, 0.008338909f, 0.007644000f, 0.007056000f, 0.006552000f, 0.006115200f, + 0.005733000f, 0.005395765f, 0.005096000f, 0.004827789f, 0.004586400f, 0.004368000f, 0.004169455f, 0.003988174f, + 0.003822000f, 0.003669120f, 0.003528000f, 0.003397333f, 0.003276000f, 0.003163034f, 0.003057600f, 0.002958968f, + 0.002866500f, 0.002779636f, 0.002697882f, 0.002620800f, 0.002548000f, 0.002479135f, 0.002413895f, 0.002352000f, + 0.002293200f, 0.002237268f, 0.002184000f, 0.002133209f, 0.002084727f, 0.002038400f, 0.001994087f, 0.001951660f, + 0.001911000f, 0.001872000f, 0.001834560f, 0.001798588f, 0.001764000f, 0.001730717f, 0.001698667f, 0.001667782f, + 0.001638000f, 0.001609263f, 0.001581517f, 0.001554712f, 0.001528800f, 0.001503738f, 0.001479484f, 0.001456000f, + + /* Row 2 = (4095.0 / (x * ((1.0 / (1.6 * 14.0)) / 8.0 ))) / 1000000.0 */ + 0.0f, 0.733824000f, 0.366912000f, 0.244608000f, 0.183456000f, 0.146764800f, 0.122304000f, 0.104832000f, + 0.091728000f, 0.081536000f, 0.073382400f, 0.066711273f, 0.061152000f, 0.056448000f, 0.052416000f, 0.048921600f, + 0.045864000f, 0.043166118f, 0.040768000f, 0.038622316f, 0.036691200f, 0.034944000f, 0.033355636f, 0.031905391f, + 0.030576000f, 0.029352960f, 0.028224000f, 0.027178667f, 0.026208000f, 0.025304276f, 0.024460800f, 0.023671742f, + 0.022932000f, 0.022237091f, 0.021583059f, 0.020966400f, 0.020384000f, 0.019833081f, 0.019311158f, 0.018816000f, + 0.018345600f, 0.017898146f, 0.017472000f, 0.017065674f, 0.016677818f, 0.016307200f, 0.015952696f, 0.015613277f, + 0.015288000f, 0.014976000f, 0.014676480f, 0.014388706f, 0.014112000f, 0.013845736f, 0.013589333f, 0.013342255f, + 0.013104000f, 0.012874105f, 0.012652138f, 0.012437695f, 0.012230400f, 0.012029902f, 0.011835871f, 0.011648000f, + + /* Row 3 = (4095.0 / (x * ((1.0 / (1.6 * 14.0)) / 64.0 ))) / 1000000.0 */ + 0.0f, 5.870592000f, 2.935296000f, 1.956864000f, 1.467648000f, 1.174118400f, 0.978432000f, 0.838656000f, + 0.733824000f, 0.652288000f, 0.587059200f, 0.533690182f, 0.489216000f, 0.451584000f, 0.419328000f, 0.391372800f, + 0.366912000f, 0.345328941f, 0.326144000f, 0.308978526f, 0.293529600f, 0.279552000f, 0.266845091f, 0.255243130f, + 0.244608000f, 0.234823680f, 0.225792000f, 0.217429333f, 0.209664000f, 0.202434207f, 0.195686400f, 0.189373935f, + 0.183456000f, 0.177896727f, 0.172664471f, 0.167731200f, 0.163072000f, 0.158664649f, 0.154489263f, 0.150528000f, + 0.146764800f, 0.143185171f, 0.139776000f, 0.136525395f, 0.133422545f, 0.130457600f, 0.127621565f, 0.124906213f, + 0.122304000f, 0.119808000f, 0.117411840f, 0.115109647f, 0.112896000f, 0.110765887f, 0.108714667f, 0.106738036f, + 0.104832000f, 0.102992842f, 0.101217103f, 0.099501559f, 0.097843200f, 0.096239213f, 0.094686968f, 0.093184000f, + + /* Row 4 = (4095.0 / (x * ((1.0 / (1.6 * 14.0)) / 512.0))) / 1000000.0 */ + 0.0f, 46.964736000f,23.482368000f,15.654912000f,11.741184000f, 9.392947200f, 7.827456000f, 6.709248000f, + 5.870592000f, 5.218304000f, 4.696473600f, 4.269521455f, 3.913728000f, 3.612672000f, 3.354624000f, 3.130982400f, + 2.935296000f, 2.762631529f, 2.609152000f, 2.471828211f, 2.348236800f, 2.236416000f, 2.134760727f, 2.041945043f, + 1.956864000f, 1.878589440f, 1.806336000f, 1.739434667f, 1.677312000f, 1.619473655f, 1.565491200f, 1.514991484f, + 1.467648000f, 1.423173818f, 1.381315765f, 1.341849600f, 1.304576000f, 1.269317189f, 1.235914105f, 1.204224000f, + 1.174118400f, 1.145481366f, 1.118208000f, 1.092203163f, 1.067380364f, 1.043660800f, 1.020972522f, 0.999249702f, + 0.978432000f, 0.958464000f, 0.939294720f, 0.920877176f, 0.903168000f, 0.886127094f, 0.869717333f, 0.853904291f, + 0.838656000f, 0.823942737f, 0.809736828f, 0.796012475f, 0.782745600f, 0.769913705f, 0.757495742f, 0.745472000f + }; #ifdef DEBUG_GUSPAT #define GUSPAT_FILENAME_DEBUG(dx) fprintf(stderr,"\r%s\n",dx) @@ -48,6 +95,11 @@ #define GUSPAT_END_DEBUG() #endif +#ifdef DEBUG_SAMPLES +#define SAMPLE_CONVERT_DEBUG(dx) printf("\r%s\n",dx) +#else +#define SAMPLE_CONVERT_DEBUG(dx) +#endif /* * sample data conversion functions * convert data to signed shorts @@ -70,8 +122,7 @@ static int convert_8s(unsigned char *data, struct _sample *gus_sample) { return 0; } - _WM_ERROR_NEW("(%s:%i) ERROR: calloc failed (%s)", __FUNCTION__, __LINE__, - strerror(errno)); + _WM_ERROR_NEW("Calloc failed (%s)\n", strerror(errno)); return -1; } @@ -703,7 +754,8 @@ static int convert_16urp(unsigned char *data, struct _sample *gus_sample) { /* sample loading */ -struct _sample * _WM_load_gus_pat(const char *filename, int fix_release) { +struct _sample * Instruments::load_gus_pat(const char *filename) +{ unsigned char *gus_patch; unsigned long int gus_size; unsigned long int gus_ptr; @@ -736,7 +788,7 @@ struct _sample * _WM_load_gus_pat(const char *filename, int fix_release) { SAMPLE_CONVERT_DEBUG(__FUNCTION__); SAMPLE_CONVERT_DEBUG(filename); - if ((gus_patch = _WM_BufferFile(filename, &gus_size)) == NULL) { + if ((gus_patch = _WM_BufferFile(sfreader, filename, &gus_size)) == NULL) { return NULL; } if (gus_size < 239) { @@ -918,8 +970,8 @@ struct _sample * _WM_load_gus_pat(const char *filename, int fix_release) { / ((float) _WM_SampleRate * env_time_table[env_rate])); GUSPAT_INT_DEBUG("Envelope Rate",gus_sample->env_rate[i]); GUSPAT_INT_DEBUG("GUSPAT Rate",env_rate); if (gus_sample->env_rate[i] == 0) { - _WM_ERROR_NEW("%s: Warning: found invalid envelope(%lu) rate setting in %s. Using %f instead.", - __FUNCTION__, i, filename, env_time_table[63]); + _WM_ERROR_NEW("Warning: found invalid envelope(%lu) rate setting in %s. Using %f instead.\n", + i, filename, env_time_table[63]); gus_sample->env_rate[i] = (signed long int) (4194303.0 / ((float) _WM_SampleRate * env_time_table[63])); GUSPAT_FLOAT_DEBUG("Envelope Time",env_time_table[63]); @@ -979,3 +1031,5 @@ struct _sample * _WM_load_gus_pat(const char *filename, int fix_release) { free(gus_patch); return first_gus_sample; } + +} diff --git a/src/sound/wildmidi/gus_pat.h b/src/sound/wildmidi/gus_pat.h index 084b8473ab..31e8c5de68 100644 --- a/src/sound/wildmidi/gus_pat.h +++ b/src/sound/wildmidi/gus_pat.h @@ -27,51 +27,14 @@ #ifndef __GUS_PAT_H #define __GUS_PAT_H +namespace WildMidi +{ + +class SoundFontReaderInterface; /* Guspat Envelope Rate Timings */ +extern float env_time_table[]; -static float env_time_table[] = { -/* Row 1 = (4095.0 / (x * ( 1.0 / (1.6 * 14.0) ))) / 1000000.0 */ - 0.0f, 0.091728000f, 0.045864000f, 0.030576000f, 0.022932000f, 0.018345600f, 0.015288000f, 0.013104000f, - 0.011466000f, 0.010192000f, 0.009172800f, 0.008338909f, 0.007644000f, 0.007056000f, 0.006552000f, 0.006115200f, - 0.005733000f, 0.005395765f, 0.005096000f, 0.004827789f, 0.004586400f, 0.004368000f, 0.004169455f, 0.003988174f, - 0.003822000f, 0.003669120f, 0.003528000f, 0.003397333f, 0.003276000f, 0.003163034f, 0.003057600f, 0.002958968f, - 0.002866500f, 0.002779636f, 0.002697882f, 0.002620800f, 0.002548000f, 0.002479135f, 0.002413895f, 0.002352000f, - 0.002293200f, 0.002237268f, 0.002184000f, 0.002133209f, 0.002084727f, 0.002038400f, 0.001994087f, 0.001951660f, - 0.001911000f, 0.001872000f, 0.001834560f, 0.001798588f, 0.001764000f, 0.001730717f, 0.001698667f, 0.001667782f, - 0.001638000f, 0.001609263f, 0.001581517f, 0.001554712f, 0.001528800f, 0.001503738f, 0.001479484f, 0.001456000f, - -/* Row 2 = (4095.0 / (x * ((1.0 / (1.6 * 14.0)) / 8.0 ))) / 1000000.0 */ - 0.0f, 0.733824000f, 0.366912000f, 0.244608000f, 0.183456000f, 0.146764800f, 0.122304000f, 0.104832000f, - 0.091728000f, 0.081536000f, 0.073382400f, 0.066711273f, 0.061152000f, 0.056448000f, 0.052416000f, 0.048921600f, - 0.045864000f, 0.043166118f, 0.040768000f, 0.038622316f, 0.036691200f, 0.034944000f, 0.033355636f, 0.031905391f, - 0.030576000f, 0.029352960f, 0.028224000f, 0.027178667f, 0.026208000f, 0.025304276f, 0.024460800f, 0.023671742f, - 0.022932000f, 0.022237091f, 0.021583059f, 0.020966400f, 0.020384000f, 0.019833081f, 0.019311158f, 0.018816000f, - 0.018345600f, 0.017898146f, 0.017472000f, 0.017065674f, 0.016677818f, 0.016307200f, 0.015952696f, 0.015613277f, - 0.015288000f, 0.014976000f, 0.014676480f, 0.014388706f, 0.014112000f, 0.013845736f, 0.013589333f, 0.013342255f, - 0.013104000f, 0.012874105f, 0.012652138f, 0.012437695f, 0.012230400f, 0.012029902f, 0.011835871f, 0.011648000f, - -/* Row 3 = (4095.0 / (x * ((1.0 / (1.6 * 14.0)) / 64.0 ))) / 1000000.0 */ - 0.0f, 5.870592000f, 2.935296000f, 1.956864000f, 1.467648000f, 1.174118400f, 0.978432000f, 0.838656000f, - 0.733824000f, 0.652288000f, 0.587059200f, 0.533690182f, 0.489216000f, 0.451584000f, 0.419328000f, 0.391372800f, - 0.366912000f, 0.345328941f, 0.326144000f, 0.308978526f, 0.293529600f, 0.279552000f, 0.266845091f, 0.255243130f, - 0.244608000f, 0.234823680f, 0.225792000f, 0.217429333f, 0.209664000f, 0.202434207f, 0.195686400f, 0.189373935f, - 0.183456000f, 0.177896727f, 0.172664471f, 0.167731200f, 0.163072000f, 0.158664649f, 0.154489263f, 0.150528000f, - 0.146764800f, 0.143185171f, 0.139776000f, 0.136525395f, 0.133422545f, 0.130457600f, 0.127621565f, 0.124906213f, - 0.122304000f, 0.119808000f, 0.117411840f, 0.115109647f, 0.112896000f, 0.110765887f, 0.108714667f, 0.106738036f, - 0.104832000f, 0.102992842f, 0.101217103f, 0.099501559f, 0.097843200f, 0.096239213f, 0.094686968f, 0.093184000f, - -/* Row 4 = (4095.0 / (x * ((1.0 / (1.6 * 14.0)) / 512.0))) / 1000000.0 */ - 0.0f, 46.964736000f,23.482368000f,15.654912000f,11.741184000f, 9.392947200f, 7.827456000f, 6.709248000f, - 5.870592000f, 5.218304000f, 4.696473600f, 4.269521455f, 3.913728000f, 3.612672000f, 3.354624000f, 3.130982400f, - 2.935296000f, 2.762631529f, 2.609152000f, 2.471828211f, 2.348236800f, 2.236416000f, 2.134760727f, 2.041945043f, - 1.956864000f, 1.878589440f, 1.806336000f, 1.739434667f, 1.677312000f, 1.619473655f, 1.565491200f, 1.514991484f, - 1.467648000f, 1.423173818f, 1.381315765f, 1.341849600f, 1.304576000f, 1.269317189f, 1.235914105f, 1.204224000f, - 1.174118400f, 1.145481366f, 1.118208000f, 1.092203163f, 1.067380364f, 1.043660800f, 1.020972522f, 0.999249702f, - 0.978432000f, 0.958464000f, 0.939294720f, 0.920877176f, 0.903168000f, 0.886127094f, 0.869717333f, 0.853904291f, - 0.838656000f, 0.823942737f, 0.809736828f, 0.796012475f, 0.782745600f, 0.769913705f, 0.757495742f, 0.745472000f -}; - -extern struct _sample * _WM_load_gus_pat (const char *filename, int _fix_release); +} #endif /* __GUS_PAT_H */ diff --git a/src/sound/wildmidi/reverb.cpp b/src/sound/wildmidi/reverb.cpp index 6c6af88d4b..2f95e28bd2 100644 --- a/src/sound/wildmidi/reverb.cpp +++ b/src/sound/wildmidi/reverb.cpp @@ -32,6 +32,8 @@ #include "common.h" #include "reverb.h" +namespace WildMidi +{ /* reverb function */ @@ -396,3 +398,4 @@ void _WM_do_reverb(struct _rvb *rvb, signed int *buffer, int size) { } } +} diff --git a/src/sound/wildmidi/reverb.h b/src/sound/wildmidi/reverb.h index 162de61eb4..5362792a55 100644 --- a/src/sound/wildmidi/reverb.h +++ b/src/sound/wildmidi/reverb.h @@ -27,6 +27,9 @@ #ifndef __REVERB_H #define __REVERB_H +namespace WildMidi +{ + struct _rvb { /* filter data */ signed int l_buf_flt_in[8][6][2]; @@ -54,4 +57,6 @@ struct _rvb { extern void _WM_free_reverb (struct _rvb *rvb); extern void _WM_do_reverb (struct _rvb *rvb, signed int *buffer, int size); +} + #endif /* __REVERB_H */ diff --git a/src/sound/wildmidi/wildmidi_file.h b/src/sound/wildmidi/wildmidi_file.h new file mode 100644 index 0000000000..aae9c98c1b --- /dev/null +++ b/src/sound/wildmidi/wildmidi_file.h @@ -0,0 +1,146 @@ +/* + wildmidi_file.h + + Midi Wavetable Processing library + + Copyright (C) 2019 Christoph Oelckers + + WildMIDI is free software: you can redistribute and/or modify the player + under the terms of the GNU General Public License and you can redistribute + and/or modify the library under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation, either version 3 of + the licenses, or(at your option) any later version. + + WildMIDI is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License and + the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License and the + GNU Lesser General Public License along with WildMIDI. If not, see + . + */ + +#pragma once +#include +#include +#include + +namespace WildMidi +{ + + struct wildmidi_file + { + std::string filename; + + virtual ~wildmidi_file() {} + virtual char* gets(char* buff, int n) = 0; + virtual long read(void* buff, int32_t size, int32_t nitems) = 0; + long read(void* buff, int32_t size) { return read(buff, 1, size); } + virtual long seek(long offset, int whence) = 0; + virtual long tell() = 0; + virtual void close() = 0; + }; + + class SoundFontReaderInterface + { + public: + virtual ~SoundFontReaderInterface() {} + virtual struct wildmidi_file* open_wildmidi_file(const char* fn) = 0; + virtual void wildmidi_add_path(const char* path) = 0; + }; + + + // A minimalistic sound font reader interface. Normally this should be replaced with something better tied into the host application. +#ifdef USE_BASE_INTERFACE + + // Base version of timidity_file using stdio's FILE. + struct wildmidi_file_FILE : public wildmidi_file + { + FILE* f = nullptr; + + ~wildmidi_file_FILE() + { + if (f) fclose(f); + } + char* gets(char* buff, int n) override + { + if (!f) return nullptr; + return fgets(buff, n, f); + } + long read(void* buff, int32_t size, int32_t nitems) override + { + if (!f) return 0; + return (long)fread(buff, size, nitems, f); + } + long seek(long offset, int whence) override + { + if (!f) return 0; + return fseek(f, offset, whence); + } + long tell() override + { + if (!f) return 0; + return ftell(f); + } + void close() + { + if (f) fclose(f); + delete this; + } + }; + + class BaseSoundFontReader : public SoundFontReaderInterface + { + std::vector paths; + + bool IsAbsPath(const char *name) + { + if (name[0] == '/' || name[0] == '\\') return true; +#ifdef _WIN32 + /* [A-Za-z]: (for Windows) */ + if (isalpha(name[0]) && name[1] == ':') return true; +#endif /* _WIN32 */ + return 0; + } + + struct wildmidi_file* open_wildmidi_file(const char* fn) + { + FILE *f = nullptr; + std::string fullname; + if (!fn) + { + f = fopen("timidity.cfg", "rt"); + fullname = "timidity.cfg"; + } + else + { + if (!IsAbsPath(fn)) + { + for(int i = (int)paths.size()-1; i>=0; i--) + { + fullname = paths[i] + fn; + f = fopen(fullname.c_str(), "rt"); + break; + } + } + if (!f) f = fopen(fn, "rt"); + } + if (!f) return nullptr; + auto tf = new wildmidi_file_FILE; + tf->f = f; + tf->filename = fullname; + return tf; + } + + void wildmidi_add_path(const char* path) + { + std::string p = path; + if (p.back() != '/' && p.back() != '\\') p += '/'; // always let it end with a slash. + paths.push_back(p); + } + }; +#endif + +} + diff --git a/src/sound/wildmidi/wildmidi_lib.cpp b/src/sound/wildmidi/wildmidi_lib.cpp index d0441cc006..d6aea8c4ca 100644 --- a/src/sound/wildmidi/wildmidi_lib.cpp +++ b/src/sound/wildmidi/wildmidi_lib.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #ifndef _WIN32 #include #endif @@ -44,7 +45,9 @@ #include "reverb.h" #include "gus_pat.h" #include "wildmidi_lib.h" -#include "i_soundfont.h" + +namespace WildMidi +{ #define IS_DIR_SEPARATOR(c) ((c) == '/' || (c) == '\\') #ifdef _WIN32 @@ -63,28 +66,8 @@ #define MEM_CHUNK 8192 -static int WM_Initialized = 0; -static signed short int WM_MasterVolume = 948; -static unsigned short int WM_MixerOptions = 0; -static char WM_Version[] = "WildMidi Processing Library"; - -unsigned short int _WM_SampleRate; - -static struct _patch *patch[128]; - -static float reverb_room_width = 16.875f; -static float reverb_room_length = 22.5f; - -static float reverb_listen_posx = 8.4375f; -static float reverb_listen_posy = 16.875f; - -static int fix_release = 0; -static int auto_amp = 0; -static int auto_amp_with_amp = 0; - -static std::mutex patch_lock; -extern std::unique_ptr wm_sfreader; +static const char WM_Version[] = "WildMidi Processing Library"; struct _channel { unsigned char bank; @@ -174,10 +157,8 @@ struct _mdi { /* Gauss Interpolation code adapted from code supplied by Eric. A. Welsh */ static double newt_coeffs[58][58]; /* for start/end of samples */ -#define MAX_GAUSS_ORDER 34 /* 34 is as high as we can go before errors crop up */ -static double *gauss_table = NULL; /* *gauss_table[1< gauss_table; /* *gauss_table[1< lock(gauss_lock); - if (gauss_table) { + if (gauss_table.size()) { return; } @@ -218,7 +198,8 @@ static void init_gauss(void) { for (j = 0, sign = (int)pow(-1., i); j <= i; j++, sign *= -1) newt_coeffs[i][j] *= sign; - t = (double*)malloc((1< lock(gauss_lock); - free(gauss_table); - gauss_table = NULL; -} - -struct _hndl { - void * handle; - struct _hndl *next; - struct _hndl *prev; -}; /* f: ( VOLUME / 127.0 ) * 1024.0 */ -static signed short int lin_volume[] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, +static const signed short int lin_volume[] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 129, 137, 145, 153, 161, 169, 177, 185, 193, 201, 209, 217, 225, 233, 241, 249, 258, 266, 274, 282, 290, 298, 306, 314, 322, 330, 338, 346, 354, 362, 370, 378, 387, 395, 403, 411, 419, @@ -266,7 +233,7 @@ static signed short int lin_volume[] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 991, 999, 1007, 1015, 1024 }; /* f: As per midi 2 standard */ -static float dBm_volume[] = { -999999.999999f, -84.15214884f, -72.11094901f, +static const float dBm_volume[] = { -999999.999999f, -84.15214884f, -72.11094901f, -65.06729865f, -60.06974919f, -56.19334866f, -53.02609882f, -50.34822724f, -48.02854936f, -45.98244846f, -44.15214884f, -42.49644143f, -40.984899f, -39.59441475f, -38.30702741f, -37.10849848f, -35.98734953f, -34.93419198f, @@ -294,7 +261,7 @@ static float dBm_volume[] = { -999999.999999f, -84.15214884f, -72.11094901f, -0.5559443807f, -0.4152814317f, -0.2757483179f, -0.1373270335f, 0 }; /* f: As per midi 2 standard */ -static float dBm_pan_volume[127] = { +static const float dBm_pan_volume[127] = { -999999.999999f, -87.6945020928f, -73.8331126923f, -65.7264009888f, -59.9763864074f, -55.5181788833f, -51.8774481743f, -48.8011722841f, -46.1383198371f, -43.7914727130f, -41.6941147218f, -39.7988027954f, @@ -328,7 +295,7 @@ static float dBm_pan_volume[127] = { -0.0560023899f, -0.0388794497f, -0.0248770409f, -0.0139907967f, -0.0062173263f, -0.0015542108f, 0.0000000000f }; -static unsigned int freq_table[] = { 837201792, 837685632, 838169728, +static const unsigned int freq_table[] = { 837201792, 837685632, 838169728, 838653568, 839138240, 839623232, 840108480, 840593984, 841079680, 841565184, 842051648, 842538240, 843025152, 843512320, 843999232, 844486976, 844975040, 845463360, 845951936, 846440320, 846929536, @@ -544,19 +511,13 @@ static unsigned int freq_table[] = { 837201792, 837685632, 838169728, * ========================= */ -static void WM_InitPatches(void) { - int i; - for (i = 0; i < 128; i++) { - patch[i] = NULL; - } -} -static void WM_FreePatches(void) { +void Instruments::FreePatches() +{ int i; struct _patch * tmp_patch; struct _sample * tmp_sample; - std::lock_guard lock(patch_lock); for (i = 0; i < 128; i++) { while (patch[i]) { while (patch[i]->first_sample) { @@ -649,7 +610,8 @@ static char** WM_LC_Tokenize_Line(char *line_data) return token_data; } -static int WM_LoadConfig(const char *config_file, bool main) { +int Instruments::LoadConfig(const char *config_parm) +{ unsigned long int config_size = 0; char *config_buffer = NULL; const char *dir_end = NULL; @@ -660,20 +622,20 @@ static int WM_LoadConfig(const char *config_file, bool main) { struct _patch * tmp_patch; char **line_tokens = NULL; int token_count = 0; - auto config_parm = config_file; + std::string config_file_s; - config_buffer = (char *)_WM_BufferFile(config_parm, &config_size); + config_buffer = (char *)_WM_BufferFile(sfreader, config_parm, &config_size, &config_file_s); if (!config_buffer) { - WM_FreePatches(); + FreePatches(); return -1; } - - if (config_parm == nullptr) config_file = wm_sfreader->basePath().GetChars(); // Re-get the base path because for archives this is empty. + + auto config_file = config_file_s.c_str(); // This part was rewritten because the original depended on a header that was GPL'd. dir_end = strrchr(config_file, '/'); #ifdef _WIN32 - const char *dir_end2 = strrchr(config_file, '\\'); + const char *dir_end2 = strrchr(config_file.c, '\\'); if (dir_end2 > dir_end) dir_end = dir_end2; #endif @@ -683,7 +645,7 @@ static int WM_LoadConfig(const char *config_file, bool main) { _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse config", errno); _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); - WM_FreePatches(); + FreePatches(); free(config_buffer); return -1; } @@ -714,7 +676,7 @@ static int WM_LoadConfig(const char *config_file, bool main) { "(missing name in dir line)", 0); _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); - WM_FreePatches(); + FreePatches(); free(line_tokens); free(config_buffer); return -1; @@ -723,7 +685,7 @@ static int WM_LoadConfig(const char *config_file, bool main) { "to parse config", errno); _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); - WM_FreePatches(); + FreePatches(); free(line_tokens); free(config_buffer); return -1; @@ -739,7 +701,7 @@ static int WM_LoadConfig(const char *config_file, bool main) { "(missing name in source line)", 0); _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); - WM_FreePatches(); + FreePatches(); free(line_tokens); free(config_buffer); return -1; @@ -752,7 +714,7 @@ static int WM_LoadConfig(const char *config_file, bool main) { "to parse config", errno); _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); - WM_FreePatches(); + FreePatches(); free(config_dir); free(line_tokens); free(config_buffer); @@ -766,13 +728,13 @@ static int WM_LoadConfig(const char *config_file, bool main) { "to parse config", errno); _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); - WM_FreePatches(); + FreePatches(); free(line_tokens); free(config_buffer); return -1; } } - if (WM_LoadConfig(new_config, false) == -1) { + if (LoadConfig(new_config) == -1) { free(new_config); free(line_tokens); free(config_buffer); @@ -786,7 +748,7 @@ static int WM_LoadConfig(const char *config_file, bool main) { "(syntax error in bank line)", 0); _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); - WM_FreePatches(); + FreePatches(); free(config_dir); free(line_tokens); free(config_buffer); @@ -799,7 +761,7 @@ static int WM_LoadConfig(const char *config_file, bool main) { "(syntax error in drumset line)", 0); _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); - WM_FreePatches(); + FreePatches(); free(config_dir); free(line_tokens); free(config_buffer); @@ -813,7 +775,7 @@ static int WM_LoadConfig(const char *config_file, bool main) { 0); _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); - WM_FreePatches(); + FreePatches(); free(config_dir); free(line_tokens); free(config_buffer); @@ -838,7 +800,7 @@ static int WM_LoadConfig(const char *config_file, bool main) { 0); _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); - WM_FreePatches(); + FreePatches(); free(config_dir); free(line_tokens); free(config_buffer); @@ -863,7 +825,7 @@ static int WM_LoadConfig(const char *config_file, bool main) { 0); _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); - WM_FreePatches(); + FreePatches(); free(config_dir); free(line_tokens); free(config_buffer); @@ -885,7 +847,7 @@ static int WM_LoadConfig(const char *config_file, bool main) { 0); _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); - WM_FreePatches(); + FreePatches(); free(config_dir); free(line_tokens); free(config_buffer); @@ -920,7 +882,7 @@ static int WM_LoadConfig(const char *config_file, bool main) { NULL, errno); _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); - WM_FreePatches(); + FreePatches(); free(config_dir); free(line_tokens); free(config_buffer); @@ -958,7 +920,7 @@ static int WM_LoadConfig(const char *config_file, bool main) { _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); - WM_FreePatches(); + FreePatches(); free(config_dir); free(line_tokens); free(config_buffer); @@ -988,7 +950,7 @@ static int WM_LoadConfig(const char *config_file, bool main) { WM_ERR_MEM, NULL, errno); _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); - WM_FreePatches(); + FreePatches(); free(config_dir); free(line_tokens); free(config_buffer); @@ -1011,7 +973,7 @@ static int WM_LoadConfig(const char *config_file, bool main) { "(missing name in patch line)", 0); _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); - WM_FreePatches(); + FreePatches(); free(config_dir); free(line_tokens); free(config_buffer); @@ -1025,7 +987,7 @@ static int WM_LoadConfig(const char *config_file, bool main) { NULL, 0); _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); - WM_FreePatches(); + FreePatches(); free(config_dir); free(line_tokens); free(config_buffer); @@ -1039,7 +1001,7 @@ static int WM_LoadConfig(const char *config_file, bool main) { NULL, 0); _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, config_file, 0); - WM_FreePatches(); + FreePatches(); free(config_dir); free(line_tokens); free(config_buffer); @@ -1185,7 +1147,8 @@ static int WM_LoadConfig(const char *config_file, bool main) { /* sample loading */ -static int load_sample(struct _patch *sample_patch) { +int Instruments::load_sample(struct _patch *sample_patch) + { struct _sample *guspat = NULL; struct _sample *tmp_sample = NULL; unsigned int i = 0; @@ -1193,7 +1156,7 @@ static int load_sample(struct _patch *sample_patch) { /* we only want to try loading the guspat once. */ sample_patch->loaded = 1; - if ((guspat = _WM_load_gus_pat(sample_patch->filename, fix_release)) == NULL) { + if ((guspat = load_gus_pat(sample_patch->filename)) == NULL) { return -1; } @@ -1305,12 +1268,10 @@ static int load_sample(struct _patch *sample_patch) { return 0; } -static struct _patch * -get_patch_data(unsigned short patchid) { +struct _patch *Instruments::get_patch_data(unsigned short patchid) +{ struct _patch *search_patch; - std::lock_guard lock(patch_lock); - search_patch = patch[patchid & 0x007F]; if (search_patch == NULL) { @@ -1329,7 +1290,8 @@ get_patch_data(unsigned short patchid) { return NULL; } -static void load_patch(struct _mdi *mdi, unsigned short patchid) { +void Instruments::load_patch(struct _mdi *mdi, unsigned short patchid) +{ unsigned int i; struct _patch *tmp_patch = NULL; @@ -1344,7 +1306,6 @@ static void load_patch(struct _mdi *mdi, unsigned short patchid) { return; } - std::lock_guard lock(patch_lock); if (!tmp_patch->loaded) { if (load_sample(tmp_patch) == -1) { return; @@ -1362,12 +1323,11 @@ static void load_patch(struct _mdi *mdi, unsigned short patchid) { tmp_patch->inuse_count++; } -static struct _sample * -get_sample_data(struct _patch *sample_patch, unsigned long int freq) { +static struct _sample *get_sample_data(struct _patch *sample_patch, unsigned long int freq) + { struct _sample *last_sample = NULL; struct _sample *return_sample = NULL; - std::lock_guard lock(patch_lock); if (sample_patch == NULL) { return NULL; } @@ -1394,7 +1354,8 @@ get_sample_data(struct _patch *sample_patch, unsigned long int freq) { } /* Should be called in any function that effects note volumes */ -void _WM_AdjustNoteVolumes(struct _mdi *mdi, unsigned char ch, struct _note *nte) { +void Renderer::AdjustNoteVolumes(struct _mdi *mdi, unsigned char ch, struct _note *nte) + { double premix_dBm; double premix_lin; int pan_ofs; @@ -1450,7 +1411,8 @@ void _WM_AdjustNoteVolumes(struct _mdi *mdi, unsigned char ch, struct _note *nte /* Should be called in any function that effects channel volumes */ /* Calling this function with a value > 15 will make it adjust notes on all channels */ -void _WM_AdjustChannelVolumes(struct _mdi *mdi, unsigned char ch) { +void Renderer::AdjustChannelVolumes(struct _mdi *mdi, unsigned char ch) +{ struct _note *nte = mdi->note; if (nte != NULL) { do { @@ -1460,8 +1422,8 @@ void _WM_AdjustChannelVolumes(struct _mdi *mdi, unsigned char ch) { } } else { _DO_ADJUST: - _WM_AdjustNoteVolumes(mdi, ch, nte); - if (nte->replay) _WM_AdjustNoteVolumes(mdi, ch, nte->replay); + AdjustNoteVolumes(mdi, ch, nte); + if (nte->replay) AdjustNoteVolumes(mdi, ch, nte->replay); } nte = nte->next; } while (nte != NULL); @@ -1538,7 +1500,8 @@ static void do_note_off(struct _mdi *mdi, struct _event_data *data) { } } -static inline unsigned long int get_inc(struct _mdi *mdi, struct _note *nte) { +unsigned long int Renderer::get_inc(struct _mdi *mdi, struct _note *nte) +{ int ch = nte->noteid >> 8; signed long int note_f; unsigned long int freq; @@ -1555,11 +1518,12 @@ static inline unsigned long int get_inc(struct _mdi *mdi, struct _note *nte) { note_f = 12700; } freq = freq_table[(note_f % 1200)] >> (10 - (note_f / 1200)); - return (((freq / ((_WM_SampleRate * 100) / 1024)) * 1024 + return (((freq / ((instruments->GetSampleRate() * 100) / 1024)) * 1024 / nte->sample->inc_div)); } -static void do_note_on(struct _mdi *mdi, struct _event_data *data) { +void Renderer::do_note_on(struct _mdi *mdi, struct _event_data *data) +{ struct _note *nte; struct _note *prev_nte; struct _note *nte_array; @@ -1584,7 +1548,7 @@ static void do_note_on(struct _mdi *mdi, struct _event_data *data) { } freq = freq_table[(note % 12) * 100] >> (10 - (note / 12)); } else { - patch = get_patch_data(((mdi->channel[ch].bank << 8) | note | 0x80)); + patch = instruments->get_patch_data(((mdi->channel[ch].bank << 8) | note | 0x80)); if (patch == NULL) { return; } @@ -1648,10 +1612,11 @@ static void do_note_on(struct _mdi *mdi, struct _event_data *data) { nte->hold = mdi->channel[ch].hold; nte->replay = NULL; nte->is_off = 0; - _WM_AdjustNoteVolumes(mdi, ch, nte); + AdjustNoteVolumes(mdi, ch, nte); } -static void do_aftertouch(struct _mdi *mdi, struct _event_data *data) { +void Renderer::do_aftertouch(struct _mdi *mdi, struct _event_data *data) +{ struct _note *nte; unsigned char ch = data->channel; @@ -1666,10 +1631,10 @@ static void do_aftertouch(struct _mdi *mdi, struct _event_data *data) { } nte->velocity = (unsigned char)data->data; - _WM_AdjustNoteVolumes(mdi, ch, nte); + AdjustNoteVolumes(mdi, ch, nte); if (nte->replay) { nte->replay->velocity = (unsigned char)data->data; - _WM_AdjustNoteVolumes(mdi, ch, nte->replay); + AdjustNoteVolumes(mdi, ch, nte->replay); } } @@ -1692,37 +1657,38 @@ static void do_control_data_entry_course(struct _mdi *mdi, } } -static void do_control_channel_volume(struct _mdi *mdi, - struct _event_data *data) { +void Renderer::do_control_channel_volume(struct _mdi *mdi, struct _event_data *data) +{ struct _note *note_data = mdi->note; unsigned char ch = data->channel; mdi->channel[ch].volume = (unsigned char)data->data; - _WM_AdjustChannelVolumes(mdi, ch); + AdjustChannelVolumes(mdi, ch); } -static void do_control_channel_balance(struct _mdi *mdi, - struct _event_data *data) { +void Renderer::do_control_channel_balance(struct _mdi *mdi, struct _event_data *data) +{ unsigned char ch = data->channel; mdi->channel[ch].balance = (signed char)(data->data); - _WM_AdjustChannelVolumes(mdi, ch); + AdjustChannelVolumes(mdi, ch); } -static void do_control_channel_pan(struct _mdi *mdi, struct _event_data *data) { +void Renderer::do_control_channel_pan(struct _mdi *mdi, struct _event_data *data) + { unsigned char ch = data->channel; mdi->channel[ch].pan = (signed char)(data->data); - _WM_AdjustChannelVolumes(mdi, ch); + AdjustChannelVolumes(mdi, ch); } -static void do_control_channel_expression(struct _mdi *mdi, - struct _event_data *data) { +void Renderer::do_control_channel_expression(struct _mdi *mdi, struct _event_data *data) +{ struct _note *note_data = mdi->note; unsigned char ch = data->channel; mdi->channel[ch].expression = (unsigned char)data->data; - _WM_AdjustChannelVolumes(mdi, ch); + AdjustChannelVolumes(mdi, ch); } static void do_control_data_entry_fine(struct _mdi *mdi, @@ -1862,8 +1828,8 @@ static void do_control_channel_sound_off(struct _mdi *mdi, } } -static void do_control_channel_controllers_off(struct _mdi *mdi, - struct _event_data *data) { +void Renderer::do_control_channel_controllers_off(struct _mdi *mdi, struct _event_data *data) +{ struct _note *note_data = mdi->note; unsigned char ch = data->channel; @@ -1875,7 +1841,7 @@ static void do_control_channel_controllers_off(struct _mdi *mdi, mdi->channel[ch].pitch_adjust = 0; mdi->channel[ch].hold = 0; - _WM_AdjustChannelVolumes(mdi, ch); + AdjustChannelVolumes(mdi, ch); } static void do_control_channel_notes_off(struct _mdi *mdi, @@ -1911,17 +1877,19 @@ static void do_control_channel_notes_off(struct _mdi *mdi, } } -static void do_patch(struct _mdi *mdi, struct _event_data *data) { +void Renderer::do_patch(struct _mdi *mdi, struct _event_data *data) +{ unsigned char ch = data->channel; MIDI_EVENT_DEBUG(__FUNCTION__,ch); if (!mdi->channel[ch].isdrum) { - mdi->channel[ch].patch = get_patch_data((unsigned short)(((mdi->channel[ch].bank << 8) | data->data))); + mdi->channel[ch].patch = instruments->get_patch_data((unsigned short)(((mdi->channel[ch].bank << 8) | data->data))); } else { mdi->channel[ch].bank = (unsigned char)data->data; } } -static void do_channel_pressure(struct _mdi *mdi, struct _event_data *data) { +void Renderer::do_channel_pressure(struct _mdi *mdi, struct _event_data *data) +{ struct _note *note_data = mdi->note; unsigned char ch = data->channel; @@ -1930,17 +1898,18 @@ static void do_channel_pressure(struct _mdi *mdi, struct _event_data *data) { while (note_data) { if ((note_data->noteid >> 8) == ch) { note_data->velocity = (unsigned char)data->data; - _WM_AdjustNoteVolumes(mdi, ch, note_data); + AdjustNoteVolumes(mdi, ch, note_data); if (note_data->replay) { note_data->replay->velocity = (unsigned char)data->data; - _WM_AdjustNoteVolumes(mdi, ch, note_data->replay); + AdjustNoteVolumes(mdi, ch, note_data->replay); } } note_data = note_data->next; } } -static void do_pitch(struct _mdi *mdi, struct _event_data *data) { + void Renderer::do_pitch(struct _mdi *mdi, struct _event_data *data) +{ struct _note *note_data = mdi->note; unsigned char ch = data->channel; @@ -1965,8 +1934,8 @@ static void do_pitch(struct _mdi *mdi, struct _event_data *data) { } } -static void do_sysex_roland_drum_track(struct _mdi *mdi, - struct _event_data *data) { +void Renderer::do_sysex_roland_drum_track(struct _mdi *mdi, struct _event_data *data) +{ unsigned char ch = data->channel; MIDI_EVENT_DEBUG(__FUNCTION__,ch); @@ -1976,16 +1945,17 @@ static void do_sysex_roland_drum_track(struct _mdi *mdi, mdi->channel[ch].patch = NULL; } else { mdi->channel[ch].isdrum = 0; - mdi->channel[ch].patch = get_patch_data(0); + mdi->channel[ch].patch = instruments->get_patch_data(0); } } -static void do_sysex_gm_reset(struct _mdi *mdi, struct _event_data *data) { +void Renderer::do_sysex_gm_reset(struct _mdi *mdi, struct _event_data *data) +{ int i; for (i = 0; i < 16; i++) { mdi->channel[i].bank = 0; if (i != 9) { - mdi->channel[i].patch = get_patch_data(0); + mdi->channel[i].patch = instruments->get_patch_data(0); } else { mdi->channel[i].patch = NULL; } @@ -2002,22 +1972,24 @@ static void do_sysex_gm_reset(struct _mdi *mdi, struct _event_data *data) { } /* I would not expect notes to be active when this event triggers but we'll adjust active notes as well just in case */ - _WM_AdjustChannelVolumes(mdi,16); // A setting > 15 adjusts all channels + AdjustChannelVolumes(mdi,16); // A setting > 15 adjusts all channels mdi->channel[9].isdrum = 1; UNUSED(data); /* NOOP, to please the compiler gods */ } -static void do_sysex_roland_reset(struct _mdi *mdi, struct _event_data *data) { +void Renderer::do_sysex_roland_reset(struct _mdi *mdi, struct _event_data *data) +{ do_sysex_gm_reset(mdi, data); } -static void do_sysex_yamaha_reset(struct _mdi *mdi, struct _event_data *data) { +void Renderer::do_sysex_yamaha_reset(struct _mdi *mdi, struct _event_data *data) +{ do_sysex_gm_reset(mdi, data); } -static struct _mdi * -Init_MDI(void) { +struct _mdi *Renderer::Init_MDI() +{ struct _mdi *mdi; mdi = new _mdi; @@ -2025,7 +1997,7 @@ Init_MDI(void) { mdi->info.copyright = NULL; mdi->info.mixer_options = WM_MixerOptions; - load_patch(mdi, 0x0000); + instruments->load_patch(mdi, 0x0000); mdi->samples_to_mix = 0; mdi->info.current_sample = 0; @@ -2037,12 +2009,12 @@ Init_MDI(void) { return mdi; } -static void freeMDI(struct _mdi *mdi) { +static void freeMDI(struct _mdi *mdi) +{ struct _sample *tmp_sample; unsigned long int i; if (mdi->patch_count != 0) { - std::lock_guard lock(patch_lock); for (i = 0; i < mdi->patch_count; i++) { mdi->patches[i]->inuse_count--; if (mdi->patches[i]->inuse_count == 0) { @@ -2243,7 +2215,7 @@ static int *WM_Mix_Linear(midi * handle, int * buffer, unsigned long int count) static int *WM_Mix_Gauss(midi * handle, int * buffer, unsigned long int count) { - if (!gauss_table) init_gauss(); + if (!gauss_table.size()) init_gauss(); struct _mdi *mdi = (struct _mdi *)handle; unsigned long int data_pos; @@ -2484,118 +2456,32 @@ int *WM_Mix(midi *handle, int *buffer, unsigned long count) * ========================= */ -WM_SYMBOL const char * -WildMidi_GetString(unsigned short int info) { - switch (info) { +const char *WildMidi_GetString(unsigned short int info) +{ + switch (info) + { case WM_GS_VERSION: return WM_Version; } return NULL; } -WM_SYMBOL int WildMidi_Init(FSoundFontReader *reader, unsigned short int rate, - unsigned short int options) { - if (WM_Initialized) { - _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_ALR_INIT, NULL, 0); - return -1; - } - WM_InitPatches(); - wm_sfreader.reset(reader); - if (WM_LoadConfig(nullptr, true) == -1) { - return -1; - } - - if (options & 0x5FF8) { - _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(invalid option)", - 0); - WM_FreePatches(); - return -1; - } - WM_MixerOptions = options; - - if (rate < 11025) { - _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, - "(rate out of bounds, range is 11025 - 65535)", 0); - WM_FreePatches(); - return -1; - } - _WM_SampleRate = rate; - WM_Initialized = 1; - - return 0; -} - -WM_SYMBOL int WildMidi_GetSampleRate(void) +midi * Renderer::NewMidi() { - return _WM_SampleRate; -} - -WM_SYMBOL int WildMidi_MasterVolume(unsigned char master_volume) { - struct _mdi *mdi = NULL; - int i = 0; - - if (!WM_Initialized) { - _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_INIT, NULL, 0); - return -1; - } - if (master_volume > 127) { - _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, - "(master volume out of range, range is 0-127)", 0); - return -1; - } - - WM_MasterVolume = lin_volume[master_volume]; - - return 0; -} - -WM_SYMBOL int WildMidi_Close(midi * handle) { - struct _mdi *mdi = (struct _mdi *) handle; - - if (!WM_Initialized) { - _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_INIT, NULL, 0); - return -1; - } - if (handle == NULL) { - _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(NULL handle)", - 0); - return -1; - } - - freeMDI(mdi); - return 0; -} - -midi *WildMidi_NewMidi() { midi * ret = NULL; - if (!WM_Initialized) { - _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_INIT, NULL, 0); - return NULL; - } ret = Init_MDI(); - if ((((_mdi*)ret)->reverb = _WM_init_reverb(_WM_SampleRate, reverb_room_width, - reverb_room_length, reverb_listen_posx, reverb_listen_posy)) - == NULL) { - _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to init reverb", 0); - WildMidi_Close(ret); - ret = NULL; - } - - + ((_mdi*)ret)->reverb = _WM_init_reverb(instruments->GetSampleRate(), instruments->reverb_room_width, + instruments->reverb_room_length, instruments->reverb_listen_posx, instruments->reverb_listen_posy); return ret; } -WM_SYMBOL int WildMidi_SetOption(midi * handle, unsigned short int options, - unsigned short int setting) { +int Renderer::SetOption(int options, int setting) +{ struct _mdi *mdi; - if (!WM_Initialized) { - _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_NOT_INIT, NULL, 0); - return -1; - } if (handle == NULL) { _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID_ARG, "(NULL handle)", 0); @@ -2618,7 +2504,7 @@ WM_SYMBOL int WildMidi_SetOption(midi * handle, unsigned short int options, | (options & setting)); if (options & WM_MO_LOG_VOLUME) { - _WM_AdjustChannelVolumes(mdi, 16); // Settings greater than 15 + AdjustChannelVolumes(mdi, 16); // Settings greater than 15 // adjust all channels } else if (options & WM_MO_REVERB) { _WM_reset_reverb(mdi->reverb); @@ -2627,42 +2513,20 @@ WM_SYMBOL int WildMidi_SetOption(midi * handle, unsigned short int options, return 0; } -WM_SYMBOL int WildMidi_Shutdown(void) { - if (!WM_Initialized) { - // No error if trying to shut down an uninitialized device. - return 0; - } - WM_FreePatches(); - free_gauss(); - - /* reset the globals */ - WM_MasterVolume = 948; - WM_MixerOptions = 0; - fix_release = 0; - auto_amp = 0; - auto_amp_with_amp = 0; - reverb_room_width = 16.875f; - reverb_room_length = 22.5f; - reverb_listen_posx = 8.4375f; - reverb_listen_posy = 16.875f; - - WM_Initialized = 0; - - return 0; -} - -WildMidi_Renderer::WildMidi_Renderer() +Renderer::Renderer(Instruments *instr, unsigned mixOpt) { - handle = WildMidi_NewMidi(); + init_gauss(); + WM_MixerOptions = mixOpt; + handle = NewMidi(); } -WildMidi_Renderer::~WildMidi_Renderer() +Renderer::~Renderer() { - WildMidi_Close((midi *)handle); + freeMDI((_mdi *)handle); } -void WildMidi_Renderer::ShortEvent(int status, int parm1, int parm2) +void Renderer::ShortEvent(int status, int parm1, int parm2) { _mdi *mdi = (_mdi *)handle; _event_data ev; @@ -2725,7 +2589,7 @@ void WildMidi_Renderer::ShortEvent(int status, int parm1, int parm2) } } -void WildMidi_Renderer::LongEvent(const unsigned char *data, int len) +void Renderer::LongEvent(const unsigned char *data, int len) { // Check for Roland SysEx if (len >= 11 && // Must be at least 11 bytes @@ -2782,7 +2646,7 @@ void WildMidi_Renderer::LongEvent(const unsigned char *data, int len) } } -void WildMidi_Renderer::ComputeOutput(float *fbuffer, int len) +void Renderer::ComputeOutput(float *fbuffer, int len) { _mdi *mdi = (_mdi *)handle; int *buffer = (int *)fbuffer; @@ -2797,12 +2661,12 @@ void WildMidi_Renderer::ComputeOutput(float *fbuffer, int len) } } -void WildMidi_Renderer::LoadInstrument(int bank, int percussion, int instr) +void Renderer::LoadInstrument(int bank, int percussion, int instr) { - load_patch((_mdi *)handle, (bank << 8) | instr | (percussion ? 0x80 : 0)); + instruments->load_patch((_mdi *)handle, (bank << 8) | instr | (percussion ? 0x80 : 0)); } -int WildMidi_Renderer::GetVoiceCount() +int Renderer::GetVoiceCount() { int count = 0; for (_note *note_data = ((_mdi *)handle)->note; note_data != NULL; note_data = note_data->next) @@ -2812,7 +2676,10 @@ int WildMidi_Renderer::GetVoiceCount() return count; } -void WildMidi_Renderer::SetOption(int opt, int set) + +void Renderer::SetMasterVolume(unsigned char master_volume) { - WildMidi_SetOption((_mdi*)handle, (unsigned short)opt, (unsigned short)set); + WM_MasterVolume = lin_volume[std::min(127, master_volume)]; +} + } diff --git a/src/sound/wildmidi/wildmidi_lib.h b/src/sound/wildmidi/wildmidi_lib.h index c5d27f5956..39079afc5e 100644 --- a/src/sound/wildmidi/wildmidi_lib.h +++ b/src/sound/wildmidi/wildmidi_lib.h @@ -27,21 +27,21 @@ #ifndef WILDMIDI_LIB_H #define WILDMIDI_LIB_H -#define WM_MO_LOG_VOLUME 0x0001 -#define WM_MO_ENHANCED_RESAMPLING 0x0002 -#define WM_MO_REVERB 0x0004 -#define WM_MO_WHOLETEMPO 0x8000 -#define WM_MO_ROUNDTEMPO 0x2000 +namespace WildMidi +{ +enum EMixerOptions +{ + WM_MO_LOG_VOLUME = 0x0001, + WM_MO_ENHANCED_RESAMPLING = 0x0002, + WM_MO_REVERB = 0x0004, + WM_MO_WHOLETEMPO = 0x8000, + WM_MO_ROUNDTEMPO = 0x2000, + + WM_GS_VERSION = 0x0001, +}; -#define WM_GS_VERSION 0x0001 -#define WM_SYMBOL // we do not need this in ZDoom - -/* -#if defined(__cplusplus) -extern "C" { -#endif -*/ +class SoundFontReaderInterface; struct _WM_Info { char *copyright; @@ -52,36 +52,89 @@ struct _WM_Info { }; typedef void midi; - -WM_SYMBOL const char * WildMidi_GetString (unsigned short int info); -WM_SYMBOL int WildMidi_Init (FSoundFontReader *reader, unsigned short int rate, unsigned short int options); -WM_SYMBOL int WildMidi_MasterVolume (unsigned char master_volume); -WM_SYMBOL int WildMidi_SetOption (midi * handle, unsigned short int options, unsigned short int setting); -WM_SYMBOL int WildMidi_Close (midi * handle); -WM_SYMBOL int WildMidi_Shutdown (void); -WM_SYMBOL int WildMidi_GetSampleRate (void); - -/* -#if defined(__cplusplus) -} -#endif -*/ - -class WildMidi_Renderer + +struct Instruments { + SoundFontReaderInterface *sfreader; + + struct _patch *patch[128] = {}; + float reverb_room_width = 16.875f; + float reverb_room_length = 22.5f; + + float reverb_listen_posx = 8.4375f; + float reverb_listen_posy = 16.875f; + + int fix_release = 0; + int auto_amp = 0; + int auto_amp_with_amp = 0; + + unsigned short int _WM_SampleRate; // WildMidi makes the sample rate a property of the patches, not the renderer. Meaning that the instruments need to be reloaded when it changes... :? + + Instruments(SoundFontReaderInterface *reader, int samplerate) + { + sfreader = reader; + _WM_SampleRate = samplerate; + } + + int LoadConfig(const char *config_file); + int load_sample(struct _patch *sample_patch); + struct _patch *get_patch_data(unsigned short patchid); + void load_patch(struct _mdi *mdi, unsigned short patchid); + int GetSampleRate() { return _WM_SampleRate; } + struct _sample * load_gus_pat(const char *filename); + +private: + void FreePatches(void); +}; + +const char * WildMidi_GetString (unsigned short int info); + + + +class Renderer +{ + Instruments *instruments; + + signed int WM_MasterVolume = 948; + unsigned int WM_MixerOptions = 0; + public: - WildMidi_Renderer(); - ~WildMidi_Renderer(); + Renderer(Instruments *instr, unsigned mixOpt = 0); + ~Renderer(); void ShortEvent(int status, int parm1, int parm2); void LongEvent(const unsigned char *data, int len); void ComputeOutput(float *buffer, int len); void LoadInstrument(int bank, int percussion, int instr); int GetVoiceCount(); - void SetOption(int opt, int set); + int SetOption(int opt, int set); + + void SetMasterVolume(unsigned char master_volume); + midi * NewMidi(); + private: void *handle; + + void AdjustNoteVolumes(struct _mdi *mdi, unsigned char ch, struct _note *nte); + void AdjustChannelVolumes(struct _mdi *mdi, unsigned char ch); + void do_note_on(struct _mdi *mdi, struct _event_data *data); + void do_aftertouch(struct _mdi *mdi, struct _event_data *data); + void do_control_channel_volume(struct _mdi *mdi, struct _event_data *data); + void do_control_channel_balance(struct _mdi *mdi, struct _event_data *data); + void do_control_channel_pan(struct _mdi *mdi, struct _event_data *data); + void do_control_channel_expression(struct _mdi *mdi, struct _event_data *data); + void do_control_channel_controllers_off(struct _mdi *mdi, struct _event_data *data); + void do_pitch(struct _mdi *mdi, struct _event_data *data); + void do_patch(struct _mdi *mdi, struct _event_data *data); + void do_channel_pressure(struct _mdi *mdi, struct _event_data *data); + void do_sysex_roland_drum_track(struct _mdi *mdi, struct _event_data *data); + void do_sysex_gm_reset(struct _mdi *mdi, struct _event_data *data); + void do_sysex_roland_reset(struct _mdi *mdi, struct _event_data *data); + void do_sysex_yamaha_reset(struct _mdi *mdi, struct _event_data *data); + struct _mdi *Init_MDI(); + unsigned long int get_inc(struct _mdi *mdi, struct _note *nte); }; +} #endif /* WILDMIDI_LIB_H */ diff --git a/src/sound/wildmidi/wm_error.cpp b/src/sound/wildmidi/wm_error.cpp index eab56c437a..5411d87d76 100644 --- a/src/sound/wildmidi/wm_error.cpp +++ b/src/sound/wildmidi/wm_error.cpp @@ -29,22 +29,26 @@ #include #include #include "wm_error.h" -#include "doomtype.h" -#include "v_text.h" + +namespace WildMidi +{ +static void def_error_func(const char *wmfmt, va_list args) +{ + vprintf(wmfmt, args); +} + +void (*wm_error_func)(const char *wmfmt, va_list args) = def_error_func; void _WM_ERROR_NEW(const char * wmfmt, ...) { va_list args; - fprintf(stderr, "\r"); va_start(args, wmfmt); - vfprintf(stderr, wmfmt, args); - va_end(args); - fprintf(stderr, "\n"); + wm_error_func(wmfmt, args); } void _WM_ERROR(const char * func, unsigned int lne, int wmerno, const char * wmfor, int error) { - static const char *errors[WM_ERR_MAX+1] = { + static const char *const errors[WM_ERR_MAX+1] = { "No error", "Unable to obtain memory", "Unable to stat", @@ -67,20 +71,21 @@ void _WM_ERROR(const char * func, unsigned int lne, int wmerno, if (wmfor != NULL) { if (error != 0) { - Printf(TEXTCOLOR_RED "libWildMidi(%s:%u): ERROR %s %s (%s)\n", func, - lne, errors[wmerno], wmfor, strerror(error)); + _WM_ERROR_NEW("libWildMidi(%s:%u): ERROR %s %s (%s)\n", func, lne, + errors[wmerno], wmfor, strerror(error)); } else { - Printf(TEXTCOLOR_RED "libWildMidi(%s:%u): ERROR %s %s\n", func, lne, + _WM_ERROR_NEW("libWildMidi(%s:%u): ERROR %s %s\n", func, lne, errors[wmerno], wmfor); } } else { if (error != 0) { - Printf(TEXTCOLOR_RED "libWildMidi(%s:%u): ERROR %s (%s)\n", func, lne, + _WM_ERROR_NEW("libWildMidi(%s:%u): ERROR %s (%s)\n", func, lne, errors[wmerno], strerror(error)); } else { - Printf(TEXTCOLOR_RED "libWildMidi(%s:%u): ERROR %s\n", func, lne, + _WM_ERROR_NEW("libWildMidi(%s:%u): ERROR %s\n", func, lne, errors[wmerno]); } } } +} diff --git a/src/sound/wildmidi/wm_error.h b/src/sound/wildmidi/wm_error.h index 3169246482..5fa6f43340 100644 --- a/src/sound/wildmidi/wm_error.h +++ b/src/sound/wildmidi/wm_error.h @@ -27,6 +27,9 @@ #ifndef __WM_ERROR_H #define __WM_ERROR_H +namespace WildMidi +{ + enum { WM_ERR_NONE = 0, WM_ERR_MEM, @@ -53,4 +56,5 @@ enum { extern void _WM_ERROR(const char * func, unsigned int lne, int wmerno, const char * wmfor, int error); +} #endif /* __WM_ERROR_H */