private void OnPitchDetected(PitchEvent pitchEvent) { if (pitchEvent == null || !isCalibrationInProgress || pauseTime > 0) { return; } string targetMidiNoteName = midiNoteNames[currentIteration]; if (MidiUtils.GetAbsoluteName(pitchEvent.MidiNote) == targetMidiNoteName) { audioSource.Stop(); float delayInSeconds = Time.time - startTimeInSeconds; int delayInMillis = (int)(delayInSeconds * 1000); delaysInMillis.Add(delayInMillis); Debug.Log($"Mic delay calibration - delay of iteration {currentIteration}: {delayInMillis}"); currentIteration++; if (currentIteration >= midiNoteNames.Count) { OnEndCalibration(); } else { // Wait a bit for silence before the next iteration. pauseTime = 0.5f; } } else { Debug.Log("Mic delay calibration - wrong pitch: " + MidiUtils.GetAbsoluteName(pitchEvent.MidiNote)); } }
private void CreateUiRecordedNote(RecordedNote recordedNote, bool useRoundedMidiNote) { if (recordedNote.StartBeat == recordedNote.EndBeat) { return; } int midiNote = (useRoundedMidiNote) ? recordedNote.RoundedMidiNote : recordedNote.RecordedMidiNote; UiRecordedNote uiNote = Instantiate(uiRecordedNotePrefab, uiRecordedNotesContainer); if (micProfile != null) { uiNote.SetColorOfMicProfile(micProfile); } Text uiNoteText = uiNote.GetComponentInChildren <Text>(); if (showPitchOfNotes) { string pitchName = MidiUtils.GetAbsoluteName(midiNote); uiNoteText.text = " (" + pitchName + ")"; } else { uiNoteText.text = ""; } RectTransform uiNoteRectTransform = uiNote.GetComponent <RectTransform>(); PositionUiNote(uiNoteRectTransform, midiNote, recordedNote.StartBeat, recordedNote.EndBeat); recordedNoteToUiRecordedNoteMap[recordedNote] = uiNote; }
private void TestPitchDetection(Func <int, IAudioSamplesAnalyzer> audioSamplesAnalyzerProvider) { MicProfile micProfile = CreateDummyMicProfile(); string assetsPath = Application.dataPath; string sineWaveToneDir = assetsPath + "/Common/Audio/SineWaveTones/"; Dictionary <string, string> pathToExpectedMidiNoteNameMap = new(); pathToExpectedMidiNoteNameMap.Add(sineWaveToneDir + "sine-wave-a3-220hz.ogg", "A3"); pathToExpectedMidiNoteNameMap.Add(sineWaveToneDir + "sine-wave-a4-440hz.ogg", "A4"); pathToExpectedMidiNoteNameMap.Add(sineWaveToneDir + "sine-wave-a5-880hz.ogg", "A5"); pathToExpectedMidiNoteNameMap.Add(sineWaveToneDir + "sine-wave-c2-61,74hz.ogg", "C2"); pathToExpectedMidiNoteNameMap.Add(sineWaveToneDir + "sine-wave-c4-261,64hz.ogg", "C4"); pathToExpectedMidiNoteNameMap.Add(sineWaveToneDir + "sine-wave-c6-1046,50hz.ogg", "C6"); foreach (KeyValuePair <string, string> pathAndNoteName in pathToExpectedMidiNoteNameMap) { // Load the audio clip string uri = "file://" + pathAndNoteName.Key; AudioClip audioClip = AudioUtils.GetAudioClipUncached(uri, false); float[] samples = new float[audioClip.samples]; audioClip.GetData(samples, 0); // Analyze the samples IAudioSamplesAnalyzer audioSamplesAnalyzer = audioSamplesAnalyzerProvider(audioClip.frequency); PitchEvent pitchEvent = audioSamplesAnalyzer.ProcessAudioSamples(samples, 0, samples.Length - 1, micProfile); // Check result Assert.NotNull(pitchEvent, $"No pitch detected when analyzing audio resource {uri}"); string expectedName = pathAndNoteName.Value; string analyzedName = MidiUtils.GetAbsoluteName(pitchEvent.MidiNote); Assert.AreEqual(expectedName, analyzedName, $"Expected {expectedName} but was {analyzedName} when analyzing audio resource {uri}"); } }
protected 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 && recordedNote.TargetNote != null) { midiNote = MidiUtils.GetMidiNoteOnOctaveOfTargetMidiNote(recordedNote.RoundedMidiNote, recordedNote.TargetNote.MidiNote); } 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); }
private void OnPitchDetected(int midiNote) { // Show the note that has been detected if (midiNote > 0) { currentNoteLabel.text = "Note: " + MidiUtils.GetAbsoluteName(midiNote); } else { currentNoteLabel.text = "Note: unkown"; } }
private void OnPitchDetected(PitchEvent pitchEvent) { // Show the note that has been detected if (pitchEvent != null && pitchEvent.MidiNote > 0) { currentNoteLabel.text = "Note: " + MidiUtils.GetAbsoluteName(pitchEvent.MidiNote); } else { currentNoteLabel.text = "Note: ?"; } }
private void UpdateLastMidiNoteFields(PitchEvent pitchEvent) { if (pitchEvent == null) { lastMidiNoteName = ""; lastMidiNote = 0; } else { lastMidiNoteName = MidiUtils.GetAbsoluteName(pitchEvent.MidiNote); lastMidiNote = pitchEvent.MidiNote; } }
public void SyncWithNote() { bool isSelected = selectionController.IsSelected(Note); goldenNoteImageOverlay.gameObject.SetActive(Note.IsGolden); SetLyrics(Note.Text); SetSelected(isSelected); pitchLabel.text = MidiUtils.GetAbsoluteName(Note.MidiNote); if (Note.Sentence != null && Note.Sentence.Voice != null) { Color color = songEditorSceneController.GetColorForVoice(Note.Sentence.Voice); SetColor(color); } }
private void OnPitchDetected(PitchEvent pitchEvent) { // Show the note that has been detected if (pitchEvent != null && pitchEvent.MidiNote > 0) { currentNoteLabel.text = TranslationManager.GetTranslation(R.Messages.options_note, "value", MidiUtils.GetAbsoluteName(pitchEvent.MidiNote)); } else { currentNoteLabel.text = TranslationManager.GetTranslation(R.Messages.options_note, "value", "?"); } }
public void GetAbsoluteNameTest() { Dictionary <int, string> midiNoteToAbsoluteNameMap = new Dictionary <int, string>(); midiNoteToAbsoluteNameMap.Add(36, "C2"); midiNoteToAbsoluteNameMap.Add(57, "A3"); midiNoteToAbsoluteNameMap.Add(60, "C4"); midiNoteToAbsoluteNameMap.Add(69, "A4"); midiNoteToAbsoluteNameMap.Add(81, "A5"); midiNoteToAbsoluteNameMap.Add(84, "C6"); foreach (KeyValuePair <int, string> midiNoteAndName in midiNoteToAbsoluteNameMap) { string noteName = MidiUtils.GetAbsoluteName(midiNoteAndName.Key); Assert.AreEqual(midiNoteAndName.Value, noteName); } }
private void DisplayNote(Sentence sentence, Note note) { UiNote uiNote = Instantiate(uiNotePrefab); uiNote.transform.SetParent(transform); uiNote.Note = note; uiNote.isGolden = note.IsGolden; Text uiNoteText = uiNote.GetComponentInChildren <Text>(); uiNoteText.text = note.Text + " (" + MidiUtils.GetAbsoluteName(note.MidiNote) + ")"; RectTransform uiNoteRectTransform = uiNote.GetComponent <RectTransform>(); PositionUiNote(uiNoteRectTransform, note.MidiNote, note.StartBeat, note.EndBeat); }
private void CreateLabelForMidiNote(int midiNote) { Text uiText = Instantiate(labelPrefab, labelContainer); RectTransform label = uiText.GetComponent <RectTransform>(); float y = (float)noteArea.GetVerticalPositionForMidiNote(midiNote); float anchorHeight = noteArea.HeightForSingleNote; label.anchorMin = new Vector2(0, y - (anchorHeight / 2f)); label.anchorMax = new Vector2(1, y + (anchorHeight / 2f)); label.anchoredPosition = Vector2.zero; label.sizeDelta = new Vector2(0, 0); string midiNoteName = MidiUtils.GetAbsoluteName(midiNote); uiText.text = midiNoteName; }
private void DisplayRecordedNote(RecordedNote recordedNote, bool useRoundedNote = true) { int midiNote = (useRoundedNote) ? recordedNote.RoundedMidiNote : recordedNote.RecordedMidiNote; UiRecordedNote uiNote = Instantiate(uiRecordedNotePrefab); uiNote.transform.SetParent(transform); Text uiNoteText = uiNote.GetComponentInChildren <Text>(); uiNoteText.text = (useRoundedNote) ? MidiUtils.GetAbsoluteName(recordedNote.RoundedMidiNote) : MidiUtils.GetAbsoluteName(recordedNote.RecordedMidiNote); RectTransform uiNoteRectTransform = uiNote.GetComponent <RectTransform>(); PositionUiNote(uiNoteRectTransform, midiNote, recordedNote.StartBeat, recordedNote.EndBeat); }
protected virtual UiNote CreateUiNote(Note note) { if (note.StartBeat == note.EndBeat) { return(null); } UiNote uiNote = Instantiate(uiNotePrefab, uiNotesContainer); uiNote.Init(note, uiEffectsContainer); if (micProfile != null) { uiNote.SetColorOfMicProfile(micProfile); } Text uiNoteText = uiNote.lyricsUiText; string pitchName = MidiUtils.GetAbsoluteName(note.MidiNote); if (settings.GraphicSettings.showLyricsOnNotes && showPitchOfNotes) { uiNoteText.text = GetDisplayText(note) + " (" + pitchName + ")"; } else if (settings.GraphicSettings.showLyricsOnNotes) { uiNoteText.text = GetDisplayText(note); } else if (showPitchOfNotes) { uiNoteText.text = pitchName; } else { uiNoteText.text = ""; } RectTransform uiNoteRectTransform = uiNote.RectTransform; PositionUiNote(uiNoteRectTransform, note.MidiNote, note.StartBeat, note.EndBeat); noteToUiNoteMap[note] = uiNote; return(uiNote); }
private Label CreateLabelForMidiNote(int midiNote) { Label label = new(); label.AddToClassList("tinyFont"); label.enableRichText = false; label.style.position = new StyleEnum <Position>(Position.Absolute); label.style.unityTextAlign = new StyleEnum <TextAnchor>(TextAnchor.MiddleCenter); label.style.left = 0; string midiNoteName = MidiUtils.GetAbsoluteName(midiNote); label.text = midiNoteName; UpdateMidiNoteLabelPosition(label, midiNote); horizontalGridLabelContainer.Add(label); return(label); }
private void CreateUiNote(Note note) { if (note.StartBeat == note.EndBeat) { return; } UiNote uiNote = Instantiate(uiNotePrefab, uiNotesContainer); uiNote.Init(note, uiEffectsContainer); if (micProfile != null) { uiNote.SetColorOfMicProfile(micProfile); } Text uiNoteText = uiNote.GetComponentInChildren <Text>(); string pitchName = MidiUtils.GetAbsoluteName(note.MidiNote); if (showLyricsOfNotes && showPitchOfNotes) { uiNoteText.text = note.Text + " (" + pitchName + ")"; } else if (showLyricsOfNotes) { uiNoteText.text = note.Text; } else if (showPitchOfNotes) { uiNoteText.text = pitchName; } else { uiNoteText.text = ""; } RectTransform uiNoteRectTransform = uiNote.GetComponent <RectTransform>(); PositionUiNote(uiNoteRectTransform, note.MidiNote, note.StartBeat, note.EndBeat); }
public void TestPitchDetection() { MicProfile micProfile = CreateDummyMicProfile(); string assetsPath = Application.dataPath; string sineWaveToneDir = assetsPath + "/Editor/Tests/SineWaveTones/"; Dictionary <string, string> pathToExpectedMidiNoteNameMap = new Dictionary <string, string>(); pathToExpectedMidiNoteNameMap.Add(sineWaveToneDir + "sine-wave-a3-220hz.ogg", "A3"); pathToExpectedMidiNoteNameMap.Add(sineWaveToneDir + "sine-wave-a4-440hz.ogg", "A4"); pathToExpectedMidiNoteNameMap.Add(sineWaveToneDir + "sine-wave-a5-880hz.ogg", "A5"); pathToExpectedMidiNoteNameMap.Add(sineWaveToneDir + "sine-wave-c2-61,74hz.ogg", "C2"); pathToExpectedMidiNoteNameMap.Add(sineWaveToneDir + "sine-wave-c4-261,64hz.ogg", "C4"); pathToExpectedMidiNoteNameMap.Add(sineWaveToneDir + "sine-wave-c6-1046,50hz.ogg", "C6"); foreach (KeyValuePair <string, string> pathAndNoteName in pathToExpectedMidiNoteNameMap) { // Load the audio clip string path = pathAndNoteName.Key; AudioClip audioClip = AudioUtils.GetAudioClip(path); float[] samples = new float[audioClip.samples]; audioClip.GetData(samples, 0); // Analyze the samples IAudioSamplesAnalyzer audioSamplesAnalyzer = new CamdAudioSamplesAnalyzer(audioClip.frequency); audioSamplesAnalyzer.Enable(); PitchEvent pitchEvent = audioSamplesAnalyzer.ProcessAudioSamples(samples, samples.Length, micProfile); // Check result Assert.NotNull(pitchEvent, $"No pitch detected when analyzing {path}"); string expectedName = pathAndNoteName.Value; string analyzedName = MidiUtils.GetAbsoluteName(pitchEvent.MidiNote); Assert.AreEqual(expectedName, analyzedName, $"Expected {expectedName} but was {analyzedName} when analyzing {path}"); } }
private void HandleEndOfNote(MidiEvent midiEvent, Dictionary <int, Note> midiPitchToNoteUnderConstruction, List <Note> loadedNotes) { int midiPitch = midiEvent.parameter1; int deltaTimeInMillis = GetDeltaTimeInMillis(midiEvent); int endBeat = (int)Math.Round(BpmUtils.MillisecondInSongToBeat(songMeta, deltaTimeInMillis)); if (midiPitchToNoteUnderConstruction.TryGetValue(midiPitch, out Note existingNote)) { if (endBeat > existingNote.StartBeat) { existingNote.SetEndBeat(endBeat); loadedNotes.Add(existingNote); } else { Debug.LogWarning($"End beat {endBeat} is not after start beat {existingNote.StartBeat}. Skipping this note."); } midiPitchToNoteUnderConstruction.Remove(midiPitch); } else { Debug.LogWarning($"No Note for pitch {MidiUtils.GetAbsoluteName(midiPitch)} is being constructed. Ignoring this Note_Off event at {deltaTimeInMillis} ms."); } }