- moved MIDI format detection and source creation into zmusic project.

This commit is contained in:
Christoph Oelckers 2019-09-29 14:47:10 +02:00
parent 54b994e863
commit 6d7b6fb9fd
7 changed files with 128 additions and 93 deletions

View file

@ -404,3 +404,86 @@ void MIDISource::CreateSMF(std::vector<uint8_t> &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;
}
}

View file

@ -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
};
}

View file

@ -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

View file

@ -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);

View file

@ -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)
{

View file

@ -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;

View file

@ -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