private void SaveMuzak(string filename) { AudioSynthesis.Sequencer.MidiFileSequencer mseq = st.mseq; MidiMessage[] mdata = mseq.mdata; double time = 0; int maxPixel = this.Width; Dictionary <int, MidiMessage> last = new Dictionary <int, MidiMessage>(); Dictionary <int, double> lastTime = new Dictionary <int, double>(); Dictionary <byte, int> priorities = noteViewer1.ChannelPriorities; //<midiFreq, int[] axisPlayingPriority = new int[nAxes]; Array.Clear(axisPlayingPriority, 0, nAxes); Dictionary <int, Tuple <int, List <Tuple <int, int> > > > muzak = new Dictionary <int, Tuple <int, List <Tuple <int, int> > > >(); //muzak = Dictionary<timestamp, Tuple<Duration, List<Tuple<priority, midiFreq>>>> //i.e. the song is divided into pieces of time, where each slice has a number of notes that should play. //We'll try to play them in priority order, depending on chords and what was playing previously... SortedDictionary <int, List <MuzakNote> > currentNotes = new SortedDictionary <int, List <MuzakNote> >(); int lastTimeStamp = 0; foreach (MidiMessage mm in mdata) { if (mm.channel == 255) { continue; } time = (double)mm.delta; if (!noteViewer1.ChannelPriorities.ContainsKey(mm.channel)) { continue; } bool startOk = time >= noteViewer1.startTime || noteViewer1.startTime < 0; bool endOk = time <= noteViewer1.endTime || noteViewer1.endTime < 0; if (startOk && endOk) { if (lastTime.Count == 0) { foreach (var c in channels) { lastTime.Add(c, time); } } if (!last.ContainsKey(mm.channel)) { last.Add(mm.channel, new MidiMessage(mm.channel, 0, 0, 0)); } long us = (long)(time - lastTime[mm.channel]); if (mm.command == (int)MidiEventTypeEnum.NoteOn || mm.command == (int)MidiEventTypeEnum.NoteOff) { int currentTimeStamp = mm.delta; int timeDelta = currentTimeStamp - lastTimeStamp; if (timeDelta > 0) { List <Tuple <int, int> > timeSlice = new List <Tuple <int, int> >(); muzak.Add(lastTimeStamp, new Tuple <int, List <Tuple <int, int> > >(timeDelta, timeSlice)); //muzak = Dictionary<timestamp, List<Tuple<priority, midiFreq>>> //i.e. the song is divided into pieces of time, where each slice has a number of notes that should play. //We'll try to play them in priority order, depending on chords and what was playing previously... foreach (var x in currentNotes) { int pri = x.Key; foreach (var note in x.Value) { timeSlice.Add(new Tuple <int, int>(pri, note.midiFreq)); } } lastTimeStamp = mm.delta; } //List<List<MuzakNote>> toOutput = new List<List<MuzakNote>>(); //foreach (int pri in currentNotes.Keys) //{ // toOutput.Add(currentNotes[pri]); // Console.Write(String.Join(", ", currentNotes[pri]) + " | "); //} //Console.WriteLine(""); } if (mm.command == (int)MidiEventTypeEnum.NoteOn) { int pri = priorities[mm.channel]; var toStart = new MuzakNote(mm.data1, pri, mm.channel); if (currentNotes.ContainsKey(pri)) { currentNotes[pri].Add(toStart); } else { currentNotes.Add(pri, new List <MuzakNote>() { toStart }); } } else if (mm.command == (int)MidiEventTypeEnum.NoteOff) { MuzakNote toEnd = null; bool multipleNotes = false; foreach (var notes in currentNotes.Values) { foreach (var note in notes) { if (note.channel == mm.channel && note.midiFreq == mm.data1) { toEnd = note; multipleNotes = notes.Count > 1; } } } if (toEnd != null) { if (multipleNotes) { currentNotes[toEnd.priority].Remove(toEnd); //Remove note from list at this priority } else { currentNotes.Remove(toEnd.priority); //Remove this entire priority } } } last[mm.channel] = mm; lastTime[mm.channel] = time; } } WriteMuzak(filename, muzak); }
public static MuzakNote Delay(long _length, byte _channel) { MuzakNote n = new MuzakNote(0, _length, 0, _channel); return(n); }