#include MidiData::MidiData(const String &midiPathFileName) : mTimerCallback(this,&MidiData::timerEvent), mMidiFile(midiPathFileName,FileIO::BigEndian), MidiTrack(mMidiFile) { insertHandler(&mTimerCallback); if(!readHeader(mMidiFile))return; ::OutputDebugString(String("[MidiData::MidiData]MIDI header=")+String(MidiHeader::toString()+String("\n")).str()); setMethod(timingMethod()); } MidiData::~MidiData() { stopTimer(); mMIDIOutDevice.closeDevice(); mMIDIEventVector.size(0); } bool MidiData::play(WORD blocking) { mPlayIndex=0; if(!makeRealTime())return false; startTimer(TimerDelay); if(blocking)waitEvent(); return true; } bool MidiData::makeRealTime(void) { TimeBlock timeBlock; mTempoChange.remove(); if(!tracks())return false; while(readTrack()); if(!mTempoChange.size())return false; timeBlock.setTempo(mTempoChange[0].microsecsPerQtrNote()); timeBlock.setDivision(method()); timeBlock.setStartTime(getSystemTime()+TwoSecs); timeBlock.fixTimeBlock(mMIDIEvents,mMIDIEventVector); return true; } CallbackData::ReturnType MidiData::timerEvent(CallbackData &/*someCallbackData*/) { DWORD currTime(getSystemTime()); if(!mMIDIOutDevice.hasDevice()||!mMIDIEventVector.size())return closeDevice(); while(mMIDIEventVector[mPlayIndex].playTime()<=currTime) { if(!mMIDIOutDevice.midiEvent(mMIDIEventVector[mPlayIndex]))return closeDevice(); if(++mPlayIndex>=mMIDIEventVector.size())return closeDevice(); } return (CallbackData::ReturnType)TRUE; } CallbackData::ReturnType MidiData::closeDevice(void) { mMIDIOutDevice.closeDevice(); return (CallbackData::ReturnType)FALSE; } // virtual overloads void MidiData::midiChannelMessage(PureEvent &midiEvent) { mMIDIEvents[midiEvent.channel()].insert(&midiEvent); return; } void MidiData::setTempo(DWORD microsecsPerQtrNote) { mTempoChange.insert(&TempoChange(microsecsPerQtrNote,0L)); return; } void MidiData::smpteFormat(const SMPTEFormat &someSMPTEFormat) { mSMPTEFormat=someSMPTEFormat; return; } void MidiData::timeSignature(const TimeInfo &/*someTimeInfo*/) { return; }