public void WriteMusic(MidiMusic music) { WriteHeader(music.Format, (short)music.Tracks.Count, music.DeltaTimeSpec); foreach (var track in music.Tracks) { WriteTrack(track); } }
public void Read(Stream stream) { this.stream = stream; data = new MidiMusic(); try { DoParse(); } finally { this.stream = null; } }
public MidiPlayer(MidiMusic music, IMidiOutput output, IMidiTimeManager timeManager) { if (music == null) { throw new ArgumentNullException("music"); } if (output == null) { throw new ArgumentNullException("output"); } if (timeManager == null) { throw new ArgumentNullException("timeManager"); } this.output = output; player = new MidiSyncPlayer(music, timeManager); EventReceived += (m) => { switch (m.EventType) { case MidiEvent.NoteOn: case MidiEvent.NoteOff: if (channel_mask != null && channel_mask [m.Channel]) { return; // ignore messages for the masked channel. } goto default; case MidiEvent.SysEx1: case MidiEvent.SysEx2: if (buffer.Length <= m.Data.Length) { buffer = new byte [buffer.Length * 2]; } buffer [0] = m.StatusByte; Array.Copy(m.Data, 0, buffer, 1, m.Data.Length); output.Send(buffer, 0, m.Data.Length + 1, 0); break; case MidiEvent.Meta: // do nothing. break; default: var size = MidiEvent.FixedDataSize(m.StatusByte); buffer [0] = m.StatusByte; buffer [1] = m.Msb; buffer [2] = m.Lsb; output.Send(buffer, 0, size + 1, 0); break; } }; }
public MidiSyncPlayer(MidiMusic music, IMidiTimeManager timeManager) { if (music == null) { throw new ArgumentNullException("music"); } time_manager = timeManager; this.music = music; messages = SmfTrackMerger.Merge(music).Tracks [0].Messages; state = PlayerState.Stopped; }
public void Read(Stream stream) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } this.stream = stream; data = new MidiMusic(); try { DoParse(); } finally { this.stream = null; } }
public MidiMusic Split() { int totalDeltaTime = 0; foreach (var e in source) { totalDeltaTime += e.DeltaTime; int id = GetTrackID(e); GetTrack(id).AddMessage(totalDeltaTime, e); } var m = new MidiMusic(); m.DeltaTimeSpec = delta_time_spec; foreach (var t in tracks.Values) { m.Tracks.Add(t.Track); } return(m); }
public MidiPlayer(MidiMusic music, IMidiOutput output, IMidiPlayerTimeManager timeManager) { if (music == null) { throw new ArgumentNullException("music"); } if (output == null) { throw new ArgumentNullException("output"); } if (timeManager == null) { throw new ArgumentNullException("timeManager"); } this.music = music; this.output = output; messages = SmfTrackMerger.Merge(music).Tracks [0].Messages; player = new MidiEventLooper(messages, timeManager, music.DeltaTimeSpec); player.Starting += () => { // all control reset on all channels. for (int i = 0; i < 16; i++) { buffer [0] = (byte)(i + 0xB0); buffer [1] = 0x79; buffer [2] = 0; output.Send(buffer, 0, 3, 0); } }; EventReceived += (m) => { switch (m.EventType) { case MidiEvent.NoteOn: case MidiEvent.NoteOff: if (channel_mask != null && channel_mask [m.Channel]) { return; // ignore messages for the masked channel. } goto default; case MidiEvent.SysEx1: case MidiEvent.SysEx2: if (buffer.Length <= m.Data.Length) { buffer = new byte [buffer.Length * 2]; } buffer [0] = m.StatusByte; Array.Copy(m.Data, 0, buffer, 1, m.Data.Length); output.Send(buffer, 0, m.Data.Length + 1, 0); break; case MidiEvent.Meta: // do nothing. break; default: var size = MidiEvent.FixedDataSize(m.StatusByte); buffer [0] = m.StatusByte; buffer [1] = m.Msb; buffer [2] = m.Lsb; output.Send(buffer, 0, size + 1, 0); break; } }; }
public static MidiMusic Merge(MidiMusic source) { return(new SmfTrackMerger(source).GetMergedMessages()); }
public MidiPlayer(MidiMusic music, IMidiPlayerTimeManager timeManager) : this(music, MidiAccessManager.Empty, timeManager) { }
public MidiPlayer(MidiMusic music, IMidiAccess access, IMidiPlayerTimeManager timeManager) : this(music, access.OpenOutputAsync(access.Outputs.First().Id).Result, timeManager) { should_dispose_output = true; }
public MidiPlayer(MidiMusic music, IMidiAccess access) : this(music, access, new SimpleAdjustingMidiPlayerTimeManager()) { }
public MidiPlayer(MidiMusic music, IMidiOutput output) : this(music, output, new SimpleAdjustingMidiPlayerTimeManager()) { }
public MidiPlayer(MidiMusic music) : this(music, MidiAccessManager.Empty) { }
SmfTrackMerger(MidiMusic source) { this.source = source; }
public MidiSyncPlayer(MidiMusic music) : this(music, new SimpleMidiTimeManager()) { }
public int GetTotalPlayTimeMilliseconds() { return(MidiMusic.GetTotalPlayTimeMilliseconds(messages, music.DeltaTimeSpec)); }
// FIXME: it should rather be implemented to iterate all // tracks with index to messages, pick the track which contains // the nearest event and push the events into the merged queue. // It's simpler, and costs less by removing sort operation // over thousands of events. MidiMusic GetMergedMessages() { if (source.Format == 0) { return(source); } IList <MidiMessage> l = new List <MidiMessage> (); foreach (var track in source.Tracks) { int delta = 0; foreach (var mev in track.Messages) { delta += mev.DeltaTime; l.Add(new MidiMessage(delta, mev.Event)); } } if (l.Count == 0) { return new MidiMusic() { DeltaTimeSpec = source.DeltaTimeSpec } } ; // empty (why did you need to sort your song file?) // Usual Sort() over simple list of MIDI events does not work as expected. // For example, it does not always preserve event // orders on the same channels when the delta time // of event B after event A is 0. It could be sorted // either as A->B or B->A. // // To resolve this issue, we have to sort "chunk" // of events, not all single events themselves, so // that order of events in the same chunk is preserved // i.e. [AB] at 48 and [CDE] at 0 should be sorted as // [CDE] [AB]. var idxl = new List <int> (l.Count); idxl.Add(0); int prev = 0; for (int i = 0; i < l.Count; i++) { if (l [i].DeltaTime != prev) { idxl.Add(i); prev = l [i].DeltaTime; } } idxl.Sort(delegate(int i1, int i2) { return(l [i1].DeltaTime - l [i2].DeltaTime); }); // now build a new event list based on the sorted blocks. var l2 = new List <MidiMessage> (l.Count); int idx; for (int i = 0; i < idxl.Count; i++) { for (idx = idxl [i], prev = l [idx].DeltaTime; idx < l.Count && l [idx].DeltaTime == prev; idx++) { l2.Add(l [idx]); } } l = l2; // now messages should be sorted correctly. var waitToNext = l [0].DeltaTime; for (int i = 0; i < l.Count - 1; i++) { if (l [i].Event.Value != 0) // if non-dummy { var tmp = l [i + 1].DeltaTime - l [i].DeltaTime; l [i] = new MidiMessage(waitToNext, l [i].Event); waitToNext = tmp; } } l [l.Count - 1] = new MidiMessage(waitToNext, l [l.Count - 1].Event); var m = new MidiMusic(); m.DeltaTimeSpec = source.DeltaTimeSpec; m.Format = 0; m.Tracks.Add(new MidiTrack(l)); return(m); } }