static private MIDIMetaEvent ReadMetaEvent(int deltaTicks) { int metaEventType = ReadByte(); int dataLength = ReadVariableLengthInt(); switch (metaEventType) { case (int)MIDIMetaEventType.Tempo: MIDITempoEvent tempoEvent = new MIDITempoEvent(); tempoEvent.deltaTicks = deltaTicks; tempoEvent.tempo = ReadMultiByteInt((uint)dataLength); tempoEvent.dataLength = dataLength; return(tempoEvent); case (int)MIDIMetaEventType.Time_Signature: MIDITimeSignatureEvent timeSignatureEvent = new MIDITimeSignatureEvent(); timeSignatureEvent.deltaTicks = deltaTicks; timeSignatureEvent.numerator = ReadByte(); timeSignatureEvent.denominator = (int)Mathf.Pow(2, ReadByte()); timeSignatureEvent.ticksPerMetronomeClick = ReadByte(); timeSignatureEvent.numberOf32ndNotesPerBeat = ReadByte(); timeSignatureEvent.dataLength = dataLength; return(timeSignatureEvent); case (int)MIDIMetaEventType.Key_Signature: MIDIKeySignatureEvent keySignatureEvent = new MIDIKeySignatureEvent(); keySignatureEvent.deltaTicks = deltaTicks; keySignatureEvent.key = ReadByte(); if (ReadByte() == 0) { keySignatureEvent.isMajor = true; } else { keySignatureEvent.isMajor = false; } keySignatureEvent.dataLength = dataLength; return(keySignatureEvent); default: ReadBytes((uint)dataLength); return(null); } }
static private void CalcEventTimestamps() { float elapsedTime = 0.0f; float secondsPerTick = CalcSecondsPerTick(m_defaultMicrosecondsPerQuarterNote); List <MIDIEvent> nextEventList = new List <MIDIEvent>(); foreach (MIDITrack track in m_song.tracks) { nextEventList.Add(track.events[0]); } MIDIEvent minNextEvent; do { minNextEvent = FindMinNextEvent(nextEventList); if (minNextEvent != null) { elapsedTime += secondsPerTick * minNextEvent.deltaTicks; minNextEvent.timestamp = elapsedTime; CorrectDeltaTicksOfNextEvents(minNextEvent, nextEventList); ForwardMinNextEvent(minNextEvent, nextEventList); // adjust tempo if respective event occurs if (minNextEvent.GetType() == typeof(MIDITempoEvent)) { MIDITempoEvent tempoEvent = minNextEvent as MIDITempoEvent; secondsPerTick = CalcSecondsPerTick(tempoEvent.tempo); } } }while (minNextEvent != null); m_song.duration = elapsedTime; }
static private void CalcMeasureTimestamps() { m_song.measureTimestamps = new List <float>(); // GetMetaEvents List <MIDIEvent> metaEvents = new List <MIDIEvent>(); foreach (MIDITrack track in m_song.tracks) { foreach (MIDIEvent midiEvent in track.events) { if (midiEvent.GetType().IsSubclassOf(typeof(MIDIMetaEvent))) { metaEvents.Add(midiEvent); } } } // Sort MetaEvents by Timestamp metaEvents.Sort(new MIDIEventComparer()); // calc timing metrics float microsecondsPerQuarterNote = m_defaultMicrosecondsPerQuarterNote; float beatsPerMeasure = 4.0f; float beatNoteLength = 1.0f / 4.0f; float quarterNotesPerBeat = 4.0f * beatNoteLength; float secondsPerMeasure = CalcSecondsPerMeasure(microsecondsPerQuarterNote, quarterNotesPerBeat, beatsPerMeasure); // iterate through measures for (float elapsedTime = 0.0f; elapsedTime < m_song.duration + secondsPerMeasure; elapsedTime += secondsPerMeasure) { List <MIDIEvent> metaEventsToRemove = new List <MIDIEvent>(); foreach (MIDIEvent metaEvent in metaEvents) { if (metaEvent.timestamp <= elapsedTime) { if (metaEvent.GetType() == typeof(MIDITempoEvent)) { MIDITempoEvent tempoEvent = metaEvent as MIDITempoEvent; microsecondsPerQuarterNote = tempoEvent.tempo; secondsPerMeasure = CalcSecondsPerMeasure(microsecondsPerQuarterNote, quarterNotesPerBeat, beatsPerMeasure); } else if (metaEvent.GetType() == typeof(MIDITimeSignatureEvent)) { MIDITimeSignatureEvent timeSignatureEvent = metaEvent as MIDITimeSignatureEvent; beatsPerMeasure = timeSignatureEvent.numerator; beatNoteLength = 1.0f / timeSignatureEvent.denominator; quarterNotesPerBeat = 4.0f * beatNoteLength; secondsPerMeasure = CalcSecondsPerMeasure(microsecondsPerQuarterNote, quarterNotesPerBeat, beatsPerMeasure); } metaEventsToRemove.Add(metaEvent); } } foreach (MIDIEvent metaEventToRemove in metaEventsToRemove) { metaEvents.Remove(metaEventToRemove); } m_song.measureTimestamps.Add(elapsedTime); } m_song.firstMeasureDuration = m_song.measureTimestamps[1] - m_song.measureTimestamps[0]; }