diff --git a/libraries/zmusic/midisources/midisource.cpp b/libraries/zmusic/midisources/midisource.cpp index 22e62af05..0fa3d0fdb 100644 --- a/libraries/zmusic/midisources/midisource.cpp +++ b/libraries/zmusic/midisources/midisource.cpp @@ -404,3 +404,86 @@ void MIDISource::CreateSMF(std::vector &file, int looplimit) } +//========================================================================== +// +// Global interface (identification / creation of MIDI sources) +// +//========================================================================== + +extern int MUSHeaderSearch(const uint8_t *head, int len); + +//========================================================================== +// +// identify MIDI file type +// +//========================================================================== + +EMIDIType IdentifyMIDIType(uint32_t *id, int size) +{ + // Check for MUS format + // Tolerate sloppy wads by searching up to 32 bytes for the header + if (MUSHeaderSearch((uint8_t*)id, size) >= 0) + { + return MIDI_MUS; + } + // Check for HMI format + else + if (id[0] == MAKE_ID('H','M','I','-') && + id[1] == MAKE_ID('M','I','D','I') && + id[2] == MAKE_ID('S','O','N','G')) + { + return MIDI_HMI; + } + // Check for HMP format + else + if (id[0] == MAKE_ID('H','M','I','M') && + id[1] == MAKE_ID('I','D','I','P')) + { + return MIDI_HMI; + } + // Check for XMI format + else + if ((id[0] == MAKE_ID('F','O','R','M') && + id[2] == MAKE_ID('X','D','I','R')) || + ((id[0] == MAKE_ID('C','A','T',' ') || id[0] == MAKE_ID('F','O','R','M')) && + id[2] == MAKE_ID('X','M','I','D'))) + { + return MIDI_XMI; + } + // Check for MIDI format + else if (id[0] == MAKE_ID('M','T','h','d')) + { + return MIDI_MIDI; + } + else + { + return MIDI_NOTMIDI; + } +} + +//========================================================================== +// +// create a source based on MIDI file type +// +//========================================================================== + +MIDISource *CreateMIDISource(const uint8_t *data, size_t length, EMIDIType miditype) +{ + switch (miditype) + { + case MIDI_MUS: + return new MUSSong2(data, length); + + case MIDI_MIDI: + return new MIDISong2(data, length); + + case MIDI_HMI: + return new HMISong(data, length); + + case MIDI_XMI: + return new XMISong(data, length); + + default: + return nullptr; + } +} diff --git a/libraries/zmusic/zmusic/midiconfig.h b/libraries/zmusic/zmusic/midiconfig.h index 149e71bbe..df6cd5527 100644 --- a/libraries/zmusic/zmusic/midiconfig.h +++ b/libraries/zmusic/zmusic/midiconfig.h @@ -139,15 +139,18 @@ struct DumbConfig float mod_dumb_mastervolume; }; +// The rest is not used yet. struct misc { bool snd_midiprecache; - float gme_stereodepth + float gme_stereodepth; int snd_streambuffersize; }; +namespace ZMusic +{ enum EZMusicIntConfigKey { @@ -171,7 +174,6 @@ enum EZMusicIntConfigKey opl_numchips, opl_core, opl_fullpan, - oplConfig.fullpan = self; opn_chips_count, opn_emulator_id, @@ -214,7 +216,7 @@ enum EZMusicIntConfigKey snd_streambuffersize, NUM_INT_CONFIGS -} +}; enum EZMusicFloatConfigKey { @@ -233,6 +235,8 @@ enum EZMusicFloatConfigKey gme_stereodepth, mod_dumb_mastervolume, + + NUM_FLOAT_CONFIGS }; enum EMusicStringConfigKey @@ -245,4 +249,8 @@ enum EMusicStringConfigKey gus_patchdir, timidity_config, wildmidi_config, + + NUM_STRING_CONFIGS }; + +} \ No newline at end of file diff --git a/libraries/zmusic/zmusic/mididefs.h b/libraries/zmusic/zmusic/mididefs.h index a42e22eaf..42418feaa 100644 --- a/libraries/zmusic/zmusic/mididefs.h +++ b/libraries/zmusic/zmusic/mididefs.h @@ -13,7 +13,7 @@ inline constexpr uint32_t MEVENT_EVENTPARM(uint32_t x) { return ((x) & 0xffffff) // These constants must match the corresponding values of the Windows headers // to avoid readjustment in the native Windows device's playback functions // and should not be changed. -enum +enum EMidiDeviceClass { MIDIDEV_MIDIPORT = 1, MIDIDEV_SYNTH, @@ -24,7 +24,16 @@ enum MIDIDEV_SWSYNTH }; -enum : uint8_t +enum EMIDIType +{ + MIDI_NOTMIDI, + MIDI_MIDI, + MIDI_HMI, + MIDI_XMI, + MIDI_MUS +}; + +enum EMidiEvent : uint8_t { MEVENT_TEMPO = 1, MEVENT_NOP = 2, @@ -49,10 +58,9 @@ enum EMidiDevice struct SoundStreamInfo { - // Format is always 32 bit float. If mBufferSize is 0, the song doesn't use streaming but plays through a different interface. - int mBufferSize; + int mBufferSize; // If mBufferSize is 0, the song doesn't use streaming but plays through a different interface. int mSampleRate; - int mNumChannels; + int mNumChannels; // If mNumChannels is negative, 16 bit integer format is used instead of floating point. }; #ifndef MAKE_ID diff --git a/libraries/zmusic/zmusic/zmusic.h b/libraries/zmusic/zmusic/zmusic.h new file mode 100644 index 000000000..10f4d2d5f --- /dev/null +++ b/libraries/zmusic/zmusic/zmusic.h @@ -0,0 +1,8 @@ +#pragma once + +#include "mididefs.h" + +// These exports is needed by the MIDI dumpers which need to remain on the client side. +class MIDISource; // abstract for the client +EMIDIType IdentifyMIDIType(uint32_t *id, int size); +MIDISource *CreateMIDISource(const uint8_t *data, size_t length, EMIDIType miditype); diff --git a/src/console/c_cvars.cpp b/src/console/c_cvars.cpp index af65f82d2..24c29b826 100644 --- a/src/console/c_cvars.cpp +++ b/src/console/c_cvars.cpp @@ -87,6 +87,7 @@ FBaseCVar::FBaseCVar (const char *var_name, uint32_t flags, void (*callback)(FBa m_Callback = callback; Flags = 0; Name = NULL; + inCallback = false; if (var_name) { diff --git a/src/console/c_cvars.h b/src/console/c_cvars.h index bc6050b22..6d43f1667 100644 --- a/src/console/c_cvars.h +++ b/src/console/c_cvars.h @@ -65,6 +65,7 @@ enum CVAR_IGNORE = 16384,// do not send cvar across the network/inaccesible from ACS (dummy mod cvar) CVAR_CHEAT = 32768,// can be set only when sv_cheats is enabled CVAR_UNSAFECONTEXT = 65536,// cvar value came from unsafe context + CVAR_VIRTUAL = 0x20000, //do not invoke the callback recursively so it can be used to mirror an external variable. }; union UCVarValue @@ -97,7 +98,15 @@ public: FBaseCVar (const char *name, uint32_t flags, void (*callback)(FBaseCVar &)); virtual ~FBaseCVar (); - inline void Callback () { if (m_Callback) m_Callback (*this); } + inline void Callback () + { + if (m_Callback && !inCallback) + { + inCallback = !!(Flags & CVAR_VIRTUAL); // Virtual CVARs never invoke the callback recursively, giving it a chance to manipulate the value without side effects. + m_Callback(*this); + inCallback = false; + } + } inline const char *GetName () const { return Name; } inline uint32_t GetFlags () const { return Flags; } @@ -145,6 +154,7 @@ protected: char *Name; FString SafeValue; uint32_t Flags; + bool inCallback; private: FBaseCVar (const FBaseCVar &var) = delete; diff --git a/src/sound/music/i_music.cpp b/src/sound/music/i_music.cpp index 395b43a40..a5993a794 100644 --- a/src/sound/music/i_music.cpp +++ b/src/sound/music/i_music.cpp @@ -47,6 +47,7 @@ #include "stats.h" #include "vm.h" #include "s_music.h" +#include "zmusic/zmusic.h" #include "streamsources/streamsource.h" #include "filereadermusicinterface.h" #include "../libraries/zmusic/midisources/midisource.h" @@ -66,15 +67,6 @@ EXTERN_CVAR(Float, gme_stereodepth) #define GZIP_FNAME 8 #define GZIP_FCOMMENT 16 -enum EMIDIType -{ - MIDI_NOTMIDI, - MIDI_MIDI, - MIDI_HMI, - MIDI_XMI, - MIDI_MUS -}; - extern int MUSHeaderSearch(const uint8_t *head, int len); void I_InitSoundFonts(); extern "C" void dumb_exit(); @@ -280,32 +272,6 @@ MusInfo *MusInfo::GetWaveDumper(const char *filename, int rate) return nullptr; } -//========================================================================== -// -// create a source based on MIDI file type -// -//========================================================================== - -static MIDISource *CreateMIDISource(const uint8_t *data, size_t length, EMIDIType miditype) -{ - switch (miditype) - { - case MIDI_MUS: - return new MUSSong2(data, length); - - case MIDI_MIDI: - return new MIDISong2(data, length); - - case MIDI_HMI: - return new HMISong(data, length); - - case MIDI_XMI: - return new XMISong(data, length); - - default: - return nullptr; - } -} //========================================================================== // @@ -319,55 +285,6 @@ static MIDIStreamer *CreateMIDIStreamer(EMidiDevice devtype, const char *args) return me; } -//========================================================================== -// -// identify MIDI file type -// -//========================================================================== - -static EMIDIType IdentifyMIDIType(uint32_t *id, int size) -{ - // Check for MUS format - // Tolerate sloppy wads by searching up to 32 bytes for the header - if (MUSHeaderSearch((uint8_t*)id, size) >= 0) - { - return MIDI_MUS; - } - // Check for HMI format - else - if (id[0] == MAKE_ID('H','M','I','-') && - id[1] == MAKE_ID('M','I','D','I') && - id[2] == MAKE_ID('S','O','N','G')) - { - return MIDI_HMI; - } - // Check for HMP format - else - if (id[0] == MAKE_ID('H','M','I','M') && - id[1] == MAKE_ID('I','D','I','P')) - { - return MIDI_HMI; - } - // Check for XMI format - else - if ((id[0] == MAKE_ID('F','O','R','M') && - id[2] == MAKE_ID('X','D','I','R')) || - ((id[0] == MAKE_ID('C','A','T',' ') || id[0] == MAKE_ID('F','O','R','M')) && - id[2] == MAKE_ID('X','M','I','D'))) - { - return MIDI_XMI; - } - // Check for MIDI format - else if (id[0] == MAKE_ID('M','T','h','d')) - { - return MIDI_MIDI; - } - else - { - return MIDI_NOTMIDI; - } -} - //========================================================================== // // identify a music lump's type and set up a player for it