Ejemplo n.º 1
0
        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;
            }
        }
Ejemplo n.º 2
0
        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);
        }