Exemple #1
0
        private static void RandomlyPlaystuff()
        {
            int    midiOutDevice = 0; // GS Wavetable Synth
            Random r             = new Random();

            Dictionary <string, NoteOnEvent> currentlyPlaying = new Dictionary <string, NoteOnEvent>();


            using (var midiOut = new MidiOut(midiOutDevice))
            {
                // first lets set the patches for channels 1-9
                for (int i = 1; i <= 9; i++)
                {
                    var patchChange = new PatchChangeEvent(0, i, (i - 1) * 8);
                    midiOut.Send(patchChange.GetAsShortMessage());
                }
                // Okay, now lets figure out where our things are at

                for (int i = 0; i < 100; i++)
                {
                    int noteToPlay     = r.Next(20, 100);
                    int velocityToPlay = r.Next(50, 100);
                    int channel        = r.Next(1, 2); // channel indicates patch

                    string hash = $"{channel}";

                    NoteOnEvent existingNoteOn;
                    if (currentlyPlaying.TryGetValue(hash, out existingNoteOn))
                    {
                        midiOut.Send(existingNoteOn.OffEvent.GetAsShortMessage());
                        currentlyPlaying.Remove(hash);
                    }

                    var noteOn = new NoteOnEvent(0, channel, noteToPlay, velocityToPlay, 0);
                    midiOut.Send(noteOn.GetAsShortMessage());
                    Console.ReadLine();
                }
                foreach (var existingNote in currentlyPlaying.Values)
                {
                    midiOut.Send(existingNote.OffEvent.GetAsShortMessage());
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Return information about a midifile : patch change, copyright, ...
        /// </summary>
        /// <param name="pathfilename"></param>
        /// <param name="Info"></param>
        static public void GeneralInfo(string pathfilename, BuilderInfo Info)
        {
            try
            {
                int NumberBeatsMeasure;
                int NumberQuarterBeat;
                Debug.Log("Open midifile :" + pathfilename);
                MidiLoad midifile = new MidiLoad();
                midifile.Load(pathfilename);
                if (midifile != null)
                {
                    Info.Add(string.Format("Format: {0}", midifile.midifile.FileFormat));
                    Info.Add(string.Format("Tracks: {0}", midifile.midifile.Tracks));
                    Info.Add(string.Format("Ticks Quarter Note: {0}", midifile.midifile.DeltaTicksPerQuarterNote));

                    //if (false)
                    {
                        foreach (TrackMidiEvent trackEvent in midifile.MidiSorted)
                        {
                            if (trackEvent.Event.CommandCode == MidiCommandCode.NoteOn)
                            {
                                // Not used
                                //if (((NoteOnEvent)trackEvent.Event).OffEvent != null)
                                //{
                                //    //infoTrackMidi[e.Channel].Events.Add((NoteOnEvent)e);
                                //    NoteOnEvent noteon = (NoteOnEvent)trackEvent.Event;
                                //}
                            }
                            else if (trackEvent.Event.CommandCode == MidiCommandCode.NoteOff)
                            {
                                Debug.Log("NoteOff");
                            }
                            else if (trackEvent.Event.CommandCode == MidiCommandCode.ControlChange)
                            {
                                // Not used
                                //ControlChangeEvent controlchange = (ControlChangeEvent)e;
                                //Debug.Log(string.Format("CtrlChange  Track:{0} Channel:{1,2:00} {2}", track, e.Channel, controlchange.ToString()));
                            }
                            else if (trackEvent.Event.CommandCode == MidiCommandCode.PatchChange)
                            {
                                PatchChangeEvent change = (PatchChangeEvent)trackEvent.Event;
                                Info.Add(BuildInfoTrack(trackEvent) + string.Format("PatchChange {0,3:000} {1}", change.Patch, PatchChangeEvent.GetPatchName(change.Patch)), 2);
                            }
                            else if (trackEvent.Event.CommandCode == MidiCommandCode.MetaEvent)
                            {
                                MetaEvent meta = (MetaEvent)trackEvent.Event;
                                switch (meta.MetaEventType)
                                {
                                case MetaEventType.SetTempo:
                                    TempoEvent tempo = (TempoEvent)meta;
                                    Info.Add(BuildInfoTrack(trackEvent) + string.Format("SetTempo Tempo:{0} MicrosecondsPerQuarterNote:{1}", Math.Round(tempo.Tempo, 0), tempo.MicrosecondsPerQuarterNote), 2);
                                    //tempo.Tempo
                                    break;

                                case MetaEventType.TimeSignature:

                                    TimeSignatureEvent timesig = (TimeSignatureEvent)meta;
                                    // Numerator: counts the number of beats in a measure.
                                    // For example a numerator of 4 means that each bar contains four beats.

                                    // Denominator: number of quarter notes in a beat.0=ronde, 1=blanche, 2=quarter, 3=eighth, etc.
                                    // Set default value
                                    NumberBeatsMeasure = timesig.Numerator;
                                    NumberQuarterBeat  = System.Convert.ToInt32(System.Math.Pow(2, timesig.Denominator));
                                    Info.Add(BuildInfoTrack(trackEvent) + string.Format("TimeSignature Beats Measure:{0} Beat Quarter:{1}", NumberBeatsMeasure, NumberQuarterBeat), 2);
                                    break;

                                case MetaEventType.SequenceTrackName:   // Sequence / Track Name
                                case MetaEventType.ProgramName:
                                case MetaEventType.TrackInstrumentName: // Track instrument name
                                case MetaEventType.TextEvent:           // Text event
                                case MetaEventType.Copyright:           // Copyright
                                    Info.Add(BuildInfoTrack(trackEvent) + ((TextEvent)meta).Text, 1);
                                    break;

                                case MetaEventType.Lyric:     // lyric
                                case MetaEventType.Marker:    // marker
                                case MetaEventType.CuePoint:  // cue point
                                case MetaEventType.DeviceName:
                                    //Info.Add(BuildInfoTrack(trackEvent) + string.Format("{0} '{1}'", meta.MetaEventType.ToString(), ((TextEvent)meta).Text));
                                    break;
                                }
                            }
                            else
                            {
                                // Other midi event
                                //Debug.Log(string.Format("Track:{0} Channel:{1,2:00} CommandCode:{2,3:000} AbsoluteTime:{3,6:000000}", track, e.Channel, e.CommandCode.ToString(), e.AbsoluteTime));
                            }
                        }
                    }
                    //else DebugMidiSorted(midifile.MidiSorted);
                }
                else
                {
                    Info.Add("Error reading midi file");
                }
            }
            catch (System.Exception ex)
            {
                MidiPlayerGlobal.ErrorDetail(ex);
            }
        }
Exemple #3
0
        /// <summary>
        /// Convert neb steps to midi file.
        /// </summary>
        /// <param name="steps"></param>
        /// <param name="midiFileName"></param>
        /// <param name="channels">Map of channel number to channel name.</param>
        /// <param name="bpm">Beats per minute.</param>
        /// <param name="info">Extra info to add to midi file.</param>
        public static void ExportToMidi(StepCollection steps, string midiFileName, Dictionary <int, string> channels, double bpm, string info)
        {
            int exportPpq = 96;

            // Events per track.
            Dictionary <int, IList <MidiEvent> > trackEvents = new();

            ///// Meta file stuff.
            MidiEventCollection events = new(1, exportPpq);

            ///// Add Header chunk stuff.
            IList <MidiEvent> lhdr = events.AddTrack();

            //lhdr.Add(new TimeSignatureEvent(0, 4, 2, (int)ticksPerClick, 8));
            //TimeSignatureEvent me = new TimeSignatureEvent(long absoluteTime, int numerator, int denominator, int ticksInMetronomeClick, int no32ndNotesInQuarterNote);
            //  - numerator of the time signature (as notated).
            //  - denominator of the time signature as a negative power of 2 (ie 2 represents a quarter-note, 3 represents an eighth-note, etc).
            //  - number of MIDI clocks between metronome clicks.
            //  - number of notated 32nd-notes in a MIDI quarter-note (24 MIDI Clocks). The usual value for this parameter is 8.

            //lhdr.Add(new KeySignatureEvent(0, 0, 0));
            //  - number of flats (-ve) or sharps (+ve) that identifies the key signature (-7 = 7 flats, -1 = 1 //flat, 0 = key of C, 1 = 1 sharp, etc).
            //  - major (0) or minor (1) key.
            //  - abs time.

            // Tempo.
            lhdr.Add(new TempoEvent(0, 0)
            {
                Tempo = bpm
            });

            // General info.
            lhdr.Add(new TextEvent("Midi file created by Nebulator.", MetaEventType.TextEvent, 0));
            lhdr.Add(new TextEvent(info, MetaEventType.TextEvent, 0));

            lhdr.Add(new MetaEvent(MetaEventType.EndTrack, 0, 0));

            ///// Make one midi event collection per track.
            foreach (int channel in channels.Keys)
            {
                IList <MidiEvent> le = events.AddTrack();
                trackEvents.Add(channel, le);
                le.Add(new TextEvent(channels[channel], MetaEventType.SequenceTrackName, 0));
                // >> 0 SequenceTrackName G.MIDI Acou Bass
            }

            // Make a transformer.
            MidiTime mt = new()
            {
                InternalPpq = Time.SubdivsPerBeat,
                MidiPpq     = exportPpq,
                Tempo       = bpm
            };

            // Run through the main steps and create a midi event per.
            foreach (Time time in steps.Times)
            {
                long mtime = mt.InternalToMidi(time.TotalSubdivs);

                foreach (Step step in steps.GetSteps(time))
                {
                    MidiEvent evt;

                    switch (step)
                    {
                    case StepNoteOn stt:
                        evt = new NoteEvent(mtime,
                                            stt.ChannelNumber,
                                            MidiCommandCode.NoteOn,
                                            (int)MathUtils.Constrain(stt.NoteNumber, 0, Definitions.MAX_MIDI),
                                            (int)(MathUtils.Constrain(stt.VelocityToPlay, 0, 1.0) * Definitions.MAX_MIDI));
                        trackEvents[step.ChannelNumber].Add(evt);

                        if (stt.Duration.TotalSubdivs > 0)     // specific duration
                        {
                            evt = new NoteEvent(mtime + mt.InternalToMidi(stt.Duration.TotalSubdivs),
                                                stt.ChannelNumber,
                                                MidiCommandCode.NoteOff,
                                                (int)MathUtils.Constrain(stt.NoteNumber, 0, Definitions.MAX_MIDI),
                                                0);
                            trackEvents[step.ChannelNumber].Add(evt);
                        }
                        break;

                    case StepNoteOff stt:
                        evt = new NoteEvent(mtime,
                                            stt.ChannelNumber,
                                            MidiCommandCode.NoteOff,
                                            (int)MathUtils.Constrain(stt.NoteNumber, 0, Definitions.MAX_MIDI),
                                            0);
                        trackEvents[step.ChannelNumber].Add(evt);
                        break;

                    case StepControllerChange stt:
                        if (stt.ControllerId == ControllerDef.NoteControl)
                        {
                            // Shouldn't happen, ignore.
                        }
                        else if (stt.ControllerId == ControllerDef.PitchControl)
                        {
                            evt = new PitchWheelChangeEvent(mtime,
                                                            stt.ChannelNumber,
                                                            (int)MathUtils.Constrain(stt.Value, 0, Definitions.MAX_MIDI));
                            trackEvents[step.ChannelNumber].Add(evt);
                        }
                        else     // CC
                        {
                            evt = new ControlChangeEvent(mtime,
                                                         stt.ChannelNumber,
                                                         (MidiController)stt.ControllerId,
                                                         (int)MathUtils.Constrain(stt.Value, 0, Definitions.MAX_MIDI));
                            trackEvents[step.ChannelNumber].Add(evt);
                        }
                        break;

                    case StepPatch stt:
                        evt = new PatchChangeEvent(mtime,
                                                   stt.ChannelNumber,
                                                   (int)stt.Patch);
                        trackEvents[step.ChannelNumber].Add(evt);
                        break;

                    default:
                        break;
                    }
                }
            }

            // Finish up channels with end marker.
            foreach (IList <MidiEvent> let in trackEvents.Values)
            {
                long ltime = let.Last().AbsoluteTime;
                let.Add(new MetaEvent(MetaEventType.EndTrack, 0, ltime));
            }

            MidiFile.Export(midiFileName, events);
        }
    }
Exemple #4
0
        public void Load(string path)
        {
            LoadedMidi = new MidiFile(path, false);
            // Parse the midi for info; we want to start by getting a list of all the channels
            // We also need to know the highest and lowest note for each Instrument/Channel (screw tracks)
            // And of course, that gives us overall highest/lowest
            MidiChannelMap = new Dictionary <int, MidiChannel>();
            MidiTrackMap   = new Dictionary <int, MidiTrack>();
            MidiChannels   = new List <MidiChannel>();
            MidiTracks     = new List <MidiTrack>();

            for (int i = 0; i < LoadedMidi.Tracks; i++)
            {
                var newTrack = new MidiTrack("Untitled", i);
                MidiTrackMap[i] = newTrack;
                MidiTracks.Add(newTrack);
                var e = LoadedMidi.Events[i];
                foreach (var ie in e)
                {
                    if (ie is TextEvent)
                    {
                        var me = ie as TextEvent;
                        if (me.MetaEventType == MetaEventType.SequenceTrackName)
                        {
                            MidiTrackMap[i].TrackName = me.Text;
                        }
                    }
                    else if (ie is PatchChangeEvent)
                    {
                        // These are the correct events, they happen at the start to set the instrument for a channel
                        // Note that specifically channel 10 is usually interpreted as drums, and the instrument they set on it is arbitrary
                        var    patchChange    = ie as PatchChangeEvent;
                        string instrumentName = "Drums";
                        if (ie.Channel != 10)
                        {
                            instrumentName = PatchChangeEvent.GetPatchName(patchChange.Patch);
                        }
                        var channel = new MidiChannel(instrumentName, ie.Channel);
                        MidiChannelMap[ie.Channel] = channel;
                        MidiChannels.Add(channel);
                    }
                    else if (ie is NoteOnEvent)
                    {
                        var         noteEvent = ie as NoteOnEvent;
                        MidiChannel channel;
                        if (!MidiChannelMap.ContainsKey(ie.Channel))
                        {
                            // We got a note for a channel that never had an instrument set
                            // Initialize it as piano
                            channel = new MidiChannel("Piano (Default)", ie.Channel);
                            MidiChannelMap[ie.Channel] = channel;
                            MidiChannels.Add(channel);
                        }
                        else
                        {
                            channel = MidiChannelMap[ie.Channel];
                        }

                        // If the OffEvent is null, that means this is itself an off event... otherwise it links to the one that ends it
                        if (noteEvent.OffEvent != null && noteEvent.Velocity > 0)
                        {
                            if (channel.HighestNote == null || noteEvent.NoteNumber > channel.HighestNote.Number)
                            {
                                channel.HighestNote = new MidiNote(noteEvent.NoteNumber);
                            }
                            if (channel.LowestNote == null || noteEvent.NoteNumber < channel.LowestNote.Number)
                            {
                                channel.LowestNote = new MidiNote(noteEvent.NoteNumber);
                            }
                        }
                    }
                }
            }
        }
Exemple #5
0
        /// <summary>
        /// Return information about a midifile : patch change, copyright, ...
        /// </summary>
        /// <param name="pathfilename"></param>
        /// <param name="Info"></param>
        static public List <string> GeneralInfo(string pathfilename, bool withNoteOn, bool withNoteOff, bool withControlChange, bool withPatchChange, bool withAfterTouch, bool withMeta, bool withOthers)
        {
            List <string> Info = new List <string>();

            try
            {
                int      NumberBeatsMeasure;
                int      NumberQuarterBeat;
                MidiLoad midifile = new MidiLoad();
                midifile.KeepNoteOff = withNoteOff;
                midifile.MPTK_Load(pathfilename);
                if (midifile != null)
                {
                    Info.Add(string.Format("Format: {0}", midifile.midifile.FileFormat));
                    Info.Add(string.Format("Tracks: {0}", midifile.midifile.Tracks));
                    Info.Add(string.Format("Events count: {0}", midifile.MidiSorted.Count()));
                    Info.Add(string.Format("Duration: {0} ({1} seconds) {2} Ticks", midifile.MPTK_RealDuration, midifile.MPTK_RealDuration.TotalSeconds, midifile.MPTK_TickLast));
                    Info.Add(string.Format("Initial Tempo: {0,0:F2} BPM", midifile.MPTK_InitialTempo));
                    Info.Add(string.Format("Beats in a measure: {0}", midifile.MPTK_NumberBeatsMeasure));
                    Info.Add(string.Format("Quarters count in a beat:{0}", midifile.MPTK_NumberQuarterBeat));
                    Info.Add(string.Format("Ticks per Quarter Note: {0}", midifile.midifile.DeltaTicksPerQuarterNote));
                    Info.Add("");
                    //if (false)
                    {
                        foreach (TrackMidiEvent trackEvent in midifile.MidiSorted)
                        {
                            switch (trackEvent.Event.CommandCode)
                            {
                            case MidiCommandCode.NoteOn:
                                if (withNoteOn)
                                {
                                    if (((NoteOnEvent)trackEvent.Event).OffEvent != null)
                                    {
                                        NoteOnEvent noteon = (NoteOnEvent)trackEvent.Event;
                                        Info.Add(BuildInfoTrack(trackEvent) + string.Format("NoteOn {0,3} ({1,3}) Len:{2,3} Vel:{3,3}", noteon.NoteName, noteon.NoteNumber, noteon.NoteLength, noteon.Velocity));
                                    }
                                }
                                break;

                            case MidiCommandCode.NoteOff:
                                if (withNoteOff)
                                {
                                    NoteEvent noteoff = (NoteEvent)trackEvent.Event;
                                    Info.Add(BuildInfoTrack(trackEvent) + string.Format("NoteOff {0,3} ({1,3}) Vel:{2,3}", noteoff.NoteName, noteoff.NoteNumber, noteoff.Velocity));
                                }
                                break;

                            case MidiCommandCode.PitchWheelChange:
                                if (withOthers)
                                {
                                    PitchWheelChangeEvent aftertouch = (PitchWheelChangeEvent)trackEvent.Event;
                                    Info.Add(BuildInfoTrack(trackEvent) + string.Format("PitchWheelChange {0,3}", aftertouch.Pitch));
                                }
                                break;

                            case MidiCommandCode.KeyAfterTouch:
                                if (withAfterTouch)
                                {
                                    NoteEvent aftertouch = (NoteEvent)trackEvent.Event;
                                    Info.Add(BuildInfoTrack(trackEvent) + string.Format("KeyAfterTouch {0,3} ({1,3}) Pressure:{2,3}", aftertouch.NoteName, aftertouch.NoteNumber, aftertouch.Velocity));
                                }
                                break;

                            case MidiCommandCode.ChannelAfterTouch:
                                if (withAfterTouch)
                                {
                                    ChannelAfterTouchEvent aftertouch = (ChannelAfterTouchEvent)trackEvent.Event;
                                    Info.Add(BuildInfoTrack(trackEvent) + string.Format("ChannelAfterTouch Pressure:{0,3}", aftertouch.AfterTouchPressure));
                                }
                                break;

                            case MidiCommandCode.ControlChange:
                                if (withControlChange)
                                {
                                    ControlChangeEvent controlchange = (ControlChangeEvent)trackEvent.Event;
                                    Info.Add(BuildInfoTrack(trackEvent) + string.Format("ControlChange {0,3} ({1,3}) Value:{2,3}", controlchange.Controller, controlchange.Controller, controlchange.ControllerValue));
                                }
                                break;

                            case MidiCommandCode.PatchChange:
                                if (withPatchChange)
                                {
                                    PatchChangeEvent change = (PatchChangeEvent)trackEvent.Event;
                                    Info.Add(BuildInfoTrack(trackEvent) + string.Format("PatchChange {0,3:000} {1}", change.Patch, PatchChangeEvent.GetPatchName(change.Patch)));
                                }
                                break;

                            case MidiCommandCode.MetaEvent:
                                if (withMeta)
                                {
                                    MetaEvent meta = (MetaEvent)trackEvent.Event;
                                    switch (meta.MetaEventType)
                                    {
                                    case MetaEventType.SetTempo:
                                        TempoEvent tempo = (TempoEvent)meta;
                                        Info.Add(BuildInfoTrack(trackEvent) + string.Format("SetTempo Tempo:{0} MicrosecondsPerQuarterNote:{1}", Math.Round(tempo.Tempo, 0), tempo.MicrosecondsPerQuarterNote));
                                        //tempo.Tempo
                                        break;

                                    case MetaEventType.TimeSignature:
                                        TimeSignatureEvent timesig = (TimeSignatureEvent)meta;
                                        // Numerator: counts the number of beats in a measure.
                                        // For example a numerator of 4 means that each bar contains four beats.

                                        // Denominator: number of quarter notes in a beat.0=ronde, 1=blanche, 2=quarter, 3=eighth, etc.
                                        // Set default value
                                        NumberBeatsMeasure = timesig.Numerator;
                                        NumberQuarterBeat  = System.Convert.ToInt32(Mathf.Pow(2, timesig.Denominator));
                                        Info.Add(BuildInfoTrack(trackEvent) + string.Format("TimeSignature Beats Measure:{0} Beat Quarter:{1}", NumberBeatsMeasure, NumberQuarterBeat));
                                        break;

                                    default:
                                        string text = meta is TextEvent ? " '" + ((TextEvent)meta).Text + "'" : "";
                                        Info.Add(BuildInfoTrack(trackEvent) + meta.MetaEventType.ToString() + text);
                                        break;
                                    }
                                }
                                break;

                            default:
                                // Other midi event
                                if (withOthers)
                                {
                                    Info.Add(BuildInfoTrack(trackEvent) + string.Format(" {0} ({1})", trackEvent.Event.CommandCode, (int)trackEvent.Event.CommandCode));
                                }
                                break;
                            }
                        }
                    }
                    //else DebugMidiSorted(midifile.MidiSorted);
                }
                else
                {
                    Info.Add("Error reading midi file");
                }
            }
            catch (System.Exception ex)
            {
                MidiPlayerGlobal.ErrorDetail(ex);
            }
            return(Info);
        }
        /// <summary>
        /// Read midi event Tempo and Patch change from start
        /// </summary>
        /// <param name="timeFromStartMS"></param>
        /// <returns></returns>
        public List <MPTKEvent> ReadChangeFromStart(int position)
        {
            List <MPTKEvent> midievents = new List <MPTKEvent>();;

            try
            {
                if (midifile != null)
                {
                    if (position < 0 || position >= MidiSorted.Count)
                    {
                        position = MidiSorted.Count - 1;
                    }

                    for (int currentPosEvent = 0; currentPosEvent < position; currentPosEvent++)
                    {
                        TrackMidiEvent trackEvent = MidiSorted[currentPosEvent];
                        MPTKEvent      midievent  = null;
                        switch (trackEvent.Event.CommandCode)
                        {
                        case MidiCommandCode.ControlChange:
                            ControlChangeEvent controlchange = (ControlChangeEvent)trackEvent.Event;
                            midievent = new MPTKEvent()
                            {
                                Tick       = trackEvent.AbsoluteQuantize,
                                Command    = MPTKCommand.ControlChange,
                                Channel    = trackEvent.Event.Channel - 1,
                                Controller = (MPTKController)controlchange.Controller,
                                Value      = controlchange.ControllerValue,
                            };
                            break;

                        case MidiCommandCode.PatchChange:
                            PatchChangeEvent change = (PatchChangeEvent)trackEvent.Event;
                            midievent = new MPTKEvent()
                            {
                                Tick    = trackEvent.AbsoluteQuantize,
                                Command = MPTKCommand.PatchChange,
                                Channel = trackEvent.Event.Channel - 1,
                                Value   = change.Patch,
                            };
                            break;

                        case MidiCommandCode.MetaEvent:
                            MetaEvent meta = (MetaEvent)trackEvent.Event;
                            if (meta.MetaEventType == MetaEventType.SetTempo)
                            {
                                TempoEvent tempo = (TempoEvent)meta;
                                midievent = new MPTKEvent()
                                {
                                    Tick     = trackEvent.AbsoluteQuantize,
                                    Command  = MPTKCommand.MetaEvent,
                                    Channel  = trackEvent.Event.Channel - 1,
                                    Meta     = (MPTKMeta)meta.MetaEventType,
                                    Duration = tempo.Tempo,
                                };
                            }
                            break;
                        }
                        if (midievent != null)
                        {
                            midievents.Add(midievent);
                        }
                    }
                }
            }
            catch (System.Exception ex)
            {
                MidiPlayerGlobal.ErrorDetail(ex);
            }
            return(midievents);
        }
        /// <summary>
        /// Add a TrackMidiEvent to a list of MPTKEvent.
        /// </summary>
        /// <param name="mptkEvents">Must be alloc before the call</param>
        /// <param name="trackEvent"></param>
        /// <returns></returns>

        private bool ConvertToEventForNote(List <MPTKEvent> mptkEvents, TrackMidiEvent trackEvent)
        {
            bool      exitLoop  = false;
            MPTKEvent midievent = null;

            switch (trackEvent.Event.CommandCode)
            {
            case MidiCommandCode.NoteOn:

                if (((NoteOnEvent)trackEvent.Event).OffEvent != null)
                {
                    NoteOnEvent noteon = (NoteOnEvent)trackEvent.Event;
                    //Debug.Log(string.Format("Track:{0} NoteNumber:{1,3:000} AbsoluteTime:{2,6:000000} NoteLength:{3,6:000000} OffDeltaTime:{4,6:000000} ", track, noteon.NoteNumber, noteon.AbsoluteTime, noteon.NoteLength, noteon.OffEvent.DeltaTime));
                    if (noteon.NoteLength > 0)
                    {
                        midievent = new MPTKEvent()
                        {
                            Tick     = trackEvent.AbsoluteQuantize,
                            Command  = MPTKCommand.NoteOn,
                            Value    = noteon.NoteNumber,
                            Channel  = trackEvent.Event.Channel - 1,
                            Velocity = noteon.Velocity,
                            Duration = noteon.NoteLength * TickLengthMs,
                            Length   = noteon.NoteLength,
                        };
                        //mptkEvents.Add(midievent);

                        // show playing note
                        //Debug.Log(midievent.Channel);
                        if (midievent.Channel == selectedChannel)
                        {
                            Kbd_PKeyGen.instance.ShowMidiNoteOn(noteon.NoteNumber);
                        }

                        if (LogEvents)
                        {
                            string notename = (midievent.Channel != 9) ?
                                              String.Format("{0}{1}", NoteNames[midievent.Value % 12], midievent.Value / 12) : "Drum";
                            Debug.Log(BuildInfoTrack(trackEvent) + string.Format("NoteOn  {0,3:000}\t{1,-4}\tLenght:{2,5}\t{3}\tVeloc:{4,3}",
                                                                                 midievent.Value, notename, noteon.NoteLength, NoteLength(midievent), noteon.Velocity));
                        }
                    }
                    else if (KeepNoteOff)
                    {
                        midievent = CreateNoteOffForNote(mptkEvents, trackEvent);
                    }
                }
                break;

            case MidiCommandCode.NoteOff:
                midievent = CreateNoteOffForNote(mptkEvents, trackEvent);
                break;

            case MidiCommandCode.ControlChange:

                ControlChangeEvent controlchange = (ControlChangeEvent)trackEvent.Event;
                midievent = new MPTKEvent()
                {
                    Tick       = trackEvent.AbsoluteQuantize,
                    Command    = MPTKCommand.ControlChange,
                    Channel    = trackEvent.Event.Channel - 1,
                    Controller = (MPTKController)controlchange.Controller,
                    Value      = controlchange.ControllerValue,
                };
                mptkEvents.Add(midievent);

                // Other midi event
                if (LogEvents)
                {
                    Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Control {0} {1}", controlchange.Controller, controlchange.ControllerValue));
                }

                break;

            case MidiCommandCode.PatchChange:
                PatchChangeEvent change = (PatchChangeEvent)trackEvent.Event;
                midievent = new MPTKEvent()
                {
                    Tick    = trackEvent.AbsoluteQuantize,
                    Command = MPTKCommand.PatchChange,
                    Channel = trackEvent.Event.Channel - 1,
                    Value   = change.Patch,
                };
                mptkEvents.Add(midievent);
                if (LogEvents)
                {
                    Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Patch   {0,3:000} {1}", change.Patch, PatchChangeEvent.GetPatchName(change.Patch)));
                }
                break;

            case MidiCommandCode.MetaEvent:
                MetaEvent meta = (MetaEvent)trackEvent.Event;
                midievent = new MPTKEvent()
                {
                    Tick    = trackEvent.AbsoluteQuantize,
                    Command = MPTKCommand.MetaEvent,
                    Channel = trackEvent.Event.Channel - 1,
                    Meta    = (MPTKMeta)meta.MetaEventType,
                };

                switch (meta.MetaEventType)
                {
                case MetaEventType.TimeSignature:
                    AnalyzeTimeSignature(meta);
                    break;

                case MetaEventType.SetTempo:
                    TempoEvent tempo = (TempoEvent)meta;
                    // Tempo change will be done in MidiFilePlayer
                    midievent.Duration = tempo.Tempo;
                    MPTK_MicrosecondsPerQuarterNote = tempo.MicrosecondsPerQuarterNote;
                    // Force exit loop
                    exitLoop = true;
                    break;

                case MetaEventType.SequenceTrackName:
                    midievent.Info = ((TextEvent)meta).Text;
                    if (!string.IsNullOrEmpty(SequenceTrackName))
                    {
                        SequenceTrackName += "\n";
                    }
                    SequenceTrackName += string.Format("T{0,2:00} {1}", trackEvent.IndexTrack, midievent.Info);
                    //if (LogEvents) Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Sequence   '{0}'", note.Info));
                    break;

                case MetaEventType.ProgramName:
                    midievent.Info = ((TextEvent)meta).Text;
                    ProgramName   += midievent.Info + " ";
                    //if (LogEvents) Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Program   '{0}'", note.Info));
                    break;

                case MetaEventType.TrackInstrumentName:
                    midievent.Info = ((TextEvent)meta).Text;
                    if (!string.IsNullOrEmpty(TrackInstrumentName))
                    {
                        TrackInstrumentName += "\n";
                    }
                    TrackInstrumentName += string.Format("T{0,2:00} {1}", trackEvent.IndexTrack, midievent.Info);
                    //if (LogEvents) Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Text      '{0}'", ((TextEvent)meta).Text));
                    break;

                case MetaEventType.TextEvent:
                    midievent.Info = ((TextEvent)meta).Text;
                    TextEvent     += midievent.Info + " ";
                    //if (LogEvents) Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Sequence  '{0}'", ((TextEvent)meta).Text));
                    break;

                case MetaEventType.Copyright:
                    midievent.Info = ((TextEvent)meta).Text;
                    Copyright     += midievent.Info + " ";
                    //if (LogEvents) Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Copyright '{0}'", ((TextEvent)meta).Text));
                    break;

                case MetaEventType.Lyric:         // lyric
                    midievent.Info = ((TextEvent)meta).Text;
                    break;

                case MetaEventType.Marker:         // marker
                case MetaEventType.CuePoint:       // cue point
                case MetaEventType.DeviceName:
                    break;
                }

                if (LogEvents && !string.IsNullOrEmpty(midievent.Info))
                {
                    Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Meta    {0,15} '{1}'", midievent.Meta, midievent.Info));
                }

                mptkEvents.Add(midievent);
                //Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Meta {0} {1}", meta.MetaEventType, meta.ToString()));
                break;

            default:
                // Other midi event
                if (LogEvents)
                {
                    Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Other   {0,15} Not handle by MPTK", trackEvent.Event.CommandCode));
                }
                break;
            }

            return(exitLoop);
        }
Exemple #8
0
    IEnumerator MidiPlayer(MidiEventCollection mec)
    {
        Debug.Log("Player");
        int counter            = 0;
        IList <MidiEvent> list = mec[0]; //We only have 1 track

        using (MidiOut midiOut = new MidiOut(0))
        {
            while (counter < list.Count)
            {
                MidiEvent mEv = list[counter];

                if (realNoteList[counter].RealTime > Time.time) //Not time yet to play TODO Make it general, not from start of app (Time.time)
                {
                    //Debug.Log("Yield: " + list[i].AbsoluteTime + " " + Time.time);
                    yield return(null);
                }
                else
                {
                    //midiOut.Volume = 65535;
                    //Debug.Log(mEv.ToString());

                    bool off = false;
                    if (mEv is NoteEvent)
                    {
                        if ((mEv as NoteEvent).Velocity == 0)
                        {
                            off = true;
                        }
                    }

                    if (mEv.CommandCode == MidiCommandCode.NoteOn && !off)
                    {
                        NoteOnEvent nOE      = (NoteOnEvent)mEv;
                        int         note     = nOE.NoteNumber;
                        int         velocity = nOE.Velocity;
                        if (velocity == 0)
                        {
                            off = true;
                            continue;
                        }

                        int channel = nOE.Channel;
                        midiOut.Send(MidiMessage.StartNote(note, velocity, channel).RawData);

                        float lifeTime = (float)nOE.NoteLength / 1000;
                        lifeTime *= realNoteList[counter].Factor;
                        int        relativePos = note - 40;
                        GameObject cubeCopy    = Instantiate(cubePrefab, new Vector3(relativePos, channel * 3 - 20, 50), Quaternion.identity) as GameObject;
                        cubeCopy.transform.localScale *= ((float)velocity / 127.0f);
                        StartCoroutine(CubeFade(cubeCopy, lifeTime));
                    }
                    else if (mEv.CommandCode == MidiCommandCode.NoteOff || off)
                    {
                        NoteEvent nE       = (NoteEvent)mEv;
                        int       note     = nE.NoteNumber;
                        int       velocity = nE.Velocity;
                        int       channel  = nE.Channel;
                        midiOut.Send(MidiMessage.StopNote(note, velocity, channel).RawData);
                    }
                    else if (mEv.CommandCode == MidiCommandCode.PatchChange)
                    {
                        PatchChangeEvent pce = (PatchChangeEvent)mEv;
                        midiOut.Send(MidiMessage.ChangePatch(pce.Patch, pce.Channel).RawData);
                    }
                    else if (mEv.CommandCode == MidiCommandCode.ControlChange)
                    {
                        ControlChangeEvent cce = (ControlChangeEvent)mEv;
                        midiOut.Send(MidiMessage.ChangeControl(cce.Controller.GetHashCode(), cce.ControllerValue, cce.Channel).RawData);
                    }

                    /**
                     * else if (mEv.CommandCode == MidiCommandCode.MetaEvent)
                     * {
                     *
                     *  MetaEvent metaEv = (MetaEvent)mEv;
                     *  switch (metaEv.MetaEventType)
                     *  {
                     *      case MetaEventType.TrackSequenceNumber:
                     *          break;
                     *      case MetaEventType.TextEvent:
                     *          break;
                     *      case MetaEventType.Copyright:
                     *          break;
                     *      case MetaEventType.SequenceTrackName:
                     *          break;
                     *      case MetaEventType.TrackInstrumentName:
                     *          break;
                     *      case MetaEventType.Lyric:
                     *          break;
                     *      case MetaEventType.Marker:
                     *          break;
                     *      case MetaEventType.CuePoint:
                     *          break;
                     *      case MetaEventType.ProgramName:
                     *          break;
                     *      case MetaEventType.DeviceName:
                     *          break;
                     *      case MetaEventType.MidiChannel:
                     *          break;
                     *      case MetaEventType.MidiPort:
                     *          break;
                     *      case MetaEventType.EndTrack:
                     *          break;
                     *      case MetaEventType.SetTempo:
                     *          break;
                     *      case MetaEventType.SmpteOffset:
                     *          break;
                     *      case MetaEventType.TimeSignature:
                     *          break;
                     *      case MetaEventType.KeySignature:
                     *          break;
                     *      case MetaEventType.SequencerSpecific:
                     *          break;
                     *      default:
                     *          break;
                     *  }
                     *
                     *
                     * }**/


                    //Debug.Log("Yield: " + ((float)list[i].AbsoluteTime) / 1000 + " " + Time.time);

                    counter++;
                }
            }
        }
    }
    public void FromVegas(Vegas vegas)
    {
        // select a midi file
        MessageBox.Show("请选择一个MIDI文件。");
        OpenFileDialog openFileDialog = new OpenFileDialog();

        openFileDialog.Filter           = "*.mid|*.mid|所有文件|*.*";
        openFileDialog.RestoreDirectory = true;
        openFileDialog.FilterIndex      = 1;
        if (openFileDialog.ShowDialog() == DialogResult.OK)
        {
            midiName = openFileDialog.FileName;
        }
        else
        {
            return;
        }

        MidiFile midi = new MidiFile(midiName);

        // generate statistics of each midi track
        String[] trackInfo       = new String[midi.Events.Tracks];
        int      ticksPerQuarter = midi.DeltaTicksPerQuarterNote;
        double   msPerQuarter    = 0;

        for (int i = 0; i < midi.Events.Tracks; i++)
        {
            String info1      = "轨道 " + i.ToString() + ": ";
            String info2      = "";
            int    notesCount = 0;
            String info3      = "起音 ";

            foreach (MidiEvent midiEvent in midi.Events[i])
            {
                if ((midiEvent is NoteEvent) && !(midiEvent is NoteOnEvent))
                {
                    NoteEvent noteEvent = midiEvent as NoteEvent;
                    if (notesCount == 0)
                    {
                        info3 = info3 + noteEvent.NoteName;
                    }
                    notesCount++;
                }
                if ((midiEvent is PatchChangeEvent) && info2.Length == 0)
                {
                    PatchChangeEvent patchEvent = midiEvent as PatchChangeEvent;
                    for (int j = 4; j < patchEvent.ToString().Split(' ').Length; j++)
                    {
                        info2 += patchEvent.ToString().Split(' ')[j];
                    }
                }
                if ((midiEvent is TempoEvent) && msPerQuarter == 0)
                {
                    TempoEvent tempoEvent = midiEvent as TempoEvent;
                    msPerQuarter = Convert.ToDouble(tempoEvent.MicrosecondsPerQuarterNote) / 1000;
                }
            }

            trackInfo[i] = info1 + info2 + "; 音符数: " + notesCount.ToString() + "; " + info3;
        }

        // select a video clip
        MessageBox.Show("请选择一个视频或图片素材片段。");
        openFileDialog.Filter           = "所有文件|*.*";
        openFileDialog.RestoreDirectory = true;
        openFileDialog.FilterIndex      = 1;
        if (openFileDialog.ShowDialog() == DialogResult.OK)
        {
            clipName = openFileDialog.FileName;
        }
        else
        {
            return;
        }
        Media  media       = new Media(clipName);
        double mediaLength = media.Length.ToMilliseconds();

        // start configuration
        Form2 configForm = new Form2();

        for (int i = 1; i < midi.Events.Tracks; i++)
        {
            configForm.comboBox1.Items.Add(trackInfo[i]);
        }
        configForm.comboBox1.SelectedIndex = 0;
        Application.Run(configForm);

        // apply condiguration
        for (int i = 1; i < midi.Events.Tracks; i++)
        {
            if (trackInfo[i] == configForm.comboBox1.SelectedItem.ToString())
            {
                midiTrack = i;
            }
        }
        sheetWidth    = int.Parse(configForm.width);
        sheetPosition = int.Parse(configForm.position);
        sheetGap      = int.Parse(configForm.gap);
        if (configForm.comboBox2.Text == "2/4")
        {
            sheetTempo = 2;
        }
        if (configForm.comboBox2.Text == "3/4")
        {
            sheetTempo = 3;
        }
        if (configForm.comboBox3.Text == "低音")
        {
            sheetCelf = 1;
        }

        // start processing MIDI
        VideoTrack[] noteTracks   = new VideoTrack[100];
        int          trackCount   = -1;
        int          trackPointer = 0;
        double       barStartTime = 0;
        double       barLength    = msPerQuarter * sheetTempo;

        foreach (MidiEvent midiEvent in midi.Events[midiTrack])
        {
            if (midiEvent is NoteOnEvent)
            {
                NoteEvent   noteEvent   = midiEvent as NoteEvent;
                NoteOnEvent noteOnEvent = midiEvent as NoteOnEvent;
                double      startTime   = midiEvent.AbsoluteTime * msPerQuarter / ticksPerQuarter;
                double      duration    = noteOnEvent.NoteLength * msPerQuarter / ticksPerQuarter;
                int         pitch       = noteEvent.NoteNumber;


                // next page
                while (startTime >= barStartTime + barLength)
                {
                    barStartTime = barStartTime + barLength;
                    trackPointer = 0;
                }

                // generate video events
                if (trackPointer > trackCount)
                {
                    trackCount             = trackCount + 1;
                    noteTracks[trackCount] = vegas.Project.AddVideoTrack();
                }

                VideoEvent videoEvent = noteTracks[trackPointer].AddVideoEvent(Timecode.FromMilliseconds(startTime), Timecode.FromMilliseconds(barStartTime + barLength - startTime));
                Take       take       = videoEvent.AddTake(media.GetVideoStreamByIndex(0));
                TrackEvent trackEvent = videoEvent as TrackEvent;
                trackEvent.Loop = true;

                TrackMotionKeyframe keyFrame = noteTracks[trackPointer].TrackMotion.InsertMotionKeyframe(Timecode.FromMilliseconds(startTime));
                keyFrame.Type      = VideoKeyframeType.Hold;
                keyFrame.Width     = sheetGap * 2 * vegas.Project.Video.Width / vegas.Project.Video.Height;
                keyFrame.Height    = sheetGap * 2;
                keyFrame.PositionX = -sheetWidth / 2 + sheetWidth / barLength * (startTime - barStartTime);
                int octave = pitch / 12;
                int line   = pitchMap[pitch % 12];
                keyFrame.PositionY = sheetPosition - sheetGap * 3 + (octave - 5) * sheetGap * 3.5 + line * sheetGap * 0.5 + sheetCelf * 12;

                trackPointer = trackPointer + 1;
            }
        }
    }
Exemple #10
0
        private void sr_OnTrackEvent(object sender, TrackEventArgs e)
        {
            long counter     = 0;
            long notesBefore = TotalNotes;

            foreach (var ev in e.Events.Where(x => x is MidiUtils.IO.MidiEvent))
            {
                counter++;
                // Convert the event to NAudio's system so we can get a shortMessage
                var em = (MidiUtils.IO.MidiEvent)ev;
                if (ev.Type == EventType.NoteOn)
                {
                    TotalNotes++;
                }
                MidiEvent me;
                try
                {
                    switch (ev.Type)
                    {
                    case EventType.NoteOn:
                    case EventType.NoteOff:
                    case EventType.PolyphonicKeyPressure:
                        if (em.Data2 > 0 && ev.Type == EventType.NoteOn)
                        {
                            me = new NoteOnEvent(ev.Tick, em.Channel + 1, em.Data1, em.Data2, 0);
                        }
                        else
                        {
                            me = new NoteEvent(ev.Tick, em.Channel + 1, (MidiCommandCode)(int)ev.Type, em.Data1, em.Data2);
                        }
                        break;

                    case EventType.ControlChange:
                        me = new ControlChangeEvent(ev.Tick, em.Channel + 1, (MidiController)em.Data1, em.Data2);
                        break;

                    case EventType.ProgramChange:
                        me = new PatchChangeEvent(ev.Tick, em.Channel + 1, em.Data1);
                        break;

                    case EventType.ChannelPressure:
                        me = new ChannelAfterTouchEvent(ev.Tick, em.Channel + 1, em.Data1);
                        break;

                    case EventType.Pitchbend:
                        me = new PitchWheelChangeEvent(ev.Tick, em.Channel + 1, em.Data1 + (em.Data2 << 7));
                        break;

                    default:
                        throw new InvalidOperationException("Unsupported MIDI event type: " + ev.Type);
                    }
                }
                catch (Exception ex)
                {
                    Exceptions++;
                    continue;
                }

                // Send the message
                try { _midi.Send(me.GetAsShortMessage()); }
                catch (MmException ex)
                {
                    if ((int)ex.Result == 67)
                    {
                        Overloads++;
                    }
                    else
                    {
                        Exceptions++;
                    }
                    continue;
                }
                if (ev.Type == EventType.NoteOn)
                {
                    SuccessNotes++;
                }
            }
            PeakNotesPerInterval  = Math.Max(PeakNotesPerInterval, TotalNotes - notesBefore);
            PeakEventsPerInterval = Math.Max(PeakEventsPerInterval, counter);
            TotalEvents          += counter;
        }
Exemple #11
0
        /// <summary>
        /// Creates MusicTwo instance using midi file
        /// </summary>
        /// <param name="midiFile">Midi file to use</param>
        /// <param name="firstNoteMode">Use first note mode. If some notes appears at same time, use the first one, else the last</param>
        /// <returns>Created MusicTwo instance</returns>
        public static MusicTwo FromMidiFile(MidiFile midiFile, bool firstNoteMode)
        {
            double       tempo  = 0;
            List <Track> tracks = new List <Track>();

            for (int track_ = 1; track_ <= midiFile.Tracks; track_++)
            {
                Track track__ = new Track();
                foreach (var e in midiFile.Events)
                {
                    foreach (var ee in e)
                    {
                        if (ee is NoteEvent)
                        {
                            NoteEvent eee = (NoteEvent)ee;
                            if (eee is NoteOnEvent)
                            {
                                var  eeee = (NoteOnEvent)eee;
                                Note nt   = new Note();
                                nt.time   = (int)(eeee.AbsoluteTime / (double)midiFile.DeltaTicksPerQuarterNote * tempo);
                                nt.length = 0;
                                if (eeee.OffEvent != null)
                                {
                                    nt.length = (int)(eeee.NoteLength / (double)midiFile.DeltaTicksPerQuarterNote * tempo);
                                }
                                nt.number     = eeee.NoteNumber;
                                nt.instrument = track__.instrument;
                                if (eeee.Channel == track_)
                                {
                                    track__.notes.Add(nt);
                                }
                            }
                        }
                        if (ee is MetaEvent)
                        {
                            MetaEvent eee = (MetaEvent)ee;
                            if (eee.MetaEventType == MetaEventType.SetTempo)
                            {
                                TempoEvent eeee = (TempoEvent)eee;
                                tempo = eeee.MicrosecondsPerQuarterNote / 1000;
                            }
                        }

                        if (ee is PatchChangeEvent)
                        {
                            PatchChangeEvent eee = (PatchChangeEvent)ee;
                            if (eee.Channel == track_)
                            {
                                track__.instrument = eee.Patch;
                            }
                        }
                    }
                }
                tracks.Add(track__);
            }
            for (int i = 0; i < tracks.Count; i++)
            {
                for (int ii = 0; ii < tracks[i].notes.Count; ii++)
                {
                    if (tracks[i].notes[ii].length == 0)
                    {
                        tracks[i].notes.RemoveAt(ii);
                    }
                }
                if (tracks[i].notes.Count == 0)
                {
                    tracks.RemoveAt(i);
                    i--;
                }
            }



            MusicTwo music = new MusicTwo();

            for (int tracko = 0; tracko < tracks.Count; tracko++)
            {
                Track    track = tracks[tracko];
                TrackTwo nts   = new TrackTwo();
                NoteTwo  ntt   = new NoteTwo();
                ntt.Number = 0;
                ntt.Length = 0;
                nts.Notes.Add(ntt);
                Note lastNote = (new Note());
                Note en       = new Note();
                lastNote.time   = 0;
                lastNote.number = 0;
                lastNote.length = 0;
                en.time         = 0;
                en.number       = 0;
                en.length       = 0;
                for (int i = 0; i < track.notes.Last().time + track.notes.Last().length; i++)
                {
                    Note nowNote = en;
                    for (int ii = 0; ii < track.notes.Count; ii++)
                    {
                        if (i >= track.notes[ii].time && i <= track.notes[ii].time + track.notes[ii].length)
                        {
                            nowNote = track.notes[ii];
                            if (firstNoteMode)
                            {
                                goto c1;
                            }
                        }
                    }
c1:
                    if (nts.Notes.Last().Number == nowNote.number)
                    {
                        nts.Notes.Last().Length++;
                        continue;
                    }
                    else
                    {
                        NoteTwo nttt = new NoteTwo();
                        nttt.Number = nowNote.number;
                        nttt.Length = 1;
                        nttt.IsBass = isInstrumentBass(nowNote.instrument);
                        nts.Notes.Add(nttt);
                    }
                }
                music.tracks.Add(nts);
            }
            return(music);
        }
Exemple #12
0
 PatchInfo(int id)
 {
     Id      = id;
     Caption = PatchChangeEvent.GetPatchName(id);
 }
    public void FromVegas(Vegas vegas)
    {
        // select a midi file
        MessageBox.Show("请选择一个MIDI文件。");
        OpenFileDialog openFileDialog = new OpenFileDialog();

        openFileDialog.Filter           = "*.mid|*.mid|所有文件|*.*";
        openFileDialog.RestoreDirectory = true;
        openFileDialog.FilterIndex      = 1;
        if (openFileDialog.ShowDialog() == DialogResult.OK)
        {
            midiName = openFileDialog.FileName;
        }
        else
        {
            return;
        }

        MidiFile midi = new MidiFile(midiName);

        // generate statistics of each midi track
        String[] trackInfo       = new String[midi.Events.Tracks];
        int      ticksPerQuarter = midi.DeltaTicksPerQuarterNote;
        double   msPerQuarter    = 0;

        for (int i = 0; i < midi.Events.Tracks; i++)
        {
            String info1      = "轨道 " + i.ToString() + ": ";
            String info2      = "";
            int    notesCount = 0;
            String info3      = "起音 ";

            foreach (MidiEvent midiEvent in midi.Events[i])
            {
                if ((midiEvent is NoteEvent) && !(midiEvent is NoteOnEvent))
                {
                    NoteEvent noteEvent = midiEvent as NoteEvent;
                    if (notesCount == 0)
                    {
                        info3 = info3 + noteEvent.NoteName;
                    }
                    notesCount++;
                }
                if ((midiEvent is PatchChangeEvent) && info2.Length == 0)
                {
                    PatchChangeEvent patchEvent = midiEvent as PatchChangeEvent;
                    for (int j = 4; j < patchEvent.ToString().Split(' ').Length; j++)
                    {
                        info2 += patchEvent.ToString().Split(' ')[j];
                    }
                }
                if ((midiEvent is TempoEvent) && msPerQuarter == 0)
                {
                    TempoEvent tempoEvent = midiEvent as TempoEvent;
                    msPerQuarter = Convert.ToDouble(tempoEvent.MicrosecondsPerQuarterNote) / 1000;
                }
            }

            trackInfo[i] = info1 + info2 + "; 音符数: " + notesCount.ToString() + "; " + info3;
        }

        // select a video clip
        MessageBox.Show("请选择一个视频或音频素材片段。");
        openFileDialog.Filter           = "所有文件|*.*";
        openFileDialog.RestoreDirectory = true;
        openFileDialog.FilterIndex      = 1;
        if (openFileDialog.ShowDialog() == DialogResult.OK)
        {
            clipName = openFileDialog.FileName;
        }
        else
        {
            return;
        }
        Media  media       = new Media(clipName);
        double mediaLength = media.Length.ToMilliseconds();

        // start configuration
        ConfigForm configForm = new ConfigForm();

        for (int i = 0; i < midi.Events.Tracks; i++)
        {
            configForm.comboBoxTrack.Items.Add(trackInfo[i]);
        }
        configForm.comboBoxTrack.SelectedIndex = 0;
        Application.Run(configForm);

        // apply configuration
        aconfig          = configForm.checkBoxA.Checked;
        aconfigNoTune    = configForm.checkBoxNoTune.Checked;
        vconfig          = configForm.checkBoxV.Checked;
        vconfigAutoFlip  = configForm.checkBoxFlip.Checked;
        vconfigStartSize = configForm.hScrollBar1.Value;
        vconfigEndSize   = configForm.hScrollBar2.Value;
        vconfigFadein    = configForm.hScrollBar4.Value;
        vconfigFadeout   = configForm.hScrollBar3.Value;
        aconfigBasePitch = pitchMap[configForm.comboBoxA1.SelectedItem.ToString() + configForm.comboBoxA2.SelectedItem.ToString()];
        for (int i = 0; i < midi.Events.Tracks; i++)
        {
            if (trackInfo[i] == configForm.comboBoxTrack.SelectedItem.ToString())
            {
                aconfigTrack = i;
            }
        }
        configStartTime = Convert.ToDouble(configForm.startT) * 1000;
        configEndTime   = Convert.ToDouble(configForm.endT) * 1000;

        // start processing MIDI
        VideoTrack vTrack = vegas.Project.AddVideoTrack();

        AudioTrack[] aTracks         = new AudioTrack[20];
        double       vTrackPosition  = 0;
        int          vTrackDirection = 1;

        double[] aTrackPositions = new double[20];
        aTracks[0]         = vegas.Project.AddAudioTrack();
        aTrackPositions[0] = 0;
        int aTrackCount = 1;

        foreach (MidiEvent midiEvent in midi.Events[aconfigTrack])
        {
            if (midiEvent is NoteOnEvent)
            {
                NoteEvent   noteEvent   = midiEvent as NoteEvent;
                NoteOnEvent noteOnEvent = midiEvent as NoteOnEvent;
                double      startTime   = midiEvent.AbsoluteTime * msPerQuarter / ticksPerQuarter;
                double      duration    = noteOnEvent.NoteLength * msPerQuarter / ticksPerQuarter;
                int         pitch       = noteEvent.NoteNumber;
                int         trackIndex  = 0;

                if (startTime < configStartTime)
                {
                    continue;
                }
                if (startTime > configEndTime)
                {
                    break;
                }

                // generate audio events
                if (aconfig == true)
                {
                    while (startTime < aTrackPositions[trackIndex])
                    {
                        trackIndex++;
                        if (trackIndex == aTrackCount)
                        {
                            aTrackCount++;
                            aTracks[trackIndex] = vegas.Project.AddAudioTrack();
                        }
                    }
                    AudioEvent audioEvent = aTracks[trackIndex].AddAudioEvent(Timecode.FromMilliseconds(startTime), Timecode.FromMilliseconds(duration));
                    Take       take       = audioEvent.AddTake(media.GetAudioStreamByIndex(0));
                    aTrackPositions[trackIndex] = startTime + duration;
                    TrackEvent trackEvent = audioEvent as TrackEvent;
                    trackEvent.PlaybackRate = mediaLength / duration;
                    trackEvent.Loop         = false;

                    // apply pitch shifting

                    if (aconfigNoTune == false)
                    {
                        int pitchDelta = pitch - aconfigBasePitch;
                        if (pitchDelta > 0)
                        {
                            while (pitchDelta > 12)
                            {
                                PlugInNode plugIn0 = vegas.AudioFX.FindChildByName("Pitch Shift");
                                Effect     effect0 = new Effect(plugIn0);
                                audioEvent.Effects.Add(effect0);
                                effect0.Preset = "12";
                                pitchDelta    -= 12;
                            }
                            PlugInNode plugIn = vegas.AudioFX.FindChildByName("Pitch Shift");
                            Effect     effect = new Effect(plugIn);
                            audioEvent.Effects.Add(effect);
                            effect.Preset = pitchDelta.ToString();
                        }
                        else
                        {
                            while (pitchDelta < -12)
                            {
                                PlugInNode plugIn0 = vegas.AudioFX.FindChildByName("Pitch Shift");
                                Effect     effect0 = new Effect(plugIn0);
                                audioEvent.Effects.Add(effect0);
                                effect0.Preset = "-12";
                                pitchDelta    += 12;
                            }
                            PlugInNode plugIn = vegas.AudioFX.FindChildByName("Pitch Shift");
                            Effect     effect = new Effect(plugIn);
                            audioEvent.Effects.Add(effect);
                            effect.Preset = pitchDelta.ToString();
                        }
                    }
                }

                // generate video events
                if (vconfig == true)
                {
                    vTrackPosition = startTime + duration;
                    VideoEvent videoEvent = vTrack.AddVideoEvent(Timecode.FromMilliseconds(startTime), Timecode.FromMilliseconds(duration));
                    Take       take       = videoEvent.AddTake(media.GetVideoStreamByIndex(0));
                    TrackEvent trackEvent = videoEvent as TrackEvent;
                    trackEvent.PlaybackRate = mediaLength / duration;
                    trackEvent.Loop         = false;

                    videoEvent.FadeIn.Length  = Timecode.FromMilliseconds(duration * vconfigFadein / 100);
                    videoEvent.FadeOut.Length = Timecode.FromMilliseconds(duration * vconfigFadeout / 100);

                    VideoMotionKeyframe key0 = videoEvent.VideoMotion.Keyframes[0];
                    VideoMotionKeyframe key1 = new VideoMotionKeyframe(Timecode.FromMilliseconds(duration));
                    videoEvent.VideoMotion.Keyframes.Add(key1);
                    key0.ScaleBy(new VideoMotionVertex((vconfigStartSize / 100) * vTrackDirection, (vconfigStartSize / 100)));
                    key1.ScaleBy(new VideoMotionVertex((vconfigEndSize / 100) * vTrackDirection, (vconfigEndSize / 100)));

                    if (vconfigAutoFlip == true)
                    {
                        vTrackDirection *= -1;
                    }
                }
            }
        }
    }
        public static List <HitsoundLayer> ImportMidi(string path, double offset = 0, bool instruments = true, bool keysounds = true, bool lengths = true, double lengthRoughness = 1, bool velocities = true, double velocityRoughness = 1)
        {
            List <HitsoundLayer> hitsoundLayers = new List <HitsoundLayer>();

            var strictMode = false;
            var mf         = new MidiFile(path, strictMode);

            Console.WriteLine(
                $@"Format {mf.FileFormat}, " +
                $@"Tracks {mf.Tracks}, " +
                $@"Delta Ticks Per Quarter Note {mf.DeltaTicksPerQuarterNote}");

            List <TempoEvent> tempos = new List <TempoEvent>();

            foreach (var track in mf.Events)
            {
                tempos.AddRange(track.OfType <TempoEvent>());
            }
            tempos = tempos.OrderBy(o => o.AbsoluteTime).ToList();

            List <double> cumulativeTime = CalculateCumulativeTime(tempos, mf.DeltaTicksPerQuarterNote);

            Dictionary <int, int> channelBanks   = new Dictionary <int, int>();
            Dictionary <int, int> channelPatches = new Dictionary <int, int>();

            // Loop through every event of every track
            for (int track = 0; track < mf.Tracks; track++)
            {
                foreach (var midiEvent in mf.Events[track])
                {
                    if (midiEvent is PatchChangeEvent pc)
                    {
                        channelPatches[pc.Channel] = pc.Patch;
                    }
                    else if (midiEvent is ControlChangeEvent co)
                    {
                        if (co.Controller == MidiController.BankSelect)
                        {
                            channelBanks[co.Channel] = (co.ControllerValue * 128) + (channelBanks.ContainsKey(co.Channel) ? (byte)channelBanks[co.Channel] : 0);
                        }
                        else if (co.Controller == MidiController.BankSelectLsb)
                        {
                            channelBanks[co.Channel] = co.ControllerValue + (channelBanks.ContainsKey(co.Channel) ? channelBanks[co.Channel] >> 8 * 128 : 0);
                        }
                    }
                    else if (MidiEvent.IsNoteOn(midiEvent))
                    {
                        var on = midiEvent as NoteOnEvent;

                        double time   = CalculateTime(on.AbsoluteTime, tempos, cumulativeTime, mf.DeltaTicksPerQuarterNote);
                        double length = on.OffEvent != null
                            ? CalculateTime(on.OffEvent.AbsoluteTime,
                                            tempos,
                                            cumulativeTime,
                                            mf.DeltaTicksPerQuarterNote) -
                                        time
                            : -1;

                        length = RoundLength(length, lengthRoughness);

                        bool keys = keysounds || on.Channel == 10;

                        int bank = instruments
                            ? on.Channel == 10 ? 128 :
                                   channelBanks.ContainsKey(on.Channel) ? channelBanks[on.Channel] : 0
                            : -1;
                        int patch = instruments && channelPatches.ContainsKey(on.Channel)
                            ? channelPatches[on.Channel]
                            : -1;
                        int instrument = -1;
                        int key        = keys ? on.NoteNumber : -1;
                        length = lengths ? length : -1;
                        int velocity = velocities ? on.Velocity : -1;
                        velocity = (int)RoundVelocity(velocity, velocityRoughness);

                        string lengthString = Math.Round(length).ToString(CultureInfo.InvariantCulture);
                        string filename     = $"{bank}\\{patch}\\{instrument}\\{key}\\{lengthString}\\{velocity}.wav";

                        string instrumentName = on.Channel == 10 ? "Percussion" :
                                                patch >= 0 && patch <= 127 ? PatchChangeEvent.GetPatchName(patch) : "Undefined";
                        string keyName = on.NoteName;

                        string name = instrumentName;
                        if (keysounds)
                        {
                            name += "," + keyName;
                        }
                        if (lengths)
                        {
                            name += "," + lengthString;
                        }
                        if (velocities)
                        {
                            name += "," + velocity;
                        }


                        var sampleArgs = new SampleGeneratingArgs(filename, bank, patch, instrument, key, length, velocity);
                        var importArgs = new LayerImportArgs(ImportType.MIDI)
                        {
                            Path              = path,
                            Bank              = bank,
                            Patch             = patch,
                            Key               = key,
                            Length            = length,
                            LengthRoughness   = lengthRoughness,
                            Velocity          = velocity,
                            VelocityRoughness = velocityRoughness
                        };

                        // Find the hitsoundlayer with this path
                        HitsoundLayer layer = hitsoundLayers.Find(o => o.ImportArgs == importArgs);

                        if (layer != null)
                        {
                            // Find hitsound layer with this path and add this time
                            layer.Times.Add(time + offset);
                        }
                        else
                        {
                            // Add new hitsound layer with this path
                            HitsoundLayer newLayer = new HitsoundLayer(name, SampleSet.Normal, Hitsound.Normal, sampleArgs, importArgs);
                            newLayer.Times.Add(time + offset);

                            hitsoundLayers.Add(newLayer);
                        }
                    }
                }
            }
            // Stretch the velocities to reach 127
            int maxVelocity = hitsoundLayers.Max(o => o.SampleArgs.Velocity);

            foreach (var hsl in hitsoundLayers)
            {
                hsl.SampleArgs.Velocity = (int)Math.Round(hsl.SampleArgs.Velocity / (float)maxVelocity * 127);
            }

            // Sort the times
            hitsoundLayers.ForEach(o => o.Times = o.Times.OrderBy(t => t).ToList());

            // Sort layers by name
            hitsoundLayers = hitsoundLayers.OrderBy(o => o.Name).ToList();

            return(hitsoundLayers);
        }
Exemple #15
0
        /// <summary>
        /// Add a TrackMidiEvent to a list of MPTKEvent.
        /// </summary>
        /// <param name="mptkEvents">Must be alloc before the call</param>
        /// <param name="trackEvent"></param>
        /// <returns></returns>
        private void ConvertToEvent(List <MPTKEvent> mptkEvents, TrackMidiEvent trackEvent)
        {
            MPTKEvent midievent = null;

            switch (trackEvent.Event.CommandCode)
            {
            case MidiCommandCode.NoteOn:
                //if (((NoteOnEvent)trackEvent.Event).OffEvent != null)
            {
                NoteOnEvent noteon = (NoteOnEvent)trackEvent.Event;
                //Debug.Log(string.Format("Track:{0} NoteNumber:{1,3:000} AbsoluteTime:{2,6:000000} NoteLength:{3,6:000000} OffDeltaTime:{4,6:000000} ", track, noteon.NoteNumber, noteon.AbsoluteTime, noteon.NoteLength, noteon.OffEvent.DeltaTime));
                if (noteon.OffEvent != null)
                {
                    midievent = new MPTKEvent()
                    {
                        Track    = trackEvent.IndexTrack,
                        Tick     = trackEvent.AbsoluteQuantize,
                        Command  = MPTKCommand.NoteOn,
                        Value    = noteon.NoteNumber,
                        Channel  = trackEvent.Event.Channel - 1,
                        Velocity = noteon.Velocity,
                        Duration = Convert.ToInt64(noteon.NoteLength * MPTK_PulseLenght),
                        Length   = noteon.NoteLength,
                    };
                    mptkEvents.Add(midievent);
                    if (LogEvents && seek_ticks < 0)
                    {
                        string notename = (midievent.Channel != 9) ?
                                          String.Format("{0}{1}", NoteNames[midievent.Value % 12], midievent.Value / 12) : "Drum";
                        Debug.Log(BuildInfoTrack(trackEvent) + string.Format("NoteOn  {0,3:000}\t{1,-4}\tLenght:{2,5}\t{3}\tVeloc:{4,3}",
                                                                             midievent.Value, notename, noteon.NoteLength, NoteLength(midievent), noteon.Velocity));
                    }
                }
                else         // It's a noteoff
                {
                    if (KeepNoteOff)
                    {
                        midievent = new MPTKEvent()
                        {
                            Track    = trackEvent.IndexTrack,
                            Tick     = trackEvent.AbsoluteQuantize,
                            Command  = MPTKCommand.NoteOff,
                            Value    = noteon.NoteNumber,
                            Channel  = trackEvent.Event.Channel - 1,
                            Velocity = noteon.Velocity,
                            Duration = Convert.ToInt64(noteon.NoteLength * MPTK_PulseLenght),
                            Length   = noteon.NoteLength,
                        };
                        mptkEvents.Add(midievent);

                        if (LogEvents && seek_ticks < 0)
                        {
                            string notename = (midievent.Channel != 9) ?
                                              String.Format("{0}{1}", NoteNames[midievent.Value % 12], midievent.Value / 12) : "Drum";
                            Debug.Log(BuildInfoTrack(trackEvent) + string.Format("NoteOff {0,3:000}\t{1,-4}\tLenght:{2}", midievent.Value, notename, " Note Off"));
                        }
                    }
                }
            }
            break;

            case MidiCommandCode.NoteOff:
                if (KeepNoteOff)
                {
                    NoteEvent noteoff = (NoteEvent)trackEvent.Event;
                    //Debug.Log(string.Format("Track:{0} NoteNumber:{1,3:000} AbsoluteTime:{2,6:000000} NoteLength:{3,6:000000} OffDeltaTime:{4,6:000000} ", track, noteon.NoteNumber, noteon.AbsoluteTime, noteon.NoteLength, noteon.OffEvent.DeltaTime));
                    midievent = new MPTKEvent()
                    {
                        Track    = trackEvent.IndexTrack,
                        Tick     = trackEvent.AbsoluteQuantize,
                        Command  = MPTKCommand.NoteOff,
                        Value    = noteoff.NoteNumber,
                        Channel  = trackEvent.Event.Channel - 1,
                        Velocity = noteoff.Velocity,
                        Duration = 0,
                        Length   = 0,
                    };

                    mptkEvents.Add(midievent);

                    if (LogEvents && seek_ticks < 0)
                    {
                        string notename = (midievent.Channel != 9) ?
                                          String.Format("{0}{1}", NoteNames[midievent.Value % 12], midievent.Value / 12) : "Drum";
                        Debug.Log(BuildInfoTrack(trackEvent) + string.Format("NoteOff {0,3:000}\t{1,-4}\tLenght:{2}", midievent.Value, notename, " Note Off"));
                    }
                }
                break;

            case MidiCommandCode.PitchWheelChange:
                PitchWheelChangeEvent pitch = (PitchWheelChangeEvent)trackEvent.Event;
                midievent = new MPTKEvent()
                {
                    Track   = trackEvent.IndexTrack,
                    Tick    = trackEvent.AbsoluteQuantize,
                    Command = MPTKCommand.PitchWheelChange,
                    Channel = trackEvent.Event.Channel - 1,
                    Value   = pitch.Pitch,    // Pitch Wheel Value 0 is minimum, 0x2000 (8192) is default, 0x3FFF (16383) is maximum
                };
                mptkEvents.Add(midievent);
                if (LogEvents && seek_ticks < 0)
                {
                    Debug.Log(BuildInfoTrack(trackEvent) + string.Format("PitchWheelChange {0}", pitch.Pitch));
                }
                break;

            case MidiCommandCode.ControlChange:
                ControlChangeEvent controlchange = (ControlChangeEvent)trackEvent.Event;
                midievent = new MPTKEvent()
                {
                    Track      = trackEvent.IndexTrack,
                    Tick       = trackEvent.AbsoluteQuantize,
                    Command    = MPTKCommand.ControlChange,
                    Channel    = trackEvent.Event.Channel - 1,
                    Controller = (MPTKController)controlchange.Controller,
                    Value      = controlchange.ControllerValue,
                };

                //if ((MPTKController)controlchange.Controller != MPTKController.Sustain)
                mptkEvents.Add(midievent);

                // Other midi event
                if (LogEvents && seek_ticks < 0)
                {
                    Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Control {0} {1}", controlchange.Controller, controlchange.ControllerValue));
                }

                break;

            case MidiCommandCode.PatchChange:
                PatchChangeEvent change = (PatchChangeEvent)trackEvent.Event;
                midievent = new MPTKEvent()
                {
                    Track   = trackEvent.IndexTrack,
                    Tick    = trackEvent.AbsoluteQuantize,
                    Command = MPTKCommand.PatchChange,
                    Channel = trackEvent.Event.Channel - 1,
                    Value   = change.Patch,
                };
                mptkEvents.Add(midievent);
                if (LogEvents && seek_ticks < 0)
                {
                    Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Patch   {0,3:000} {1}", change.Patch, PatchChangeEvent.GetPatchName(change.Patch)));
                }
                break;

            case MidiCommandCode.MetaEvent:
                MetaEvent meta = (MetaEvent)trackEvent.Event;
                midievent = new MPTKEvent()
                {
                    Track   = trackEvent.IndexTrack,
                    Tick    = trackEvent.AbsoluteQuantize,
                    Command = MPTKCommand.MetaEvent,
                    Channel = trackEvent.Event.Channel - 1,
                    Meta    = (MPTKMeta)meta.MetaEventType,
                };

                switch (meta.MetaEventType)
                {
                case MetaEventType.EndTrack:
                    midievent.Info = "End Track";
                    break;

                case MetaEventType.TimeSignature:
                    AnalyzeTimeSignature(meta, trackEvent);
                    break;

                case MetaEventType.SetTempo:
                    if (EnableChangeTempo)
                    {
                        TempoEvent tempo = (TempoEvent)meta;
                        // Tempo change will be done in MidiFilePlayer
                        midievent.Duration = (long)tempo.Tempo;
                        MPTK_MicrosecondsPerQuarterNote = tempo.MicrosecondsPerQuarterNote;
                        fluid_player_set_midi_tempo(tempo.MicrosecondsPerQuarterNote);

                        // Force exit loop
                        if (LogEvents && seek_ticks < 0)
                        {
                            Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Meta     {0,-15} Tempo:{1} MicrosecondsPerQuarterNote:{2}", meta.MetaEventType, tempo.Tempo, tempo.MicrosecondsPerQuarterNote));
                        }
                    }
                    break;

                case MetaEventType.SequenceTrackName:
                    midievent.Info = ((TextEvent)meta).Text;
                    if (!string.IsNullOrEmpty(SequenceTrackName))
                    {
                        SequenceTrackName += "\n";
                    }
                    SequenceTrackName += string.Format("T{0,2:00} {1}", trackEvent.IndexTrack, midievent.Info);
                    break;

                case MetaEventType.ProgramName:
                    midievent.Info = ((TextEvent)meta).Text;
                    ProgramName   += midievent.Info + " ";
                    break;

                case MetaEventType.TrackInstrumentName:
                    midievent.Info = ((TextEvent)meta).Text;
                    if (!string.IsNullOrEmpty(TrackInstrumentName))
                    {
                        TrackInstrumentName += "\n";
                    }
                    TrackInstrumentName += string.Format("T{0,2:00} {1}", trackEvent.IndexTrack, midievent.Info);
                    break;

                case MetaEventType.TextEvent:
                    midievent.Info = ((TextEvent)meta).Text;
                    TextEvent     += midievent.Info + " ";
                    break;

                case MetaEventType.Copyright:
                    midievent.Info = ((TextEvent)meta).Text;
                    Copyright     += midievent.Info + " ";
                    break;

                case MetaEventType.Lyric:         // lyric
                    midievent.Info = ((TextEvent)meta).Text;
                    TextEvent     += midievent.Info + " ";
                    break;

                case MetaEventType.Marker:         // marker
                    midievent.Info = ((TextEvent)meta).Text;
                    TextEvent     += midievent.Info + " ";
                    break;

                case MetaEventType.CuePoint:         // cue point
                case MetaEventType.DeviceName:
                    break;
                }

                if (LogEvents && !string.IsNullOrEmpty(midievent.Info) && seek_ticks < 0)
                {
                    Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Meta     {0,-15} '{1}'", midievent.Meta, midievent.Info));
                }

                mptkEvents.Add(midievent);
                //Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Meta {0} {1}", meta.MetaEventType, meta.ToString()));
                break;

            default:
                // Other midi event
                if (LogEvents && seek_ticks < 0)
                {
                    Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Other    {0,-15} Not handle by MPTK", trackEvent.Event.CommandCode));
                }
                break;
            }
        }
Exemple #16
0
        public List <MidiNote> ReadMidiEvents(double timeFromStartMS)
        {
            List <MidiNote> notes = null;

            try
            {
                EndMidiEvent = false;
                if (midifile != null)
                {
                    if (NextPosEvent < MidiSorted.Count)
                    {
                        // The BPM measures how many quarter notes happen in a minute. To work out the length of each pulse we can use the following formula:
                        // Pulse Length = 60 / (BPM * PPQN)
                        // Calculate current pulse to play
                        CurrentPulse += Convert.ToInt64((timeFromStartMS - LastTimeFromStartMS) / PulseLengthMs);

                        LastTimeFromStartMS = timeFromStartMS;

                        // From the last position played
                        for (int currentPosEvent = NextPosEvent; currentPosEvent < MidiSorted.Count; currentPosEvent++)
                        {
                            TrackMidiEvent trackEvent = MidiSorted[currentPosEvent];
                            if (Quantization != 0)
                            {
                                trackEvent.AbsoluteQuantize = ((trackEvent.Event.AbsoluteTime + Quantization / 2) / Quantization) * Quantization;
                            }
                            else
                            {
                                trackEvent.AbsoluteQuantize = trackEvent.Event.AbsoluteTime;
                            }

                            //Debug.Log("ReadMidiEvents - timeFromStartMS:" + Convert.ToInt32(timeFromStartMS) + " LastTimeFromStartMS:" + Convert.ToInt32(LastTimeFromStartMS) + " CurrentPulse:" + CurrentPulse + " AbsoluteQuantize:" + trackEvent.AbsoluteQuantize);

                            if (trackEvent.AbsoluteQuantize <= CurrentPulse)
                            {
                                NextPosEvent = currentPosEvent + 1;

                                if (trackEvent.Event.CommandCode == MidiCommandCode.NoteOn)
                                {
                                    if (((NoteOnEvent)trackEvent.Event).OffEvent != null)
                                    {
                                        NoteOnEvent noteon = (NoteOnEvent)trackEvent.Event;
                                        // if (noteon.OffEvent != null)
                                        {
                                            if (notes == null)
                                            {
                                                notes = new List <MidiNote>();
                                            }

                                            //Debug.Log(string.Format("Track:{0} NoteNumber:{1,3:000} AbsoluteTime:{2,6:000000} NoteLength:{3,6:000000} OffDeltaTime:{4,6:000000} ", track, noteon.NoteNumber, noteon.AbsoluteTime, noteon.NoteLength, noteon.OffEvent.DeltaTime));
                                            MidiNote note = new MidiNote()
                                            {
                                                AbsoluteQuantize = trackEvent.AbsoluteQuantize,
                                                Midi             = noteon.NoteNumber,
                                                Channel          = trackEvent.Event.Channel,
                                                Velocity         = noteon.Velocity,
                                                Duration         = noteon.NoteLength * PulseLengthMs,
                                                Length           = noteon.NoteLength,
                                                Patch            = PatchChanel[trackEvent.Event.Channel - 1],
                                                Drum             = (trackEvent.Event.Channel == 10),
                                                Delay            = 0,
                                                Pan = EnablePanChange ? PanChanel[trackEvent.Event.Channel - 1] : -1,
                                            };
                                            if (VolumeChanel[note.Channel - 1] != 127)
                                            {
                                                note.Velocity = Mathf.RoundToInt(((float)note.Velocity) * ((float)VolumeChanel[trackEvent.Event.Channel - 1]) / 127f);
                                            }
                                            notes.Add(note);
                                            if (LogEvents)
                                            {
                                                Debug.Log(BuildInfoTrack(trackEvent) + string.Format("{0,-4} {1,3:000} Lenght:{2} {3} Veloc:{4}",
                                                                                                     noteon.NoteName, noteon.NoteNumber, noteon.NoteLength, NoteLength(note), noteon.Velocity));
                                            }
                                        }
                                    }
                                }
                                else if (trackEvent.Event.CommandCode == MidiCommandCode.NoteOff)
                                {
                                    // no need, noteoff are associated with noteon
                                }
                                else if (trackEvent.Event.CommandCode == MidiCommandCode.ControlChange)
                                {
                                    ControlChangeEvent controlchange = (ControlChangeEvent)trackEvent.Event;
                                    if (controlchange.Controller == MidiController.Expression)
                                    {
                                        VolumeChanel[trackEvent.Event.Channel - 1] = controlchange.ControllerValue;
                                    }
                                    else if (controlchange.Controller == MidiController.MainVolume)
                                    {
                                        VolumeChanel[trackEvent.Event.Channel - 1] = controlchange.ControllerValue;
                                    }
                                    else if (controlchange.Controller == MidiController.Pan)
                                    {
                                        PanChanel[trackEvent.Event.Channel - 1] = controlchange.ControllerValue;
                                    }
                                    // Other midi event
                                    if (LogEvents)
                                    {
                                        Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Control {0} {1}", controlchange.Controller, controlchange.ControllerValue));
                                    }
                                }
                                else if (trackEvent.Event.CommandCode == MidiCommandCode.PatchChange)
                                {
                                    PatchChangeEvent change = (PatchChangeEvent)trackEvent.Event;
                                    PatchChanel[trackEvent.Event.Channel - 1] = trackEvent.Event.Channel == 10 ? 0 : change.Patch;
                                    if (LogEvents)
                                    {
                                        Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Patch   {0,3:000} {1}", change.Patch, PatchChangeEvent.GetPatchName(change.Patch)));
                                    }
                                }
                                else if (trackEvent.Event.CommandCode == MidiCommandCode.MetaEvent)
                                {
                                    MetaEvent meta = (MetaEvent)trackEvent.Event;
                                    switch (meta.MetaEventType)
                                    {
                                    case MetaEventType.SetTempo:
                                        if (EnableChangeTempo)
                                        {
                                            TempoEvent tempo = (TempoEvent)meta;
                                            //NewQuarterPerMinuteValue = tempo.Tempo;
                                            ChangeTempo(tempo.Tempo);
                                            //if (LogEvents)Debug.Log(BuildInfoTrack(trackEvent) + string.Format("SetTempo   {0} MicrosecondsPerQuarterNote:{1}", tempo.Tempo, tempo.MicrosecondsPerQuarterNote));
                                        }
                                        break;

                                    case MetaEventType.SequenceTrackName:
                                        if (!string.IsNullOrEmpty(SequenceTrackName))
                                        {
                                            SequenceTrackName += "\n";
                                        }
                                        SequenceTrackName += string.Format("T{0,2:00} {1}", trackEvent.IndexTrack, ((TextEvent)meta).Text);
                                        if (LogEvents)
                                        {
                                            Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Sequence   '{0}'", ((TextEvent)meta).Text));
                                        }
                                        break;

                                    case MetaEventType.ProgramName:
                                        ProgramName += ((TextEvent)meta).Text + " ";
                                        if (LogEvents)
                                        {
                                            Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Program   '{0}'", ((TextEvent)meta).Text));
                                        }
                                        break;

                                    case MetaEventType.TrackInstrumentName:
                                        if (!string.IsNullOrEmpty(TrackInstrumentName))
                                        {
                                            TrackInstrumentName += "\n";
                                        }
                                        TrackInstrumentName += string.Format("T{0,2:00} {1}", trackEvent.IndexTrack, ((TextEvent)meta).Text);
                                        if (LogEvents)
                                        {
                                            Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Text      '{0}'", ((TextEvent)meta).Text));
                                        }
                                        break;

                                    case MetaEventType.TextEvent:
                                        TextEvent += ((TextEvent)meta).Text + " ";
                                        if (LogEvents)
                                        {
                                            Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Sequence  '{0}'", ((TextEvent)meta).Text));
                                        }
                                        break;

                                    case MetaEventType.Copyright:
                                        Copyright += ((TextEvent)meta).Text + " ";
                                        if (LogEvents)
                                        {
                                            Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Copyright '{0}'", ((TextEvent)meta).Text));
                                        }
                                        break;

                                    case MetaEventType.Lyric:     // lyric
                                    case MetaEventType.Marker:    // marker
                                    case MetaEventType.CuePoint:  // cue point
                                    case MetaEventType.DeviceName:
                                        break;
                                    }
                                    //Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Meta {0} {1}", meta.MetaEventType, meta.ToString()));
                                }
                                else
                                {
                                    // Other midi event
                                    //Debug.Log(string.Format("Track:{0} Channel:{1,2:00} CommandCode:{2,3:000} AbsoluteTime:{3,6:000000}", track, e.Channel, e.CommandCode.ToString(), e.AbsoluteTime));
                                }
                            }
                            else
                            {
                                // Out of time, exit for loop
                                break;
                            }
                        }

                        if (notes != null)
                        {
                            //if (CancelNextReadEvents)
                            //{
                            //    notes = null;
                            //    //Debug.Log("CancelNextReadEvents");
                            //    CancelNextReadEvents = false;
                            //}
                            //else
                            //if (notes.Count > 3 && (notes[notes.Count - 1].AbsoluteQuantize - notes[0].AbsoluteQuantize) > midifile.DeltaTicksPerQuarterNote * 8)
                            //{
                            //    //notes.RemoveRange(0, notes.Count - 1);
                            //    Debug.Log("--> Too much notes " + notes.Count + " timeFromStartMS:" + Convert.ToInt32(timeFromStartMS) + " Start:" + notes[0].AbsoluteQuantize + " Ecart:" + (notes[notes.Count - 1].AbsoluteQuantize - notes[0].AbsoluteQuantize) + " CurrentPulse:" + CurrentPulse);
                            //    //notes = null;
                            //}
                        }
                    }
                    else
                    {
                        // End of midi events
                        EndMidiEvent = true;
                    }
                }
            }
            catch (System.Exception ex)
            {
                MidiPlayerGlobal.ErrorDetail(ex);
            }
            return(notes);
        }
Exemple #17
0
        private static List <TimeSlice> ReadMidiFile(MidiFile mf, ICollection <int> tracksToSkip, double tempoRatio, bool skipDrums)
        {
            var timeSliceList = new List <TimeSlice>();

            var tempo = (int)Math.Round(120 * tempoRatio);

            Console.WriteLine("Default Tempo: {0}", tempo);

            var trackNumber = 0;

            foreach (var midiEventList in mf.Events)
            {
                Console.WriteLine("");
                Console.WriteLine("Track #{0}", trackNumber);
                Console.WriteLine("---------");

                if (tracksToSkip.Contains(trackNumber))
                {
                    trackNumber++;
                    continue;
                }

                Console.WriteLine("Track length: {0}", midiEventList.Count);

                var drumFilteredMidiEventList = midiEventList.Where(midiEvent => !skipDrums || (midiEvent.Channel != 10));

                foreach (var midiEvent in drumFilteredMidiEventList)
                {
                    if (midiEvent is TextEvent textEvent) // : MetaEvent
                    {
                        Console.WriteLine("{0}: {1}", textEvent.MetaEventType.ToString(), textEvent.Text);
                    }
                    else if (midiEvent is TimeSignatureEvent timeSignatureEvent) // : MetaEvent
                    {
                        //WriteWarningLine("TimeSignatureEvent", timeSignatureEvent.ToString());
                    }
                    else if (midiEvent is TrackSequenceNumberEvent trackSequenceNumberEvent) // : MetaEvent
                    {
                        WriteWarningLine("TrackSequenceNumberEvent", trackSequenceNumberEvent.ToString());
                    }
                    else if (midiEvent is KeySignatureEvent keySignatureEvent) // : MetaEvent
                    {
                        //WriteWarningLine("KeySignatureEvent", keySignatureEvent.ToString());
                    }
                    else if (midiEvent is TempoEvent tempoEvent) // : MetaEvent
                    {
                        tempo = (int)Math.Round(tempoEvent.Tempo * tempoRatio);
                        Console.WriteLine("Tempo: {0}", tempo);
                    }
                    else if (midiEvent is MetaEvent metaEvent)
                    {
                        if ((metaEvent.MetaEventType != MetaEventType.SequencerSpecific) && (metaEvent.MetaEventType != MetaEventType.EndTrack) && (metaEvent.MetaEventType != MetaEventType.MidiChannel) && (metaEvent.MetaEventType != MetaEventType.MidiPort))
                        {
                            WriteWarningLine("MetaEvent", metaEvent.ToString());
                        }
                    }
                    else if (midiEvent is ControlChangeEvent controlChangeEvent)
                    {
                        //WriteWarningLine("ControlChangeEvent", controlChangeEvent.ToString());
                    }
                    else if (midiEvent is PatchChangeEvent patchChangeEvent)
                    {
                        Console.WriteLine("Patch: {0}", PatchChangeEvent.GetPatchName(patchChangeEvent.Patch));

                        if (skipDrums && (patchChangeEvent.Patch >= 112))
                        {
                            Console.WriteLine("Skipping track...");
                            break;
                        }
                    }
                    else if (midiEvent is NoteOnEvent noteEvent1)
                    {
                        if (MidiEvent.IsNoteOff(noteEvent1) == false)
                        {
                            if (noteEvent1.OffEvent != null)
                            {
                                var ticksPerMinute      = mf.DeltaTicksPerQuarterNote * tempo;
                                var millisecondsPerTick = 60.0 * 1000.0 / ticksPerMinute;

                                var start = (int)Math.Round(noteEvent1.AbsoluteTime * millisecondsPerTick);
                                var stop  = (int)Math.Round(noteEvent1.OffEvent.AbsoluteTime * millisecondsPerTick);

                                timeSliceList.Add(new TimeSlice(start, stop, new Note(noteEvent1.NoteNumber, noteEvent1.Velocity)));
                            }
                            else
                            {
                                WriteWarningLine("NoteOnEvent", "No Corresponding Note Off Event");
                            }
                        }
                    }
                    else if (midiEvent is NoteEvent noteEvent)
                    {
                        if (noteEvent.CommandCode != MidiCommandCode.NoteOff)
                        {
                            WriteWarningLine("NoteEvent", noteEvent.ToString());
                        }
                    }
                    else
                    {
                        WriteWarningLine("MIDI Event Type", midiEvent.GetType().ToString());
                    }
                }

                trackNumber++;
            }

            timeSliceList.Sort(CompareTimeSlicesByStartTime);

            return(timeSliceList);
        }