Add Hi-Res authenticity check

Introduce a per-file Hi-Res authenticity checker and optional auto re-download for flagged fake Hi-Res downloads. Adds Rust checker modules (fft, evidence, FLAC/WAV decoding, tests) and a mobile API (check_hires_authenticity). Wire platform bindings for Android/iOS and PlatformBridge. Add Dart HiResCheckService, UI HiResCheckCard, settings toggle (redownloadFakeHiRes) and integration in the download pipeline to quarantine and replace suspicious files with LOSSLESS when safe. Adds claxon FLAC dependency.
This commit is contained in:
Bartolo committed 2026-09-23 22:29:15 +02:00
1 parent 83bd55bb64
commit 14ce4bc868
33 files changed
+3012 -2

No files matched your search

@@ -195,6 +195,7 @@ internal interface CoreBackend {
fun sanitizeFilename(filename: String): String
fun fileMetadataImplementation(path: String): String
fun readFileMetadata(path: String, hint: String): String
fun checkHiResAuthenticity(path: String, optionsJson: String): String
fun readAudioMetadata(path: String, hint: String, cacheKey: String): String
fun setLibraryCoverCacheDirectory(path: String)
fun scanLibraryFolder(folder: String): String
@@ -86,6 +86,7 @@ class MainActivity: FlutterFragmentActivity() {
"runPostProcessingV2",
"readAudioMetadata",
"readFileMetadata",
"checkHiResAuthenticity",
"editFileMetadata",
"reEnrichFile",
"setLibraryCoverCacheDir",
@@ -1442,6 +1443,24 @@ class MainActivity: FlutterFragmentActivity() {
}
result.success(response)
}
"checkHiResAuthenticity" -> {
val filePath = call.argument<String>("file_path") ?: ""
val optionsJson = call.argument<String>("options_json") ?: ""
val response = withContext(Dispatchers.IO) {
try {
if (filePath.startsWith("content://")) {
checkHiResAuthenticityFromUri(Uri.parse(filePath), optionsJson)
?.toString()
?: errorJson("Failed to read SAF audio file")
} else {
coreBackend.checkHiResAuthenticity(filePath, optionsJson)
}
} catch (e: Exception) {
errorJson(e.message ?: "Hi-Res check failed")
}
}
result.success(response)
}
"editFileMetadata" -> {
val filePath = call.argument<String>("file_path") ?: ""
val metadataJson = call.argument<String>("metadata_json") ?: "{}"
@@ -299,6 +299,15 @@ internal fun MainActivity.readAudioMetadataFromUri(
obj.takeUnless { it.has("error") }
}
/** The Hi-Res check reads only a window from the middle of the file, so a
* seekable descriptor avoids copying the whole track out of SAF. */
internal fun MainActivity.checkHiResAuthenticityFromUri(
uri: Uri,
optionsJson: String,
): JSONObject? = readMetadataFromUri(uri) { path, _ ->
JSONObject(coreBackend.checkHiResAuthenticity(path, optionsJson))
}?.put("file_path", uri.toString())
internal fun MainActivity.readCompleteMetadataFromUri(
uri: Uri,
displayNameHint: String? = null,
@@ -218,6 +218,9 @@ internal object RustCoreBackend : CoreBackend {
override fun readFileMetadata(path: String, hint: String): String =
com.spotiflac.backend.readFileMetadata(path, hint, null)
override fun checkHiResAuthenticity(path: String, optionsJson: String): String =
com.spotiflac.backend.checkHiresAuthenticity(path, optionsJson, null)
override fun readAudioMetadata(path: String, hint: String, cacheKey: String): String =
owner().readAudioMetadata(File(path).canonicalPath, hint, cacheKey, null)