/// <summary> /// Initializes the TempoChangeBuilder with the specified MetaMessage. /// </summary> /// <param name="message"> /// The MetaMessage to use for initializing the TempoChangeBuilder. /// </param> /// <exception cref="ArgumentException"> /// If the specified MetaMessage is not a tempo type. /// </exception> public void Initialize(MetaMessage e) { int t = 0; var b = e.GetBytes(); // If this platform uses little endian byte order. if (BitConverter.IsLittleEndian) { int d = b.Length - 1; // Pack tempo. for (int i = 0; i < e.Length; i++) { t |= b[d] << (Shift * i); d--; } } // Else this platform uses big endian byte order. else { // Pack tempo. for (int i = 0; i < e.Length; i++) { t |= b[i] << (Shift * i); } } tempo = t; }
public KeySignature(MetaMessage msg) { var b = msg.GetBytes(); IsMajor = (((sbyte)b[1]) == 0); Key = FromBytes(b[0], b[1]); }
private void Write(MetaMessage message) { trackData.Add((byte)message.Status); trackData.Add((byte)message.MetaType); WriteVariableLengthValue(message.Length); trackData.AddRange(message.GetBytes()); }
public static void clearFingeringInMidiFile(Midi.Sequence file) { Regex signaturePattern = new Regex("^Fingering"); Regex fingerPattern = new Regex("^finger:"); foreach (Midi.Track track in file) { System.Collections.Generic.List <int> toRemove = new System.Collections.Generic.List <int>(); for (int i = track.Count - 1; i >= 0; --i) { Midi.MidiEvent e = track.GetMidiEvent(i); if (e.MidiMessage.MessageType == Midi.MessageType.Meta) { Midi.MetaMessage msg = e.MidiMessage as Midi.MetaMessage; switch (msg.MetaType) { case Midi.MetaType.Text: if (signaturePattern.Match(Encoding.Default.GetString(msg.GetBytes())).Length > 0) { toRemove.Add(i); } break; case Midi.MetaType.Marker: if (fingerPattern.Match(Encoding.Default.GetString(msg.GetBytes())).Length > 0) { toRemove.Add(i); } break; } } } foreach (int i in toRemove) { track.RemoveAt(i); } } }
/// <summary> /// Initializes the TimeSignatureBuilder with the specified MetaMessage. /// </summary> /// <param name="message"> /// The MetaMessage to use for initializing the TimeSignatureBuilder. /// </param> /// <exception cref="ArgumentException"> /// If the specified MetaMessage is not a time signature type. /// </exception> public void Initialize(MetaMessage message) { #region Require if (message.MetaType != MetaType.TimeSignature) { throw new ArgumentException("Wrong meta event type.", "message"); } #endregion data = message.GetBytes(); }
/// <summary> /// Initializes the MetaMessageTextBuilder with the specified MetaMessage. /// </summary> /// <param name="message"> /// The MetaMessage to use for initializing the MetaMessageTextBuilder. /// </param> /// <exception cref="ArgumentException"> /// If the MetaMessage is not a text based type. /// </exception> public void Initialize(MetaMessage message) { #region Require if (!IsTextType(message.MetaType)) { throw new ArgumentException("Not text based meta message.", "message"); } #endregion ASCIIEncoding encoding = new ASCIIEncoding(); text = encoding.GetString(message.GetBytes()); this.type = message.MetaType; }
public static NotationTrack parseMidiTrack(Midi.Track track, int division, ref Regex fingerPattern) { int microsecondsPerBeat = Midi.PpqnClock.DefaultTempo; float time = 0; TrackStatus trackStatus = new TrackStatus(); FingerChordMap fingerMap = new FingerChordMap(); List <Note> notes = new List <Note>(); Regex fingerMetaPattern = new Regex("fingering-marker-pattern:(.*)"); string name = ""; foreach (Midi.MidiEvent e in track.Iterator()) { time += e.DeltaTicks * microsecondsPerBeat / (division * 1000); switch (e.MidiMessage.MessageType) { case Midi.MessageType.Meta: Midi.MetaMessage mm = e.MidiMessage as Midi.MetaMessage; switch (mm.MetaType) { case Midi.MetaType.Tempo: Midi.TempoChangeBuilder builder = new Midi.TempoChangeBuilder(mm); microsecondsPerBeat = builder.Tempo; break; case Midi.MetaType.Text: { string text = Encoding.Default.GetString(mm.GetBytes()); var match = fingerMetaPattern.Match(text); if (match.Success) { fingerPattern = new Regex(match.Groups[1].ToString()); Debug.LogFormat("Finger Pattern found: {0}", fingerPattern.ToString()); } } break; case Midi.MetaType.Marker: if (fingerPattern != null) { string text = Encoding.Default.GetString(mm.GetBytes()); var match = fingerPattern.Match(text); if (match.Success) { //Debug.LogFormat("Finger: {0}", text); try { int pitch = int.Parse(match.Groups[1].ToString()); Finger finger = (Finger)int.Parse(match.Groups[2].ToString()); if (!fingerMap.ContainsKey(e.AbsoluteTicks)) { fingerMap[e.AbsoluteTicks] = new FingerChord(); } fingerMap[e.AbsoluteTicks][pitch] = finger; } catch (System.Exception except) { Debug.LogWarningFormat("fingering marker parse failed: {0}, {1}", text, except.Message); } } //else // Debug.LogWarningFormat("fail marker: {0}", text); } break; case Midi.MetaType.TrackName: name = Encoding.Default.GetString(mm.GetBytes()); break; } break; case Midi.MessageType.Channel: Midi.ChannelMessage cm = e.MidiMessage as Midi.ChannelMessage; if (!trackStatus.ContainsKey(cm.MidiChannel)) { trackStatus[cm.MidiChannel] = new ChannelStatus(); } var commandType = cm.Command; if (commandType == Midi.ChannelCommand.NoteOn && cm.Data2 == 0) { commandType = Midi.ChannelCommand.NoteOff; } switch (commandType) { case Midi.ChannelCommand.NoteOn: { int pitch = cm.Data1; int velocity = cm.Data2; if (pitch >= Piano.PitchMin && pitch <= Piano.PitchMax) { trackStatus[cm.MidiChannel][pitch] = new PitchStatus { tick = e.AbsoluteTicks, startTime = time, velocity = velocity } } ; } break; case Midi.ChannelCommand.NoteOff: { int pitch = cm.Data1; if (!trackStatus[cm.MidiChannel].ContainsKey(pitch)) { Debug.LogWarningFormat("Unexpected noteOff: {0}, {1}", e.AbsoluteTicks, pitch); } else { PitchStatus status = trackStatus[cm.MidiChannel][pitch]; Note note = new Note { tick = status.tick, start = status.startTime, duration = time - status.startTime, pitch = pitch, velocity = status.velocity }; if (fingerMap.ContainsKey(note.tick) && fingerMap[note.tick].ContainsKey(note.pitch)) { note.finger = fingerMap[note.tick][note.pitch]; } notes.Add(note); } } break; } break; } } NotationTrack notation = new NotationTrack(); notation.notes = notes.ToArray(); notation.name = name; return(notation); }
private void ProcessMIDI() { Midi.Sequence _MIDISequence; // default MIDI tempos/milliseconds per tick int tempo = 500000; float msPerTick = (tempo / 48) / 1000.0f; _MIDISequence = new Midi.Sequence(); _MIDISequence.Load(_sequence.MusicFile); if (_MIDISequence.SequenceType != Sanford.Multimedia.Midi.SequenceType.Ppqn) { MessageBox.Show("Unsupported MIDI type...sorry!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } foreach (Midi.Track t in _MIDISequence) { IEnumerator <Midi.MidiEvent> en = t.Iterator().GetEnumerator(); while (en.MoveNext()) { Midi.MidiEvent e = en.Current; switch (e.MidiMessage.MessageType) { // starta new channel case Sanford.Multimedia.Midi.MessageType.Channel: Midi.ChannelMessage channel = (Midi.ChannelMessage)e.MidiMessage; // if it's a note on command and it's in our mapping list if (channel.Command == Sanford.Multimedia.Midi.ChannelCommand.NoteOn && _midiMap.ContainsKey(channel.MidiChannel) && (int)((e.AbsoluteTicks * msPerTick) / 50) < _sequence.Channels[_midiMap[channel.MidiChannel]].Data.Length) { // this means the note is on if (channel.Data2 > 0) { _sequence.Channels[_midiMap[channel.MidiChannel]].Data[(int)((e.AbsoluteTicks * msPerTick) / 50)] = true; } else { // the note is off _sequence.Channels[_midiMap[channel.MidiChannel]].Data[(int)((e.AbsoluteTicks * msPerTick) / 50)] = false; if (chkHold.Checked) { // backfill the grid for (int i = (int)((e.AbsoluteTicks * msPerTick) / 50); i > 0 && !_sequence.Channels[_midiMap[channel.MidiChannel]].Data[i]; i--) { _sequence.Channels[_midiMap[channel.MidiChannel]].Data[i] = true; } } } } // true note off...don't see this used much if (channel.Command == Sanford.Multimedia.Midi.ChannelCommand.NoteOff && _midiMap.ContainsKey(channel.MidiChannel)) { _sequence.Channels[_midiMap[channel.MidiChannel]].Data[(int)((e.AbsoluteTicks * msPerTick) / 50)] = false; if (chkHold.Checked) { for (int i = (int)((e.AbsoluteTicks * msPerTick) / 50); i > 0 && !_sequence.Channels[_midiMap[channel.MidiChannel]].Data[i]; i--) { _sequence.Channels[_midiMap[channel.MidiChannel]].Data[i] = true; } } } break; case Sanford.Multimedia.Midi.MessageType.Meta: Midi.MetaMessage meta = (Midi.MetaMessage)e.MidiMessage; switch (meta.MetaType) { // again, get the tempo value case Sanford.Multimedia.Midi.MetaType.Tempo: tempo = meta.GetBytes()[0] << 16 | meta.GetBytes()[1] << 8 | meta.GetBytes()[2]; msPerTick = (tempo / _MIDISequence.Division) / 1000.0f; break; } break; } } } }
private void GetMIDIInfo(string file, bool fillTime) { Midi.Sequence MIDISequence; int tempo = 500000; int maxtick = 0; float msPerTick = (tempo / 48) / 1000.0f; string title = string.Empty; _MIDIChannels = new BindingList <MIDIChannel>(); // load the MIDI file MIDISequence = new Midi.Sequence(); MIDISequence.Load(file); // we don't handle non-PPQN MIDI files if (MIDISequence.SequenceType != Sanford.Multimedia.Midi.SequenceType.Ppqn) { MessageBox.Show("Unsupported MIDI type...sorry!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } foreach (Midi.Track t in MIDISequence) { // get the command enumerator IEnumerator <Midi.MidiEvent> en = t.Iterator().GetEnumerator(); bool channelAdded = false; while (en.MoveNext()) { Midi.MidiEvent e = en.Current; switch (e.MidiMessage.MessageType) { case Sanford.Multimedia.Midi.MessageType.Channel: // track the # of channels Midi.ChannelMessage channel = (Midi.ChannelMessage)e.MidiMessage; if (!channelAdded) { _MIDIChannels.Add(new MIDIChannel(channel.MidiChannel, title)); channelAdded = true; } break; case Sanford.Multimedia.Midi.MessageType.Meta: Midi.MetaMessage meta = (Midi.MetaMessage)e.MidiMessage; switch (meta.MetaType) { // cache away the track name for the grid case Sanford.Multimedia.Midi.MetaType.TrackName: title = Encoding.ASCII.GetString(meta.GetBytes()); break; // get the tempo and convert to a time value we can use case Sanford.Multimedia.Midi.MetaType.Tempo: tempo = meta.GetBytes()[0] << 16 | meta.GetBytes()[1] << 8 | meta.GetBytes()[2]; msPerTick = (tempo / MIDISequence.Division) / 1000.0f; break; } break; } // find the highest time value if (e.AbsoluteTicks > maxtick) { maxtick = e.AbsoluteTicks; } } } // and use that value to fill in the minutes/seconds if (fillTime) { txtMinutes.Text = (((int)(msPerTick * maxtick) / 1000) / 60).ToString(); txtSeconds.Text = (((int)(msPerTick * maxtick) / 1000) % 60 + 1).ToString(); } }
/// <summary> /// Initializes the MetaMessageTextBuilder with the specified MetaMessage. /// </summary> /// <param name="message"> /// The MetaMessage to use for initializing the MetaMessageTextBuilder. /// </param> /// <exception cref="ArgumentException"> /// If the MetaMessage is not a text based type. /// </exception> public void Initialize(MetaMessage message) { #region Require if(!IsTextType(message.MetaType)) { throw new ArgumentException("Not text based meta message.", "message"); } #endregion ASCIIEncoding encoding = new ASCIIEncoding(); text = encoding.GetString(message.GetBytes()); this.type = message.MetaType; }
private void Write(MetaMessage message, int trackid, int ticks) { string sy = string.Empty; //trackData.Add((byte)message.Status); //trackData.Add((byte)message.MetaType); //WriteVariableLengthValue(message.Length); //trackData.AddRange(message.GetBytes()); switch (message.MetaType) { case MetaType.Copyright: break; case MetaType.CuePoint: break; case MetaType.DeviceName: break; case MetaType.EndOfTrack: break; case MetaType.InstrumentName: break; case MetaType.KeySignature: break; case MetaType.Lyric: // Track, Time, Lyric_t, Text byte[] b = message.GetBytes(); // Replace byte value 13 (cr) by antislash for (int i = 0; i < b.Length; i++) { if (b[i] == 13) { b[i] = 92; } } sy = System.Text.Encoding.Default.GetString(b); // comma is the separator : remove all comma ? //sy = sy.Replace(',', '-'); stream.WriteLine(string.Format("{0}, {1}, Lyric_t, \"{2}\"", trackid, ticks, sy)); break; case MetaType.Marker: break; case MetaType.ProgramName: break; case MetaType.ProprietaryEvent: break; case MetaType.SequenceNumber: break; case MetaType.SmpteOffset: break; case MetaType.Tempo: break; case MetaType.Text: // Track, Time, Text_t, Text //sy = System.Text.Encoding.Default.GetString(message.GetBytes()).Trim(); sy = System.Text.Encoding.Default.GetString(message.GetBytes()); sy = sy.Replace("\r\n", "\r"); sy = sy.Replace("\r", "\\"); sy = sy.Replace("\n", "\\"); // comma is the separator : remove all comma ? //sy = sy.Replace(',', '-'); stream.WriteLine(string.Format("{0}, {1}, Text_t, \"{2}\"", trackid, ticks, sy)); break; case MetaType.TimeSignature: break; case MetaType.TrackName: break; } }
/// <summary> /// Initializes the TimeSignatureBuilder with the specified MetaMessage. /// </summary> /// <param name="message"> /// The MetaMessage to use for initializing the TimeSignatureBuilder. /// </param> /// <exception cref="ArgumentException"> /// If the specified MetaMessage is not a time signature type. /// </exception> public void Initialize(MetaMessage message) { #region Require if(message.MetaType != MetaType.TimeSignature) { throw new ArgumentException("Wrong meta event type.", "message"); } #endregion data = message.GetBytes(); }
private float TicksPerQuarterSingular(MetaMessage message) { var bytes = message.GetBytes(); return 0; }