예제 #1
0
            TreeNode(TreeNode parent_, int choiceIndex_)
            {
                parent      = parent_;
                choiceIndex = choiceIndex_;

                Choice choice = s_ChoiceSequence[Index][choiceIndex];

                fingerChord = choice.chord;
                staticCost  = choice.staticCost;
                wrists      = choice.wrists;
                note        = s_NoteSeq[Index];
                startTime   = note.start;
                timeUnit    = choice.deltaTime / s_BenchmarkDuration;

                leftFingers  = generateFingerStates(parent.leftFingers, -1, fingerChord, note, Index);
                rightFingers = generateFingerStates(parent.rightFingers, 1, fingerChord, note, Index);
            }
예제 #2
0
        Choice evaluateChordChoice(FingerChord chord, int index)
        {
            float deltaTime = index > 0 ? NoteSeq[index].start - NoteSeq[index - 1].start : 0;

            NoteChord note = NoteSeq[index];

            HandConfig.RangePair wrists = Config.getFingerChordWristRange(chord);

            double cost = 0;

            // wrist position naturality reward
            if (wrists.left != null)
            {
                float distance = Math.Abs(wrists.left.middle - -HandConfig.WristNaturePosition);
                cost = Math.Pow(distance / 14, 4) * CostCoeff.WRIST_POSITION_NATURALITY_REWARD;
            }

            if (wrists.right != null)
            {
                float distance = Math.Abs(wrists.right.middle - HandConfig.WristNaturePosition);
                cost = Math.Pow(distance / 14, 4) * CostCoeff.WRIST_POSITION_NATURALITY_REWARD;
            }

            // wrist crowd punish
            if (wrists.left != null && wrists.right != null)
            {
                float distance = Math.Max(Math.Abs(wrists.left.high - wrists.right.low), Math.Abs(wrists.right.high - wrists.left.low));
                if (distance < 5)
                {
                    cost += CostCoeff.WRIST_CROWD_PUNISH * (5f - distance) / 5f;
                }
            }

            foreach (Finger f in chord.Values)
            {
                // shift fingers punish
                if (Math.Abs((int)f) > 10)
                {
                    cost += CostCoeff.SHIFT_FINGERS_PUNISH;
                }
            }

            int leftFingerCount  = 0;
            int rightFingerCount = 0;

            foreach (var pair in chord)
            {
                if (pair.Value != Finger.EMPTY)
                {
                    // black key short punish
                    if (Piano.isBlackKey(pair.Key))
                    {
                        int finger = Math.Abs((int)pair.Value);
                        int first  = (int)Math.Floor(finger / 10f) - 1;
                        int second = finger % 10 - 1;

                        float sh = HandConfig.BlackKeyShort[second];
                        if (first >= 0)
                        {
                            sh = Math.Max(HandConfig.BlackKeyShort[first], sh);
                        }

                        cost += sh * CostCoeff.BLACK_KEY_SHORT_PUNISH;
                    }

                    if (pair.Value > Finger.EMPTY)
                    {
                        ++rightFingerCount;
                    }
                    else if (pair.Value < Finger.EMPTY)
                    {
                        ++leftFingerCount;
                    }
                }
                else
                {
                    // omit key punish
                    float importance = NotationUtils.getNoteImportanceInChord(note, pair.Key);
                    cost += CostCoeff.OMIT_KEY_PUNISH * importance;
                }
            }

            // multiple fingers punish
            if (leftFingerCount > 0)
            {
                float value = leftFingerCount / 5f;
                cost += CostCoeff.MULTIPLE_FINGERS_PUNISH * value * value;
            }
            if (rightFingerCount > 0)
            {
                float value = rightFingerCount / 5f;
                cost += CostCoeff.MULTIPLE_FINGERS_PUNISH * value * value;
            }

            return(new Choice {
                chord = chord, staticCost = cost, wrists = wrists, deltaTime = deltaTime, node = new TreeNodeChoice()
            });
        }