private void OnBeatAnalyzed(PlayerPitchTracker.BeatAnalyzedEvent beatAnalyzedEvent) { // Check if pitch was detected where a note is expected in the song if (beatAnalyzedEvent.PitchEvent == null || beatAnalyzedEvent.NoteAtBeat == null) { return; } if (beatAnalyzedEvent.Beat < NextBeatToScore) { return; } Note analyzedNote = beatAnalyzedEvent.NoteAtBeat; // Check if note was hit if (MidiUtils.GetRelativePitch(beatAnalyzedEvent.RoundedMidiNote) != MidiUtils.GetRelativePitch(analyzedNote.MidiNote)) { return; } // The beat was sung correctly. if (!ScoreData.NoteToNoteScoreMap.TryGetValue(analyzedNote, out NoteScore noteScore)) { noteScore = new NoteScore(analyzedNote); ScoreData.NoteToNoteScoreMap.Add(analyzedNote, noteScore); } noteScore.CorrectlySungBeats++; Sentence analyzedSentence = beatAnalyzedEvent.NoteAtBeat.Sentence; if (!ScoreData.SentenceToSentenceScoreMap.TryGetValue(analyzedSentence, out SentenceScore sentenceScore)) { sentenceScore = new SentenceScore(analyzedSentence); ScoreData.SentenceToSentenceScoreMap.Add(analyzedSentence, sentenceScore); } if (analyzedNote.IsNormal) { ScoreData.CorrectNormalNoteLengthTotal++; sentenceScore.CorrectlySungNormalBeats++; } else if (analyzedNote.IsGolden) { ScoreData.CorrectGoldenNoteLengthTotal++; sentenceScore.CorrectlySungGoldenBeats++; } }
private void OnBeatAnalyzed(PlayerPitchTracker.BeatAnalyzedEvent beatAnalyzedEvent) { // Check if pitch was detected where a note is expected in the song if (beatAnalyzedEvent.PitchEvent == null || beatAnalyzedEvent.NoteAtBeat == null) { return; } if (beatAnalyzedEvent.Beat < NextBeatToScore) { return; } Note analyzedNote = beatAnalyzedEvent.NoteAtBeat; // Check if note was hit if (MidiUtils.GetRelativePitch(beatAnalyzedEvent.RoundedRecordedMidiNote) != MidiUtils.GetRelativePitch(analyzedNote.MidiNote)) { return; } // The beat was sung correctly. if (!ScoreData.NoteToNoteScoreMap.TryGetValue(analyzedNote, out NoteScore noteScore)) { noteScore = new NoteScore(analyzedNote); ScoreData.NoteToNoteScoreMap.Add(analyzedNote, noteScore); } noteScore.CorrectlySungBeats++; Sentence analyzedSentence = beatAnalyzedEvent.NoteAtBeat.Sentence; if (!ScoreData.SentenceToSentenceScoreMap.TryGetValue(analyzedSentence, out SentenceScore sentenceScore)) { sentenceScore = CreateSentenceScore(analyzedSentence); ScoreData.SentenceToSentenceScoreMap.Add(analyzedSentence, sentenceScore); } if (IsPerfectHit(beatAnalyzedEvent)) { ScoreData.GetBeatData(analyzedNote).IfNotNull(it => it.PerfectBeats++); sentenceScore.GetBeatData(analyzedNote).IfNotNull(it => it.PerfectBeats++); } else if (IsGoodHit(beatAnalyzedEvent)) { ScoreData.GetBeatData(analyzedNote).IfNotNull(it => it.GoodBeats++); sentenceScore.GetBeatData(analyzedNote).IfNotNull(it => it.GoodBeats++); } }
private int GetCorrectlySungNoteLength(RecordedNote recordedNote) { if (recordedNote.TargetNote == null) { return(0); } if (MidiUtils.GetRelativePitch(recordedNote.TargetNote.MidiNote) != MidiUtils.GetRelativePitch(recordedNote.RoundedMidiNote)) { return(0); } int correctlySungNoteLength = (int)(recordedNote.EndBeat - recordedNote.StartBeat); return(correctlySungNoteLength); }
public static int GetRelativePitchDistanceSigned(int fromMidiNote, int toMidiNote) { int toRelativeMidiNote = MidiUtils.GetRelativePitch(toMidiNote); int fromRelativeMidiNote = MidiUtils.GetRelativePitch(fromMidiNote); // Distance when going from 2 to 10 via 3, 4, 5... -> (8) // Distance when going from 10 to 2 via 9, 8, 7... -> (-8) int distanceUnwrapped = toRelativeMidiNote - fromRelativeMidiNote; // Distance when going from 2 to 10 via 1, 0, 11, 10 -> (-4) // Distance when going from 10 to 2 via 11, 0, 1, 2 -> (4) int distanceWrapped = distanceUnwrapped >= 0 ? distanceUnwrapped - 12 : distanceUnwrapped + 12; int distance = Math.Abs(distanceUnwrapped) < Math.Abs(distanceWrapped) ? distanceUnwrapped : distanceWrapped; return(distance); }
void Update() { if (songAudioPlayer.PositionInSongInMillis <= 0) { return; } PitchEvent pitchEvent = playerPitchTracker.GetPitchEventOfSamples(micSampleRecorder.MicSamples.Length - 1 - samplesPerBeat, micSampleRecorder.MicSamples.Length - 1); if (pitchEvent != null) { // Shift midi note to octave of last recorded midi note (can be different because PlayerPitchTracker is rounding towards the target note) int midiNote = lastRecordedRoundedMidiNote > 0 ? MidiUtils.GetRelativePitch(pitchEvent.MidiNote) + (12 * (MidiUtils.GetOctave(lastRecordedRoundedMidiNote) + 1)) : pitchEvent.MidiNote; UpdatePosition(midiNote); } }
private void CheckPerfectlySungNote(RecordedNote lastRecordedNote) { if (lastRecordedNote == null || lastRecordedNote.TargetNote == null) { return; } Note targetNote = lastRecordedNote.TargetNote; int targetMidiNoteRelative = MidiUtils.GetRelativePitch(targetNote.MidiNote); int recordedMidiNoteRelative = MidiUtils.GetRelativePitch(lastRecordedNote.RoundedMidiNote); bool isPerfect = ((targetMidiNoteRelative == recordedMidiNoteRelative) && (targetNote.StartBeat >= lastRecordedNote.StartBeat) && (targetNote.EndBeat <= lastRecordedNote.EndBeat)); if (isPerfect) { playerUiController.CreatePerfectNoteEffect(targetNote); } }
private void UpdateMidiNoteLines() { horizontalGridImage.ClearTexture(); int minMidiNote = noteArea.MinMidiNoteInViewport; int maxMidiNote = noteArea.MaxMidiNoteInViewport; for (int midiNote = minMidiNote; midiNote <= maxMidiNote; midiNote++) { // Notes are drawn on lines and between lines alternatingly. bool hasLine = (midiNote % 2 == 0); if (hasLine) { Color color = (MidiUtils.GetRelativePitch(midiNote) == 0) ? lineHighlightColor : lineNormalColor; DrawHorizontalGridLine(midiNote, color); } } horizontalGridImage.ApplyTexture(); }
private void UpdateMidiNoteLines() { dynamicTexture.ClearTexture(); int minMidiNote = noteAreaControl.MinMidiNoteInCurrentViewport; int maxMidiNote = noteAreaControl.MaxMidiNoteInCurrentViewport; for (int midiNote = minMidiNote; midiNote <= maxMidiNote; midiNote++) { // Notes are drawn on lines and between lines alternatingly. bool hasLine = (midiNote % 2 == 0); if (hasLine) { Color color = (MidiUtils.GetRelativePitch(midiNote) == 0) ? NoteAreaHorizontalRulerControl.highlightLineColor : NoteAreaHorizontalRulerControl.normalLineColor; DrawHorizontalGridLine(midiNote, color); } } dynamicTexture.ApplyTexture(); }
private bool IsPerfectHit(PlayerPitchTracker.BeatAnalyzedEvent beatAnalyzedEvent) { return(MidiUtils.GetRelativePitch(beatAnalyzedEvent.NoteAtBeat.MidiNote) == MidiUtils.GetRelativePitch(beatAnalyzedEvent.RecordedMidiNote)); }
private void CreateUiRecordedNote(RecordedNote recordedNote, bool useRoundedMidiNote) { if (recordedNote.StartBeat == recordedNote.EndBeat) { return; } // Pitch detection algorithms often have issues finding the correct octave. However, the octave is irrelevant for scores. // When notes are drawn far away from the target note because the pitch detection got the wrong octave then it looks wrong. // Thus, only the relative pitch of the roundedMidiNote is used and drawn on the octave of the target note. int midiNote; if (useRoundedMidiNote) { int relativeSignedDistance = MidiUtils.GetRelativePitchDistanceSigned(recordedNote.TargetNote.MidiNote, recordedNote.RoundedMidiNote); int roundedMidiNoteOnOctaveOfTargetNote = recordedNote.TargetNote.MidiNote + relativeSignedDistance; if (MidiUtils.GetRelativePitch(recordedNote.RoundedMidiNote) != MidiUtils.GetRelativePitch(roundedMidiNoteOnOctaveOfTargetNote)) { // Should never happen Debug.LogError($"The displayed midi note does not correspond to the rounded recorded midi note:" + $"recorded {recordedNote.RoundedMidiNote}, target: {recordedNote.TargetNote.MidiNote}, displayed: {roundedMidiNoteOnOctaveOfTargetNote}"); } midiNote = roundedMidiNoteOnOctaveOfTargetNote; } else { midiNote = recordedNote.RecordedMidiNote; } UiRecordedNote uiNote = Instantiate(uiRecordedNotePrefab, uiRecordedNotesContainer); uiNote.RecordedNote = recordedNote; uiNote.StartBeat = recordedNote.StartBeat; uiNote.TargetEndBeat = recordedNote.EndBeat; // Draw already a portion of the note uiNote.LifeTimeInSeconds = Time.deltaTime; uiNote.EndBeat = recordedNote.StartBeat + (uiNote.LifeTimeInSeconds * beatsPerSecond); uiNote.MidiNote = midiNote; if (micProfile != null) { uiNote.SetColorOfMicProfile(micProfile); } Text uiNoteText = uiNote.lyricsUiText; if (showPitchOfNotes) { string pitchName = MidiUtils.GetAbsoluteName(midiNote); uiNoteText.text = " (" + pitchName + ")"; } else { uiNoteText.text = ""; } RectTransform uiNoteRectTransform = uiNote.RectTransform; PositionUiNote(uiNoteRectTransform, midiNote, uiNote.StartBeat, uiNote.EndBeat); uiRecordedNotes.Add(uiNote); recordedNoteToUiRecordedNotesMap.AddInsideList(recordedNote, uiNote); }