private static void TestRemoveAt() { Track a = new Track(); ChannelMessage message = new ChannelMessage(ChannelCommand.NoteOff, 0, 60, 0); a.Insert(0, message); a.Insert(10, message); a.Insert(20, message); a.Insert(30, message); a.Insert(40, message); int count = a.Count; a.RemoveAt(0); Debug.Assert(a.Count == count - 1); a.RemoveAt(a.Count - 2); Debug.Assert(a.Count == count - 2); Debug.Assert(a.GetMidiEvent(0).AbsoluteTicks == 10); Debug.Assert(a.GetMidiEvent(a.Count - 2).AbsoluteTicks == 30); a.RemoveAt(0); a.RemoveAt(0); a.RemoveAt(0); Debug.Assert(a.Count == 1); }
private void ReadMetaLyric(string[] ar) { string sy = string.Empty; if (ar.Length != 4) { if (ar.Length < 4) { throw new ArgumentException("Meta Lyric Length"); } for (int i = 3; i < ar.Length; i++) { sy += ar[i]; } } else { sy = ar[3]; } // Format: Track, Time, Lyric_t, Text int ticks = Convert.ToInt32(ar[1]); byte[] newdata = Encoding.Default.GetBytes(sy); MetaMessage mtMsg = new MetaMessage(MetaType.Lyric, newdata); track.Insert(ticks, mtMsg); manageMetaLyrics(newdata, ticks); }
private static void TestGunshotTrack(Sequence sequence) { var track = new Track(); track.Insert(0, new ChannelMessage(ChannelCommand.ProgramChange, 1, 127)); track.Insert(0, new ChannelMessage(ChannelCommand.NoteOn, 1, 35, 127)); track.Insert(100, new ChannelMessage(ChannelCommand.NoteOff, 1, 35, 0)); track.Insert(101, new ChannelMessage(ChannelCommand.NoteOn, 1, 76, 127)); track.Insert(200, new ChannelMessage(ChannelCommand.NoteOff, 1, 76, 0)); sequence.Add(track); }
private static void TestInsert() { Track track = new Track(); int midiEventCount = 2000; int positionMax = 32000; int endOfTrackOffset = 1000; int length = 0; int position = 0; ChannelMessage message = new ChannelMessage(ChannelCommand.NoteOff, 0, 60, 0); Random r = new Random(); for (int i = 0; i < midiEventCount; i++) { position = r.Next(positionMax); if (position > length) { length = position; } track.Insert(position, message); } track.EndOfTrackOffset = endOfTrackOffset; length += track.EndOfTrackOffset; Debug.Assert(track.Count == midiEventCount + 1); Debug.Assert(track.Length == length); }
private static void TestInsert() { Track track = new Track(); int midiEventCount = 2000; int positionMax = 32000; int endOfTrackOffset = 1000; int length = 0; int position = 0; ChannelMessage message = new ChannelMessage(ChannelCommand.NoteOff, 0, 60, 0); Random r = new Random(); for(int i = 0; i < midiEventCount; i++) { position = r.Next(positionMax); if(position > length) { length = position; } track.Insert(position, message); } track.EndOfTrackOffset = endOfTrackOffset; length += track.EndOfTrackOffset; Debug.Assert(track.Count == midiEventCount + 1); Debug.Assert(track.Length == length); }
private static void TestMerge() { Track a = new Track(); Track b = new Track(); a.Merge(b); Debug.Assert(a.Count == 1); ChannelMessage message = new ChannelMessage(ChannelCommand.NoteOff, 0, 60, 0); b.Insert(0, message); b.Insert(10, message); b.Insert(20, message); b.Insert(30, message); b.Insert(40, message); a.Merge(b); Debug.Assert(a.Count == 1 + b.Count - 1); a.Clear(); Debug.Assert(a.Count == 1); a.Insert(0, message); a.Insert(10, message); a.Insert(20, message); a.Insert(30, message); a.Insert(40, message); int count = a.Count; a.Merge(b); Debug.Assert(a.Count == count + b.Count - 1); Debug.Assert(a.GetMidiEvent(0).DeltaTicks == 0); Debug.Assert(a.GetMidiEvent(1).DeltaTicks == 0); Debug.Assert(a.GetMidiEvent(2).DeltaTicks == 10); Debug.Assert(a.GetMidiEvent(3).DeltaTicks == 0); Debug.Assert(a.GetMidiEvent(4).DeltaTicks == 10); Debug.Assert(a.GetMidiEvent(5).DeltaTicks == 0); Debug.Assert(a.GetMidiEvent(6).DeltaTicks == 10); Debug.Assert(a.GetMidiEvent(7).DeltaTicks == 0); Debug.Assert(a.GetMidiEvent(8).DeltaTicks == 10); Debug.Assert(a.GetMidiEvent(9).DeltaTicks == 0); }
public void Build() { result = new Track(); buffer.Sort(new TimestampComparer()); foreach (TimestampedMessage tm in buffer) { result.Insert(tm.ticks, tm.message); } }
private void ParseChannelMessage() { if (trackIndex >= trackData.Length) { throw new MidiFileException("End of track unexpectedly reached."); } cmBuilder.Command = ChannelMessage.UnpackCommand(status); cmBuilder.MidiChannel = ChannelMessage.UnpackMidiChannel(status); cmBuilder.Data1 = trackData[trackIndex]; trackIndex++; if (ChannelMessage.DataBytesPerType(cmBuilder.Command) == 2) { if (trackIndex >= trackData.Length) { throw new MidiFileException("End of track unexpectedly reached."); } cmBuilder.Data2 = trackData[trackIndex]; trackIndex++; } cmBuilder.Build(); newTrack.Insert(ticks, cmBuilder.Result); runningStatus = status; }
private void ParseChannelMessage() { if (trackIndex >= trackData.Length) { throw new MidiFileException("End of track unexpectedly reached."); } var command = ChannelMessage.UnpackCommand(status); var channel = ChannelMessage.UnpackMidiChannel(status); var data1 = trackData[trackIndex]; trackIndex++; var data2 = 0; if (ChannelMessage.DataBytesPerType(command) == 2) { if (trackIndex >= trackData.Length) { throw new MidiFileException("End of track unexpectedly reached."); } data2 = trackData[trackIndex]; trackIndex++; } newTrack.Insert(ticks, new ChannelMessage(command, data1, data2, channel)); runningStatus = status; }
public static void Save(List<List<Event>> allEvents, string path) { Sequence sequence = new Sequence(); Dictionary<int, Track> tracks = new Dictionary<int, Track>(); for (int trackIndex = 0; trackIndex < allEvents.Count; trackIndex++) { Track track = new Track(); sequence.Add(track); List<Event> trackEvents = allEvents[trackIndex]; foreach (var midiEvent in trackEvents.Select(trackEvent => new { Tick = trackEvent.Tick, MidiMessage = Convert(trackEvent, track) })) { track.Insert(midiEvent.Tick, midiEvent.MidiMessage); } } sequence.Save(path); }
/// <summary> /// Create new track and add it to the list newtracks /// </summary> private void CreateTrack() { track = new Track() { MidiChannel = Channel, Name = TrackName, InstrumentName = InstrumentName, ProgramChange = ProgramChange, Volume = Volume, Pan = Pan, Reverb = Reverb, }; ChannelMessage message = new ChannelMessage(ChannelCommand.ProgramChange, track.MidiChannel, track.ProgramChange, 0); track.Insert(0, message); newTracks.Add(track); }
private static void TestPianoTrack(Sequence sequence) { var track = new Track(); track.Insert(0, new ChannelMessage(ChannelCommand.ProgramChange, 0, 0)); track.Insert(0, new ChannelMessage(ChannelCommand.NoteOn, 0, 35, 127)); track.Insert(100, new ChannelMessage(ChannelCommand.NoteOff, 0, 35, 0)); track.Insert(101, new ChannelMessage(ChannelCommand.NoteOn, 0, 76, 127)); track.Insert(200, new ChannelMessage(ChannelCommand.NoteOff, 0, 76, 0)); for (int i = 0; i < 1000; i += 10) { track.Insert(i, new ChannelMessage(ChannelCommand.NoteOn, 0, 76, 127)); track.Insert(i + 9, new ChannelMessage(ChannelCommand.NoteOff, 0, 76)); } sequence.Add(track); }
public void Start() { #region Require if(disposed) { throw new ObjectDisposedException(this.GetType().Name); } #endregion List<Track> newTracks = new List<Track>(); for (int i=0; i<Sequence.Count; i++) { Track t = new Track(); foreach (MidiEvent e in Sequence[i].Iterator()) { bool discard = false; if (e.MidiMessage.MessageType == MessageType.Channel) { ChannelMessage m = (e.MidiMessage as ChannelMessage); if (m.Command == ChannelCommand.Controller && (m.Data1 == (int)ControllerType.Volume || m.Data1 == (int)ControllerType.VolumeFine)) { discard = true; } } if (!discard) t.Insert(e.AbsoluteTicks, e.MidiMessage); } Sequence.Remove(Sequence[i]); /*if (i == 0)*/ newTracks.Add(t); } foreach (Track t in newTracks) Sequence.Add(t); foreach (MidiEvent e in Sequence[0].Iterator()) { if (e.MidiMessage.MessageType == MessageType.Channel) { ChannelMessage m = (e.MidiMessage as ChannelMessage); if (m.Command == ChannelCommand.NoteOn) { int a = e.AbsoluteTicks ; } } } //for (int i=0; i<4; i++) // Sequence[i].Insert(1, new ChannelMessage(ChannelCommand.Controller, i, (int)ControllerType.Volume, 0 )); lock(lockObject) { Stop(); Position = 0; Continue(); } }
private void onLoad(object sender, EventArgs args) { List<Track> newTracks = new List<Track>(); for (int i = 0; i < sequence1.Count; i++) { Track t = new Track(); foreach (MidiEvent e in sequence1[i].Iterator()) { bool discard = false; if (e.MidiMessage.MessageType == MessageType.Channel) { ChannelMessage m = (e.MidiMessage as ChannelMessage); if (m.Command == ChannelCommand.Controller && (m.Data1 == (int)ControllerType.Volume || m.Data1 == (int)ControllerType.VolumeFine)) { discard = true; } } if (!discard) t.Insert(e.AbsoluteTicks, e.MidiMessage); } sequence1.Remove(sequence1[i]); /*if (i == 0)*/ newTracks.Add(t); } foreach (Track t in newTracks) sequence1.Add(t); foreach (MidiEvent e in sequence1[0].Iterator()) { if (e.MidiMessage.MessageType == MessageType.Channel) { ChannelMessage m = (e.MidiMessage as ChannelMessage); if (m.Command == ChannelCommand.NoteOn) { int a = e.AbsoluteTicks; } } } //for (int i=0; i<4; i++) // Sequence[i].Insert(1, new ChannelMessage(ChannelCommand.Controller, i, (int)ControllerType.Volume, 0 )); // then we return to loader code if (loadComplete != null) loadComplete(); }
private Sequence GetSequenceFromWPFStaffs(List <MusicalSymbol> WPFStaffs, Models.Track track) { List <string> notesOrderWithCrosses = new List <string>() { "c", "cis", "d", "dis", "e", "f", "fis", "g", "gis", "a", "ais", "b" }; int absoluteTicks = 0; Sequence sequence = new Sequence(); Sanford.Multimedia.Midi.Track metaTrack = new Sanford.Multimedia.Midi.Track(); sequence.Add(metaTrack); // Calculate tempo var bar = (Bar)track.GetStaffs().Last().Bars.Last(); int speed = (60000000 / bar.BarContext.BeatsPerMinute); byte[] tempo = new byte[3]; tempo[0] = (byte)((speed >> 16) & 0xff); tempo[1] = (byte)((speed >> 8) & 0xff); tempo[2] = (byte)(speed & 0xff); metaTrack.Insert(0 /* Insert at 0 ticks*/, new MetaMessage(MetaType.Tempo, tempo)); Sanford.Multimedia.Midi.Track notesTrack = new Sanford.Multimedia.Midi.Track(); sequence.Add(notesTrack); for (int i = 0; i < WPFStaffs.Count; i++) { var musicalSymbol = WPFStaffs[i]; switch (musicalSymbol.Type) { case MusicalSymbolType.Note: PSAMControlLibrary.Note note = musicalSymbol as PSAMControlLibrary.Note; // Calculate duration double absoluteLength = 1.0 / (double)note.Duration; absoluteLength += (absoluteLength / 2.0) * note.NumberOfDots; double relationToQuartNote = bar.BarContext.BeatsInBar.Item2 / 4.0; double percentageOfBeatNote = (1.0 / bar.BarContext.BeatsInBar.Item2) / absoluteLength; double deltaTicks = (sequence.Division / relationToQuartNote) / percentageOfBeatNote; // Calculate height int noteHeight = notesOrderWithCrosses.IndexOf(note.Step.ToLower()) + ((note.Octave + 1) * 12); noteHeight += note.Alter; notesTrack.Insert(absoluteTicks, new ChannelMessage(ChannelCommand.NoteOn, 1, noteHeight, 90)); // Data2 = volume absoluteTicks += (int)deltaTicks; notesTrack.Insert(absoluteTicks, new ChannelMessage(ChannelCommand.NoteOn, 1, noteHeight, 0)); // Data2 = volume break; case MusicalSymbolType.TimeSignature: byte[] timeSignature = new byte[4]; // timeSignature[0] = (byte)_beatsPerBar; //timeSignature[1] = (byte)(Math.Log(_beatNote) / Math.Log(2)); metaTrack.Insert(absoluteTicks, new MetaMessage(MetaType.TimeSignature, timeSignature)); break; default: break; } } notesTrack.Insert(absoluteTicks, MetaMessage.EndOfTrackMessage); metaTrack.Insert(absoluteTicks, MetaMessage.EndOfTrackMessage); return(sequence); }
public override void SaveAsMIDI(string fileName) { if (NumTracks == 0) { throw new InvalidDataException("This song has no tracks."); } CalculateTicks(); var midi = new Sequence(24) { Format = 1 }; var metaTrack = new Sanford.Multimedia.Midi.Track(); midi.Add(metaTrack); for (int i = 0; i < NumTracks; i++) { var track = new Sanford.Multimedia.Midi.Track(); midi.Add(track); int endOfPattern = 0, startOfPatternTicks = 0, endOfPatternTicks = 0, shift = 0; var playing = new List <M4ANoteCommand>(); for (int j = 0; j < Commands[i].Count; j++) { var e = Commands[i][j]; int ticks = e.AbsoluteTicks + (endOfPatternTicks - startOfPatternTicks); switch (e.Command) { case KeyShiftCommand keysh: shift = keysh.Shift; break; case M4ANoteCommand note: int n = (note.Note + shift).Clamp(0, 0x7F); track.Insert(ticks, new ChannelMessage(ChannelCommand.NoteOn, i, n, note.Velocity)); if (note.Duration != -1) { track.Insert(ticks + note.Duration, new ChannelMessage(ChannelCommand.NoteOff, i, n)); } else { playing.Add(note); } break; case EndOfTieCommand eot: M4ANoteCommand nc = null; if (eot.Note == -1) { nc = playing.LastOrDefault(); } else { nc = playing.LastOrDefault(no => no.Note == eot.Note); } if (nc != null) { n = (nc.Note + shift).Clamp(0, 0x7F); track.Insert(ticks, new ChannelMessage(ChannelCommand.NoteOff, i, n)); playing.Remove(nc); } break; case PriorityCommand prio: track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, (int)ControllerType.VolumeFine, prio.Priority)); break; case VoiceCommand voice: track.Insert(ticks, new ChannelMessage(ChannelCommand.ProgramChange, i, voice.Voice)); break; case VolumeCommand vol: track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, (int)ControllerType.Volume, vol.Volume)); break; case PanpotCommand pan: track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, (int)ControllerType.Pan, pan.Panpot + 0x40)); break; case BendCommand bend: track.Insert(ticks, new ChannelMessage(ChannelCommand.PitchWheel, i, 0, bend.Bend + 0x40)); break; case BendRangeCommand bendr: track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, 20, bendr.Range)); break; case LFOSpeedCommand lfos: track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, 21, lfos.Speed)); break; case LFODelayCommand lfodl: track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, 26, lfodl.Delay)); break; case ModDepthCommand mod: track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, (int)ControllerType.ModulationWheel, mod.Depth)); break; case ModTypeCommand modt: track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, 22, modt.Type)); break; case TuneCommand tune: track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, 24, tune.Tune)); break; case LibraryCommand xcmd: track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, 30, xcmd.Command)); track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, 29, xcmd.Argument)); break; case TempoCommand tempo: var change = new TempoChangeBuilder { Tempo = (60000000 / tempo.Tempo) }; change.Build(); metaTrack.Insert(ticks, change.Result); break; case CallCommand patt: int callCmd = Commands[i].FindIndex(c => c.GetOffset() == patt.Offset); endOfPattern = j; endOfPatternTicks = e.AbsoluteTicks; j = callCmd - 1; // -1 for incoming ++ startOfPatternTicks = Commands[i][j + 1].AbsoluteTicks; break; case ReturnCommand _: if (endOfPattern != 0) { j = endOfPattern; endOfPattern = startOfPatternTicks = endOfPatternTicks = 0; } break; case GoToCommand goTo: if (i == 0) { int jumpCmd = Commands[i].FindIndex(c => c.GetOffset() == goTo.Offset); metaTrack.Insert(Commands[i][jumpCmd].AbsoluteTicks, new MetaMessage(MetaType.Marker, new byte[] { (byte)'[' })); metaTrack.Insert(ticks, new MetaMessage(MetaType.Marker, new byte[] { (byte)']' })); } break; case FinishCommand _: goto endOfTrack; } } endOfTrack :; } midi.Save(fileName); }
public void AddToTrack(Track track, double secondToTickMultiplier) { int startAbsoluteTick = (int)((StartTime + Program.MIDIPlaybackOffset) / secondToTickMultiplier); int endAbsoluteTick = (int)((EndTime + Program.MIDIPlaybackOffset) / secondToTickMultiplier); ChannelMessage startMessage = new ChannelMessage(ChannelCommand.NoteOn, 0, NoteIndex - Program.MIDI_OFFSET, Program.MIDIPlayer.Volume); ChannelMessage endMessage = new ChannelMessage(ChannelCommand.NoteOff, 0, NoteIndex - Program.MIDI_OFFSET); try { track.Insert(startAbsoluteTick, startMessage); track.Insert(endAbsoluteTick, endMessage); } catch (Exception) { } }
static void Main(string[] args) { bool outputMidiVelocity = false; //var filename = "01-v-drac.s3m"; //S3MFile f = S3MFile.Parse(filename); //var tempo = 60000000 / (f.Header.InitialTempo); //byte numerator = 4; //byte denominator = 4; //var speed = 3; //var skip = 0; var filename = "02-v-bewm.s3m"; S3MFile f = S3MFile.Parse(filename); var tempo = 60000000 / (f.Header.InitialTempo); byte numerator = 4; byte denominator = 4; var speed = 3; var skip = 0; outputMidiVelocity = true; /* var filename = "V-OPTION.S3M"; S3MFile f = S3MFile.Parse(filename); var tempo = 60000000 / (f.Header.InitialTempo); byte numerator = 6; byte denominator = 8; var speed = 3; var skip = 4; */ /* var filename = "V-FALCON.S3M"; S3MFile f = S3MFile.Parse(filename); var tempo = 60000000 / (1 * f.Header.InitialTempo); byte numerator = 4; byte denominator = 4; var speed = 3; var skip = 0; */ /* var filename = "V-CONTRA.IT"; S3MFile f = S3MFile.Parse(filename); var tempo = 60000000 / (1 * f.Header.InitialTempo); byte numerator = 4; byte denominator = 4; var speed = 3; var skip = 0; * */ /* var filename = "V-BLAST.S3M"; S3MFile f = S3MFile.Parse(filename); var tempo = 60000000 / (1 * f.Header.InitialTempo); byte numerator = 4; byte denominator = 4; var speed = 3; var skip = 0;*/ Sequence s = new Sequence(); Track t1 = new Track(); Track t2 = new Track(); Track t3 = new Track(); Track drums = new Track(); Track kick = new Track(); Track timeTrack = new Track(); s.Add(timeTrack); s.Add(t1); s.Add(t2); s.Add(t3); //s.Add(drums); //s.Add(kick); var drumPC = new ChannelMessageBuilder(); drumPC.MidiChannel = 09; drumPC.Command = ChannelCommand.ProgramChange; drumPC.Data1 = 0;// 79 + ce.Instrument; drumPC.Build(); drums.Insert(0, drumPC.Result); kick.Insert(0, drumPC.Result); TimeSignatureBuilder tsb = new TimeSignatureBuilder(); tsb.Numerator = numerator; tsb.Denominator = denominator; tsb.ClocksPerMetronomeClick = 24; tsb.ThirtySecondNotesPerQuarterNote = 8; tsb.Build(); timeTrack.Insert(0, tsb.Result); TempoChangeBuilder tcb = new TempoChangeBuilder(); tcb.Tempo = tempo; tcb.Build(); timeTrack.Insert(0, tcb.Result); var outputPatterns = new int[] { 5, 6, 7}; //var c1 = (from p in f.OrderedPatterns // where patterns.Contains(p.PatternNumber) // select p) // .SelectMany(p => p.Channels) // .Where(c => c.ChannelNumber == 1) // .SelectMany(ce => ce.ChannelEvents); //var c2 = (from p in f.OrderedPatterns // where patterns.Contains(p.PatternNumber) // select p) // .SelectMany(p => p.Channels) // .Where(c => c.ChannelNumber == 2) // .SelectMany(ce => ce.ChannelEvents); //var c3 = (from p in f.OrderedPatterns // where patterns.Contains(p.PatternNumber) // select p) // .SelectMany(p => p.Channels) // .Where(c => c.ChannelNumber == 3) // .SelectMany(ce => ce.ChannelEvents); var patterns = from p in f.OrderedPatterns.Skip(skip) /*where outputPatterns.Contains(p.PatternNumber) */select p; //.SelectMany(p => p.Rows); Dictionary<int, TrackInfo> tracks = new Dictionary<int, TrackInfo>(); tracks.Add(1, new TrackInfo(t1)); tracks[1].Channel = 0; tracks.Add(2, new TrackInfo(t2)); tracks[2].Channel = 1; tracks.Add(3, new TrackInfo(t3)); tracks[3].Channel = 2; var di = new TrackInfo(drums); di.Channel = 9; var mapper = new Func<ChannelEvent, int>(ce => { switch (ce.Instrument) { case 6: return 42; case 8: return 35; case 9: return 38; case 10: return 47; default: Debug.Fail(ce.Instrument.ToString()); return 0; } }); di.NoteMapper = mapper; var kickInfo = new TrackInfo(kick); kickInfo.Channel = 9; kickInfo.NoteMapper = mapper; tracks.Add(4, di); tracks.Add(5, kickInfo); var tick = 0; foreach (var pattern in patterns) { bool breakPattern = false; foreach (var row in pattern.Rows) { //if ((row.RowNumber-1) % 16 == 0) //{ // drums.Insert(tick, kickOn); // drums.Insert(tick + speed, kickOff); //} foreach (var ce in row.ChannelEvents) { if (ce == null) { //Console.Out.WriteLine("skip"); continue; } if (ce.Command == 3) { var modulo = row.RowNumber % 32; if (modulo != 0) { // sad to say, not sure why mod 8 but divide by 16 works var m8 = row.RowNumber % 8; if (m8 == 0) { var restore = tsb.Result; tsb.Numerator = (byte)(row.RowNumber / 16); tsb.Build(); var change = tsb.Result; timeTrack.Insert(tick, change); timeTrack.Insert(tick + 3, restore); } } //Debugger.Break(); // pattern break // figure out the time signature of the pattern up to this point // then go back and insert a time signature change message at the beginning // of the pattern // and another one at the end to revert //var restore = tsb.Result; //tsb.Numerator = 2; //tsb.Build(); //var change = tsb.Result; //timeTrack.Insert(rowStartTick, change); //timeTrack.Insert(tick + 3, restore); breakPattern = true; } if (!tracks.ContainsKey(ce.ChannelNumber)) continue; TrackInfo ti = tracks[ce.ChannelNumber]; if (ce.Note == -1 ) { // skip } else if( ce.Note == 0xFF) { // re-use current note, but change instrument //Console.Out.WriteLine("skip"); } else if (ce.Note == 0xFE) //off { if (ti.LastPitch != -1) { NoteOff(tick, ti); } } else { //if (ce.Volume != -1 && ce.Volume < 32) continue; if (ti.LastPitch != -1) { NoteOff(tick, ti); } //p = ProgramChange(ti.Track, tick, p, ce); var delay = 0; if (ce.Command == 19) { if (208 <= ce.Data && ce.Data <= 214) // HACK: 214 is a guess at the top range of SD commands { delay = ce.Data - 208; Debug.Assert(delay >= 0); } } NoteOn(tick + delay, ti, ce); } } tick += speed; if (breakPattern) { break; } } } foreach (var pair in tracks) { if (pair.Value.LastPitch != -1) { NoteOff(tick, pair.Value); } } foreach (MidiEvent m in drums.Iterator().Take(5)) { if (m.MidiMessage is ChannelMessage) { ChannelMessage cm = (ChannelMessage)m.MidiMessage; Console.Out.WriteLine("{0} {1}", m.AbsoluteTicks, cm.Command); } } s.Save(Path.ChangeExtension(filename, ".mid")); /* var tick = 0; var speed = 3; var lastNote = -1; var p = -1; foreach (var ce in c1) { if (ce == null || ce.Note == -1 || ce.Note == 0xFF) { tick += speed; Console.Out.WriteLine("skip"); continue; } else if (ce.Note == 0xFE) //off { lastNote = NoteOff(t, tick, lastNote); } else { if (lastNote != -1) { lastNote = NoteOff(t, tick, lastNote); } p = ProgramChange(t, tick, p, ce); var delay = 0; if (ce.Command == 19) { if (208 <= ce.Data && ce.Data <= 214) // HACK: 214 is a guess at the top range of SD commands { delay = ce.Data - 208; Debug.Assert(delay >= 0); } } lastNote = NoteOn(t, tick + delay, ce.Note); } tick += speed; } lastNote = NoteOff(t, tick, lastNote); * * */ }
IEnumerable<Data1ChannelEventList> checkForInvalidNotes(GuitarMessageList owner, Track track, IEnumerable<int> data1List) { var ret = new List<Data1ChannelEventList>(); try { var notesOnData2Zero = track.ChanMessages.Where(x => x.Data2 == 0 && x.Command == ChannelCommand.NoteOn).ToList(); if (notesOnData2Zero.Any()) { track.Remove(notesOnData2Zero); foreach (var x in notesOnData2Zero) { track.Insert(x.AbsoluteTicks, new ChannelMessage(ChannelCommand.NoteOff, x.Data1, 0, x.Channel)); } } if (track.Name.IsGuitarTrackName6()) { var bassTrainers = track.Meta.Where(x => x.Text.IsTrainerBass()).ToList(); var guitarTrainers = track.Meta.Where(x => x.Text.IsTrainerGuitar()).ToList(); if (bassTrainers.Any()) { bassTrainers.ForEach(x => track.Remove(x)); } } if (track.Name.IsBassTrackName6()) { var bassTrainers = track.Meta.Where(x => x.Text.IsTrainerBass()).ToList(); var guitarTrainers = track.Meta.Where(x => x.Text.IsTrainerGuitar()).ToList(); if (guitarTrainers.Any()) { guitarTrainers.ForEach(x => track.Remove(x)); } } ret.AddRange(track.GetCleanMessageList(data1List, owner)); } catch (Exception ex) { ex.Message.OutputDebug(); } return ret; }
private static int ProgramChange(Track t, int tick, int p, int channel, ChannelEvent ce) { if (p != ce.Instrument) { Console.Out.WriteLine("PC " + ce.Instrument); ChannelMessageBuilder pc = new ChannelMessageBuilder(); pc.MidiChannel = channel; pc.Command = ChannelCommand.ProgramChange; pc.Data1 = 0;// 79 + ce.Instrument; pc.Build(); t.Insert(tick, pc.Result); p = ce.Instrument; } return p; }
public void CreateChordNameEvents(GuitarDifficulty difficulty, int[] GuitarTuning, int[] BassTuning, Track ownerTrack) { var x108 = Generate108().Where(x => x.Chord != null).ToList(); foreach (var item in x108) { if (item.Chord.Notes.Count() > 1) { ChordNameMeta name = null; if (ownerTrack.Name.IsBassTrackName()) { name = item.Chord.GetTunedChordName(BassTuning); } else { name = item.Chord.GetTunedChordName(GuitarTuning); } int data1 = -1; var useUserChordName = false; var chordName = string.Empty; var hideChordName = false; item.Chord.RootNoteConfig.IfNotNull(x => useUserChordName = x.UseUserChordName); item.Chord.RootNoteConfig.IfNotNull(x => chordName = x.UserChordName); item.Chord.RootNoteConfig.IfNotNull(x => data1 = x.RootNoteData1); item.Chord.RootNoteConfig.IfNotNull(x => hideChordName = x.HideNoteName); if (difficulty == GuitarDifficulty.Expert) { if (hideChordName || (data1 == -1 && (name == null || (name != null && name.ToneName.ToToneNameData1() == ToneNameData1.NotSet)))) { ownerTrack.Insert(item.Ticks.Down, new ChannelMessage(ChannelCommand.NoteOn, Utility.ChordNameHiddenData1, 100 + item.Fret)); ownerTrack.Insert(item.Ticks.Up, new ChannelMessage(ChannelCommand.NoteOff, Utility.ChordNameHiddenData1, 0)); } else { if (data1 == -1) { data1 = name.ToneName.ToToneNameData1().ToInt(); } ownerTrack.Insert(item.Ticks.Down, new ChannelMessage(ChannelCommand.NoteOn, data1, 100 + item.Fret)); ownerTrack.Insert(item.Ticks.Up, new ChannelMessage(ChannelCommand.NoteOff, data1, 0)); } } var chordNameText = Utility.CreateChordNameText(item.Chord.Difficulty, useUserChordName ? chordName : name.ToStringEx()); if (chordNameText.IsNotEmpty()) { ownerTrack.Insert(item.Chord.AbsoluteTicks, new MetaMessage(MetaType.Text, chordNameText)); } } } }
public override void SaveAsMIDI(string fileName) { if (NumTracks == 0) { throw new InvalidDataException("Questa canzone non ha tracce."); } CalculateTicks(); var midi = new Sequence(24) { Format = 1 }; var metaTrack = new Sanford.Multimedia.Midi.Track(); midi.Add(metaTrack); for (int i = 0; i < NumTracks; i++) { var track = new Sanford.Multimedia.Midi.Track(); midi.Add(track); int endOfPattern = 0, startOfPatternTicks = 0, endOfPatternTicks = 0, shift = 0; var playing = new List <M4ANoteCommand>(); for (int j = 0; j < Commands[i].Count; j++) { var e = Commands[i][j]; int ticks = e.AbsoluteTicks + (endOfPatternTicks - startOfPatternTicks); if (e.Command is KeyShiftCommand keysh) { shift = keysh.Shift; } else if (e.Command is M4ANoteCommand note) { int n = (note.Note + shift).Clamp(0, 0x7F); track.Insert(ticks, new ChannelMessage(ChannelCommand.NoteOn, i, n, note.Velocity)); if (note.Duration != -1) { track.Insert(ticks + note.Duration, new ChannelMessage(ChannelCommand.NoteOff, i, n)); } else { playing.Add(note); } } else if (e.Command is EndOfTieCommand eot) { M4ANoteCommand nc = null; if (eot.Note == -1) { nc = playing.LastOrDefault(); } else { nc = playing.LastOrDefault(n => n.Note == eot.Note); } if (nc != null) { int no = (nc.Note + shift).Clamp(0, 0x7F); track.Insert(ticks, new ChannelMessage(ChannelCommand.NoteOff, i, no)); playing.Remove(nc); } } else if (e.Command is VoiceCommand voice) { // TODO: Fork and remove restriction track.Insert(ticks, new ChannelMessage(ChannelCommand.ProgramChange, i, voice.Voice & 0x7F)); } else if (e.Command is VolumeCommand vol) { track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, (int)ControllerType.Volume, vol.Volume)); } else if (e.Command is PanpotCommand pan) { track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, (int)ControllerType.Pan, pan.Panpot + 0x40)); } else if (e.Command is BendCommand bend) { track.Insert(ticks, new ChannelMessage(ChannelCommand.PitchWheel, i, 0, bend.Bend + 0x40)); } else if (e.Command is BendRangeCommand bendr) { track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, 20, bendr.Range)); } else if (e.Command is LFOSpeedCommand lfos) { track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, 21, lfos.Speed)); } else if (e.Command is LFODelayCommand lfodl) { track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, 26, lfodl.Delay)); } else if (e.Command is ModDepthCommand mod) { track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, (int)ControllerType.ModulationWheel, mod.Depth)); } else if (e.Command is ModTypeCommand modt) { track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, 22, modt.Type)); } else if (e.Command is TuneCommand tune) { track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, 24, tune.Tune)); } else if (e.Command is TempoCommand tempo) { var change = new TempoChangeBuilder { Tempo = (60000000 / tempo.Tempo) }; change.Build(); metaTrack.Insert(ticks, change.Result); } else if (e.Command is CallCommand patt) { int callCmd = Commands[i].FindIndex(c => c.GetOffset() == patt.Offset); endOfPattern = j; endOfPatternTicks = e.AbsoluteTicks; j = callCmd - 1; // -1 for incoming ++ startOfPatternTicks = Commands[i][j + 1].AbsoluteTicks; } else if (e.Command is ReturnCommand) { if (endOfPattern != 0) { j = endOfPattern; endOfPattern = startOfPatternTicks = endOfPatternTicks = 0; } } else if (i == 0 && e.Command is GoToCommand goTo) { int jumpCmd = Commands[i].FindIndex(c => c.GetOffset() == goTo.Offset); metaTrack.Insert(Commands[i][jumpCmd].AbsoluteTicks, new MetaMessage(MetaType.Marker, new byte[] { (byte)'[' })); metaTrack.Insert(ticks, new MetaMessage(MetaType.Marker, new byte[] { (byte)']' })); } else if (e.Command is FinishCommand fine) { // TODO: Fix ticks before end of track event // Library automatically is updating track.EndOfTrackOffset for us break; } } } midi.Save(fileName); }
public override void SaveAsMIDI(string fileName) { if (NumTracks == 0) { throw new InvalidDataException("Questa canzone non ha tracce."); } CalculateTicks(); var midi = new Sequence(96) { Format = 1 }; var metaTrack = new Sanford.Multimedia.Midi.Track(); midi.Add(metaTrack); for (int i = 0; i < NumTracks; i++) { var track = new Sanford.Multimedia.Midi.Track(); midi.Add(track); FreeNoteCommand freeNote = null; MidiEvent freeNoteOff = null; for (int j = 0; j < Commands[i].Count; j++) { var e = Commands[i][j]; // Extended note ended ended and wasn't renewed if (freeNoteOff != null && freeNoteOff.AbsoluteTicks < e.AbsoluteTicks * 2) { freeNote = null; freeNoteOff = null; } if (e.Command is VolumeCommand vol) { track.Insert(e.AbsoluteTicks * 2, new ChannelMessage(ChannelCommand.Controller, i, (int)ControllerType.Volume, vol.Volume / 2)); } else if (e.Command is VoiceCommand voice) { // TODO: Fork and remove restriction track.Insert(e.AbsoluteTicks * 2, new ChannelMessage(ChannelCommand.ProgramChange, i, voice.Voice & 0x7F)); } else if (e.Command is PanpotCommand pan) { track.Insert(e.AbsoluteTicks * 2, new ChannelMessage(ChannelCommand.Controller, i, (int)ControllerType.Pan, pan.Panpot / 2 + 0x40)); } else if (e.Command is BendCommand bend) { track.Insert(e.AbsoluteTicks * 2, new ChannelMessage(ChannelCommand.PitchWheel, i, 0, bend.Bend / 2 + 0x40)); } else if (e.Command is BendRangeCommand bendr) { track.Insert(e.AbsoluteTicks * 2, new ChannelMessage(ChannelCommand.Controller, i, 20, bendr.Range / 2)); } else if (e.Command is MLSSNoteCommand note) { // Extended note is playing and it should be extended by this note if (freeNote != null && freeNote.Note - 0x80 == note.Note) { // Move the note off command track.Move(freeNoteOff, freeNoteOff.AbsoluteTicks + note.Duration * 2); } // Extended note is playing but this note is different OR there is no extended note playing // Either way we play a new note and forget that one else { track.Insert(e.AbsoluteTicks * 2, new ChannelMessage(ChannelCommand.NoteOn, i, note.Note, 0x7F)); track.Insert(e.AbsoluteTicks * 2 + note.Duration * 2, new ChannelMessage(ChannelCommand.NoteOff, i, note.Note)); freeNote = null; freeNoteOff = null; } } else if (e.Command is FreeNoteCommand free) { // Extended note is playing and it should be extended if (freeNote != null && freeNote.Note == free.Note) { // Move the note off command track.Move(freeNoteOff, freeNoteOff.AbsoluteTicks + free.Duration * 2); } // Extended note is playing but this note is different OR there is no extended note playing // Either way we play a new note and forget that one else { track.Insert(e.AbsoluteTicks * 2, new ChannelMessage(ChannelCommand.NoteOn, i, free.Note - 0x80, 0x7F)); track.Insert(e.AbsoluteTicks * 2 + free.Duration * 2, new ChannelMessage(ChannelCommand.NoteOff, i, free.Note - 0x80)); freeNote = free; freeNoteOff = track.GetMidiEvent(track.Count - 2); // -1 would be the end of track event } } else if (i == 0 && e.Command is TempoCommand tempo) { var change = new TempoChangeBuilder { Tempo = (60000000 / tempo.Tempo) }; change.Build(); metaTrack.Insert(e.AbsoluteTicks * 2, change.Result); } else if (i == 0 && e.Command is GoToCommand goTo) { int jumpCmd = Commands[i].FindIndex(c => c.GetOffset() == goTo.Offset); metaTrack.Insert(Commands[i][jumpCmd].AbsoluteTicks * 2, new MetaMessage(MetaType.Marker, new byte[] { (byte)'[' })); metaTrack.Insert(e.AbsoluteTicks * 2, new MetaMessage(MetaType.Marker, new byte[] { (byte)']' })); } else if (e.Command is FinishCommand fine) { // TODO: Fix ticks before end of track event // Library automatically is updating track.EndOfTrackOffset for us break; } } } midi.Save(fileName); }
private void UpdateTrack(Track track) { try { TrackProperties.FirstOrDefault(x => x.Track == track).IfObjectNotNull(trackProp => { if (trackProp.Track.ChanMessages.Count() > 5) { if (!trackProp.Scale.IsNull()) { track.Remove(track.ChanMessages.ToList()); var ev = trackProp.Events.Chords.ToList(); var scale = trackProp.Scale; if (scale < 0.001) scale = 0.001; var offset = trackProp.Offset; var firstTime = ev.First().TimePair; var firstTick = ev.First().TickPair; ev.ForEach(x => { x.Notes.ForEach(n => { var scaledLength = x.TimeLength * scale; var scaledStart = (x.StartTime - firstTime.Down) * scale + offset; var downTick = EditorPro.GuitarTrack.TimeToTick(scaledStart); var upTick = EditorPro.GuitarTrack.TimeToTick(scaledStart + scaledLength); var data1 = Utility.GetStringLowE(GuitarDifficulty.Expert) + n.NoteString; track.Insert((int)(downTick), new ChannelMessage(ChannelCommand.NoteOn, data1, n.NoteFretDown + 100, n.Channel)); track.Insert((int)(upTick), new ChannelMessage(ChannelCommand.NoteOff, data1, 0, n.Channel)); }); }); } } }); } catch { } }
private void ParseChannelMessage() { if (trackIndex >= trackData.Length) { //throw new MidiFileException("End of track unexpectedly reached."); Console.Write("\nERROR: End of track unexpectedly reached (TrackReader.cs ParseChannelMessage)"); return; } cmBuilder.Command = ChannelMessage.UnpackCommand(status); cmBuilder.MidiChannel = ChannelMessage.UnpackMidiChannel(status); cmBuilder.Data1 = trackData[trackIndex]; // PROGRAM CHANGE if (cmBuilder.Command == ChannelCommand.ProgramChange) { newTrack.ProgramChange = cmBuilder.Data1; newTrack.MidiChannel = cmBuilder.MidiChannel; } trackIndex++; if (ChannelMessage.DataBytesPerType(cmBuilder.Command) == 2) { if (trackIndex >= trackData.Length) { //throw new MidiFileException("End of track unexpectedly reached."); Console.Write("\nERROR: End of track unexpectedly reached (TrackReader.cs ParseChannelMessage)"); return; } // FAB : 07/08/2014 if (trackData[trackIndex] <= 127) { cmBuilder.Data2 = trackData[trackIndex]; } else { cmBuilder.Data2 = 127; } if (cmBuilder.Data1 == 0x07) { // Volume de la piste newTrack.Volume = cmBuilder.Data2; } else if (cmBuilder.Data1 == 0x5B) { // Reverb 91 // FAB 2017 newTrack.Reverb = cmBuilder.Data2; } else if (cmBuilder.Data1 == 0x0A) { // pan 10 // FAB 2017 newTrack.Pan = cmBuilder.Data2; } // Collecte des notes if (cmBuilder.Command == ChannelCommand.NoteOn) { newTrack.ContainsNotes = true; newTrack.Visible = true; // Data1 = Note number // Data2 = Velocity if (ticks >= 0 && cmBuilder.Data2 > 0) { // FAB : // Add a MidiNote to this track. This is called for each NoteOn event */ newTrack.MidiChannel = cmBuilder.MidiChannel; MidiNote note = new MidiNote(ticks, newTrack.MidiChannel, cmBuilder.Data1, 0, cmBuilder.Data2, false); newTrack.Notes.Add(note); } else { // FAB if (newTrack.Notes.Count > 0) { newTrack.MidiChannel = cmBuilder.MidiChannel; NoteOff(newTrack.MidiChannel, cmBuilder.Data1, ticks); } } } else if (ticks >= 0 && cmBuilder.Command == ChannelCommand.NoteOff) { // FAB newTrack.ContainsNotes = true; newTrack.Visible = true; newTrack.MidiChannel = cmBuilder.MidiChannel; NoteOff(newTrack.MidiChannel, cmBuilder.Data1, ticks); } trackIndex++; } cmBuilder.Build(); newTrack.Insert(ticks, cmBuilder.Result); runningStatus = status; }
private void Message(ChannelMessage message) { _track.Insert((int)_player.ElapsedTicks, message); }
private void SetMIDITempo() { Track setTempoTrack = new Track(); setTempoTrack.Insert(0, new MetaMessage(MetaType.TimeSignature, TimeSignatureData)); setTempoTrack.Insert(0, new MetaMessage(MetaType.Tempo, SetTempoData)); sequence.Add(setTempoTrack); }
internal void SaveAsMIDI(string fileName) { if (NumTracks == 0) { throw new InvalidDataException("This song has no tracks."); } if (ROM.Instance.Game.Engine.Type != EngineType.M4A) { throw new PlatformNotSupportedException("Exporting to MIDI from this game engine is not supported at this time."); } CalculateTicks(); var midi = new Sequence(Engine.GetTicksPerBar() / 4) { Format = 2 }; for (int i = 0; i < NumTracks; i++) { var track = new Sanford.Multimedia.Midi.Track(); midi.Add(track); int endOfPattern = 0, startOfPatternTicks = 0, endOfPatternTicks = 0, shift = 0; var playing = new List <M4ANoteCommand>(); for (int j = 0; j < Commands[i].Count; j++) { var e = Commands[i][j]; int ticks = (int)(e.AbsoluteTicks + (endOfPatternTicks - startOfPatternTicks)); if (e.Command is KeyShiftCommand keysh) { shift = keysh.Shift; } else if (e.Command is M4ANoteCommand note) { int n = (note.Note + shift).Clamp(0, 127); track.Insert(ticks, new ChannelMessage(ChannelCommand.NoteOn, i, n, note.Velocity)); if (note.Duration != -1) { track.Insert(ticks + note.Duration, new ChannelMessage(ChannelCommand.NoteOff, i, n)); } else { playing.Add(note); } } else if (e.Command is EndOfTieCommand eot) { M4ANoteCommand nc = null; if (eot.Note == -1) { nc = playing.LastOrDefault(); } else { nc = playing.LastOrDefault(n => n.Note == eot.Note); } if (nc != null) { int no = (nc.Note + shift).Clamp(0, 127); track.Insert(ticks, new ChannelMessage(ChannelCommand.NoteOff, i, no)); playing.Remove(nc); } } else if (e.Command is VoiceCommand voice) { track.Insert(ticks, new ChannelMessage(ChannelCommand.ProgramChange, i, voice.Voice)); } else if (e.Command is VolumeCommand vol) { track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, (int)ControllerType.Volume, vol.Volume)); } else if (e.Command is PanpotCommand pan) { track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, (int)ControllerType.Pan, pan.Panpot + 0x40)); } else if (e.Command is BendCommand bend) { track.Insert(ticks, new ChannelMessage(ChannelCommand.PitchWheel, i, 0, bend.Bend + 0x40)); } else if (e.Command is BendRangeCommand bendr) { track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, 20, bendr.Range)); } else if (e.Command is LFOSpeedCommand lfos) { track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, 21, lfos.Speed)); } else if (e.Command is LFODelayCommand lfodl) { track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, 26, lfodl.Delay)); } else if (e.Command is ModDepthCommand mod) { track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, (int)ControllerType.ModulationWheel, mod.Depth)); } else if (e.Command is ModTypeCommand modt) { track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, 22, modt.Type)); } else if (e.Command is TuneCommand tune) { track.Insert(ticks, new ChannelMessage(ChannelCommand.Controller, i, 24, tune.Tune)); } else if (e.Command is TempoCommand tempo) { var change = new TempoChangeBuilder { Tempo = (60000000 / tempo.Tempo) }; change.Build(); track.Insert(ticks, change.Result); } else if (e.Command is CallCommand patt) { int callCmd = Commands[i].FindIndex(c => c.Offset == patt.Offset); endOfPattern = j; endOfPatternTicks = (int)e.AbsoluteTicks; j = callCmd - 1; // -1 for incoming ++ startOfPatternTicks = (int)Commands[i][j + 1].AbsoluteTicks; } else if (e.Command is ReturnCommand) { if (endOfPattern != 0) { j = endOfPattern; endOfPattern = startOfPatternTicks = endOfPatternTicks = 0; } } else if (i == 0 && e.Command is GoToCommand goTo) { track.Insert(ticks, new MetaMessage(MetaType.Marker, new byte[] { (byte)']' })); int jumpCmd = Commands[i].FindIndex(c => c.Offset == goTo.Offset); track.Insert((int)Commands[i][jumpCmd].AbsoluteTicks, new MetaMessage(MetaType.Marker, new byte[] { (byte)'[' })); } else if (e.Command is FinishCommand fine) { track.Insert(ticks, new MetaMessage(MetaType.EndOfTrack, new byte[0])); break; } } } midi.Save(fileName); }