Beispiel #1
0
    public static NotationTrack[] parseMidiFile(Midi.Sequence file)
    {
        NotationTrack[] tracks = new NotationTrack[file.Count];

        Regex fingerPattern = null;

        for (int i = 0; i < file.Count; ++i)
        {
            tracks[i] = parseMidiTrack(file[i], file.Division, ref fingerPattern);
        }

        return(tracks);
    }
Beispiel #2
0
    public static NotationTrack parseMidiTrack(Midi.Track track, int division, ref Regex fingerPattern)
    {
        int microsecondsPerBeat = Midi.PpqnClock.DefaultTempo;

        float time = 0;

        TrackStatus    trackStatus = new TrackStatus();
        FingerChordMap fingerMap   = new FingerChordMap();

        List <Note> notes = new List <Note>();

        Regex fingerMetaPattern = new Regex("fingering-marker-pattern:(.*)");

        string name = "";

        foreach (Midi.MidiEvent e in track.Iterator())
        {
            time += e.DeltaTicks * microsecondsPerBeat / (division * 1000);

            switch (e.MidiMessage.MessageType)
            {
            case Midi.MessageType.Meta:
                Midi.MetaMessage mm = e.MidiMessage as Midi.MetaMessage;
                switch (mm.MetaType)
                {
                case Midi.MetaType.Tempo:
                    Midi.TempoChangeBuilder builder = new Midi.TempoChangeBuilder(mm);
                    microsecondsPerBeat = builder.Tempo;

                    break;

                case Midi.MetaType.Text:
                {
                    string text  = Encoding.Default.GetString(mm.GetBytes());
                    var    match = fingerMetaPattern.Match(text);
                    if (match.Success)
                    {
                        fingerPattern = new Regex(match.Groups[1].ToString());
                        Debug.LogFormat("Finger Pattern found: {0}", fingerPattern.ToString());
                    }
                }

                break;

                case Midi.MetaType.Marker:
                    if (fingerPattern != null)
                    {
                        string text  = Encoding.Default.GetString(mm.GetBytes());
                        var    match = fingerPattern.Match(text);
                        if (match.Success)
                        {
                            //Debug.LogFormat("Finger: {0}", text);
                            try
                            {
                                int    pitch  = int.Parse(match.Groups[1].ToString());
                                Finger finger = (Finger)int.Parse(match.Groups[2].ToString());

                                if (!fingerMap.ContainsKey(e.AbsoluteTicks))
                                {
                                    fingerMap[e.AbsoluteTicks] = new FingerChord();
                                }

                                fingerMap[e.AbsoluteTicks][pitch] = finger;
                            }
                            catch (System.Exception except)
                            {
                                Debug.LogWarningFormat("fingering marker parse failed: {0}, {1}", text, except.Message);
                            }
                        }
                        //else
                        //	Debug.LogWarningFormat("fail marker: {0}", text);
                    }

                    break;

                case Midi.MetaType.TrackName:
                    name = Encoding.Default.GetString(mm.GetBytes());

                    break;
                }

                break;

            case Midi.MessageType.Channel:
                Midi.ChannelMessage cm = e.MidiMessage as Midi.ChannelMessage;

                if (!trackStatus.ContainsKey(cm.MidiChannel))
                {
                    trackStatus[cm.MidiChannel] = new ChannelStatus();
                }

                var commandType = cm.Command;
                if (commandType == Midi.ChannelCommand.NoteOn && cm.Data2 == 0)
                {
                    commandType = Midi.ChannelCommand.NoteOff;
                }

                switch (commandType)
                {
                case Midi.ChannelCommand.NoteOn:
                {
                    int pitch    = cm.Data1;
                    int velocity = cm.Data2;

                    if (pitch >= Piano.PitchMin && pitch <= Piano.PitchMax)
                    {
                        trackStatus[cm.MidiChannel][pitch] = new PitchStatus {
                            tick = e.AbsoluteTicks, startTime = time, velocity = velocity
                        }
                    }
                    ;
                }

                break;

                case Midi.ChannelCommand.NoteOff:
                {
                    int pitch = cm.Data1;

                    if (!trackStatus[cm.MidiChannel].ContainsKey(pitch))
                    {
                        Debug.LogWarningFormat("Unexpected noteOff: {0}, {1}", e.AbsoluteTicks, pitch);
                    }
                    else
                    {
                        PitchStatus status = trackStatus[cm.MidiChannel][pitch];

                        Note note = new Note {
                            tick = status.tick, start = status.startTime, duration = time - status.startTime, pitch = pitch, velocity = status.velocity
                        };

                        if (fingerMap.ContainsKey(note.tick) && fingerMap[note.tick].ContainsKey(note.pitch))
                        {
                            note.finger = fingerMap[note.tick][note.pitch];
                        }

                        notes.Add(note);
                    }
                }

                break;
                }

                break;
            }
        }

        NotationTrack notation = new NotationTrack();

        notation.notes = notes.ToArray();
        notation.name  = name;

        return(notation);
    }
    public void run()
    {
        if (MidiSeq.Count == 0)
        {
            Debug.LogWarning("MIDI no track found.");
            return;
        }

        if (!HandConfigLib)
        {
            HandConfigLib = GetComponent <HandConfigLibrary>();
        }

        if (!HandConfigLib)
        {
            Debug.LogError("HandConfigLibrary is null.");
        }

        var trackMap = HandTracksMap;

        Fingering[] results     = new Fingering[trackMap.Count];
        int         resultIndex = 0;

        foreach (var pair in trackMap)
        {
            if (pair.Key >= Hands.Length)
            {
                Debug.LogErrorFormat("Hand index {0} out of hand config range.", pair.Key);
                return;
            }

            Hand hand = Hands[pair.Key];

            int[] trackList = pair.Value;

            NotationTrack[] tracks = new NotationTrack[trackList.Length];
            for (int track = 0; track < trackList.Length; ++track)
            {
                tracks[track] = Notation[trackList[track]];
            }

            Navigator.Track                   = NotationTrack.merge(tracks);
            Navigator.Config                  = HandConfigLib.getConfig(hand.Config);
            Navigator.KeepConstraints         = KeepConstraints;
            Navigator.MinStepCount            = StepCountMin;
            Navigator.MaxStepCount            = StepCountMax;
            Navigator.BubbleLength            = BubbleLength;
            Navigator.EstimationStepIncrement = EstimationStepIncrement;

            if (Navigator.Config == null)
            {
                Debug.LogErrorFormat("Hand config of {0} is null.", hand.Config);
                return;
            }

            Navigator.HandType      = hand.Type;
            Navigator.AdaptionSpeed = hand.AdaptionSpeed;

            results[resultIndex++] = Navigator.run();

            if (DumpTree)
            {
#if UNITY_EDITOR
                UnityEditor.EditorUtility.DisplayProgressBar("FingeringGenerator", "DumpTree ...", 0);
#endif

                FileStream file = new FileStream(Application.dataPath + "/Editor/Log/FingeringNavigatorTreeDump" + pair.Key.ToString() + ".txt", FileMode.Create);

                byte[] bytes = System.Text.Encoding.Default.GetBytes(Navigator.getTreeJsonDump());
#if UNITY_EDITOR
                UnityEditor.EditorUtility.DisplayProgressBar("FingeringGenerator", string.Format("DumpTree {0:n} bytes...", bytes.Length), 0);
#endif
                file.Write(bytes, 0, bytes.Length);

                file.Close();

#if UNITY_EDITOR
                UnityEditor.EditorUtility.ClearProgressBar();
#endif
            }

            /*// dump leaf nodes
             * {
             *      FileStream file = new FileStream(Application.dataPath + "/Editor/Log/leaves.txt", FileMode.Create);
             *
             *      file.WriteByte((byte)'[');
             *      List<FingeringNavigator.TreeNode> leaves = Navigator.TreeLeaves;
             *      leaves.Sort(delegate(FingeringNavigator.TreeNode node1, FingeringNavigator.TreeNode node2)
             *      {
             *              double cost1 = node1.CommittedCost;
             *              double cost2 = node2.CommittedCost;
             *
             *              return cost1.CompareTo(cost2);
             *      });
             *      foreach(var leaf in leaves)
             *      {
             *              byte[] bytes = System.Text.Encoding.Default.GetBytes(leaf.JsonDump);
             *              file.Write(bytes, 0, bytes.Length);
             *              file.WriteByte((byte)',');
             *      }
             *      file.WriteByte((byte)'{');
             *      file.WriteByte((byte)'}');
             *      file.WriteByte((byte)']');
             *
             *      file.Close();
             * }*/
        }

        NotationUtils.appendFingeringToMidiFile(MidiSeq, results);
    }