-
Notifications
You must be signed in to change notification settings - Fork 0
⚡ Chords: vectorize HMM reference and correct relative-key prior #732
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
seonghobae
wants to merge
97
commits into
develop
Choose a base branch
from
jules-15985039724708397070-07b0954f
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
97 commits
Select commit
Hold shift + click to select a range
fb9264c
perf(backend): optimize viterbi decoding and observation probability …
seonghobae 5a4adb1
perf(backend): optimize viterbi decoding and observation probability …
seonghobae c4f1b50
test(chords): prove vectorized probability and Viterbi parity
seonghobae 327eb9c
perf(backend): optimize viterbi decoding and observation probability …
seonghobae 8cc2634
perf(backend): optimize viterbi decoding and observation probability …
seonghobae 232fa07
chore(ci): revalidate against current coverage workflow
seonghobae f1b2cec
test(analysis): prove vectorized chord parity and rolling Viterbi
seonghobae b6b4fdc
perf(backend): optimize viterbi decoding and observation probability …
seonghobae 024bb11
perf(backend): optimize viterbi decoding and observation probability …
seonghobae eecae60
test(chords): stage similarity alignment regression
seonghobae 4a45e75
ci(chords): apply frame-alignment bootstrap
seonghobae 278fca9
ci(chords): trigger one-shot alignment on PR updates
seonghobae f82512d
test(chords): cover padded similarity confidence alignment
seonghobae 07db6a0
ci(chords): verify padded-frame alignment before commit
seonghobae e4bd67c
perf(backend): optimize viterbi decoding and observation probability …
seonghobae 231da8c
test(chords): require one reusable padded-frame buffer
seonghobae 1a551f4
chore(chords): add one-shot fallback buffer finalizer
seonghobae 94e640a
ci(chords): verify reusable fallback buffer
seonghobae 07bd35a
perf(backend): optimize viterbi decoding and observation probability …
seonghobae 06af335
test(chords): restore reusable fallback allocation contract
seonghobae 0d63479
chore(chords): add final reviewed fallback reuse step
seonghobae 16b40ef
ci(chords): finalize and verify fallback allocation reuse
seonghobae 44f8226
ci(chords): make finalizer visible to pull-request verification
seonghobae 820f5ca
perf(chords): reuse padded-frame fallback allocation
github-actions[bot] a9db88f
perf(backend): optimize viterbi decoding and observation probability …
seonghobae 44e3ebd
perf(backend): optimize viterbi decoding and observation probability …
seonghobae 2a08fd4
ci: stage neutral chord fallback fix
seonghobae 86b87a4
ci: apply neutral chord fallback fix
seonghobae e379479
test(chords): cover normalized mismatch fallbacks
seonghobae b94e54b
fix(chords): keep missing-frame fallback neutral
github-actions[bot] 5bd1631
ci(chords): restore strict formatting for chord fallback vector tests
seonghobae e759965
test(chords): verify observation padding values
seonghobae b61d2e5
perf(backend): optimize viterbi decoding and observation probability …
seonghobae 58b8856
test(chords): assert observed and padded frame probabilities
seonghobae f80b6dd
chore(ci): stage chord observation review fixes
seonghobae f584d94
chore(ci): run chord observation review fixes
seonghobae fd05ae8
chore(ci): trigger chord observation finalizer
seonghobae c4d0ebb
fix(chords): keep missing observation frames neutral
github-actions[bot] dc64482
test(chords): clarify neutral metadata fallback
seonghobae 7f1a195
fix(chords): conform fallback fixes to standard format
seonghobae 65e667d
chore: retrigger ci without push
seonghobae de493d1
test(chords): verify observation frame alignment
seonghobae bdfdf70
test(chords): assert mismatch probability values
seonghobae a8e5248
chore: retrigger ci
seonghobae 1caa712
test(chords): restore semantic edge-case assertions
seonghobae 5f7244b
fix(deps): update undici to 7.29.0
seonghobae c98eca8
chore: ci retrigger
seonghobae 82a8cbf
fix(deps): update undici to resolve high severity vulnerability
seonghobae 3135945
chore: ci retrigger
seonghobae a03f3cc
style: conform line lengths to format guidelines and fix lint errors
seonghobae f3e34b2
chore: ci retrigger
seonghobae 5686a2e
ci(pr732): verify bounded chord optimization cleanup
seonghobae 83dd337
fix(chords): validate sampling rate to prevent excessive resource exh…
seonghobae 3deab33
fix(chords): Viterbi bounded optimization and removed scope pollution
seonghobae aa3e399
test(chords): add independent scalar and dense numerical oracles
seonghobae eb10fa2
docs(changelog): record chord reference optimization
seonghobae 31780c4
fix(test): sort numerical oracle imports
seonghobae 1bc3b24
fix(chords): Viterbi bounded optimization and removed scope pollution
seonghobae 9b5f19f
fix(chords): handle nn_filter crash for short audio and fix package v…
seonghobae b672697
fix(chords): handle nn_filter crash for short audio, limit RMS fallba…
seonghobae af13d8c
fix(chords): handle nn_filter crash for short audio, limit RMS fallba…
seonghobae c1cc5f4
fix(security): require patched PDF.js
seonghobae b34cc6d
fix(security): refresh vulnerable npm transitive pins
seonghobae ac94282
fix(deps): restore manifest-lock consistency
seonghobae 99d5c64
fix(chords): handle nn_filter crash for short audio, limit RMS fallba…
seonghobae 3fa0d7f
fix(chords): handle nn_filter crash for short audio, limit RMS fallba…
seonghobae 564b675
chore(chords): restore reviewed reference-only scope
seonghobae ccda9fc
fix(chords): handle nn_filter crash for short audio, limit RMS fallba…
seonghobae a246be8
fix(chords): restore reviewed scope and organize oracle imports
seonghobae 9c108c3
chore(chords): restore reviewed reference-only scope and fix ruff for…
seonghobae 6dfef20
chore(chords): restore reviewed reference-only scope and fix ruff for…
seonghobae 51a4b8d
chore(chords): restore reviewed reference-only scope and fix ruff for…
seonghobae 847d310
fix(scope): restore protected package lock
seonghobae 220fa6c
fix(chords): prevent resource exhaustion from unbounded audio input
seonghobae 735c6ed
fix(chords): restore bounded numerical PR scope
seonghobae fb514d8
test(chords): pin relative-key transition prior
seonghobae e3988a2
fix(chords): correct relative-key transition prior
seonghobae ded30d0
docs(doctoring): ground chord transition prior repair
seonghobae 7247e6b
docs(changelog): record relative-key accuracy fix
seonghobae 801fb3e
fix(chords): prevent resource exhaustion from unbounded audio input
seonghobae 51d13f7
fix(chords): remove unrelated duration-limit drift
seonghobae de492c1
test(chords): keep non-finite observations neutral
seonghobae 459d52e
fix(chords): neutralize non-finite DSP metadata
seonghobae fd73ce8
style(chords): format non-finite guard
seonghobae e0b430c
style(chords): match ruff formatter
seonghobae e004959
fix(chords): prevent resource exhaustion from unbounded audio input
seonghobae 0701cf8
test(chords): restore non-finite observation regression
seonghobae 591a3c4
test(chords): keep resource policy out of feature decoder
seonghobae 7408f1c
fix(chords): restore feature-neutral resource policy and finite obser…
seonghobae d5fc507
fix(chords): prevent resource exhaustion from unbounded audio input
seonghobae eee6f0f
test(chords): restore canonical resource and non-finite regressions
seonghobae ab9b508
fix(chords): restore canonical resource ownership and finite observat…
seonghobae 904b97a
⚡ Bolt: [performance improvement] Vectorize chord recognizer observat…
seonghobae 342695f
fix(chords): restore finite observation neutrality after Bolt drift
cursoragent 213e330
test(chords): reject non-finite confidence arithmetic
seonghobae b106a16
fix(chords): keep confidence arithmetic finite
seonghobae 830dd4c
docs(chords): align confidence with finite observation contract
seonghobae File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| # Chord observation finiteness | ||
|
|
||
| ## Status | ||
|
|
||
| **Active Draft PR evidence.** This record documents the observation-probability robustness contract on PR #732. It is not protected-`develop` shipped truth until the implementation is merged and revalidated on the protected branch. | ||
|
|
||
| ## Buyer-visible problem | ||
|
|
||
| The chord HMM consumes per-frame observation probabilities. A single non-finite chromagram bin, template-similarity score, or RMS value turns the corresponding Viterbi column into `NaN`. The decoder then emits an arbitrary or empty rehearsal chord where the player needed either a labeled chord or an honest unknown frame. | ||
|
|
||
| Missing metadata and invalid metadata are different events: | ||
|
|
||
| - missing similarity or RMS is unknown evidence and must stay neutral; | ||
| - non-finite similarity invalidates the whole frame and must fall back to a uniform chord distribution; | ||
| - non-finite RMS or chromagram variance is unknown, not evidence of silence; and | ||
| - confidence computation treats non-finite similarity as unknown evidence and returns low confidence without performing invalid entropy arithmetic. | ||
|
|
||
| The next action for a player is unchanged: read the surviving chord label, or treat a neutralized frame as “listen again” rather than as a forced no-chord cut. | ||
|
|
||
| ## Research rationale | ||
|
|
||
| Rabiner (1989) defines HMM decoding over valid observation probabilities; a non-finite column is outside that model. Lee and Slaney (2006) treat frame-level chord observations as the input to Viterbi, so observation integrity is an accuracy precondition rather than a presentation detail. Mauch and Dixon (2010) likewise keep the observation model separate from the transition prior, which is why this repair stays inside probability construction and confidence reporting and does not change the 25-state vocabulary or the Rust production decoder. | ||
|
|
||
| ## Test-first verification contract | ||
|
|
||
| - a frame with any non-finite similarity stays finite and column-normalized; | ||
| - that frame uses a uniform 24-chord fallback and does not raise the no-chord state above the chord mass; | ||
| - non-finite RMS or chromagram variance does not satisfy the silence thresholds; | ||
| - confidence on NaN or infinite similarity falls back to `low` without emitting a NumPy `RuntimeWarning` from invalid arithmetic; | ||
| - the vectorized implementation matches an independent framewise scalar oracle on the same corrupt inputs; and | ||
| - `recognize()` still forwards the full audio array to the harmonic separator, so duration policy stays upstream. | ||
|
|
||
| ## References | ||
|
|
||
| Lee, K., & Slaney, M. (2006). Automatic chord recognition from audio using an HMM with supervised learning. In *Proceedings of the 7th International Conference on Music Information Retrieval (ISMIR 2006)* (pp. 133–137). University of Victoria. https://ismir.net/conferences/ismir-2006/ | ||
|
|
||
| Mauch, M., & Dixon, S. (2010). Approximate note transcription for the improved identification of difficult chords. In *Proceedings of the 11th International Society for Music Information Retrieval Conference (ISMIR 2010)* (pp. 135–140). International Society for Music Information Retrieval. https://ismir.net/conferences/ismir-2010/ | ||
|
|
||
| Rabiner, L. R. (1989). A tutorial on hidden Markov models and selected applications in speech recognition. *Proceedings of the IEEE, 77*(2), 257–286. https://doi.org/10.1109/5.18626 |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| # Chord-transition prior evidence | ||
|
|
||
| ## Status | ||
|
|
||
| **Active Draft PR evidence.** This record documents the chord-transition correctness repair developed on PR #732. It is not protected-`develop` shipped truth until the implementation is merged and revalidated on the protected branch. | ||
|
|
||
| ## Buyer-visible problem | ||
|
|
||
| BandScope smooths frame-level chord evidence with a 25-state major/minor/no-chord HMM before emitting rehearsal chord segments. The transition matrix therefore influences which chord label survives when acoustic evidence is ambiguous. A wrong harmonic prior can turn a plausible rehearsal progression into an unrelated chord change even when the frame observations themselves are sound. | ||
|
|
||
| The existing relative-key calculation was reversed: | ||
|
|
||
| - a major chord root used `+3` semitones for its relative minor target; and | ||
| - a minor chord root used `+9` semitones for its relative major target. | ||
|
|
||
| In pitch-class arithmetic that maps C major toward D♯ minor instead of A minor, and A minor toward F♯ major instead of C major. The corrected invariant is: | ||
|
|
||
| - major root → relative minor root: `+9 mod 12` semitones; | ||
| - minor root → relative major root: `+3 mod 12` semitones. | ||
|
|
||
| The repair changes only the relation used to populate the existing heuristic transition prior. It does not change the 24-major/minor-plus-no-chord vocabulary, observation model, Viterbi algorithm, Rust/NumPy parity boundary, filesystem/network authority, or persistence format. | ||
|
|
||
| ## Research rationale | ||
|
|
||
| Lee and Slaney (2006) established supervised-HMM automatic chord recognition as a sequence-decoding problem in which transition probabilities are part of the model rather than presentation-only metadata. Masada and Bunescu (2019) likewise identify chord-transition information as useful harmonic-syntax evidence and note that transition distributions depend on tonal context. Gotham et al. (2023) provide a large, reproducible functional-harmony meta-corpus suitable for measuring repertoire-dependent transition behavior instead of assuming that chord transitions are equiprobable. | ||
|
|
||
| These sources support two engineering conclusions. First, a transition-prior defect is an accuracy defect because the prior participates directly in decoding. Second, the current hand-authored prior should be treated as a bounded baseline rather than a universal model of harmony: future accuracy work should estimate or calibrate transition probabilities against documented corpora and stratify by musical context instead of silently increasing heuristic complexity. | ||
|
|
||
| ## Test-first verification contract | ||
|
|
||
| The regression test names musically recognizable relative pairs and compares them with the exact unrelated pairs favored by the old formula: | ||
|
|
||
| - `C → Am` must have greater transition probability than `C → D#m`; | ||
| - `Am → C` must have greater transition probability than `Am → F#`. | ||
|
|
||
| This catches the old formula in both directions without depending on an implementation constant such as the raw `related_prob`. The production correction is then one bounded pitch-class formula change. Because both the native Rust Viterbi path and the NumPy reference consume the same Python-built transition matrix, the relation is shared across the two numerical paths and remains subject to the repository's exact Rust-to-NumPy parity tests. | ||
|
|
||
| ## Accuracy follow-up | ||
|
|
||
| A commercial-quality next step is corpus-backed calibration rather than additional unvalidated hand rules. Candidate evaluation should compare the current heuristic prior with learned/key-conditioned priors on an openly documented chord corpus and report sequence metrics such as chord-symbol recall/weighted chord symbol recall together with transition-specific confusion. Any learned prior must retain deterministic fixtures for common progressions and must not reduce the existing native/reference numerical parity or fail-closed behavior. | ||
|
|
||
| ## References | ||
|
|
||
| Gotham, M., Micchi, G., López, N. N., & Sailor, M. (2023). When in Rome: A meta-corpus of functional harmony. *Transactions of the International Society for Music Information Retrieval, 6*(1), 150–166. https://doi.org/10.5334/tismir.165 | ||
|
|
||
| Lee, K., & Slaney, M. (2006). Automatic chord recognition from audio using an HMM with supervised learning. In *Proceedings of the 7th International Conference on Music Information Retrieval (ISMIR 2006)* (pp. 133–137). University of Victoria. https://ismir.net/conferences/ismir-2006/ | ||
|
|
||
| Masada, K., & Bunescu, R. C. (2019). Chord recognition in symbolic music: A segmental CRF model, segment-level features, and comparative evaluations on classical and popular music. *Transactions of the International Society for Music Information Retrieval, 2*(1), 1–13. https://doi.org/10.5334/tismir.18 |
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
27 changes: 27 additions & 0 deletions
27
services/analysis-engine/tests/test_chord_confidence_finiteness.py
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| """Regression tests for finite-only chord-confidence arithmetic.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| import warnings | ||
|
|
||
| import numpy as np | ||
| import pytest | ||
|
|
||
| from bandscope_analysis.chords.chord_recognizer import ChordRecognizer | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| "invalid_value", | ||
| [np.nan, np.inf, -np.inf], | ||
| ) | ||
| def test_non_finite_similarity_confidence_falls_back_without_runtime_warning( | ||
| invalid_value: float, | ||
| ) -> None: | ||
| """Unknown similarity evidence must yield low confidence without invalid arithmetic.""" | ||
| recognizer = ChordRecognizer() | ||
| similarity = np.linspace(0.1, 0.9, 24, dtype=float) | ||
| similarity[5] = invalid_value | ||
|
|
||
| with warnings.catch_warnings(): | ||
| warnings.simplefilter("error", RuntimeWarning) | ||
| assert recognizer._compute_confidence(similarity, best_state=0) == "low" |
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
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.