mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-22 06:25:41 +00:00
feat(playback): loudness bind rules, analysis seeding, and normalization UI
Resolve integrated loudness from SQLite only at decode bind; keep pre-trim until a row exists, then allow provisional gain from live updates. Pass DB-stable hints from the web app into play and gapless preload. Default pre-measurement attenuation -4.5 dB with an icon reset in Settings; drop redundant normalization copy and shorten pre-trim descriptions. analysis_cache seed_from_bytes returns an outcome and skips redundant waveform work on cache hits; wire callers and related frontend/backend glue.
This commit is contained in:
+53
-13
@@ -1199,8 +1199,30 @@ fn analysis_get_waveform(
|
||||
md5_16kb: String,
|
||||
cache: tauri::State<'_, analysis_cache::AnalysisCache>,
|
||||
) -> Result<Option<WaveformCachePayload>, String> {
|
||||
let key = analysis_cache::TrackKey { track_id, md5_16kb };
|
||||
let key = analysis_cache::TrackKey {
|
||||
track_id: track_id.clone(),
|
||||
md5_16kb: md5_16kb.clone(),
|
||||
};
|
||||
let row = cache.get_waveform(&key)?;
|
||||
match &row {
|
||||
Some(v) => {
|
||||
crate::app_deprintln!(
|
||||
"[analysis][waveform] db hit (exact key) track_id={} md5_16kb={} bins_len={} bin_count={} updated_at={}",
|
||||
track_id,
|
||||
md5_16kb,
|
||||
v.bins.len(),
|
||||
v.bin_count,
|
||||
v.updated_at
|
||||
);
|
||||
}
|
||||
None => {
|
||||
crate::app_deprintln!(
|
||||
"[analysis][waveform] db miss (exact key) track_id={} md5_16kb={}",
|
||||
track_id,
|
||||
md5_16kb
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(row.map(|v| WaveformCachePayload {
|
||||
bins: v.bins,
|
||||
bin_count: v.bin_count,
|
||||
@@ -1217,6 +1239,23 @@ fn analysis_get_waveform_for_track(
|
||||
cache: tauri::State<'_, analysis_cache::AnalysisCache>,
|
||||
) -> Result<Option<WaveformCachePayload>, String> {
|
||||
let row = cache.get_latest_waveform_for_track(&track_id)?;
|
||||
match &row {
|
||||
Some(v) => {
|
||||
crate::app_deprintln!(
|
||||
"[analysis][waveform] db hit track_id={} bins_len={} bin_count={} updated_at={}",
|
||||
track_id,
|
||||
v.bins.len(),
|
||||
v.bin_count,
|
||||
v.updated_at
|
||||
);
|
||||
}
|
||||
None => {
|
||||
crate::app_deprintln!(
|
||||
"[analysis][waveform] db miss track_id={}",
|
||||
track_id
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(row.map(|v| WaveformCachePayload {
|
||||
bins: v.bins,
|
||||
bin_count: v.bin_count,
|
||||
@@ -1349,18 +1388,19 @@ async fn stream_to_file(response: reqwest::Response, dest_path: &std::path::Path
|
||||
}
|
||||
|
||||
fn enqueue_analysis_seed(app: &tauri::AppHandle, track_id: &str, bytes: &[u8]) -> Result<bool, String> {
|
||||
analysis_cache::seed_from_bytes(app, track_id, bytes)
|
||||
.map_err(|e| {
|
||||
crate::app_eprintln!("[analysis] failed to seed {}: {}", track_id, e);
|
||||
e
|
||||
})?;
|
||||
let _ = app.emit(
|
||||
"analysis:waveform-updated",
|
||||
WaveformUpdatedPayload {
|
||||
track_id: track_id.to_string(),
|
||||
is_partial: false,
|
||||
},
|
||||
);
|
||||
let outcome = analysis_cache::seed_from_bytes(app, track_id, bytes).map_err(|e| {
|
||||
crate::app_eprintln!("[analysis] failed to seed {}: {}", track_id, e);
|
||||
e
|
||||
})?;
|
||||
if outcome == analysis_cache::SeedFromBytesOutcome::Upserted {
|
||||
let _ = app.emit(
|
||||
"analysis:waveform-updated",
|
||||
WaveformUpdatedPayload {
|
||||
track_id: track_id.to_string(),
|
||||
is_partial: false,
|
||||
},
|
||||
);
|
||||
}
|
||||
let has_loudness = app
|
||||
.try_state::<analysis_cache::AnalysisCache>()
|
||||
.and_then(|cache| cache.get_latest_loudness_for_track(track_id).ok().flatten())
|
||||
|
||||
Reference in New Issue
Block a user