summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/COMPLETED.md21
-rw-r--r--doc/archive/MQ_EXTRACTION_IMPROVEMENTS.md42
2 files changed, 63 insertions, 0 deletions
diff --git a/doc/COMPLETED.md b/doc/COMPLETED.md
index 67724a1..1fb51f5 100644
--- a/doc/COMPLETED.md
+++ b/doc/COMPLETED.md
@@ -29,6 +29,18 @@ Detailed historical documents have been moved to `doc/archive/` for reference:
Use `read @doc/archive/FILENAME.md` to access archived documents.
+## Recently Completed (February 18, 2026)
+
+- [x] **MQ Spectral Editor Improvements**
+ - **Goal**: Improve tracking accuracy and Bezier curve fitting for sinusoidal analysis.
+ - **Implementation**:
+ - **Predictive Kinematic Tracking**: Added velocity tracking to `mq_extract.js`. Partials now predict their next frequency (`freq + velocity`) during the search phase, improving tracking for fast glissandos and vibrato.
+ - **Peak Prominence Pruning**: Added `prominence` parameter (default 1.0 dB) to filtering. Discards peaks that don't stand out sufficiently from their surrounding "valley floor," reducing noise.
+ - **Least-Squares Bezier Fitting**: Replaced heuristic 1/3-2/3 control point placement with a proper least-squares solver for cubic Bezier curves. Minimizes global error across the entire partial trajectory.
+ - **UI Update**: Wired up the "Prominence" input in `index.html` to pass the value to the extraction engine.
+ - **Documentation**: Updated `tools/mq_editor/README.md` with new parameters and algorithm details.
+ - **Files**: `tools/mq_editor/mq_extract.js`, `tools/mq_editor/index.html`, `tools/mq_editor/README.md`
+
## Recently Completed (February 17, 2026)
- [x] **MQ Spectral Editor Phase 2: JS Synthesizer**
@@ -545,6 +557,15 @@ Use `read @doc/archive/FILENAME.md` to access archived documents.
- **Task #39: Visual Debugging System**: Implemented a comprehensive set of wireframe primitives (Sphere, Cone, Cross, Line, Trajectory) in `VisualDebug`. Updated `test_3d_render` to demonstrate usage.
- **Task #68: Mesh Wireframe Rendering**: Added `add_mesh_wireframe` to `VisualDebug` to visualize triangle edges for mesh objects. Integrated into `Renderer3D` debug path and `test_mesh` tool.
+#### mq_editor Refactoring (February 18, 2026)
+- **`utils.js`** (new): consolidated `evalBezier` (robust dt≤0 guard), `getCanvasCoords`, `buildBandPoints` — loaded first.
+- **`app.js`** (new): extracted ~450-line inline `<script>` from `index.html`.
+- **`editor.js`**: generalized `_makeJogSlider(inp, options)` with `onUpdate` callback; eliminated 50-line resonator jog duplication; uses `getCanvasCoords`.
+- **`mq_extract.js`**: extracted `findBestPeak`, replacing two identical loop bodies.
+- **`viewer.js`**: removed duplicate `evalBezier`; uses `getCanvasCoords` and `buildBandPoints`.
+- **`mq_synth.js`**: removed duplicate `evalBezier`.
+- **`index.html`**: inline script removed; load order: `utils.js` → fft → mq_extract → mq_synth → viewer → editor → `app.js`.
+
#### CNN v2 Training Pipeline Improvements (February 14, 2026) 🎯
- **Critical Training Fixes**: Resolved checkpoint saving and argument handling bugs in CNN v2 training pipeline. **Bug 1 (Missing Checkpoints)**: Training completed successfully but no checkpoint saved when `epochs < checkpoint_every` interval. Solution: Always save final checkpoint after training completes, regardless of interval settings. **Bug 2 (Stale Checkpoints)**: Old checkpoint files from previous runs with different parameters weren't overwritten due to `if not exists` check. Solution: Remove existence check, always overwrite final checkpoint. **Bug 3 (Ignored num_layers)**: When providing comma-separated kernel sizes (e.g., `--kernel-sizes 3,1,3`), the `--num-layers` parameter was used only for validation but not derived from list length. Solution: Derive `num_layers` from kernel_sizes list length when multiple values provided. **Bug 4 (Argument Passing)**: Shell script passed unquoted variables to Python, potentially causing parsing issues with special characters. Solution: Quote all shell variables when passing to Python scripts.
diff --git a/doc/archive/MQ_EXTRACTION_IMPROVEMENTS.md b/doc/archive/MQ_EXTRACTION_IMPROVEMENTS.md
new file mode 100644
index 0000000..7bc5c5d
--- /dev/null
+++ b/doc/archive/MQ_EXTRACTION_IMPROVEMENTS.md
@@ -0,0 +1,42 @@
+# MQ Extraction Improvements
+
+This document outlines three enhancements to the partial extraction algorithm (`mq_extract.js`) to improve tracking accuracy and the quality of the resulting sinusoidal model.
+
+## 1. Proposal: Predictive Kinematic Tracking
+
+- **Problem**: The original tracking algorithm assumes a partial's frequency is relatively static between frames. It can fail to track partials with significant, rapid frequency changes (e.g., fast vibrato or glissando) if the change exceeds the fixed frequency tolerance (`trackingRatio`).
+
+- **Solution**: A simple kinematic model has been added to the tracking logic.
+ - For each active partial, we now estimate its frequency "velocity" (the rate of change between the last two frames).
+ - When searching for a matching peak in the next frame, the search is centered around a *predicted* frequency: `predicted_freq = last_freq + velocity`.
+ - This allows the tracker to anticipate movement and maintain lock on partials that are undergoing rapid, continuous change.
+
+- **Implementation**:
+ - The `trackPartials` function now stores a `velocity` property on active partial objects.
+ - This velocity is updated each time a new peak is added to the partial.
+ - The core matching logic now uses the predicted frequency as its reference.
+
+## 2. Proposal: Peak Prominence Pruning
+
+- **Problem**: The original peak detection algorithm identified any local maximum within a 5-bin window. This could lead to the detection of many small, noisy, or spurious peaks that are not musically significant, creating a large number of short, irrelevant partials for the tracker to process.
+
+- **Solution**: The `detectPeaks` function has been enhanced with a "prominence" filter.
+ - A peak's prominence is its height in decibels relative to the lowest "valley" between it and the next higher peak on either side. This measures how much a peak "stands out" from the surrounding spectral landscape.
+ - A new **Prominence (dB)** parameter is available in the UI. Only peaks that exceed this prominence threshold are passed to the tracking stage.
+
+- **Implementation**:
+ - After a local maximum is found, a new algorithm searches left and right to find the lowest point (the valley floor) before encountering a bin with a higher magnitude than the peak itself.
+ - The prominence is calculated as `peak_magnitude - valley_floor_magnitude`.
+ - If this value is below the user-defined threshold, the peak is discarded. This effectively prunes insignificant peaks, cleaning the data for the tracker.
+
+## 3. Proposal: Least-Squares Bezier Fitting
+
+- **Problem**: The original `fitBezier` function used a simple heuristic. It forced the Bezier curve to pass exactly through four points (start, end, and two internal points at 1/3 and 2/3 of the duration). For noisy or complex partials, this could result in a curve that did not accurately represent the partial's overall trajectory.
+
+- **Solution**: The heuristic has been replaced with a proper **least-squares fitting algorithm**.
+ - This method calculates the cubic Bezier curve that minimizes the overall error across *all* points in the partial's trajectory.
+ - The start and end points of the curve are fixed to match the partial's birth and death, but the two intermediate control points are mathematically optimized to produce the best possible fit to the data.
+
+- **Implementation**:
+ - A new `fitBezier` function implements the normal equations to solve the 2x2 linear system for the optimal `v1` and `v2` control point values.
+ - This results in a smoother, more representative curve that is less sensitive to individual noisy points within the partial.