diff options
Diffstat (limited to 'tools/mq_editor/mq_extract.js')
| -rw-r--r-- | tools/mq_editor/mq_extract.js | 41 |
1 files changed, 17 insertions, 24 deletions
diff --git a/tools/mq_editor/mq_extract.js b/tools/mq_editor/mq_extract.js index 3f7490d..107b2ac 100644 --- a/tools/mq_editor/mq_extract.js +++ b/tools/mq_editor/mq_extract.js @@ -102,6 +102,21 @@ function normalizeAngle(angle) { return angle - 2 * Math.PI * Math.floor((angle + Math.PI) / (2 * Math.PI)); } +// Find best matching peak for a predicted freq/phase. Returns {bestIdx, bestCost}. +function findBestPeak(peaks, matched, predictedFreq, predictedPhase, tol, phaseErrorWeight) { + let bestIdx = -1, bestCost = Infinity; + for (let i = 0; i < peaks.length; ++i) { + if (matched.has(i)) continue; + const pk = peaks[i]; + const freqError = Math.abs(pk.freq - predictedFreq); + if (freqError > tol) continue; + const phaseError = Math.abs(normalizeAngle(pk.phase - predictedPhase)); + const cost = freqError + phaseErrorWeight * phaseError * predictedFreq; + if (cost < bestCost) { bestCost = cost; bestIdx = i; } + } + return { bestIdx, bestCost }; +} + // Track partials across frames using phase coherence for robust matching. function trackPartials(frames, params) { const { @@ -134,19 +149,8 @@ function trackPartials(frames, params) { const predictedPhase = lastPhase + phaseAdvance; const tol = Math.max(predictedFreq * trackingRatio, minTrackingHz); - let bestIdx = -1, bestCost = Infinity; - // Find the peak in the new frame with the lowest cost (freq + phase error). - for (let i = 0; i < frame.peaks.length; ++i) { - if (matched.has(i)) continue; - const pk = frame.peaks[i]; - const freqError = Math.abs(pk.freq - predictedFreq); - if (freqError > tol) continue; - - const phaseError = Math.abs(normalizeAngle(pk.phase - predictedPhase)); - const cost = freqError + phaseErrorWeight * phaseError * predictedFreq; - if (cost < bestCost) { bestCost = cost; bestIdx = i; } - } + const { bestIdx } = findBestPeak(frame.peaks, matched, predictedFreq, predictedPhase, tol, phaseErrorWeight); if (bestIdx >= 0) { const pk = frame.peaks[bestIdx]; @@ -175,18 +179,7 @@ function trackPartials(frames, params) { const predictedPhase = lastPhase + phaseAdvance; const tol = Math.max(predictedFreq * trackingRatio, minTrackingHz); - let bestIdx = -1, bestCost = Infinity; - - for (let j = 0; j < frame.peaks.length; ++j) { - if (matched.has(j)) continue; - const pk = frame.peaks[j]; - const freqError = Math.abs(pk.freq - predictedFreq); - if (freqError > tol) continue; - - const phaseError = Math.abs(normalizeAngle(pk.phase - predictedPhase)); - const cost = freqError + phaseErrorWeight * phaseError * predictedFreq; - if (cost < bestCost) { bestCost = cost; bestIdx = j; } - } + const { bestIdx } = findBestPeak(frame.peaks, matched, predictedFreq, predictedPhase, tol, phaseErrorWeight); if (bestIdx >= 0) { const pk = frame.peaks[bestIdx]; |
