Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
9bea7cf
db: Add MusicBrainz and AcoustID library metadata columns
Swarnadip-Kar May 21, 2026
1f42fb9
db: Add data_text column to track_analysis
Swarnadip-Kar May 21, 2026
ef6110c
db: Add Chromaprint fingerprint database tables
Swarnadip-Kar May 21, 2026
90261e1
DAO: Map fingerprint tables and columns in trackschema.h and tracksch…
Swarnadip-Kar May 24, 2026
a6aca32
DAO: Add TrackFingerprintDao headers and DTO structs
Swarnadip-Kar May 24, 2026
e593506
DAO: Implement TrackFingerprintDao operations
Swarnadip-Kar May 24, 2026
99e19c4
DAO: Register TrackFingerprintDao in TrackCollection
Swarnadip-Kar May 24, 2026
e8c9083
DAO: Manually cascade fingerprint tables on hard delete
Swarnadip-Kar May 24, 2026
98646ae
DAO: Add Debug Statements in tracksfingerprintdao.cpp
Swarnadip-Kar May 25, 2026
0098c97
DAO: Add CmrtMember DTO and method declarations
Swarnadip-Kar May 28, 2026
5f41658
DAO: Implement cmrt_members operations in TrackFingerprintDao
Swarnadip-Kar May 28, 2026
1076e86
DAO: Wire TrackFingerprintDao into TrackCollection
Swarnadip-Kar May 28, 2026
f3c5e5f
DAO: Add UserSettingsPointer to TrackFingerprintDao
Swarnadip-Kar May 28, 2026
cd22a7d
DAO: Implement .chroma file I/O operations in TrackFingerprintDao
Swarnadip-Kar May 28, 2026
1a0dcb9
DAO: Add .chroma file I/O and TrackFingerprintDao wiring
Swarnadip-Kar May 28, 2026
6fdf5e9
DAO: Add acoustid_queue operations to TrackFingerprintDao
Swarnadip-Kar May 29, 2026
f700da5
DAO: Implement acoustid_cache operations in TrackFingerprintDao
Swarnadip-Kar May 29, 2026
9003d86
DAO: Initialize TrackFingerprintDao in LibraryScanner
Swarnadip-Kar May 29, 2026
d3ead38
DAO: Add UnmatchedTrackInfo DTO and declare method hooks
Swarnadip-Kar Jun 4, 2026
8512af2
DAO: Implement getUnmatchedTracks and reQueueJob operations
Swarnadip-Kar Jun 4, 2026
dcecc1b
DAO: Declare updateAcoustIdResult
Swarnadip-Kar Jun 4, 2026
bc8601f
DAO: Implement updateAcoustIdResult
Swarnadip-Kar Jun 4, 2026
69c3d35
DAO: Make TrackDAO::updateAcoustIdResult a slot
Swarnadip-Kar Jun 6, 2026
cfb2bfc
DAO: Add clearFingerprintData and clearAllFingerprintData to TrackFin…
Swarnadip-Kar Jun 8, 2026
9b3760e
Analyzer: Add WithFingerprint mode flag to AnalyzerModeFlags
Swarnadip-Kar Jun 2, 2026
7cf0b4d
Analyzer: Add AnalyzerChromaprint header
Swarnadip-Kar Jun 2, 2026
9d07200
Analyzer: Implement AnalyzerChromaprint initialize() with cache check
Swarnadip-Kar Jun 2, 2026
537c9dc
Analyzer: Implement AnalyzerChromaprint processSamples() and storeRes…
Swarnadip-Kar Jun 2, 2026
88937f5
Analyzer: Implement AnalyzerChromaprint cleanup() and SimHash helper
Swarnadip-Kar Jun 2, 2026
23f1a93
Analyzer: Wire AnalyzerChromaprint and register in CMake
Swarnadip-Kar Jun 2, 2026
04143d3
Analyzer: Add AllWithFingerprint mode to AnalyzerModeFlags
Swarnadip-Kar Jun 4, 2026
4fa1e67
Analyzer: Decouple DB connection from WithWaveform
Swarnadip-Kar Jun 4, 2026
1e783d5
Analyzer: Add config key declaration in library_prefs.h
Swarnadip-Kar Jun 4, 2026
32571f1
Analyzer: Add config key definition in library_prefs.cpp:
Swarnadip-Kar Jun 4, 2026
a13d56a
Analyzer: Read pref, include WithFingerprint in mode flags.
Swarnadip-Kar Jun 4, 2026
752baf2
Analyzer: Add fingerprintOnly flag to AnalyzerTrack::Options
Swarnadip-Kar Jun 4, 2026
14587cd
Analyzer: Derive mode flags from fingerprintOnly in AnalysisFeature
Swarnadip-Kar Jun 4, 2026
ef5c607
Analyzer: Add fingerprint action and slot in wtrackmenu.h
Swarnadip-Kar Jun 4, 2026
d07feea
Analyzer: Implement fingerprint action in wtrackmenu
Swarnadip-Kar Jun 4, 2026
07c11ca
Analyzer: Update tooltip (dlganalysis.ui)
Swarnadip-Kar Jun 4, 2026
add7c1f
Prefs: Add AcoustID user preferences config keys
Swarnadip-Kar Jun 4, 2026
1ed683f
Prefs: Add DlgPrefFingerprint UI page header and implementation
Swarnadip-Kar Jun 4, 2026
cfa5b54
Prefs: Add dlgpreffingerprint.ui with enable checkbox
Swarnadip-Kar Jun 4, 2026
6763047
Prefs: Register fingerprint page in DlgPreferences
Swarnadip-Kar Jun 4, 2026
882d692
Prefs: Add dlgpreffingerprint to CMakeLists.txt
Swarnadip-Kar Jun 4, 2026
b690a01
Prefs: Add AcoustID API key and auto-submit fields to fingerprint page
Swarnadip-Kar Jun 6, 2026
1de61ba
Prefs: Implement fingerprint preference controls and AcoustID fields
Swarnadip-Kar Jun 6, 2026
9a0d746
Menu: Add Clear -> Fingerprint to WTrackMenu context menu
Swarnadip-Kar Jun 8, 2026
d7d5d12
Menu: Extend slotClearAllMetadata to also clear fingerprint data
Swarnadip-Kar Jun 8, 2026
0e95aea
Prefs: Add "Clear All Fingerprints" button to fingerprint preferences…
Swarnadip-Kar Jun 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1174,6 +1174,7 @@ add_library(
STATIC
EXCLUDE_FROM_ALL
src/analyzer/analyzerbeats.cpp
src/analyzer/analyzerchromaprint.cpp
src/analyzer/analyzerebur128.cpp
src/analyzer/analyzergain.cpp
src/analyzer/analyzerkey.cpp
Expand Down Expand Up @@ -1414,6 +1415,7 @@ add_library(
src/library/dao/settingsdao.cpp
src/library/dao/trackdao.cpp
src/library/dao/trackschema.cpp
src/library/dao/trackfingerprintdao.cpp
src/library/tabledelegates/defaultdelegate.cpp
src/library/dlgcoverartfullsize.cpp
src/library/dlgcoverartfullsize.ui
Expand Down Expand Up @@ -1548,6 +1550,8 @@ add_library(
src/preferences/dialog/dlgpreferencepage.cpp
src/preferences/dialog/dlgpreferences.cpp
src/preferences/dialog/dlgpreferencesdlg.ui
src/preferences/dialog/dlgpreffingerprint.cpp
src/preferences/dialog/dlgpreffingerprint.ui
src/preferences/dialog/dlgprefinterface.cpp
src/preferences/dialog/dlgprefinterfacedlg.ui
src/preferences/dialog/dlgprefkey.cpp
Expand Down
171 changes: 171 additions & 0 deletions res/schema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -593,4 +593,175 @@ reapplying those migrations.
ALTER TABLE library ADD COLUMN tuning_frequency_hz FLOAT DEFAULT 0.0;
</sql>
</revision>
<revision version="41" min_compatible="3">
<description>
Add MusicBrainz and AcoustID metadata columns to the library table
to support Chromaprint-based audio fingerprinting and AcoustID lookup.
</description>
<sql>
ALTER TABLE library ADD COLUMN musicbrainz_recording_id varchar(64);
ALTER TABLE library ADD COLUMN musicbrainz_release_id varchar(64);
ALTER TABLE library ADD COLUMN musicbrainz_track_id varchar(64);
ALTER TABLE library ADD COLUMN musicbrainz_artist_id varchar(64);
ALTER TABLE library ADD COLUMN acoustid_id varchar(64);
ALTER TABLE library ADD COLUMN acoustid_lookup_at INTEGER;
<!-- acoustid_lookup_status values: 'pending' | 'completed' | 'failed' -->
ALTER TABLE library ADD COLUMN acoustid_lookup_status varchar(16);

CREATE INDEX IF NOT EXISTS idx_library_mbid ON library (
musicbrainz_recording_id
);
CREATE INDEX IF NOT EXISTS idx_library_acoustid ON library (
acoustid_id
);
CREATE INDEX IF NOT EXISTS idx_library_mbid_artist ON library (
musicbrainz_artist_id
);
</sql>
</revision>
<revision version="42" min_compatible="3">
<description>
Add data_text column to track_analysis table for small text payloads
such as audio quality metrics and Chromaprint version metadata.
Raw fingerprint arrays are never stored in the database.
</description>
<sql>
ALTER TABLE track_analysis ADD COLUMN data_text TEXT;

CREATE INDEX IF NOT EXISTS idx_track_analysis_lookup ON track_analysis (
track_id,
type
);
</sql>
</revision>
<revision version="43" min_compatible="3">
<description>
Add Chromaprint fingerprint tables: fingerprint_metadata stores the
32-bit SimHash pre-filter and CMRT group linkage per track; cmrt_groups
holds one record per unique audio recording; cmrt_members is the
track-to-group bridge table; acoustid_queue manages background AcoustID
API submissions; acoustid_cache avoids redundant API round-trips.
Raw fingerprint data is stored as separate .chroma files on disk,
never as BLOBs in the database.
</description>
<sql>
<!-- fingerprint_hash is a 32-bit SimHash used as a non-unique pre-filter.
Full binary XOR/popcount comparison of .chroma files is required
before assigning a track to a CMRT group. See design notes. -->
CREATE TABLE IF NOT EXISTS fingerprint_metadata (
track_id INTEGER NOT NULL,
<!-- 32-bit SimHash — non-unique, multiple tracks share the same value -->
fingerprint_hash INTEGER NOT NULL,
<!-- SHA-256 hex of .chroma file — non-unique here; exact copies share it -->
chroma_sha256 varchar(64) NOT NULL,
fingerprint_duration REAL,
fingerprint_version INTEGER,
cmrt_group_id INTEGER,
cmrt_offset_seconds REAL DEFAULT 0,
is_canonical INTEGER DEFAULT 0,
fingerprint_valid INTEGER DEFAULT 1,
fingerprint_needs_regen INTEGER DEFAULT 0,
computed_at INTEGER NOT NULL,
PRIMARY KEY (track_id));

<!-- chroma_sha256 is UNIQUE here: each group has exactly one canonical
audio identity. Two groups cannot share the same SHA-256. -->
CREATE TABLE IF NOT EXISTS cmrt_groups (
group_id INTEGER NOT NULL,
fingerprint_hash INTEGER NOT NULL,
chroma_sha256 varchar(64) NOT NULL,
canonical_track_id INTEGER NOT NULL,
track_count INTEGER DEFAULT 1,
created_at INTEGER NOT NULL,
last_updated INTEGER,
musicbrainz_cmrt_mbid varchar(64),
musicbrainz_synced INTEGER DEFAULT 0,
musicbrainz_last_sync INTEGER,
musicbrainz_community_score REAL,
musicbrainz_submitted INTEGER DEFAULT 0,
musicbrainz_submission_mbid varchar(64),
local_preferred INTEGER DEFAULT 1,
conflict_resolved_at INTEGER,
<!-- conflict_resolution values: 'local_won' | 'remote_won' -->
conflict_resolution varchar(16),
PRIMARY KEY (group_id));

<!-- UNIQUE (track_id) enforces each track belongs to exactly one group -->
CREATE TABLE IF NOT EXISTS cmrt_members (
member_id INTEGER NOT NULL,
group_id INTEGER NOT NULL,
track_id INTEGER NOT NULL,
offset_from_canonical REAL DEFAULT 0,
quality_score REAL,
match_score REAL,
is_fake_lossless INTEGER DEFAULT 0,
added_at INTEGER NOT NULL,
user_quality_rating INTEGER,
PRIMARY KEY (member_id),
UNIQUE (track_id));

<!-- status values: 'queued' | 'processing' | 'completed' | 'failed' -->
CREATE TABLE IF NOT EXISTS acoustid_queue (
queue_id INTEGER NOT NULL,
track_id INTEGER NOT NULL,
priority INTEGER DEFAULT 5,
status varchar(16) DEFAULT 'queued',
attempts INTEGER DEFAULT 0,
max_attempts INTEGER DEFAULT 3,
last_attempt INTEGER,
error_message TEXT,
queued_at INTEGER NOT NULL,
PRIMARY KEY (queue_id),
UNIQUE (track_id));

<!-- keyed on chroma_sha256 (SHA-256), not fingerprint_hash (SimHash),
to avoid Birthday Paradox false cache hits -->
CREATE TABLE IF NOT EXISTS acoustid_cache (
chroma_sha256 varchar(64) NOT NULL,
acoustid_id varchar(64) NOT NULL,
musicbrainz_recording_id varchar(64),
musicbrainz_release_id varchar(64),
musicbrainz_metadata TEXT,
confidence REAL,
lookup_timestamp INTEGER NOT NULL,
expires_at INTEGER,
PRIMARY KEY (chroma_sha256));

CREATE INDEX IF NOT EXISTS idx_fm_hash ON fingerprint_metadata (
fingerprint_hash
);
CREATE INDEX IF NOT EXISTS idx_fm_sha ON fingerprint_metadata (
chroma_sha256
);
CREATE INDEX IF NOT EXISTS idx_fm_group ON fingerprint_metadata (
cmrt_group_id
);
CREATE INDEX IF NOT EXISTS idx_fm_canonical ON fingerprint_metadata (
is_canonical
);
CREATE INDEX IF NOT EXISTS idx_cg_hash ON cmrt_groups (
fingerprint_hash
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_cg_sha ON cmrt_groups (
chroma_sha256
);
CREATE INDEX IF NOT EXISTS idx_cg_mbid ON cmrt_groups (
musicbrainz_cmrt_mbid
);
CREATE INDEX IF NOT EXISTS idx_cm_group ON cmrt_members (
group_id
);
CREATE INDEX IF NOT EXISTS idx_cm_track ON cmrt_members (
track_id
);
CREATE INDEX IF NOT EXISTS idx_aq_status ON acoustid_queue (
status,
priority,
queued_at
);
CREATE INDEX IF NOT EXISTS idx_ac_mbid ON acoustid_cache (
musicbrainz_recording_id
);
</sql>
</revision>
</schema>
Loading
Loading