public MIDITrackChunk(byte[] arr) { if (Encoding.ASCII.GetString(arr.Take(4).ToArray()) != MIDITrackChunkType) { throw new Exception("Track Chunk Type is not " + MIDITrackChunkType); } Size = BitConverter.ToUInt32(arr.Skip(4).Take(4).Reverse().ToArray(), 0); var toParse = 0; while (toParse < Size) { var ev = new MTrkEvent(arr.Skip(8 + toParse).ToArray()); MTrkEvents.Add(ev); toParse += ev.ToBytes().Length; } var firstEvent = (MIDIEvent)(MTrkEvents.Where(x => x.Event is MIDIEvent).Select(x => x.Event).FirstOrDefault()); if (firstEvent != null) { Channel = firstEvent.Channel; } }
public static void ParseTracks(string f, string outFile) { var lso = LSOFile.LSOFactory(f); lso.ParseFile(); MIDIFile mf = new MIDIFile(lso.BPM); foreach (var tempo in lso.GlobalTempo) { mf.TrackChunks[0].MTrkEvents.Add(new MTrkEvent((uint)(tempo.Timing / 2)) { Event = new SetTempoMetaEvent((double)((double)tempo.Tempo / (double)10000)) }); } foreach (var channel in lso.Channels) { var tracksInChannel = channel.Value.OrderBy(x => x.TrackPosition).ToList(); foreach (var track in tracksInChannel) { var Sequencer = new List <Sequence>(); MIDITrackChunk midiTrack = null; midiTrack = new MIDITrackChunk(track.Channel, track.TrackName); midiTrack.MTrkEvents.Add(new MTrkEvent(0) { Event = new ProgramChangeEvent(track.Channel, track.InitialInstrument) }); int lastTime = 0; // Check for track loop and duplicate until next track if (track.IsLoopTrack && track.MIDIEvents.Count() > 0) { var trackIndex = tracksInChannel.IndexOf(track); var isTrackLastOne = trackIndex == tracksInChannel.Count() - 1; var stopLoopPosition = isTrackLastOne ? lso.SongLength : tracksInChannel[trackIndex + 1].TrackPosition; // replicate track data until stop var currentEvents = track.MIDIEvents.ToList(); var currentTime = track.TrackLength; var currentMIDIEvent = currentEvents.First(); var totalMidiInCurrentEvents = currentEvents.Count() - 1; var multiplier = 1; for (int midiEventIndex = 0; currentTime < stopLoopPosition; midiEventIndex++) { currentMIDIEvent = currentEvents[midiEventIndex].Clone(); var eventNewTime = currentMIDIEvent.Position + (track.TrackLength * multiplier); if (eventNewTime >= stopLoopPosition) { break; } currentMIDIEvent.Position = eventNewTime; track.MIDIEvents.Add(currentMIDIEvent); if (midiEventIndex == totalMidiInCurrentEvents) { multiplier++; midiEventIndex = -1; } currentTime = eventNewTime; } } foreach (var lme in track.MIDIEvents) { var del = track.TrackPosition + lme.Position; if (lme.MIDIFirstByte == 0xB0) { // Instrument Change Sequencer.Add(new Sequence() { eType = EvType.ControllerEvent, MLE = lme, Time = del, Channel = (byte)track.Channel, Note = lme.MIDISecondByte }); continue; } if (lme.MIDIFirstByte == 0xC0) { // Instrument Change Sequencer.Add(new Sequence() { eType = EvType.ProgramChangeEvent, MLE = lme, Time = del, Channel = (byte)track.Channel, Note = lme.MIDIThirdByte }); continue; } if (lme.MIDIFirstByte == 0xE0) { // Pitch Bend Sequencer.Add(new Sequence() { eType = EvType.PitchBend, MLE = lme, Time = del, Channel = (byte)track.Channel, Note = lme.MIDISecondByte, ThirdByte = lme.MIDIThirdByte }); continue; } // Note On Sequencer.Add(new Sequence() { eType = EvType.NoteOn, MLE = lme, Time = del, Channel = (byte)track.Channel, Note = lme.MIDISecondByte }); // Note Off Sequencer.Add(new Sequence() { eType = EvType.NoteOff, MLE = lme, Time = del + lme.MIDILength, Channel = (byte)track.Channel, Note = lme.MIDISecondByte }); } Sequencer = Sequencer.OrderBy(x => x.Time).ToList(); // Add MIDI Events foreach (var seq in Sequencer) { var delta = ((uint)(seq.Time - lastTime)) / 2; MTrkEvent midiMtrkEvent = null; switch (seq.eType) { case EvType.NoteOn: midiMtrkEvent = new MTrkEvent(delta); midiMtrkEvent.Event = new MIDIEventNoteOn(seq.Channel, seq.MLE.MIDISecondByte, seq.MLE.MIDIThirdByte); midiTrack.MTrkEvents.Add(midiMtrkEvent); break; case EvType.NoteOff: midiMtrkEvent = new MTrkEvent(delta); midiMtrkEvent.Event = new MIDIEventNoteOn(seq.Channel, seq.MLE.MIDISecondByte, 0); midiTrack.MTrkEvents.Add(midiMtrkEvent); break; case EvType.ProgramChangeEvent: midiMtrkEvent = new MTrkEvent(delta); midiMtrkEvent.Event = new ProgramChangeEvent(seq.Channel, seq.MLE.MIDIThirdByte); midiTrack.MTrkEvents.Add(midiMtrkEvent); break; case EvType.PitchBend: midiMtrkEvent = new MTrkEvent(delta); midiMtrkEvent.Event = new PitchBendEvent(seq.Channel, seq.MLE.MIDIFirstByte, seq.MLE.MIDIThirdByte); midiTrack.MTrkEvents.Add(midiMtrkEvent); break; case EvType.ControllerEvent: midiMtrkEvent = new MTrkEvent(delta); midiMtrkEvent.Event = new ControllerEvent(seq.Channel, seq.MLE.MIDISecondByte, seq.MLE.MIDIThirdByte); midiTrack.MTrkEvents.Add(midiMtrkEvent); break; } lastTime = seq.Time; } mf.TrackChunks.Add(midiTrack); } } var midiFile = mf.ToBytes(); File.WriteAllBytes(outFile, midiFile); }