mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-02 16:20:57 +02:00
fix(audio-analysis): avoid spectrogram splice noise
This commit is contained in:
@@ -3,7 +3,7 @@ part of 'audio_analysis_widget.dart';
|
||||
// Analysis result models and per-run parameter records.
|
||||
|
||||
class AudioAnalysisData {
|
||||
static const cacheVersion = 12;
|
||||
static const cacheVersion = 13;
|
||||
|
||||
final String filePath;
|
||||
final int fileSize;
|
||||
|
||||
@@ -23,7 +23,12 @@ const int audioSpectrogramWidth = 1600;
|
||||
const int audioSpectrogramHeight = 800;
|
||||
const int audioSpectralAnalysisWidth = 400;
|
||||
const double audioSpectrogramDynamicRangeDb = 120;
|
||||
const int audioSpectrogramSampleWindowCount = 300;
|
||||
// Keep splice boundaries well below the cutoff estimator's top temporal
|
||||
// percentile. Too many short excerpts turn waveform discontinuities into a
|
||||
// persistent broadband floor, which can make a real low-pass edge look like
|
||||
// full-band content. Longer windows preserve the same whole-track coverage and
|
||||
// memory bound while making the small number of seams statistical outliers.
|
||||
const int audioSpectrogramSampleWindowCount = 16;
|
||||
const int audioSpectrogramMaxSelectedChannelSamples = 8 * 1024 * 1024;
|
||||
|
||||
String formatAudioAnalysisSpectralCutoff(
|
||||
|
||||
@@ -24,7 +24,7 @@ void main() {
|
||||
|
||||
group('audio analysis cache', () {
|
||||
test('invalidates results from the previous cutoff estimator', () {
|
||||
expect(AudioAnalysisData.cacheVersion, 12);
|
||||
expect(AudioAnalysisData.cacheVersion, 13);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -142,14 +142,22 @@ lavfi.r128.true_peak=0.907
|
||||
expect(arguments, isNot(contains('-loglevel')));
|
||||
});
|
||||
|
||||
test('bounds retained audio for long high-rate files', () {
|
||||
test('bounds retained audio without making splice noise persistent', () {
|
||||
final filter = buildAudioSpectrogramFilter(
|
||||
durationSeconds: 600,
|
||||
sampleRate: 192000,
|
||||
channels: 2,
|
||||
);
|
||||
|
||||
expect(filter, contains("aselect='lt(mod(t,2.000000000),"));
|
||||
// The cutoff estimator uses temporal P90. Keep window boundaries far
|
||||
// below ten percent of its 400 columns so seam energy remains an outlier.
|
||||
expect(audioSpectrogramSampleWindowCount, 16);
|
||||
expect(
|
||||
audioSpectrogramSampleWindowCount,
|
||||
lessThan(audioSpectralAnalysisWidth * 0.10),
|
||||
);
|
||||
expect(filter, contains("aselect='lt(mod(t,37.500000000),"));
|
||||
expect(filter, contains('1.365333333'));
|
||||
expect(filter, contains('asetpts=N/SR/TB'));
|
||||
expect(filter, contains('aformat=sample_fmts=fltp'));
|
||||
expect(filter, isNot(contains('aresample')));
|
||||
@@ -246,6 +254,43 @@ lavfi.r128.true_peak=0.907
|
||||
expect(cutoff!, inInclusiveRange(21000, 23500));
|
||||
});
|
||||
|
||||
test('ignores sparse broadband seams below the temporal P90 budget', () {
|
||||
const sourceNyquist = 24000.0;
|
||||
final intensity = _blankIntensity(width, height, value: 12);
|
||||
_paintFrequencyBand(
|
||||
intensity,
|
||||
width: width,
|
||||
height: height,
|
||||
maxFrequencyHz: sourceNyquist,
|
||||
lowHz: 0,
|
||||
highHz: 20000,
|
||||
intensity: 100,
|
||||
);
|
||||
// Model discontinuities between distributed excerpts. Their columns are
|
||||
// bright at every frequency, but occupy only six percent of the image.
|
||||
_paintFrequencyBand(
|
||||
intensity,
|
||||
width: width,
|
||||
height: height,
|
||||
maxFrequencyHz: sourceNyquist,
|
||||
lowHz: 0,
|
||||
highHz: sourceNyquist,
|
||||
intensity: 255,
|
||||
startColumn: 0,
|
||||
endColumn: 12,
|
||||
);
|
||||
|
||||
final cutoff = estimateEffectiveSpectralCutoffHz(
|
||||
intensity: intensity,
|
||||
width: width,
|
||||
height: height,
|
||||
maxFrequencyHz: sourceNyquist,
|
||||
);
|
||||
|
||||
expect(cutoff, isNotNull);
|
||||
expect(cutoff!, inInclusiveRange(19400, 20600));
|
||||
});
|
||||
|
||||
test('rejects a low noise floor above a 15.8 kHz bandwidth edge', () {
|
||||
const cdNyquist = 22050.0;
|
||||
final intensity = _blankIntensity(width, height, value: 42);
|
||||
|
||||
Reference in New Issue
Block a user