Skip to content

Commit 4a46e1d

Browse files
authored
Implement pitch detection algorithm in getTunerFrequency (#5545)
Format AudioContext creation expression Minor formatting change in js/utils/synthutils.js: the AudioContext/WebKitAudioContext constructor call was collapsed from a multi-line expression into a single-line expression. No functional changes intended; only code style/whitespace adjusted.
1 parent 792de56 commit 4a46e1d

1 file changed

Lines changed: 40 additions & 26 deletions

File tree

js/utils/synthutils.js

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,21 @@ function Synth() {
535535
* @type {Object.<string, [number, number]>}
536536
*/
537537
this.noteFrequencies = {};
538+
/**
539+
* Tuner microphone input.
540+
* @type {Tone.UserMedia|null}
541+
*/
542+
this.tunerMic = null;
543+
/**
544+
* Tuner analyser for pitch detection.
545+
* @type {Tone.Analyser|null}
546+
*/
547+
this.tunerAnalyser = null;
548+
/**
549+
* Pitch detection function.
550+
* @type {function|null}
551+
*/
552+
this.detectPitch = null;
538553

539554
/**
540555
* Function to initialize a new Tone.js instance.
@@ -2379,8 +2394,8 @@ function Synth() {
23792394
this.tunerMic = new Tone.UserMedia();
23802395
await this.tunerMic.open();
23812396

2382-
const analyser = new Tone.Analyser("waveform", 2048);
2383-
this.tunerMic.connect(analyser);
2397+
this.tunerAnalyser = new Tone.Analyser("waveform", 2048);
2398+
this.tunerMic.connect(this.tunerAnalyser);
23842399

23852400
const YIN = (sampleRate, bufferSize = 2048, threshold = 0.1) => {
23862401
// Low-Pass Filter to remove high-frequency noise
@@ -2457,13 +2472,13 @@ function Synth() {
24572472
};
24582473
};
24592474

2460-
const detectPitch = YIN(Tone.context.sampleRate);
2475+
this.detectPitch = YIN(Tone.context.sampleRate);
24612476
let tunerMode = "chromatic"; // Add mode state
24622477
let targetPitch = { note: "A4", frequency: 440 }; // Default target pitch
24632478

24642479
const updatePitch = () => {
2465-
const buffer = analyser.getValue();
2466-
const pitch = detectPitch(buffer);
2480+
const buffer = this.tunerAnalyser.getValue();
2481+
const pitch = this.detectPitch(buffer);
24672482

24682483
if (pitch > 0) {
24692484
let note, cents;
@@ -2773,13 +2788,12 @@ function Synth() {
27732788
i < tempBlock._accidentalsWheel.navItems.length;
27742789
i++
27752790
) {
2776-
tempBlock._accidentalsWheel.navItems[
2777-
i
2778-
].navigateFunction = () => {
2779-
selectionState.accidental =
2780-
tempBlock._accidentalsWheel.navItems[i].title;
2781-
updateTargetNote();
2782-
};
2791+
tempBlock._accidentalsWheel.navItems[i].navigateFunction =
2792+
() => {
2793+
selectionState.accidental =
2794+
tempBlock._accidentalsWheel.navItems[i].title;
2795+
updateTargetNote();
2796+
};
27832797
}
27842798
}
27852799

@@ -2790,16 +2804,15 @@ function Synth() {
27902804
i < tempBlock._octavesWheel.navItems.length;
27912805
i++
27922806
) {
2793-
tempBlock._octavesWheel.navItems[
2794-
i
2795-
].navigateFunction = () => {
2796-
const octave =
2797-
tempBlock._octavesWheel.navItems[i].title;
2798-
if (octave && !isNaN(octave)) {
2799-
selectionState.octave = parseInt(octave);
2800-
updateTargetNote();
2801-
}
2802-
};
2807+
tempBlock._octavesWheel.navItems[i].navigateFunction =
2808+
() => {
2809+
const octave =
2810+
tempBlock._octavesWheel.navItems[i].title;
2811+
if (octave && !isNaN(octave)) {
2812+
selectionState.octave = parseInt(octave);
2813+
updateTargetNote();
2814+
}
2815+
};
28032816
}
28042817
}
28052818

@@ -3273,12 +3286,13 @@ function Synth() {
32733286
* @returns {number} The detected frequency in Hz
32743287
*/
32753288
this.getTunerFrequency = () => {
3276-
if (!this.tunerAnalyser) return 440; // Default to A4 if no analyser
3289+
if (!this.tunerAnalyser || !this.detectPitch) return 440; // Default to A4 if no analyser
32773290

32783291
const buffer = this.tunerAnalyser.getValue();
3279-
// TODO: Implement actual pitch detection algorithm
3280-
// For now, return a default value
3281-
return 440;
3292+
const pitch = this.detectPitch(buffer);
3293+
3294+
// Return detected pitch or default to A4
3295+
return pitch > 0 ? pitch : 440;
32823296
};
32833297

32843298
// Test function to verify tuner accuracy

0 commit comments

Comments
 (0)