public MIDIFile(double BPM) { Header = new MIDIHeader(); TrackChunks = new List <MIDITrackChunk>(); var FirstTrack = new MIDITrackChunk(0, ""); FirstTrack.MTrkEvents.Add(new MTrkEvent(0) { Event = new TimeSignatureMetaEvent() }); FirstTrack.MTrkEvents.Add(new MTrkEvent(0) { Event = new KeySignatureMetaEvent() }); FirstTrack.MTrkEvents.Add(new MTrkEvent(0) { Event = new SMPTEOffsetMetaEvent() }); FirstTrack.MTrkEvents.Add(new MTrkEvent(0) { Event = new SetTempoMetaEvent(BPM) }); TrackChunks.Add(FirstTrack); }
public MIDIFile(string fileName) { var arr = File.ReadAllBytes(fileName); Header = new MIDIHeader(arr); var counter = 0; while (counter + 14 < arr.Length) { var tc = new MIDITrackChunk(arr.Skip(14 + counter).ToArray()); TrackChunks.Add(tc); counter += (int)tc.Size + 8; } }
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); }