ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

揭秘 NoteLite 麦克风音准检测:浏览器里 Pitchy 单音检测与门控机制的完整原理

揭秘 NoteLite 麦克风音准检测:浏览器里 Pitchy 单音检测与门控机制的完整原理

【免费下载链接】NoteLite

Open-source OMR and guided music practice: turn sheet music PDFs/images into MusicXML/MIDI, refine scores, and practice with MIDI or microphone feedback.

项目地址:https://gitcode.com/gh_mirrors/no/NoteLite
点击查看免费下载

NoteLite 是一款开源 OMR 与音乐练习工具:把乐谱 PDF/图片识别成 MusicXML,然后跟随乐谱练习,用 MIDI 或麦克风获得实时反馈。本文完整拆解它的麦克风音准检测原理——浏览器内基于 Pitchy 的单音检测如何从一段波形中算出音高与音分偏差,以及PitchGate门控机制如何保证"持续音不会被误判成重复起音"。全程无需上传任何音频,适合想理解"浏览器音准检测怎么做"的新手。

🎤 为什么音准检测可以直接跑在浏览器里

NoteLite 的练习模式(practice workspace)把乐谱排版和音高检测都放在本地完成:麦克风采样在浏览器内处理,没有遥测、上传、CDN 或云端 API 调用。对新手来说,这意味着:

  • 练琴音频不离开设备,隐私友好;
  • 不需要安装额外插件,桌面端由本地浏览器窗口承载;
  • 音准检测与 MIDI 输入走同一个判定层,反馈逻辑一致。

三种演奏输入的分工如下(来自 README.md):

输入方式检测能力适用场景
麦克风Pitchy 单音检测 + 置信度/稳定性门控,一次只接受一个音高独奏单音旋律,远离伴奏音源
MIDI 乐器音符音高匹配、和弦、错音/漏音与起音时机键盘类、含和弦的声部
电脑键盘功能演示输入(A–K 键对应 C4–C5)快速体验跟随逻辑

麦克风输入有一个硬限制:所选段落若含和弦或重叠音(多音),NoteLite 会直接拒绝并要求改用 MIDI,因为 Pitchy 是单声部检测器。

从 PDF 到可练习的乐谱

在谈音频之前,先看图了解乐谱数据从哪来:OMR 引擎先把扫描图识别成 Book,再导出 MusicXML 供练习界面使用——麦克风检测的"标准答案"就来自这份 MusicXML。

🔊 第一步:拿到"干净"的麦克风波形

检测质量从采集端就开始控制。NoteLite 请求麦克风时主动关闭浏览器自带的回声消除、噪声抑制和自动增益(见 practice-web/src/app.js):

// practice-web/src/app.js navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: false, noiseSuppression: false, autoGainControl: false }, video: false });

这三个开关的意图很直白:系统级处理会改变波形幅度与频谱,干扰音高估计。随后通过AnalyserNode(fftSize = 4096)按requestAnimationFrame轮询读取时域浮点波形,约每秒 60 帧,每帧 4096 个采样点。

图中即桌面端 Book 菜单打开的练习工作区:左侧乐谱光标逐音推进,右侧面板实时显示"本次练习"的错音记录,底部状态栏给出当前速度与小节范围。

🎯 Pitchy 单音检测原理:一帧波形给出两个数

NoteLite 使用 MIT 许可的 Pitchy 4.1.0(第三方声明见 app/res/practice/THIRD-PARTY.txt),初始化只有一行:

const detector = PitchDetector.forFloat32Array(4096); // 固定 4096 采样窗口

每帧调用detector.findPitch(buffer, sampleRate),返回两个关键数值:

输出含义用途
hz基频估计(Hz)换算成 MIDI 音高
clarity周期性清晰度(0–1)判断"像不像一个稳定的音",供门控使用

Pitchy 内部用 FFT 寻找波形中最强的周期,clarity反映该周期占整体能量的比例——持续吹奏/拉奏的音 clarity 高,瞬态噪声、起音爆音则低。

得到频率后,NoteLite 还做了一个细节处理:按你在设置中指定的A4 调音基准(415–466 Hz 可调)缩放频率,再换算 MIDI 与音分:

raw = 69 + 12 · log2(频率 / A4基准) // 未取整的"小数 MIDI" midi = round(raw) // 最接近的标准音 cents = (raw − midi) × 100 // 音分偏差:正为偏高,负为偏低

这就是为什么练习旧谱(如 A4 = 415 Hz 的历史曲目)时音准判定不会整体偏移。

🚦 PitchGate 门控机制:五道关卡过滤误判

如果每帧检测到一个音就上报"弹了一个音",一个持续音会在几秒内触发几十个假起音。所以 NoteLite 在 practice-web/src/session.js 中实现了PitchGate门控类,每帧数据必须依次通过以下关卡:

#关卡阈值不通过时的行为
1静音门限RMS < 0.008计为静音帧;连续 3 帧才释放"正在按住"状态
2音高有效域27.5 – 4200 Hz重置稳定性计数
3清晰度阈值clarity ≥ 0.9重置稳定性计数,但不释放按住状态
4稳定确认同一 MIDI 连续稳定 ≥ 3 帧丢弃,防止瞬态触发
5持续音去重上一事件last === midi丢弃,按住不重复计数

简化后的决策流程如下(完整实现约 20 行):

// practice-web/src/session.js —— PitchGate.push 的决策顺序 if (rms < 0.008) { /* 静音:连续3帧后 last=null */ } if (hz超范围 || clarity < 0.9) { /* 重置稳定计数,但保留 last */ } if (midi连续稳定 < 3帧 || last===midi) return null; // 抑制持续音 return { midi, cents }; // 通过:放行一次真实起音

两处设计值得新手注意:

  • 只有"真静音"才释放音符:弓弦/吹奏音在持续过程中会出现短暂的周期性丢失(clarity 掉下去),如果此时就释放last,一个音会被拆成两段甚至触发"错音"。所以低 clarity 只重置稳定计数,不释放状态——这正是 practice-web/README.md 中记录的"门控修正"。
  • 3 帧 ≈ 50 毫秒:起音确认窗口很短,实时感损失小,同时足以滤掉单击、敲击等瞬态。

门控放行的事件随后进入统一判定层receive(midi, time, cents)(practice-web/src/app.js),与 MIDI、键盘输入走同一条session.noteOn路径(practice-web/src/session.js),产出五类结果:错音(wrong)、多弹/过早(extra)、漏音(missing)、抢拍/慢拍(early/late)、音准偏差(intonation)。

📏 音分偏差怎么反馈给你

  • 界面顶部的"听到"栏会实时显示音名及偏差,如A4 +8¢(偏差超过 3¢ 才显示数字);
  • 当|cents| > 35音分时,记一条intonation(音准偏差)错误,回顾页会写明"偏高/偏低 N 音分",可直接"重练此小节"。

35 音分大约是一个半音的 29%——对初学者足够宽容,对进阶者又能暴露明显偏音。开始练习前,NoteLite 还会要求你试听或人工校对乐谱(桌面编辑器仍在手边,见下图),避免把识别错误当成你的演奏错误。

⚠️ 边界与验证:作者公开承认的限制

诚实的边界说明是这套系统值得信任的原因。NoteLite 明确披露(practice-web/README.md):

  • 仅单声部:和弦、扫弦、合奏不做逐音评分,多选段落会被拒绝;
  • 重复同音需静音间隔:没有包络起音检测器,同一音高连击需要至少 3 帧(约 50 ms)静音才能再次被识别为起音——连音(legato)是同音高重复的已知难点;
  • 不评估触键、踏板、力度与指法。

验证方面,practice-web/test/audio.test.mjs 用真实的 Pitchy 4.1.0 + 生产环境 PitchGate跑确定性回归:6 类乐器谐波轮廓(正弦、长笛、单簧管、弓弦、拨弦、人声)× 3 种信噪比 × 44.1/48 kHz × 13 个音高,要求"每个持续音恰好产生 1 次精确起音",并用纯静音/白噪声验证零虚假触发;另有失谐 A4(±42 音分)用例验证音准反馈符号正确。

针对真实乐器录音(CC-BY 采样库)的基准结果如下:

批次首音匹配未检出恰 1 次正确事件/文件错误音高事件
初始 30 文件(门控修正前)30/30025/3011
同批 30 文件(修正后)30/30026/3011
独立保留 20 文件(修正后)20/20020/200

修正门控后,"按住音被拆碎"导致的重复事件从 46 降到 20,独立保留集实现零错误音高事件。作者同时提醒:这些数字不能外推为真实房间、实时演奏的整体准确率。

在 Apple 原生客户端上,麦克风采集改由 apple/NoteLite/NativePracticeInput.swift 的AVAudioEngine完成(4096 采样 tap),随后逐帧调用同一个window.NoteLiteNative.audioFrame,门控与判定逻辑和浏览器完全一致,保证跨平台体验统一。

📚 相关源码与文档索引

模块路径
每帧处理与麦克风连接practice-web/src/app.js
PitchGate 门控实现practice-web/src/session.js
音符匹配与错误分类practice-web/src/session.js
输入方式与 A4 设置界面practice-web/src/index.html
Pitchy 版本声明practice-web/package.json
音频回归测试practice-web/test/audio.test.mjs
练习模式范围说明practice-web/README.md
第三方许可声明app/res/practice/THIRD-PARTY.txt
原生端麦克风采集apple/NoteLite/NativePracticeInput.swift

一句话总结:NoteLite 的麦克风音准检测 = "Pitchy 每帧给出频率 + 清晰度" × "五道门控关卡只放行真实起音",再叠加 A4 缩放与 35 音分反馈——全部在浏览器本地完成,简单、透明、可复现。

【免费下载链接】NoteLite

Open-source OMR and guided music practice: turn sheet music PDFs/images into MusicXML/MIDI, refine scores, and practice with MIDI or microphone feedback.

项目地址:https://gitcode.com/gh_mirrors/no/NoteLite
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进