private static void TriggerEvent(MidiEvent evnt, int track) { if (evnt is TempoMetaMidiEvent) { TempoMetaMidiEvent tempoEvent = (TempoMetaMidiEvent)evnt; SetTrackTempo(track, tempoEvent.Value); } else if (evnt is EndOfTrackMetaMidiEvent) { //Loop?? _trackEventIndex[track] = 0; } else if (evnt is ControllerVoiceMidiEvent) { ControllerVoiceMidiEvent ccEvent = (ControllerVoiceMidiEvent)evnt; OnCC(track, ccEvent.Channel, ccEvent.Number, ccEvent.Value); } else if (evnt is OnNoteVoiceMidiEvent) { OnNoteVoiceMidiEvent voiceEvent = (OnNoteVoiceMidiEvent)evnt; OnNoteOn(track, voiceEvent.Channel, voiceEvent.Note, voiceEvent.Velocity); } else if (evnt is OffNoteVoiceMidiEvent) { OffNoteVoiceMidiEvent voiceEvent = (OffNoteVoiceMidiEvent)evnt; OnNoteOff(track, voiceEvent.Channel, voiceEvent.Note); } }
public void AddTempoEvent(long time, TempoMetaMidiEvent tempoEvent) { if (TempoEvents.ContainsKey(time)) { System.Diagnostics.Debug.WriteLine(string.Format("TempoEvent at time {0} already exists.", time)); return; } TempoEvents.Add(time, tempoEvent); }
/// <summary>Parse a meta MIDI event from the data stream.</summary> /// <param name="deltaTime">The previously parsed delta-time for this event.</param> /// <param name="eventType">The previously parsed type of message we're expecting to find.</param> /// <param name="data">The data stream from which to read the event information.</param> /// <param name="pos">The position of the start of the event information.</param> /// <returns>The parsed meta MIDI event.</returns> private static MidiEvent ParseMetaEvent(long deltaTime, byte eventType, byte[] data, ref long pos) { try { MidiEvent tempEvent = null; // Create the correct meta event based on its meta event id/type switch (eventType) { // Sequence number case SequenceNumberMetaMidiEvent.MetaId: pos++; // skip past the 0x02 int number = ((data[pos] << 8) | data[pos + 1]); tempEvent = new SequenceNumberMetaMidiEvent(deltaTime, number); pos += 2; // skip read values break; // Text events (copyright, lyrics, etc) case TextMetaMidiEvent.MetaId: tempEvent = new TextMetaMidiEvent(deltaTime, ReadASCIIText(data, ref pos)); break; case CopyrightTextMetaMidiEvent.MetaId: tempEvent = new CopyrightTextMetaMidiEvent(deltaTime, ReadASCIIText(data, ref pos)); break; case SequenceTrackNameTextMetaMidiEvent.MetaId: tempEvent = new SequenceTrackNameTextMetaMidiEvent(deltaTime, ReadASCIIText(data, ref pos)); break; case InstrumentTextMetaMidiEvent.MetaId: tempEvent = new InstrumentTextMetaMidiEvent(deltaTime, ReadASCIIText(data, ref pos)); break; case LyricTextMetaMidiEvent.MetaId: tempEvent = new LyricTextMetaMidiEvent(deltaTime, ReadASCIIText(data, ref pos)); break; case MarkerTextMetaMidiEvent.MetaId: tempEvent = new MarkerTextMetaMidiEvent(deltaTime, ReadASCIIText(data, ref pos)); break; case CuePointTextMetaMidiEvent.MetaId: tempEvent = new CuePointTextMetaMidiEvent(deltaTime, ReadASCIIText(data, ref pos)); break; case ProgramNameTextMetaMidiEvent.MetaId: tempEvent = new ProgramNameTextMetaMidiEvent(deltaTime, ReadASCIIText(data, ref pos)); break; case DeviceNameTextMidiEvent.MetaId: tempEvent = new DeviceNameTextMidiEvent(deltaTime, ReadASCIIText(data, ref pos)); break; // Channel prefix case ChannelPrefixMetaMidiEvent.MetaId: pos++; // skip 0x1 tempEvent = new ChannelPrefixMetaMidiEvent(deltaTime, data[pos]); pos++; // skip read value break; // Port number case MidiPortMetaMidiEvent.MetaId: pos++; // skip 0x1 tempEvent = new MidiPortMetaMidiEvent(deltaTime, data[pos]); pos++; // skip read value break; // End of track case EndOfTrackMetaMidiEvent.MetaId: pos++; // skip 0x0 tempEvent = new EndOfTrackMetaMidiEvent(deltaTime); break; // Tempo case TempoMetaMidiEvent.MetaId: pos++; // skip 0x3 int tempo = ((data[pos] << 16) | data[pos + 1] << 8 | data[pos + 2]); tempEvent = new TempoMetaMidiEvent(deltaTime, tempo); pos += 3; break; // SMPTE offset case SMPTEOffsetMetaMidiEvent.MetaId: pos++; // skip 0x5 tempEvent = new SMPTEOffsetMetaMidiEvent(deltaTime, data[pos], data[pos + 1], data[pos + 2], data[pos + 3], data[pos + 4]); pos += 5; break; // Time signature case TimeSignatureMetaMidiEvent.MetaId: pos++; // skip past 0x4 tempEvent = new TimeSignatureMetaMidiEvent(deltaTime, data[pos], data[pos + 1], data[pos + 2], data[pos + 3]); pos += 4; break; // Key signature case KeySignatureMetaMidiEvent.MetaId: pos++; // skip past 0x2 tempEvent = new KeySignatureMetaMidiEvent(deltaTime, (Key)data[pos], (Tonality)data[pos + 1]); pos += 2; break; // Proprietary case ProprietaryMetaMidiEvent.MetaId: // Read in the variable length and that much data, then store it long length = ReadVariableLength(data, ref pos); byte[] propData = new byte[length]; Array.Copy(data, (int)pos, propData, 0, (int)length); tempEvent = new ProprietaryMetaMidiEvent(deltaTime, propData); pos += length; break; // An unknown meta event! default: // Read in the variable length and that much data, then store it length = ReadVariableLength(data, ref pos); byte[] unknownData = new byte[length]; Array.Copy(data, (int)pos, unknownData, 0, (int)length); tempEvent = new UnknownMetaMidiEvent(deltaTime, eventType, unknownData); pos += length; break; } return(tempEvent); } // Something bad happened; wrap it in a parser exception catch (Exception exc) { throw new MidiParserException("Unable to parse meta MIDI event.", exc, pos); } }
private double GetMicrosecondsPerTick(TempoMetaMidiEvent tempoEvent) { int microsecondsPerBeat = tempoEvent.Value; // microseconds / beat return((double)microsecondsPerBeat / TicksPerBeatOrFrame); // returns microseconds / tick }