diff options
| author | skal <pascal.massimino@gmail.com> | 2026-02-18 15:39:33 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-02-18 15:39:33 +0100 |
| commit | 02dd7799396ebe3b5c3764796cfa3cbc72b72110 (patch) | |
| tree | 054d928cdd7cd178bc5affc1b14156f60351a8f5 /tools/mq_editor/mq_extract.js | |
| parent | a9a60dfd2df938ef1e3ecc0a06d3d50cc329ef30 (diff) | |
fix(mq_editor): correct phaseInterp quadratic coefficient and stale phase prediction
- phaseInterp: missing *0.5 on quadratic term made interpolated phase 2x off
- trackPartials: phase advance now scaled by (age+1) to cover frames missed
during a partial gap, preventing stale predictions after consecutive misses
handoff(Claude): two bugs fixed in mq_extract.js phase tracking
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'tools/mq_editor/mq_extract.js')
| -rw-r--r-- | tools/mq_editor/mq_extract.js | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/tools/mq_editor/mq_extract.js b/tools/mq_editor/mq_extract.js index a530960..c084b43 100644 --- a/tools/mq_editor/mq_extract.js +++ b/tools/mq_editor/mq_extract.js @@ -40,7 +40,7 @@ function phaseInterp(p_minus, p_center, p_plus, p_frac) { while (dp_plus > Math.PI) dp_plus -= 2 * Math.PI; while (dp_plus < -Math.PI) dp_plus += 2 * Math.PI; - const p_interp = p_center + (dp_plus - dp_minus) * p_frac * 0.5 + (dp_plus + dp_minus) * p_frac * p_frac; + const p_interp = p_center + (dp_plus - dp_minus) * p_frac * 0.5 + (dp_plus + dp_minus) * 0.5 * p_frac * p_frac; return p_interp; } @@ -130,7 +130,8 @@ function trackPartials(frames, params) { const predictedFreq = lastFreq + velocity; // Predict phase for the current frame based on the last frame's frequency. - const phaseAdvance = 2 * Math.PI * lastFreq * hopSize / sampleRate; + // Multiply by (age+1) to account for frames missed during a gap. + const phaseAdvance = 2 * Math.PI * lastFreq * (partial.age + 1) * hopSize / sampleRate; const predictedPhase = lastPhase + phaseAdvance; const tol = Math.max(predictedFreq * trackingRatio, minTrackingHz); @@ -170,6 +171,7 @@ function trackPartials(frames, params) { const velocity = cand.velocity || 0; const predictedFreq = lastFreq + velocity; + // Candidates die on first miss so age is always 0 here, but kept consistent. const phaseAdvance = 2 * Math.PI * lastFreq * hopSize / sampleRate; const predictedPhase = lastPhase + phaseAdvance; |
