Ejemplo n.º 1
0
    public void GetRelativePitchDistanceTest()
    {
        // The distance must be computed on relative notes, i.e., the pitch must be taken modulo 12.
        Assert.AreEqual(0, MidiUtils.GetRelativePitchDistance(24, 48));

        // Shortest distance via 7 to 8 = 2
        Assert.AreEqual(2, MidiUtils.GetRelativePitchDistance(6, 8));
        // Shortest distance via 1, 0, 11, 10 = 4
        Assert.AreEqual(4, MidiUtils.GetRelativePitchDistance(2, 10));

        // No distance
        Assert.AreEqual(0, MidiUtils.GetRelativePitchDistanceSigned(5, 5));
        // Shortest signed distance from F to A -> 4
        Assert.AreEqual(4, MidiUtils.GetRelativePitchDistanceSigned(53, 69));
        // Shortest signed distance via 11, 0, 1, 2 -> 4
        Assert.AreEqual(4, MidiUtils.GetRelativePitchDistanceSigned(10, 2));
        // Shortest signed distance via 1, 0, 11, 10 -> -4
        Assert.AreEqual(-4, MidiUtils.GetRelativePitchDistanceSigned(2, 10));
        // Shortest signed distance via 5, 6, 7, 8 -> 4
        Assert.AreEqual(4, MidiUtils.GetRelativePitchDistanceSigned(4, 8));
        // Shortest signed distance via 7, 6, 5, 4 -> -4
        Assert.AreEqual(-4, MidiUtils.GetRelativePitchDistanceSigned(8, 4));
        // Shortest signed distance via 0 -> 1
        Assert.AreEqual(1, MidiUtils.GetRelativePitchDistanceSigned(11, 0));
        // Shortest signed distance via 11 -> -1
        Assert.AreEqual(-1, MidiUtils.GetRelativePitchDistanceSigned(0, 11));
        // Shortest signed distance from F to B -> 6 or -6
        Assert.IsTrue(MidiUtils.GetRelativePitchDistanceSigned(77, 59)
                      is - 6
                      or 6);
        // Shortest signed distance from A to D -> 5
        Assert.AreEqual(5, MidiUtils.GetRelativePitchDistanceSigned(45, 74));
        // Shortest signed distance from D to A -> -5
        Assert.AreEqual(-5, MidiUtils.GetRelativePitchDistanceSigned(74, 45));
    }
Ejemplo n.º 2
0
    private void HandlePitchEvent(PitchEvent pitchEvent, double currentBeat)
    {
        if (pitchEvent == null || pitchEvent.MidiNote <= 0)
        {
            if (lastRecordedNote != null)
            {
                HandleRecordedNoteEnded(currentBeat);
            }
        }
        else
        {
            if (lastRecordedNote != null)
            {
                if (MidiUtils.GetRelativePitchDistance(lastRecordedNote.RoundedMidiNote, pitchEvent.MidiNote) <= roundingDistance)
                {
                    // Continue singing on same pitch
                    HandleRecordedNoteContinued(currentBeat);
                }
                else
                {
                    // Continue singing on different pitch. Finish the last recorded note.
                    HandleRecordedNoteEnded(currentBeat);
                }
            }

            // The lastRecordedNote could be ended above, so the following null check is not redundant.
            if (lastRecordedNote == null && currentBeat >= nextNoteStartBeat)
            {
                // Start singing of a new note
                HandleRecordedNoteStarted(pitchEvent.MidiNote, currentBeat);
            }
        }
    }
Ejemplo n.º 3
0
    private int GetRoundedMidiNote(int recordedMidiNote, int targetMidiNote, int roundingDistance)
    {
        int distance = MidiUtils.GetRelativePitchDistance(recordedMidiNote, targetMidiNote);

        if (distance <= roundingDistance)
        {
            return(targetMidiNote);
        }
        else
        {
            return(recordedMidiNote);
        }
    }
Ejemplo n.º 4
0
    public void GetRelativePitchDistanceTest()
    {
        // The distance must be computed on relative notes, i.e., the pitch must be taken modulo 12.
        int distanceSamePitchDifferentOctaves = MidiUtils.GetRelativePitchDistance(24, 48);

        Assert.AreEqual(0, distanceSamePitchDifferentOctaves);

        // Shortest distance via 7 to 8 = 2
        int distance1 = MidiUtils.GetRelativePitchDistance(6, 8);

        Assert.AreEqual(2, distance1);

        // Shortest distance via 1, 0, 11, 10 = 4
        int distance2 = MidiUtils.GetRelativePitchDistance(2, 10);

        Assert.AreEqual(4, distance2);
    }
Ejemplo n.º 5
0
    private void HandlePitchEvent(PitchEvent pitchEvent, double currentBeat, bool updateUi)
    {
        // Stop recording
        if (pitchEvent == null || pitchEvent.MidiNote <= 0)
        {
            if (lastRecordedNote != null)
            {
                HandleRecordedNoteEnded(currentBeat);
            }
            return;
        }

        // Start new recorded note
        if (lastRecordedNote == null)
        {
            HandleRecordedNoteStarted(pitchEvent.MidiNote, currentBeat, updateUi);
            return;
        }

        // Continue or finish existing recorded note. Possibly starting new note to change pitch.
        bool isTargetNoteHitNow = MidiUtils.GetRelativePitchDistance(lastRecordedNote.TargetNote.MidiNote, pitchEvent.MidiNote) <= roundingDistance;

        if (isTargetNoteHitNow && !IsTargetNoteHit(lastRecordedNote))
        {
            // Jump from a wrong pitch to correct pitch.
            // Otherwise, the rounding could tend towards the wrong pitch
            // when the player starts a note with the wrong pitch.
            HandleRecordedNoteEnded(currentBeat);
            HandleRecordedNoteStarted(pitchEvent.MidiNote, currentBeat, updateUi);
        }
        else if (MidiUtils.GetRelativePitchDistance(lastRecordedNote.RoundedMidiNote, pitchEvent.MidiNote) <= roundingDistance)
        {
            // Earned a joker for continued correct singing.
            if (IsTargetNoteHit(lastRecordedNote) && availableJokerCount < MaxJokerCount)
            {
                availableJokerCount++;
            }

            // Continue singing on same pitch
            HandleRecordedNoteContinued(pitchEvent.MidiNote, currentBeat, updateUi);
        }
        else
        {
            // Changed pitch while singing.
            if (!isTargetNoteHitNow &&
                IsTargetNoteHit(lastRecordedNote) &&
                availableJokerCount > 0)
            {
                // Because of the joker, this beat is still counted as correct although it is not. The joker is gone.
                availableJokerCount--;
                usedJokerCount++;
                HandleRecordedNoteContinued(lastRecordedNote.RecordedMidiNote, currentBeat, updateUi);
            }
            else
            {
                // Continue singing on different pitch.
                HandleRecordedNoteEnded(currentBeat);
                HandleRecordedNoteStarted(pitchEvent.MidiNote, currentBeat, updateUi);
            }
        }
    }