Repository navigation
perf(mic): マイクON時の負荷削減 + AirPods(HFP 16kHz)対応 (v1.56.0) - #2
Merged
Merged
Conversation
…56.0)
原因(ヘッドレスChrome実測 + 静的監査):
- detectPitchYIN が毎フレーム全域探索(1.87ms/frame, 51%) + H1メーターが別途4096点YIN(4.1ms/90ms)
- resizeCanvas が毎フレーム同値で canvas.width を再代入 → バッキングストア再生成 + clientWidth読みで強制レイアウト(3.5回/frame)
- AirPods: Play前にマイクを立てると AudioContext が16kHzで生成 → fftSize窓が3倍長(遅延)、LPCの decimFactor=4 固定で解析ナイキスト2kHz → F2以上・派生指標が消失
対策:
- A1/A2 ResizeObserver で全canvasのCSSサイズをキャッシュ、rAF経路から layout 読みを排除。canvas.width は変化時のみ代入
- A3 Loudness meter を33ms間引き + 変化時のみDOM書込(setTextIfChanged/setStyleIfChanged)
- A4 YIN入力を2:1平均で sr/2 解析(窓の時間長は不変、ビブラートsinc補正の校正を維持)
- A5 DSP.refinePeriod(シード付き狭帯域周期精密化)を新設し H1メーターの第2YINを置換。validate.mjs 1b ゲート追加
- A6 Overview/Waveform 表示時のみ ScriptProcessor(ovMonTap) を遅延起動
- A7 スペクトラム描画の毎フレーム TypedArray 確保をスクラッチ再利用に
- B1 AudioContext を {sampleRate:48000} で生成(非対応時はフォールバック)
- B2 decimFactor = round(sr/12000)、factor 1 時はフィルタ省略、16kHz時のみLPC次数を Praat則で拡張
実測(48k, spectrum): drawVisualizer 3.46→2.10 ms/frame, 強制レイアウト 2.5→0.08 回/frame, >20ms フレーム 13.7→3.2%
16kHz フォールバック: F1/F2 263/662 → 664/1402 Hz(48k基準 674/1428)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X79e2xF8tEbfRg38pf8heF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概要
マイクON時に動作が重く、AirPods使用時は特に「反応しない」件の恒久対応。ヘッドレスChrome実測(偽マイク注入・関数ラップ計測)と静的監査で原因を特定した。
原因
detectPitchYINが毎フレーム全域探索(1.87 ms/frame, drawVisualizer の51%)。H1メーターがさらに4096点の全域YINを90 msごとに実行(4.1 ms/回)resizeCanvasが毎フレーム同値でcanvas.widthを再代入 → バッキングストア再生成。clientWidth読みが DOM 書込と交互に走り強制レイアウト 3.5回/framenew AudioContext()が 16 kHz で生成 → fftSize 窓が 3 倍長(読み出し遅延 3 倍)、LPC のdecimFactor=4固定で解析ナイキストが 2 kHz → F2 以上・Vowel Space・H1*–H2* 補正が消失。CPU はむしろ減っており「重さ」の正体は遅延と欠落変更内容
canvasCssSize(): ResizeObserver で全 canvas の CSS サイズをキャッシュし rAF 経路から layout 読みを排除。canvas.width/heightは変化時のみ代入setTextIfChanged/setStyleIfChangedで変化時のみ DOM 書込(各バッジ・VQ 読み出しも同様)detectPitchFromMic: sr ≥ 32 kHz では 2:1 ペア平均して sr/2 で YIN(窓の時間長は不変 → ビブラート sinc 補正の校正を維持)DSP.refinePeriod()新設(シード付き狭帯域周期精密化、再入可能)。H1メーターの第2YINを置換。validate.mjsに 1b ゲート追加(48k/16k × 110–880 Hz、誤差 < 0.3 Hz、最悪 0.217 Hz)ovMonTap(ScriptProcessor + 30 s リング)を Overview/Waveform 表示時のみ遅延起動initAudio:new AudioContext({ sampleRate: 48000 })、非対応時は従来コンストラクタにフォールバックdecimFactor = max(1, round(sr/12000))、factor 1 ではフィルタ省略。decSr > 12.5 kHz のときのみ LPC 次数を Praat 則で拡張(48k/44.1k/24k は従来どおり 12)APP_VERSION/sw.jsVERSION → v1.56.0動作確認
node docs/dev/validate.mjs全ゲート合格(59 → 74)index.html)ヘッドレス Chrome で確認 — コンソールエラー 0、4 ビュー(spectrum / spectrogram / waveform / overview)+ 全解析パネル openmobile.html)ヘッドレス Chrome でロード確認 — JS エラー 0docs/sw.js/APP_VERSIONを更新実測(ヘッドレス、10 s、偽マイク 220 Hz + 5.5 Hz ビブラート)
16 kHz フォールバックでの F1/F2: 263/662 Hz → 664/1402 Hz(48k 基準 674/1428)。偽マイク 16 kHz でも
audioCtx.sampleRate === 48000を確認。ユーザーが気づきうる挙動変化: Loudness バーの更新が 30 Hz(EMA の見かけの立ち上がりがやや遅い)。H1 バッジはピッチトラッカーの有声判定に追従(400 ms ホールド付き)。
未対応・フォローアップ: 16 kHz コンテキスト(B1 フォールバック時のみ到達)では
detectPitchYINの前処理 0.97 プリエンファシスで無声判定になる既存バグが残る。docs/dev/validation.htmlに 1b 節は未反映。関連 Issue
なし
🤖 Generated with Claude Code
https://claude.ai/code/session_01X79e2xF8tEbfRg38pf8heF