/// <summary> /// Packs the data from a tempo meta message into an integer. /// </summary> /// <param name="message"> /// The tempo meta message. /// </param> /// <returns> /// Returns the tempo packed into an integer. /// </returns> /// <exception cref="ArgumentException"> /// Thrown if the message is not a tempo meta message. /// </exception> public static int PackTempo(MetaMessage message) { // Enforce preconditions. if (message.Type != MetaType.Tempo) { throw new ArgumentException( "Message is not a tempo meta message", "message"); } int tempo = 0; if (BitConverter.IsLittleEndian) { int d = message.data.Length - 1; for (int i = 0; i < message.data.Length; i++) { tempo |= message.data[d] << (Shift * i); d--; } } else { for (int i = 0; i < message.data.Length; i++) { tempo |= message.data[i] << (Shift * i); } } return(tempo); }
/// <summary> /// Visits meta messages. /// </summary> /// <param name="message"> /// The MetaMessage to visit. /// </param> void Multimedia.Midi.IMidiMessageVisitor.Visit(MetaMessage message) { // If the meta message is a tempo change message type. if (message.Type == MetaType.Tempo) { // Change tempo. Tempo = MetaMessage.PackTempo(message); } // Else if the meta message is an end of track message type. else if (message.Type == MetaType.EndOfTrack) { // Stop playback. Stop(); } }
/// <summary> /// Reads the data for the next track from the Midi file. /// </summary> /// <param name="trackNum"> /// The track number. /// </param> private void ReadNextTrack(int trackNum) { MetaType metaType = MetaType.TrackName; int status = 0; int runningStatus = 0; // Read length of track. binReader.ReadBytes(LengthByteCount); // Continue reading Midi events until the end of the track. while(metaType != MetaType.EndOfTrack) { // Next Midi message in track. IMidiMessage msg = null; // Ticks for next Midi event. int ticks = ReadVariableLengthQuantity(); // Read status byte for the next Midi message. status = binReader.ReadByte(); // If this is a status byte. if((status & StatusFlag) == StatusFlag) { // If the next Midi message is a channel message. if(ChannelMessage.IsChannelMessage(status)) { // Read channel message from the Midi file. msg = ReadChannelMessage(status); // Update running status. runningStatus = status; } // Else if the next Midi message is a meta message. else if(MetaMessage.IsMetaMessage(status)) { // Read the type of meta message. metaType = (MetaType)binReader.ReadByte(); // Read the length of the meta message data. int length = ReadVariableLengthQuantity(); // Read the meta message data. byte[] data = binReader.ReadBytes(length); // Create meta message. msg = new MetaMessage(metaType, data); } // Else if the next Midi message is a system exclusive // message. else if(SysExMessage.IsSysExMessage(status)) { // The type of system exclusive message. SysExType type = (SysExType)status; // Read the length of the system exclusive data. int length = ReadVariableLengthQuantity(); // Read the system exclusive data. byte[] data = binReader.ReadBytes(length); // Create system exclusive message. msg = new SysExMessage(type, data); } } // Assumes running status. else { // Create channel message. msg = ReadChannelMessage(runningStatus, status); } // Create the next Midi event and store it in the specified // track. MidiEvent e = new MidiEvent(msg, ticks); tracks[trackNum].Add(e); } }
/// <summary> /// Initializes a new instance of the MetaMessage class with /// another instance of the MetaMessage class. /// </summary> /// <param name="message"> /// The MetaMessage instance to use for initialization. /// </param> public MetaMessage(MetaMessage message) { type = message.type; data = new byte[message.data.Length]; message.data.CopyTo(data, 0); }
/// <summary> /// Reads the data for the next track from the Midi file. /// </summary> /// <param name="trackNum"> /// The track number. /// </param> private void ReadNextTrack(int trackNum) { MetaType metaType = MetaType.TrackName; int status = 0; int runningStatus = 0; // Read length of track. binReader.ReadBytes(LengthByteCount); // Continue reading Midi events until the end of the track. while (metaType != MetaType.EndOfTrack) { // Next Midi message in track. IMidiMessage msg = null; // Ticks for next Midi event. int ticks = ReadVariableLengthQuantity(); // Read status byte for the next Midi message. status = binReader.ReadByte(); // If this is a status byte. if ((status & StatusFlag) == StatusFlag) { // If the next Midi message is a channel message. if (ChannelMessage.IsChannelMessage(status)) { // Read channel message from the Midi file. msg = ReadChannelMessage(status); // Update running status. runningStatus = status; } // Else if the next Midi message is a meta message. else if (MetaMessage.IsMetaMessage(status)) { // Read the type of meta message. metaType = (MetaType)binReader.ReadByte(); // Read the length of the meta message data. int length = ReadVariableLengthQuantity(); // Read the meta message data. byte[] data = binReader.ReadBytes(length); // Create meta message. msg = new MetaMessage(metaType, data); } // Else if the next Midi message is a system exclusive // message. else if (SysExMessage.IsSysExMessage(status)) { // The type of system exclusive message. SysExType type = (SysExType)status; // Read the length of the system exclusive data. int length = ReadVariableLengthQuantity(); // Read the system exclusive data. byte[] data = binReader.ReadBytes(length); // Create system exclusive message. msg = new SysExMessage(type, data); } } // Assumes running status. else { // Create channel message. msg = ReadChannelMessage(runningStatus, status); } // Create the next Midi event and store it in the specified // track. MidiEvent e = new MidiEvent(msg, ticks); tracks[trackNum].Add(e); } }
/// <summary> /// Packs the data from a tempo meta message into an integer. /// </summary> /// <param name="message"> /// The tempo meta message. /// </param> /// <returns> /// Returns the tempo packed into an integer. /// </returns> /// <exception cref="ArgumentException"> /// Thrown if the message is not a tempo meta message. /// </exception> public static int PackTempo(MetaMessage message) { // Enforce preconditions. if(message.Type != MetaType.Tempo) throw new ArgumentException( "Message is not a tempo meta message", "message"); int tempo = 0; if(BitConverter.IsLittleEndian) { int d = message.data.Length - 1; for(int i = 0; i < message.data.Length; i++) { tempo |= message.data[d] << (Shift * i); d--; } } else { for(int i = 0; i < message.data.Length; i++) { tempo |= message.data[i] << (Shift * i); } } return tempo; }
/// <summary> /// Visits meta messages. /// </summary> /// <param name="message"> /// The MetaMessage to visit. /// </param> void Multimedia.Midi.IMidiMessageVisitor.Visit(MetaMessage message) { // If the meta message is a tempo change message type. if(message.Type == MetaType.Tempo) { // Change tempo. Tempo = MetaMessage.PackTempo(message); } // Else if the meta message is an end of track message type. else if(message.Type == MetaType.EndOfTrack) { // Stop playback. Stop(); } }