summaryrefslogtreecommitdiff
path: root/tools/mq_editor/mq_extract.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/mq_editor/mq_extract.js')
-rw-r--r--tools/mq_editor/mq_extract.js41
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];