Ejemplo n.º 1
0
            double evaluateFingerObstacleCost(FingerState state, float minPreparation, NoteChord obsNote, float startPosition, int startHeight, int pitch)
            {
                float  deltaX   = startPosition - Piano.KeyPositions[pitch];
                float  deltaY   = startHeight - Piano.getKeyHeight(pitch);
                double distance = Math.Min(Math.Sqrt(deltaX * deltaX + deltaY * deltaY), 5) + 1;

                float prepareTime = startTime - minPreparation;

                float importance = NotationUtils.getNoteImportanceInChord(obsNote, state.Pitch);

                debug += string.Format("O{0},{1},{2},{3};", state.Pitch, prepareTime, state.Release, state.Press);

                if (prepareTime >= state.Release)
                {
                    double coeff = CostCoeff.FINGER_MOVE_SPEED_PUNISH * Math.Pow(0.1, (startTime - state.Release) / minPreparation);
                    return(coeff * distance);
                }
                else if (prepareTime >= state.Press)
                {
                    double speedCost  = CostCoeff.FINGER_MOVE_SPEED_PUNISH * distance;
                    double cutoffCost = CostCoeff.NOTE_CUTOFF_PUNISH * importance * (state.Release - prepareTime) / (state.Release - state.Press);

                    return(speedCost + cutoffCost);
                }
                else
                {
                    return(CostCoeff.OMIT_KEY_PUNISH * importance);
                }
            }
Ejemplo n.º 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()
            });
        }