fix(replaygain): write and verify native Opus gain tags

Preserve audio and artwork while replacing conflicting Opus gain tags with R128 comments. Verify manual, download, and album writes, handle SAF failures, and refresh playback normalization after saving.
This commit is contained in:
zarzet
2026-09-06 21:03:57 +07:00
parent 0acdd6d0b0
commit bfffb8da11
14 changed files with 745 additions and 138 deletions
+11 -2
View File
@@ -7,10 +7,16 @@ class PlaybackNormalizationCache {
readMetadata;
final void Function(Object)? onReadError;
final Map<String, double> _volumes = {};
int _generation = 0;
static final _gainNumber = RegExp(r'-?\d+(\.\d+)?');
PlaybackNormalizationCache({required this.readMetadata, this.onReadError});
void invalidate(String source) {
_volumes.remove(source);
_generation++;
}
Future<double> volumeFor(
String path, {
String? cacheKey,
@@ -19,6 +25,7 @@ class PlaybackNormalizationCache {
final key = cacheKey ?? path;
final cached = _volumes[key];
if (cached != null) return cached;
final generation = _generation;
try {
final metadata = await readMetadata(path, displayName: displayName);
if (metadata['error'] != null) {
@@ -31,8 +38,10 @@ class PlaybackNormalizationCache {
final volume = gain == null
? 1.0
: pow(10.0, gain / 20.0).toDouble().clamp(0.0, 1.0);
if (_volumes.length >= 128) _volumes.remove(_volumes.keys.first);
_volumes[key] = volume;
if (generation == _generation) {
if (_volumes.length >= 128) _volumes.remove(_volumes.keys.first);
_volumes[key] = volume;
}
return volume;
} catch (error) {
onReadError?.call(error);