public static void appendFingeringToMidiFile(Midi.Sequence file, Fingering[] fingerings) { if (file.Count == 0) { Debug.LogWarning("MIDI no track found."); return; } var FingerMap = new Dictionary <int, Dictionary <int, Finger> >(); foreach (var fingering in fingerings) { if (fingering.markers == null) { Debug.LogWarning("fingering markers is null."); continue; } foreach (var marker in fingering.markers) { if (!FingerMap.ContainsKey(marker.tick)) { FingerMap[marker.tick] = new Dictionary <int, Finger>(); } FingerMap[marker.tick][marker.pitch] = marker.finger; //Debug.LogFormat("marker: {0}, {1}, {2}", marker.tick, marker.pitch, marker.finger); } } clearFingeringInMidiFile(file); foreach (Midi.Track track in file) { foreach (Midi.MidiEvent e in track.Iterator()) { if (e.MidiMessage.MessageType == Midi.MessageType.Channel) { Midi.ChannelMessage cm = e.MidiMessage as Midi.ChannelMessage; if (cm.Command == Midi.ChannelCommand.NoteOn) { if (FingerMap.ContainsKey(e.AbsoluteTicks) && FingerMap[e.AbsoluteTicks].ContainsKey(cm.Data1)) { Finger f = FingerMap[e.AbsoluteTicks][cm.Data1]; string marker = string.Format("finger:{0}|{1}", cm.Data1, (int)f); track.Insert(e.AbsoluteTicks, new Midi.MetaMessage(Midi.MetaType.Marker, Encoding.Default.GetBytes(marker))); } } } } } file[0].Insert(0, new Midi.MetaMessage(Midi.MetaType.Text, Encoding.Default.GetBytes(MidiSignatureText))); }
public MIDIPlayback() { _MIDISequencer = new Midi.Sequencer(); _MIDISequence = new Midi.Sequence(); // event handlers for various message types _MIDISequencer.ChannelMessagePlayed += sequencer_ChannelMessagePlayed; _MIDISequencer.Chased += sequencer_Chased; _MIDISequencer.Stopped += sequencer_Stopped; }
public List <Note> MakeScore(string FilePath) { List <Note> Score = new List <Note>(); MidiToolKit.Sequence sq = new MidiToolKit.Sequence(); sq.Load(FilePath); Score = NoteMake(sq); return(Score); }
public static NotationTrack[] parseMidiFile(Midi.Sequence file) { NotationTrack[] tracks = new NotationTrack[file.Count]; Regex fingerPattern = null; for (int i = 0; i < file.Count; ++i) { tracks[i] = parseMidiTrack(file[i], file.Division, ref fingerPattern); } return(tracks); }
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); } } }
public void load() { if (!SourceAsset) { Debug.LogError("SourceAsset is null."); return; } MemoryStream stream = new MemoryStream(); stream.Write(SourceAsset.bytes, 0, SourceAsset.bytes.Length); stream.Position = 0; MidiSeq = new Midi.Sequence(); MidiSeq.Load(stream); if (TrackHandIndices == null || TrackHandIndices.Length != MidiSeq.Count) { TrackHandIndices = Enumerable.Repeat(-1, MidiSeq.Count).ToArray(); } Notation = NotationUtils.parseMidiFile(MidiSeq); }
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(); } }
public List <Note> NoteMake(MidiToolKit.Sequence sq) { List <ChannelMessage> list_cm = new List <ChannelMessage>(); List <Note> list_note = new List <Note>(); ChannelMessage listcm = new ChannelMessage(); //시퀀스를 트랙화 foreach (MidiToolKit.Track track in sq) { //트렉안의 이벤트 foreach (MidiToolKit.MidiEvent ev in track.Iterator()) { if (ev.MidiMessage is MidiToolKit.ChannelMessage cm) { switch (cm.Command) { case MidiToolKit.ChannelCommand.NoteOn: if (cm.Data2 != 0) { ChannelMessage CM_struct = new ChannelMessage { command = "NoteOn", AbsoluteTick = ev.AbsoluteTicks, Value = cm.Data1, velocuty = cm.Data2 }; list_cm.Add(CM_struct); } else { listcm = list_cm.Find(x => x.Value.Equals(cm.Data1)); list_cm.Remove(new ChannelMessage() { Value = cm.Data1, AbsoluteTick = listcm.AbsoluteTick, command = "NoteOn", velocuty = listcm.velocuty }); list_note.Add(new Note((Byte)listcm.Value, (Byte)listcm.velocuty, listcm.AbsoluteTick, ev.AbsoluteTicks - listcm.AbsoluteTick)); } break; case MidiToolKit.ChannelCommand.NoteOff: listcm = list_cm.Find(x => x.Value.Equals(cm.Data1)); list_cm.Remove(new ChannelMessage() { Value = cm.Data1, AbsoluteTick = listcm.AbsoluteTick, command = "NoteOn", velocuty = listcm.velocuty }); list_note.Add(new Note((Byte)listcm.Value, (Byte)listcm.velocuty, listcm.AbsoluteTick, ev.AbsoluteTicks - listcm.AbsoluteTick)); break; } } } } //magenta에서 생성하는 미디의 PPQN을 현재 Song의 PPQN에 맞춰서 길이변화 int Count = 0; foreach (Note i in list_note) { list_note[Count].Start = (int)((double)i.Start * Song.Current.TimeResolution / sq.Division); list_note[Count].Length = (int)((double)i.Length * Song.Current.TimeResolution / sq.Division); if (list_note[Count].Velocity < 90) { list_note[Count].Velocity = 90; } Count++; } return(list_note); }