Files
Work/midiseq/hold/MIDITRCK.CPP
2024-08-07 09:16:27 -04:00

339 lines
8.0 KiB
C++

#include <common/math.hpp>
#include <midiseq/miditrck.hpp>
WORD MidiTrack::readTrack(void)
{
mBytesRead=0;
if(PureHeader::Unset==mTimingMethod)return FALSE;
if(!mMidiFile.read(mTrack,sizeof(mTrack)))return FALSE;
if(::strncmp(mTrack,"MTrk",sizeof(mTrack)))return FALSE;
if(!mMidiFile.read(mLengthData))return FALSE;
if(!mLengthData)return FALSE;
readTime();
while(mBytesRead<mLengthData)
{
if(!mMidiFile.read(mEventType))return TRUE;
mBytesRead++;
if(!handleEvent())return TRUE;
if(mBytesRead>=mLengthData)break;
if(NullEvent==mRunningEvent){readTime();mLastEventType=mEventType;}
else mLastEventType=mRunningEvent;
}
return TRUE;
}
void MidiTrack::readTime(void)
{
switch(mTimingMethod)
{
case PureHeader::DeltaTime :
case PureHeader::TimeCode :
mDeltaTime=readVarLength();
break;
}
}
WORD MidiTrack::handleEvent(void)
{
WORD returnCode;
switch(mEventType)
{
case MetaEvent :
mRunningEvent=NullEvent;
returnCode=handleMetaEvent();
break;
case SystemExclusiveOne :
case SystemExclusiveTwo :
mRunningEvent=NullEvent;
returnCode=handleSystemExclusiveEvent();
break;
default :
returnCode=handleMIDIChannelMessage();
break;
}
return returnCode;
}
WORD MidiTrack::isChannelMessage(BYTE eventType)const
{
BYTE status((eventType>>4)&0x0F);
if((status<=0x07)||(0x0F==status))return FALSE;
if((status>=0x08&&status<=0x0B)||(status==0x0E))return 2;
return 1;
}
WORD MidiTrack::handleMIDIChannelMessage(void)
{
WORD returnCode;
if(isRunningStatus(mEventType))
{
if(NullEvent==mRunningEvent)mRunningEvent=mLastEventType;
mEventType=mLastEventType;
}
else mRunningEvent=NullEvent;
if(isChannelMessage(mEventType))returnCode=processMIDIChannelMessage();
else returnCode=FALSE;
return returnCode;
}
WORD MidiTrack::handleMetaEvent(void)
{
BYTE entryType;
WORD returnCode(TRUE);
if(!mMidiFile.read(entryType))return FALSE;
mBytesRead++;
switch(entryType)
{
case SequenceNumberEvent :
returnCode=handleMetaSequenceNumberEvent();
break;
case TextEvent :
returnCode=handleMetaTextEvent();
break;
case CopyrightNotice :
returnCode=handleMetaTextEvent();
break;
case SequenceTrackName :
handleGenericMetaEvent();
break;
case InstrumentName :
handleGenericMetaEvent();
break;
case Lyric :
handleGenericMetaEvent();
break;
case Marker :
handleGenericMetaEvent();
break;
case CuePoint :
handleGenericMetaEvent();
break;
case ChannelPrefix :
handleChannelPrefix();
break;
case EndOfTrack :
handleGenericMetaEvent();
returnCode=FALSE;
break;
case SetTempo :
handleSetTempoEvent();
break;
case SMPTEFormatSpec :
handleSMPTEFormatEvent();
break;
case TimeSignature :
handleTimeSignatureEvent();
break;
case KeySignature :
handleGenericMetaEvent();
break;
case SequencerSpecificMetaEvent :
handleGenericMetaEvent();
break;
default :
handleGenericMetaEvent();
break;
}
return returnCode;
}
WORD MidiTrack::handleSystemExclusiveEvent(void)
{
return handleGenericMetaEvent();
}
WORD MidiTrack::handleMetaSequenceNumberEvent(void)
{
WORD sequenceNumber;
if(!mMidiFile.read(sequenceNumber))return FALSE;
mBytesRead++;
return TRUE;
}
WORD MidiTrack::handleMetaTextEvent(void)
{
BYTE textLength;
BYTE textByte;
if(!mMidiFile.read(textLength))return FALSE;
mBytesRead++;
for(short index=0;index<textLength;index++){if(!mMidiFile.read(textByte))return FALSE;mBytesRead++;}
return TRUE;
}
WORD MidiTrack::handleSetTempoEvent(void)
{
DWORD microsecsPerQtrNote(0L);
BYTE tempoBytes[TempoEventLength];
short entryLength;
entryLength=(short)readVarLength();
if(sizeof(tempoBytes)!=entryLength)return FALSE;
if(!mMidiFile.read(tempoBytes,sizeof(tempoBytes)))return FALSE;
microsecsPerQtrNote+=(DWORD)tempoBytes[0]*65536L;
microsecsPerQtrNote+=(DWORD)tempoBytes[1]*256L;
microsecsPerQtrNote+=(DWORD)tempoBytes[2];
setTempo(microsecsPerQtrNote);
return TRUE;
}
WORD MidiTrack::handleTimeSignatureEvent(void)
{
BYTE tsBytes[TimeInfo::LengthTimeInfo];
if(TimeInfo::LengthTimeInfo!=readVarLength())return FALSE;
if(!mMidiFile.read(tsBytes,sizeof(tsBytes)))return FALSE;
TimeInfo midiTimeSignature(tsBytes[0],Math::power(2,tsBytes[1]),tsBytes[2],tsBytes[3]);
timeSignature(midiTimeSignature);
return TRUE;
}
WORD MidiTrack::handleSMPTEFormatEvent(void)
{
SMPTEFormat smpteFormatInfo;
short entryLength;
if(sizeof(SMPTEFormat::SMPTEFormatLength)!=readVarLength())return FALSE;
smpteFormatInfo<<mMidiFile;
smpteFormat(smpteFormatInfo);
return TRUE;
}
WORD MidiTrack::handleChannelPrefix(void)
{
BYTE charByte;
short entryLength;
entryLength=readVarLength();
for(short index=0;index<entryLength;index++){if(!mMidiFile.read(charByte))return FALSE;mBytesRead++;}
return TRUE;
}
WORD MidiTrack::handleGenericMetaEvent(void)
{
BYTE charByte;
short entryLength;
entryLength=(short)readVarLength();
for(short index=0;index<entryLength;index++){if(!mMidiFile.read(charByte))return FALSE;mBytesRead++;}
return TRUE;
}
WORD MidiTrack::processMIDIChannelMessage(void)
{
WORD returnCode(TRUE);
BYTE channel;
BYTE messageDataOne;
BYTE messageDataTwo;
BYTE requiredDataBytes;
channel=mEventType&0x0F;
requiredDataBytes=isChannelMessage(mEventType);
switch(mEventType&0xF0)
{
case MIDIProgramChange :
mMidiFile.read(messageDataOne);
messageDataOne&=0x7F;
midiChannelMessage(PureEvent(mEventType,mDeltaTime,channel,messageDataOne,0));
mBytesRead++;
break;
case MIDINoteOff :
if(PureNote::PureNoteLength!=requiredDataBytes){returnCode=FALSE;break;}
mNoteOff<<mMidiFile;
mNoteOff.pitch(mNoteOff.pitch()&0x7F);
mNoteOff.velocity(mNoteOff.velocity()&0x7F);
midiChannelMessage(PureEvent(mEventType,mDeltaTime,channel,mNoteOff.pitch(),mNoteOff.velocity()));
mBytesRead+=PureNote::PureNoteLength;
break;
case MIDINoteOn :
if(PureNote::PureNoteLength!=requiredDataBytes){returnCode=FALSE;break;}
mNoteOn<<mMidiFile;
mNoteOn.pitch(mNoteOn.pitch()&0x7F);
mNoteOn.velocity(mNoteOn.velocity()&0x7F);
midiChannelMessage(PureEvent(mEventType,mDeltaTime,channel,mNoteOn.pitch(),mNoteOn.velocity()));
mBytesRead+=PureNote::PureNoteLength;
break;
case MIDIKeyPressure :
if(2!=requiredDataBytes){returnCode=FALSE;break;}
mMidiFile.read(messageDataOne);
mMidiFile.read(messageDataTwo);
messageDataOne&=0x7F;
messageDataTwo&=0x7F;
midiChannelMessage(PureEvent(mEventType,mDeltaTime,channel,messageDataOne,messageDataTwo));
mBytesRead+=requiredDataBytes;
break;
case MIDIParameter :
if(2!=requiredDataBytes){returnCode=FALSE;break;}
mMidiFile.read(messageDataOne);
mMidiFile.read(messageDataTwo);
messageDataOne&=0x7F;
messageDataTwo&=0x7F;
midiChannelMessage(PureEvent(mEventType,mDeltaTime,channel,messageDataOne,messageDataTwo));
mBytesRead+=requiredDataBytes;
break;
case MIDIPitchBend :
if(2!=requiredDataBytes){returnCode=FALSE;break;}
mMidiFile.read(messageDataOne);
mMidiFile.read(messageDataTwo);
messageDataOne&=0x7F;
messageDataTwo&=0x7F;
midiChannelMessage(PureEvent(mEventType,mDeltaTime,channel,messageDataOne,messageDataTwo));
mBytesRead+=requiredDataBytes;
break;
case MIDIChannelPressure :
if(1!=requiredDataBytes){returnCode=FALSE;break;}
mMidiFile.read(messageDataOne);
messageDataOne&=0x7F;
midiChannelMessage(PureEvent(mEventType,mDeltaTime,channel,messageDataOne,0));
mBytesRead++;
break;
default :
returnCode=FALSE;
break;
}
return returnCode;
}
DWORD MidiTrack::readVarLength(void)
{
DWORD valueData(0L);
BYTE byteValue;
while(TRUE)
{
mMidiFile.read(byteValue);
mBytesRead++;
valueData=(valueData*0x80)+(byteValue&0x7F);
if(!(byteValue&0x80))break;
}
return valueData;
}
// virtuals
void MidiTrack::setTempo(DWORD /*microsecondsPerQuarterNote*/)
{
return;
}
void MidiTrack::midiChannelMessage(PureEvent &/*channelEvent*/)
{
return;
}
void MidiTrack::timeSignature(const TimeInfo &/*someTimeInfo*/)
{
return;
}
void MidiTrack::smpteFormat(const SMPTEFormat &/*someSMPTEFormat*/)
{
return;
}