fmodex/src/fmod_codec_midi.h

359 lines
18 KiB
C
Raw Normal View History

#ifndef _FMOD_CODEC_MIDI_H
#define _FMOD_CODEC_MIDI_H
#include "fmod_settings.h"
#ifdef FMOD_SUPPORT_MIDI
#include "fmod_music.h"
namespace FMOD
{
class DSPI;
class ChannelPool;
class CodecMIDI;
class CodecMIDITrack;
class CodecMIDIChannel;
#ifdef FMOD_SUPPORT_PRAGMAPACK
#pragma pack(1)
#endif
typedef struct
{
char mID[4] FMOD_PACKED_INTERNAL;
unsigned int mSize FMOD_PACKED_INTERNAL;
} FMOD_PACKED MIDI_CHUNK;
typedef struct
{
MIDI_CHUNK mChunk FMOD_PACKED_INTERNAL;
unsigned short mFormat FMOD_PACKED_INTERNAL;
unsigned short mNumTracks FMOD_PACKED_INTERNAL;
unsigned short mDivision FMOD_PACKED_INTERNAL;
} FMOD_PACKED MTHD_CHUNK;
#ifdef FMOD_SUPPORT_PRAGMAPACK
#ifdef CODEWARRIOR
#pragma pack(0)
#else
#pragma pack()
#endif
#endif
typedef enum
{
MIDI_FORMAT_SINGLETRACK,
MIDI_FORMAT_MULTITRACK,
MIDI_FORMAT_PATTERN,
} MIDI_FORMAT;
static const unsigned char MIDI_VOICE_NOTEOFF = 0x80;
static const unsigned char MIDI_VOICE_NOTEON = 0x90;
static const unsigned char MIDI_VOICE_AFTERTOUCH = 0xA0;
static const unsigned char MIDI_VOICE_CONTROLLERCHANGE = 0xB0;
static const unsigned char MIDI_VOICE_PROGRAMCHANGE = 0xC0;
static const unsigned char MIDI_VOICE_CHANNELKEYPRESSURE= 0xD0;
static const unsigned char MIDI_VOICE_PITCHBEND = 0xE0;
static const unsigned char MIDI_SYSEXESCAPE = 0xF7;
static const unsigned char MIDI_SYSEXEVENT = 0xF0;
static const unsigned char MIDI_METAEVENT = 0xFF;
static const unsigned char MIDI_METAEVENT_SEQNUMBER = 0x00;
static const unsigned char MIDI_METAEVENT_TEXT = 0x01;
static const unsigned char MIDI_METAEVENT_COPYRIGHT = 0x02;
static const unsigned char MIDI_METAEVENT_NAME = 0x03;
static const unsigned char MIDI_METAEVENT_INSTRUMENT = 0x04;
static const unsigned char MIDI_METAEVENT_LYRIC = 0x05;
static const unsigned char MIDI_METAEVENT_MARKER = 0x06;
static const unsigned char MIDI_METAEVENT_CUEPOINT = 0x07;
static const unsigned char MIDI_METAEVENT_PATCHNAME = 0x08;
static const unsigned char MIDI_METAEVENT_PORTNAME = 0x09;
static const unsigned char MIDI_METAEVENT_CHANNEL = 0x20;
static const unsigned char MIDI_METAEVENT_PORT = 0x21;
static const unsigned char MIDI_METAEVENT_ENDOFTRACK = 0x2F;
static const unsigned char MIDI_METAEVENT_TEMPO = 0x51;
static const unsigned char MIDI_METAEVENT_SMTPOFFSET = 0x54;
static const unsigned char MIDI_METAEVENT_TIMESIGNATURE = 0x58;
static const unsigned char MIDI_METAEVENT_KEYSIGNATURE = 0x59;
static const unsigned char MIDI_METAEVENT_PROPRIETARY = 0x7F;
static const unsigned char MIDI_CONTROLLERCHANGE_BANKSELECT_MSB = 0; // 0-127 MSB
static const unsigned char MIDI_CONTROLLERCHANGE_MODULATIONWHEEL_MSB = 1; // 0-127 MSB
static const unsigned char MIDI_CONTROLLERCHANGE_BREATHCONTROL_MSB = 2; // 0-127 MSB
static const unsigned char MIDI_CONTROLLERCHANGE_FOOTCONTROLLER_MSB = 4; // 0-127 MSB
static const unsigned char MIDI_CONTROLLERCHANGE_PORTAMENTOTIME_MSB = 5; // 0-127 MSB
static const unsigned char MIDI_CONTROLLERCHANGE_DATAENTRY_MSB = 6; // 0-127 MSB
static const unsigned char MIDI_CONTROLLERCHANGE_CHANNELVOLUME_MSB = 7; // 0-127 MSB
static const unsigned char MIDI_CONTROLLERCHANGE_BALANCE_MSB = 8; // 0-127 MSB
static const unsigned char MIDI_CONTROLLERCHANGE_PAN_MSB = 10; // 0-127 MSB
static const unsigned char MIDI_CONTROLLERCHANGE_EXPRESSIONCONTROLLER_MSB = 11; // 0-127 MSB
static const unsigned char MIDI_CONTROLLERCHANGE_EFFECTCONTROL1_MSB = 12; // 0-127 MSB
static const unsigned char MIDI_CONTROLLERCHANGE_EFFECTCONTROL2_MSB = 13; // 0-127 MSB
static const unsigned char MIDI_CONTROLLERCHANGE_GENERALPURPOSECONTROLLER1_MSB = 16; // 0-127 MSB
static const unsigned char MIDI_CONTROLLERCHANGE_GENERALPURPOSECONTROLLER2_MSB = 17; // 0-127 MSB
static const unsigned char MIDI_CONTROLLERCHANGE_GENERALPURPOSECONTROLLER3_MSB = 18; // 0-127 MSB
static const unsigned char MIDI_CONTROLLERCHANGE_GENERALPURPOSECONTROLLER4_MSB = 19; // 0-127 MSB
static const unsigned char MIDI_CONTROLLERCHANGE_BANKSELECT_LSB = 32; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_MODULATIONWHEEL_LSB = 33; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_BREATHCONTROL_LSB = 34; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_FOOTCONTROLLER_LSB = 36; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_PORTAMENTOTIME_LSB = 37; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_DATAENTRY_LSB = 38; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_CHANNELVOLUME_LSB = 39; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_BALANCE_LSB = 40; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_PAN_LSB = 42; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_EXPRESSIONCONTROLLER_LSB = 43; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_EFFECTCONTROL1_LSB = 44; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_EFFECTCONTROL2_LSB = 45; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_GENERALPURPOSECONTROLLER1_LSB = 48; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_GENERALPURPOSECONTROLLER2_LSB = 49; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_GENERALPURPOSECONTROLLER3_LSB = 50; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_GENERALPURPOSECONTROLLER4_LSB = 51; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_DAMPERPEDALONOFF = 64; // >64=ON
static const unsigned char MIDI_CONTROLLERCHANGE_PORTAMENTOONOFF = 65; // >64=ON
static const unsigned char MIDI_CONTROLLERCHANGE_SUSTENUTOONOFF = 66; // >64=ON
static const unsigned char MIDI_CONTROLLERCHANGE_SOFTPEDALONOFF = 67; // >64=ON
static const unsigned char MIDI_CONTROLLERCHANGE_LEGATOFOOTSWITCH = 68; // >64=ON
static const unsigned char MIDI_CONTROLLERCHANGE_HOLD2 = 69; // >64=ON
static const unsigned char MIDI_CONTROLLERCHANGE_SOUNDCONTROLLER1 = 70; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_SOUNDCONTROLLER2 = 71; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_SOUNDCONTROLLER3 = 72; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_SOUNDCONTROLLER4 = 73; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_SOUNDCONTROLLER5 = 74; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_SOUNDCONTROLLER6 = 75; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_SOUNDCONTROLLER7 = 76; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_SOUNDCONTROLLER8 = 77; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_SOUNDCONTROLLER9 = 78; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_SOUNDCONTROLLER10 = 79; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_GENERALPURPOSECONTROLLER5 = 80; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_GENERALPURPOSECONTROLLER6 = 81; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_GENERALPURPOSECONTROLLER7 = 82; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_GENERALPURPOSECONTROLLER8 = 83; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_PORTAMENTOCONTROL = 84; // -127 SOURCE NOTE
static const unsigned char MIDI_CONTROLLERCHANGE_EFFECTS1DEPTH = 91; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_EFFECTS2DEPTH = 92; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_EFFECTS3DEPTH = 93; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_EFFECTS4DEPTH = 94; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_EFFECTS5DEPTH = 95; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_DATAENTRYINC = 96; // N/A
static const unsigned char MIDI_CONTROLLERCHANGE_DATAENTRYDEC = 97; // N/A
static const unsigned char MIDI_CONTROLLERCHANGE_NONREGISTEREDPARAMNUMBER_LSB = 98; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_NONREGISTEREDPARAMNUMBER_MSB = 99; // 0-127 MSB
static const unsigned char MIDI_CONTROLLERCHANGE_REGISTEREDPARAMETERNUMBER_LSB = 100; // 0-127 LSB
static const unsigned char MIDI_CONTROLLERCHANGE_REGISTEREDPARAMETERNUMBER_MSB = 101; // 0-127 MSB
static const unsigned char MIDI_CONTROLLERCHANGE_ALLSOUNDOFF = 120;
static const unsigned char MIDI_CONTROLLERCHANGE_RESETALLCONTROLLERS = 121;
static const unsigned char MIDI_CONTROLLERCHANGE_LOCALCONTROLONOFF = 122;
static const unsigned char MIDI_CONTROLLERCHANGE_ALLNOTESOFF = 123;
static const unsigned char MIDI_CONTROLLERCHANGE_OMNIMODEOFF = 124;
static const unsigned char MIDI_CONTROLLERCHANGE_OMNIMODEON = 125;
static const unsigned char MIDI_CONTROLLERCHANGE_POLYMODEONOFF = 126;
static const unsigned char MIDI_CONTROLLERCHANGE_POLYMODEON = 127;
static const unsigned char MIDI_CONTROLLERCHANGE_RPN_PITCHBENDSENSITIVITY = 0;
static const unsigned int MIDI_F_INSTRUMENT_DRUMS = 0x80000000;
static const int MIDI_DEFAULTSUBCHANNELS = 32;
static const int MIDI_MINIMUMSAMPLEGRANULARITY = 512; // 10.66ms @ 48khz :S
class CodecMIDIDLSCache : public LinkedListNode
{
public:
char mFilePath[FMOD_STRING_MAXPATHLEN];
SoundI *mDLSFile;
int mRefCount;
};
class CodecMIDISubChannel : public LinkedListNode
{
public:
CodecMIDI *mMIDI;
ChannelI mChannel;
CodecDLSInstrument *mInstrument;
float mLFOStartDelay;
float mLFOTime;
float mLFOFrequency;
CodecDLSEnvelope mVolumeEnvelope;
CodecDLSEnvelope mPitchEnvelope;
int mCurrentNote;
SoundI *mSound;
unsigned char mKeyOnKey;
unsigned char mUnityNote;
int mFineTune;
unsigned char mKeyOnVelocity;
int mNumArticulators;
DLS_CONNECTIONBLOCK *mArticulator;
float mTremoloScale;
float mVibratoScale;
float mPanbrelloScale;
bool mKeyOff;
int mMiddleC;
int mKeyGroup;
float mSampleAttenuation;
CodecMIDIChannel *mParent;
FMOD_RESULT displayArticulators();
FMOD_RESULT findArticulator(int src, int dest);
FMOD_RESULT articulateDest(CONN_SRC_FLAGS srcflags, int dest, int *usDestination);
FMOD_RESULT setUpArticulators();
FMOD_RESULT stop();
FMOD_RESULT updateVolume();
FMOD_RESULT updatePitch();
FMOD_RESULT updatePan();
float getTimeCentsFromlScale(int lScale);
};
class CodecMIDIChannel : public LinkedListNode
{
public:
CodecMIDITrack *mTrack;
CodecMIDISubChannel mChannelHead;
unsigned char mIndex;
unsigned char mKeyOffVelocity;
unsigned char mKeyOnVelocity;
unsigned char mAfterTouchKey;
unsigned char mAfterTouchPressure;
unsigned int mBank;
unsigned char mProgram;
unsigned int mRPN;
unsigned char mChannelPressure;
float mMasterVolume;
int mPitchBend;
int mPitchBendSensitivity;
bool mDamperPedal;
int mModWheel; // cc1
int mVolume; // cc7
int mPan; // cc10
int mExpression; // cc11
FMOD_RESULT getSound(int key, SoundI **sound, CodecDLSInstrument **instrument, int *unitynote, int *finetune, int *attenuation, bool *duplicateallowed, int *keygroup, int *numarticulators, DLS_CONNECTIONBLOCK **articulators);
FMOD_RESULT process(unsigned char event, bool reuse, unsigned char runningdata, bool calledfromopen);
FMOD_RESULT update();
};
class CodecMIDITrack
{
public:
CodecMIDI *mMIDI;
unsigned char *mData;
unsigned int mOffset;
unsigned int mLength;
int mIndex;
bool mReadDelta;
float mTick;
bool mFinished;
unsigned char mPort;
unsigned char mEvent;
FMOD_RESULT readVarLen(unsigned int *result);
FMOD_RESULT readByte(unsigned char *result);
FMOD_RESULT readWord(unsigned short *result);
FMOD_RESULT readDWord(unsigned int *result);
FMOD_RESULT read(void *buff, int length);
FMOD_RESULT addTag(const char *name, int length, bool calledfromopen);
FMOD_RESULT process(bool calledfromopen);
};
class CodecMIDI : public Codec
{
friend class CodecMIDIChannel;
friend class CodecMIDITrack;
private:
DSPI *mDSPHead;
ChannelPool *mChannelPool;
ChannelSoftware *mChannelSoftware; /* Array of FMOD Ex low level real channels. Each one of these lives in a ChannelI channel. */
int mNumSubChannels;
ChannelGroupI mChannelGroup;
CodecMIDISubChannel *mMIDISubChannel;
CodecMIDIChannel mMIDIChannel[16];
bool mFinished;
int mSequenceNumber;
unsigned int mMixerSamplesLeft;
unsigned int mMixerSamplesPerTick;
float mTimingScale;
unsigned int mPCMOffset;
unsigned int mDSPTick;
int mNumTracks;
MIDI_FORMAT mMIDIFormat;
int mDivision;
unsigned char mSMTPOffsetHours;
unsigned char mSMTPOffsetMinutes;
unsigned char mSMTPOffsetSeconds;
unsigned char mSMTPOffsetFrames;
unsigned char mSMTPOffsetSubFrames;
unsigned char mTimeSignatureNumerator;
unsigned char mTimeSignatureDenominator;
unsigned char mTimeSignatureMetronome;
unsigned char mTimeSignatureNotated32nds;
unsigned char mKeySignatureSF;
unsigned char mKeySignatureMI;
CodecMIDITrack *mTrack;
unsigned int mTempo;
float mTick;
float mMillisecondsPerTick;
float mMillisecondsPlayed; /* Only valid while loading */
CodecMIDIDLSCache *mDLSCache;
SoundI *mDLSSound;
CodecDLS *mDLS;
bool *mSampleInclusionList;
FMOD_RESULT play(bool fromopen);
FMOD_RESULT readVarLen(unsigned int *length);
FMOD_RESULT update(bool audible);
FMOD_RESULT openInternal(FMOD_MODE usermode, FMOD_CREATESOUNDEXINFO *userexinfo);
FMOD_RESULT closeInternal();
FMOD_RESULT readInternal(void *buffer, unsigned int size, unsigned int *read);
FMOD_RESULT setPositionInternal(int subsound, unsigned int position, FMOD_TIMEUNIT postype);
FMOD_RESULT getMusicNumChannelsInternal(int *numchannels);
FMOD_RESULT setMusicChannelVolumeInternal(int channel, float volume);
FMOD_RESULT getMusicChannelVolumeInternal(int channel, float *volume);
static CodecMIDIDLSCache gDLSCacheHead;
public:
CodecMIDISubChannel mChannelFreeListHead;
static FMOD_RESULT F_CALLBACK openCallback(FMOD_CODEC_STATE *codec, FMOD_MODE usermode, FMOD_CREATESOUNDEXINFO *userexinfo);
static FMOD_RESULT F_CALLBACK closeCallback(FMOD_CODEC_STATE *codec);
static FMOD_RESULT F_CALLBACK readCallback(FMOD_CODEC_STATE *codec, void *buffer, unsigned int sizebytes, unsigned int *bytesread);
static FMOD_RESULT F_CALLBACK setPositionCallback(FMOD_CODEC_STATE *codec, int subsound, unsigned int position, FMOD_TIMEUNIT postype);
static FMOD_RESULT F_CALLBACK getMusicNumChannelsCallback(FMOD_CODEC_STATE *codec, int *numchannels);
static FMOD_RESULT F_CALLBACK setMusicChannelVolumeCallback(FMOD_CODEC_STATE *codec, int channel, float volume);
static FMOD_RESULT F_CALLBACK getMusicChannelVolumeCallback(FMOD_CODEC_STATE *codec, int channel, float *volume);
static FMOD_CODEC_DESCRIPTION_EX *getDescriptionEx();
};
}
#endif /* FMOD_SUPPORT_MIDI */
#endif