max / audiofiles
4 files changed,
+36 insertions,
-36 deletions
| @@ -44,45 +44,45 @@ Shared libraries from `../../MNW/shared/`: [theme-common](../../MNW/shared/theme | |||
| 44 | 44 | ## Features | |
| 45 | 45 | ||
| 46 | 46 | ### Storage & Organization | |
| 47 | - | - **Content-addressed storage** -- samples stored by SHA-256 hash, automatic deduplication | |
| 48 | - | - **Virtual file system** -- organize samples in virtual directories independent of disk location, multiple VFS roots | |
| 49 | - | - **Tag system** -- hierarchical dot-notation tags with auto-suggestions from analysis results | |
| 50 | - | - **Smart folders** -- saved filter queries that update dynamically | |
| 51 | - | - **Collections** -- cross-VFS sample groupings | |
| 47 | + | - **Content-addressed storage**: samples stored by SHA-256 hash, automatic deduplication | |
| 48 | + | - **Virtual file system**: organize samples in virtual directories independent of disk location, multiple VFS roots | |
| 49 | + | - **Tag system**: hierarchical dot-notation tags with auto-suggestions from analysis results | |
| 50 | + | - **Smart folders**: saved filter queries that update dynamically | |
| 51 | + | - **Collections**: cross-VFS sample groupings | |
| 52 | 52 | ||
| 53 | 53 | ### Audio Analysis | |
| 54 | - | - **Analysis pipeline** -- loudness (peak/RMS/LUFS), BPM detection, key detection, spectral analysis | |
| 55 | - | - **ML classification** -- two-layer system: rule-based broad categories, then 200-tree random forest for drum sub-classification (94.4% accuracy on 4,343 samples) | |
| 56 | - | - **Loop detection** -- identifies seamless loops via amplitude envelope analysis | |
| 57 | - | - **Similarity search** -- VP-tree indexed fingerprinting for finding similar and duplicate samples (O(log n) lookup) | |
| 58 | - | - **Waveform display** -- pre-computed peak data with click-to-seek playback | |
| 54 | + | - **Analysis pipeline**: loudness (peak/RMS/LUFS), BPM detection, key detection, spectral analysis | |
| 55 | + | - **ML classification**: two-layer system: rule-based broad categories, then 200-tree random forest for drum sub-classification (94.4% accuracy on 4,343 samples) | |
| 56 | + | - **Loop detection**: identifies seamless loops via amplitude envelope analysis | |
| 57 | + | - **Similarity search**: VP-tree indexed fingerprinting for finding similar and duplicate samples (O(log n) lookup) | |
| 58 | + | - **Waveform display**: pre-computed peak data with click-to-seek playback | |
| 59 | 59 | ||
| 60 | 60 | ### Search & Filtering | |
| 61 | - | - **Text search** -- FTS5 indexed across filenames, tags, and metadata | |
| 62 | - | - **Parameter filters** -- BPM range, duration range, key selector, classification category | |
| 63 | - | - **Tag prefix matching** -- type a tag prefix to filter by hierarchy | |
| 61 | + | - **Text search**: FTS5 indexed across filenames, tags, and metadata | |
| 62 | + | - **Parameter filters**: BPM range, duration range, key selector, classification category | |
| 63 | + | - **Tag prefix matching**: type a tag prefix to filter by hierarchy | |
| 64 | 64 | ||
| 65 | 65 | ### Editing | |
| 66 | - | - **Destructive editing** -- trim, fade in/out, normalize, reverse, gain adjust | |
| 67 | - | - **Edit history** -- full undo/redo stack per sample | |
| 68 | - | - **Bulk operations** -- bulk delete, move, rename, tag across selections | |
| 69 | - | - **Rename engine** -- pattern-based renaming with tokens (name, bpm, key, index, etc.) | |
| 66 | + | - **Destructive editing**: trim, fade in/out, normalize, reverse, gain adjust | |
| 67 | + | - **Edit history**: full undo/redo stack per sample | |
| 68 | + | - **Bulk operations**: bulk delete, move, rename, tag across selections | |
| 69 | + | - **Rename engine**: pattern-based renaming with tokens (name, bpm, key, index, etc.) | |
| 70 | 70 | ||
| 71 | 71 | ### Device Export | |
| 72 | - | - **Rhai export profiles** -- scriptable export for 14 hardware samplers: | |
| 72 | + | - **Rhai export profiles**: scriptable export for 14 hardware samplers: | |
| 73 | 73 | M8, Digitakt, Digitakt II, Octatrack, Model:Samples, SP-404 MKII, MPC, Polyend Tracker, Deluge, Blackbox, Volca Sample 2, OP-1, Circuit Rhythm, Maschine+ | |
| 74 | 74 | ||
| 75 | 75 | ### Playback & Integration | |
| 76 | - | - **MIDI instrument** -- chromatic and multi-sample playback modes with 8-voice polyphony and ADSR envelopes | |
| 77 | - | - **Native drag-out** -- drag samples from the file list directly to Finder, Desktop, or any DAW (macOS + Windows) | |
| 78 | - | - **System tray** -- minimize to tray, quick access | |
| 76 | + | - **MIDI instrument**: chromatic and multi-sample playback modes with 8-voice polyphony and ADSR envelopes | |
| 77 | + | - **Native drag-out**: drag samples from the file list directly to Finder, Desktop, or any DAW (macOS + Windows) | |
| 78 | + | - **System tray**: minimize to tray, quick access | |
| 79 | 79 | ||
| 80 | 80 | ### Infrastructure | |
| 81 | - | - **Cloud sync** -- cross-device sync of metadata, tags, and VFS via SyncKit (E2E encrypted, ChaCha20-Poly1305 + Argon2) | |
| 82 | - | - **OTA updates** -- background update checker with consent dialog | |
| 83 | - | - **Bundled themes** -- dark, light, and high-contrast variants in TOML format (see `crates/audiofiles-browser/themes/`) | |
| 84 | - | - **Audio formats** -- WAV, FLAC, MP3, OGG, AIFF (via Symphonia, pure Rust) | |
| 85 | - | - **Platforms** -- macOS, Windows, Linux (standalone, no backend required) | |
| 81 | + | - **Cloud sync**: cross-device sync of metadata, tags, and VFS via SyncKit (E2E encrypted, ChaCha20-Poly1305 + Argon2) | |
| 82 | + | - **OTA updates**: background update checker with consent dialog | |
| 83 | + | - **Bundled themes**: dark, light, and high-contrast variants in TOML format (see `crates/audiofiles-browser/themes/`) | |
| 84 | + | - **Audio formats**: WAV, FLAC, MP3, OGG, AIFF (via Symphonia, pure Rust) | |
| 85 | + | - **Platforms**: macOS, Windows, Linux (standalone, no backend required) | |
| 86 | 86 | ||
| 87 | 87 | ## Key Paths | |
| 88 | 88 |
| @@ -34,7 +34,7 @@ The `Backend` trait in `audiofiles-browser::backend` defines every operation tha | |||
| 34 | 34 | ||
| 35 | 35 | One implementation exists: | |
| 36 | 36 | ||
| 37 | - | - **DirectBackend** -- wraps `Mutex<Database>` + `SampleStore`, calls core functions directly. Used in the app and tests. | |
| 37 | + | - **DirectBackend**: wraps `Mutex<Database>` + `SampleStore`, calls core functions directly. Used in the app and tests. | |
| 38 | 38 | ||
| 39 | 39 | This trait boundary keeps the browser UI decoupled from the data layer. | |
| 40 | 40 | ||
| @@ -74,7 +74,7 @@ Foreign keys with CASCADE ensure referential integrity. Triggers on `samples`, ` | |||
| 74 | 74 | ||
| 75 | 75 | The analysis system in `audiofiles-core::analysis` decodes audio to mono f32 via Symphonia, then runs configurable stages: | |
| 76 | 76 | ||
| 77 | - | - **Basic**: Duration, sample rate, channel count -- always computed. | |
| 77 | + | - **Basic**: Duration, sample rate, channel count, always computed. | |
| 78 | 78 | - **Loudness**: Peak dBFS, RMS dB, integrated LUFS (via bs1770). | |
| 79 | 79 | - **Spectral**: Centroid, flatness, rolloff, zero-crossing rate, bandwidth, centroid variance (via FFT with realfft). | |
| 80 | 80 | - **Waveform**: Crest factor (peak/RMS ratio), attack time (seconds to 90% of peak via 1ms RMS envelope). | |
| @@ -118,7 +118,7 @@ Sample classification colors are hardcoded (not theme-driven) so that semantic c | |||
| 118 | 118 | ||
| 119 | 119 | The cpal audio output callback runs on a real-time thread where blocking should be avoided. The design uses `parking_lot::Mutex` with `try_lock`: | |
| 120 | 120 | ||
| 121 | - | - **Preview playback**: The GUI thread decodes audio and writes the buffer into `PreviewPlayback` behind a mutex. The cpal callback calls `try_lock()` -- if the GUI holds the lock (decoding), the callback outputs silence instead of blocking. | |
| 121 | + | - **Preview playback**: The GUI thread decodes audio and writes the buffer into `PreviewPlayback` behind a mutex. The cpal callback calls `try_lock()`. If the GUI holds the lock (decoding), the callback outputs silence instead of blocking. | |
| 122 | 122 | ||
| 123 | 123 | Voice stealing in the instrument engine uses a monotonic age counter to find the oldest voice without sorting. | |
| 124 | 124 | ||
| @@ -139,7 +139,7 @@ Folder import runs in a background thread with its own database connection: | |||
| 139 | 139 | ||
| 140 | 140 | 1. **Walk**: Recursively scan the source directory, collecting paths with recognized audio extensions (wav, aiff, mp3, flac, ogg). | |
| 141 | 141 | 2. **Strategy selection**: User chooses flat (all links in current directory), new VFS (preserve directory structure), or merge into existing VFS. | |
| 142 | - | 3. **Import loop**: For each file -- hash, copy to store, create VFS node. Duplicates (name conflicts) are counted but not errors. Progress and errors are reported back to the GUI via channel events. | |
| 142 | + | 3. **Import loop**: For each file: hash, copy to store, create VFS node. Duplicates (name conflicts) are counted but not errors. Progress and errors are reported back to the GUI via channel events. | |
| 143 | 143 | 4. **Folder tagging**: After import completes, the user can assign comma-separated tags to each imported top-level folder, applied to all samples within. | |
| 144 | 144 | 5. **Analysis**: Optionally run configurable analysis (loudness, BPM, key, spectral, classification, loop detection, fingerprint, auto-suggest tags) on imported samples. | |
| 145 | 145 | 6. **Tag review**: If auto-suggest was enabled, the user reviews suggested tags with accept/reject per suggestion before committing. | |
| @@ -152,7 +152,7 @@ Cancellation is checked between files, keeping the UI responsive during large im | |||
| 152 | 152 | - **VFS abstraction** decouples user-visible organization from on-disk storage. Users can create multiple independent directory trees, rename and restructure freely, without moving files. | |
| 153 | 153 | - **Backend trait** keeps the browser UI decoupled from the data layer, making it testable with mock backends. | |
| 154 | 154 | - **Synchronous core** keeps the data layer simple and predictable. Async is confined to the sync layer (tokio) and the app. | |
| 155 | - | - **try_lock on audio thread** guarantees real-time safety. The cpal callback never blocks -- it either gets the lock and produces audio, or outputs silence. | |
| 155 | + | - **try_lock on audio thread** guarantees real-time safety. The cpal callback never blocks. It either gets the lock and produces audio, or outputs silence. | |
| 156 | 156 | - **Strongly-typed IDs** (VfsId, NodeId, SampleHash) prevent accidental mixups at compile time. Integer IDs use a macro-generated newtype; SampleHash wraps a hex string. | |
| 157 | 157 | - **Device plugin system** with Rhai scripting allows hardware sampler export profiles to be extended by users without recompiling, while keeping the sandbox constrained. | |
| 158 | 158 | - **Trigger-based sync changelog** captures all local mutations automatically without requiring callers to manually record changes, making sync integration transparent to the rest of the codebase. |
| @@ -1,6 +1,6 @@ | |||
| 1 | 1 | # audiofiles Database Schema | |
| 2 | 2 | ||
| 3 | - | SQLite schema reference. 23 inline migrations. Migrations are embedded as Rust string constants in `crates/audiofiles-core/src/db.rs` and applied via `PRAGMA user_version` tracking -- not separate SQL files. | |
| 3 | + | SQLite schema reference. 23 inline migrations. Migrations are embedded as Rust string constants in `crates/audiofiles-core/src/db.rs` and applied via `PRAGMA user_version` tracking, not separate SQL files. | |
| 4 | 4 | ||
| 5 | 5 | ## Domain Map | |
| 6 | 6 | ||
| @@ -19,7 +19,7 @@ SQLite schema reference. 23 inline migrations. Migrations are embedded as Rust s | |||
| 19 | 19 | ## Samples | |
| 20 | 20 | ||
| 21 | 21 | ### samples | |
| 22 | - | Content-addressed sample storage. The hash (of file content) is the primary key -- duplicate files are impossible by design. | |
| 22 | + | Content-addressed sample storage. The hash (of file content) is the primary key. Duplicate files are impossible by design. | |
| 23 | 23 | ||
| 24 | 24 | | Column | Type | Notes | | |
| 25 | 25 | |--------|------|-------| | |
| @@ -274,8 +274,8 @@ Indexes: `source_hash`, `result_hash`. | |||
| 274 | 274 | ||
| 275 | 275 | ## Design Patterns | |
| 276 | 276 | ||
| 277 | - | - **Content-addressed storage:** `samples.hash` is a content hash -- the same file always produces the same PK, making deduplication automatic | |
| 278 | - | - **Inline migrations:** All schema DDL is embedded as Rust `const` strings in `db.rs`, applied transactionally via `PRAGMA user_version` -- no external SQL files | |
| 277 | + | - **Content-addressed storage:** `samples.hash` is a content hash. The same file always produces the same PK, making deduplication automatic | |
| 278 | + | - **Inline migrations:** All schema DDL is embedded as Rust `const` strings in `db.rs`, applied transactionally via `PRAGMA user_version`, no external SQL files | |
| 279 | 279 | - **VFS abstraction:** Virtual file systems decouple organization from disk layout; one sample can appear in multiple VFS trees via `vfs_nodes.sample_hash` | |
| 280 | 280 | - **Self-referential tree:** `vfs_nodes.parent_id` references `vfs_nodes.id` for arbitrary directory nesting | |
| 281 | 281 | - **Dot-namespaced tags:** Flat `tag` strings with dot convention (e.g., `genre.techno`) replace the original key-value tag model (migration 002) |
| @@ -1,4 +1,4 @@ | |||
| 1 | - | # audiofiles -- Sample Classification | |
| 1 | + | # audiofiles: Sample Classification | |
| 2 | 2 | ||
| 3 | 3 | audiofiles classifies samples from deterministic DSP features only. No trained model | |
| 4 | 4 | ships in the binary: the feature extraction is plain signal measurement, and tagging is |