Skip to main content

max / audiofiles

Forge audit fixes: resampler tail, slice count, clippy gate Pre-launch deep-audit fixes (Lane F): - Resampler dropped its tail: the chunked SincFixedIn loop never flushed the resampler's internal buffer, so every rate-converted conform/export lost its final frames. Now flush with empty input until the full output length is produced, then clamp to round(num_frames * ratio). The sinc resampler already time-aligns output to input, so no leading-delay trim is applied. Added an impulse regression test asserting exact length and impulse position. - Forge chop reported slice_count as slices.len() even when a slice rendered empty and was skipped, overstating the count and leaving a gap in the file numbering. Count and number only slices actually written. - Fixed a clippy erasing_op deny (0 * SIZE) that was breaking the clippy gate, and cleared the remaining clippy warnings (needless return, sort_by_key, plus scoped allows for two intentional design lints). cargo clippy --all-targets is now clean; 840 tests pass.
Co-Authored-By
Claude Opus 4.8 <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-06-08 01:03 UTC
Signed with PGP, not checked
Commit: 04e06abe9006e3868a16a1a8de9ebc26a4b26ef7
Parent: a52d632
46 files changed, +293 insertions, -371 deletions
@@ -396,8 +396,8 @@
396 396 #[test]
397 397 fn clamp_prevents_overflow() {
398 398 // Simulate very loud mixed audio
399 - let buf = vec![1.5f32, -1.5, 0.5, -0.5];
400 - let mut data = vec![0.0f32; 4];
399 + let buf = [1.5f32, -1.5, 0.5, -0.5];
400 + let mut data = [0.0f32; 4];
401 401 for (out, &mix) in data.iter_mut().zip(buf.iter()) {
402 402 *out = mix.clamp(-1.0, 1.0);
403 403 }
@@ -292,14 +292,12 @@
292 292 let now = chrono::Utc::now();
293 293
294 294 // Clock rollback detection: if now is before last_seen_date, expire immediately
295 - if let Some(ref last) = trial.last_seen_date {
296 - if let Ok(last_seen) = chrono::DateTime::parse_from_rfc3339(last) {
297 - if now.signed_duration_since(last_seen).num_hours() < -1 {
295 + if let Some(ref last) = trial.last_seen_date
296 + && let Ok(last_seen) = chrono::DateTime::parse_from_rfc3339(last)
297 + && now.signed_duration_since(last_seen).num_hours() < -1 {
298 298 // Allow up to 1 hour of drift (DST, NTP correction)
299 299 return 0;
300 300 }
301 - }
302 - }
303 301
304 302 let elapsed = now.signed_duration_since(first);
305 303 30 - elapsed.num_days()
@@ -164,8 +164,7 @@
164 164 return Some(key);
165 165 }
166 166 // Fall back to bundled synckit.toml
167 - parse_synckit_toml_key().map(String::from)
168 - }
167 + parse_synckit_toml_key()}
169 168
170 169 /// Save an API key to the data directory for future launches.
171 170 #[cfg(test)]
@@ -526,8 +525,8 @@
526 525 let ctx = ui.ctx().clone();
527 526 let ctx = &ctx;
528 527 // Poll tray menu events
529 - if let Some(ref tray) = self.tray {
530 - if let Some(action) = tray.poll() {
528 + if let Some(ref tray) = self.tray
529 + && let Some(action) = tray.poll() {
531 530 match action {
532 531 tray::TrayAction::ShowWindow => {
533 532 ctx.send_viewport_cmd(ViewportCommand::Focus);
@@ -542,11 +541,10 @@
542 541 }
543 542 }
544 543 }
545 - }
546 544
547 545 // Update tray tooltip based on playback state
548 - if let Some(ref tray) = self.tray {
549 - if let Some(ref browser) = self.browser {
546 + if let Some(ref tray) = self.tray
547 + && let Some(ref browser) = self.browser {
550 548 let playing = browser.shared.preview.lock().playing;
551 549 if playing {
552 550 tray.set_tooltip(&browser.status);
@@ -554,23 +552,21 @@
554 552 tray.set_tooltip("audiofiles");
555 553 }
556 554 }
557 - }
558 555
559 556 // Check if sync pulled remote changes → refresh browser contents
560 - if let Some(ref sync) = self.sync_manager {
561 - if sync.status().needs_refresh {
557 + if let Some(ref sync) = self.sync_manager
558 + && sync.status().needs_refresh {
562 559 if let Some(ref mut browser) = self.browser {
563 560 browser.refresh_vfs_list();
564 561 browser.refresh_contents();
565 562 }
566 563 sync.clear_needs_refresh();
567 564 }
568 - }
569 565
570 566 // ── Sync setup actions (before draw, so UI sees results this frame) ──
571 567 // ── Vault actions ──
572 - if let Some(ref mut browser) = self.browser {
573 - if let Some(action) = browser.settings.pending_action.take() {
568 + if let Some(ref mut browser) = self.browser
569 + && let Some(action) = browser.settings.pending_action.take() {
574 570 use audiofiles_browser::state::VaultAction;
575 571 match action {
576 572 VaultAction::SwitchVault(path) => {
@@ -581,12 +577,11 @@
581 577 let switch_path = path.clone();
582 578 if self.with_vault_registry(|reg| vault::create_vault(reg, &name, &path)) {
583 579 self.switch_vault(switch_path);
584 - if loose_files {
585 - if let Some(ref mut browser) = self.browser {
580 + if loose_files
581 + && let Some(ref mut browser) = self.browser {
586 582 let _ = browser.backend.set_config("loose_files", "1");
587 583 browser.settings.is_loose_files = true;
588 584 }
589 - }
590 585 return;
591 586 }
592 587 }
@@ -637,7 +632,6 @@
637 632 }
638 633 }
639 634 }
640 - }
641 635
642 636 // ── VFS Mirror: sync if dirty ──
643 637 if let Some(ref mut browser) = self.browser {
@@ -960,7 +954,7 @@
960 954 // Empty file → falls through to bundled synckit.toml key
961 955 if std::env::var("AF_SYNC_API_KEY").is_err() {
962 956 let key = load_api_key(dir.path());
963 - assert_eq!(key, parse_synckit_toml_key().map(String::from));
957 + assert_eq!(key, parse_synckit_toml_key());
964 958 }
965 959 }
966 960
@@ -970,7 +964,7 @@
970 964 std::fs::write(dir.path().join("sync_api_key"), " \n ").unwrap();
971 965 if std::env::var("AF_SYNC_API_KEY").is_err() {
972 966 let key = load_api_key(dir.path());
973 - assert_eq!(key, parse_synckit_toml_key().map(String::from));
967 + assert_eq!(key, parse_synckit_toml_key());
974 968 }
975 969 }
976 970
@@ -979,7 +973,7 @@
979 973 let dir = tempfile::tempdir().unwrap();
980 974 if std::env::var("AF_SYNC_API_KEY").is_err() {
981 975 let key = load_api_key(dir.path());
982 - assert_eq!(key, parse_synckit_toml_key().map(String::from));
976 + assert_eq!(key, parse_synckit_toml_key());
983 977 }
984 978 }
985 979
@@ -137,7 +137,8 @@
137 137
138 138 assert_eq!(rgba.len(), SIZE * SIZE * 4);
139 139 // Middle bar (index 2) is full height — pixel at (9, 0) should be coloured
140 - let mid_offset = (0 * SIZE + 9) * 4;
140 + // (row 0, col 9) -> offset (0 * SIZE + 9) * 4
141 + let mid_offset = 9 * 4;
141 142 assert_eq!(&rgba[mid_offset..mid_offset + 4], &bar_colour);
142 143 // Corner (0,0) should be transparent
143 144 assert_eq!(&rgba[0..4], &[0, 0, 0, 0]);
@@ -187,8 +187,8 @@
187 187 Ok(resp) if resp.status().is_success() => {
188 188 match resp.json::<UpdateResponse>().await {
189 189 Ok(update) => {
190 - if let Ok(remote) = Version::parse(&update.version) {
191 - if remote > current && is_trusted_download_url(&update.url) {
190 + if let Ok(remote) = Version::parse(&update.version)
191 + && remote > current && is_trusted_download_url(&update.url) {
192 192 tracing::info!("Update available: v{}", update.version);
193 193 let mut s = status.lock();
194 194 s.available = true;
@@ -196,7 +196,6 @@
196 196 s.notes = update.notes;
197 197 s.download_url = update.url;
198 198 }
199 - }
200 199 }
201 200 Err(e) => {
202 201 tracing::warn!("Failed to parse update response: {e}");
@@ -74,11 +74,10 @@
74 74 });
75 75 ui.add_space(theme::space::SM);
76 76 ui.horizontal(|ui| {
77 - if ui.button("Choose different location...").clicked() {
78 - if let Some(path) = rfd::FileDialog::new().pick_folder() {
77 + if ui.button("Choose different location...").clicked()
78 + && let Some(path) = rfd::FileDialog::new().pick_folder() {
79 79 self.vault_setup_path = Some(path);
80 80 }
81 - }
82 81 if is_custom && ui.button("Use default").clicked() {
83 82 self.vault_setup_path = None;
84 83 }
@@ -149,7 +149,8 @@
149 149 WHERE vn.id IS NULL AND s.deleted_at IS NULL",
150 150 ) {
151 151 Ok(mut stmt) => {
152 - let rows = stmt
152 +
153 + stmt
153 154 .query_map([], |row| {
154 155 Ok((
155 156 row.get::<_, String>(0)?,
@@ -159,8 +160,7 @@
159 160 })
160 161 .ok()
161 162 .map(|iter| iter.flatten().collect::<Vec<_>>())
162 - .unwrap_or_default();
163 - rows
163 + .unwrap_or_default()
164 164 }
165 165 Err(e) => {
166 166 error!("Cleanup worker failed to query orphans: {e}");
@@ -206,11 +206,10 @@
206 206 ) {
207 207 Ok(_) => {
208 208 // Delete from disk
209 - if let Ok(path) = store.sample_path(hash, ext) {
210 - if path.exists() {
209 + if let Ok(path) = store.sample_path(hash, ext)
210 + && path.exists() {
211 211 let _ = std::fs::remove_file(&path);
212 212 }
213 - }
214 213 removed += 1;
215 214 }
216 215 Err(e) => {
@@ -403,23 +403,21 @@
403 403 if input.key_pressed(egui::Key::E) {
404 404 if state.edit.show_window {
405 405 state.close_edit_window();
406 - } else if let Some(node) = state.selected_node() {
407 - if let Some(hash) = &node.node.sample_hash {
406 + } else if let Some(node) = state.selected_node()
407 + && let Some(hash) = &node.node.sample_hash {
408 408 let hash = hash.clone();
409 409 state.open_edit_window(&hash);
410 410 }
411 - }
412 411 }
413 412 // "F" toggles the floating Sample Forge window for the selected sample
414 413 if input.key_pressed(egui::Key::F) && !shift {
415 414 if state.forge.show_window {
416 415 state.close_forge_window();
417 - } else if let Some(node) = state.selected_node() {
418 - if let Some(hash) = &node.node.sample_hash {
416 + } else if let Some(node) = state.selected_node()
417 + && let Some(hash) = &node.node.sample_hash {
419 418 let hash = hash.clone();
420 419 state.open_forge_window(&hash);
421 420 }
422 - }
423 421 }
424 422 // "L" toggles loop
425 423 if input.key_pressed(egui::Key::L) {
@@ -434,28 +432,23 @@
434 432 state.toggle_detail();
435 433 }
436 434 // Shift+F: find similar
437 - if shift && input.key_pressed(egui::Key::F) {
438 - if let Some(node) = state.selected_node() {
439 - if let Some(hash) = &node.node.sample_hash {
435 + if shift && input.key_pressed(egui::Key::F)
436 + && let Some(node) = state.selected_node()
437 + && let Some(hash) = &node.node.sample_hash {
440 438 let hash = hash.clone();
441 439 state.find_similar(&hash);
442 440 }
443 - }
444 - }
445 441 // Shift+D: find duplicates
446 - if shift && input.key_pressed(egui::Key::D) {
447 - if let Some(node) = state.selected_node() {
448 - if let Some(hash) = &node.node.sample_hash {
442 + if shift && input.key_pressed(egui::Key::D)
443 + && let Some(node) = state.selected_node()
444 + && let Some(hash) = &node.node.sample_hash {
449 445 let hash = hash.clone();
450 446 state.find_near_duplicates(&hash);
451 447 }
452 - }
453 - }
454 448 // Cmd+Shift+M: bulk move (Cmd+M alone conflicts with macOS minimize)
455 - if input.modifiers.command && input.modifiers.shift && input.key_pressed(egui::Key::M) {
456 - if state.selection.count() > 1 {
449 + if input.modifiers.command && input.modifiers.shift && input.key_pressed(egui::Key::M)
450 + && state.selection.count() > 1 {
457 451 state.open_bulk_move_modal();
458 452 }
459 - }
460 453 });
461 454 }
@@ -216,11 +216,10 @@
216 216 Ok(_) => Ok(ImportFileResult::Imported(hash, ext)),
217 217 Err(CoreError::NameConflict(_)) => Ok(ImportFileResult::Duplicate),
218 218 Err(e) => {
219 - if let CoreError::Db(ref sqlite_err) = e {
220 - if sqlite_err.to_string().contains("UNIQUE") {
219 + if let CoreError::Db(ref sqlite_err) = e
220 + && sqlite_err.to_string().contains("UNIQUE") {
221 221 return Ok(ImportFileResult::Duplicate);
222 222 }
223 - }
224 223 Err(e)
225 224 }
226 225 }