mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-23 18:11:02 +02:00
fix(analysis): detect full-band spectral cutoff
This commit is contained in:
@@ -171,13 +171,16 @@ class _AudioInfoCard extends StatelessWidget {
|
||||
value: _formatClipping(context, data.clippingSamples),
|
||||
cs: cs,
|
||||
),
|
||||
if (data.spectralCutoffHz != null)
|
||||
_MetricChip(
|
||||
icon: Icons.filter_alt_outlined,
|
||||
label: context.l10n.audioAnalysisSpectralCutoff,
|
||||
value: _formatFrequency(data.spectralCutoffHz!),
|
||||
cs: cs,
|
||||
_MetricChip(
|
||||
icon: Icons.filter_alt_outlined,
|
||||
label: context.l10n.audioAnalysisSpectralCutoff,
|
||||
value: formatAudioAnalysisSpectralCutoff(
|
||||
data.spectralCutoffHz,
|
||||
notDetectedLabel:
|
||||
context.l10n.audioAnalysisCutoffNotDetected,
|
||||
),
|
||||
cs: cs,
|
||||
),
|
||||
_MetricChip(
|
||||
icon: Icons.numbers,
|
||||
label: context.l10n.audioAnalysisSamples,
|
||||
@@ -228,11 +231,6 @@ class _AudioInfoCard extends StatelessWidget {
|
||||
return data.channels > 0 ? '${data.channels}' : 'N/A';
|
||||
}
|
||||
|
||||
String _formatFrequency(double hz) {
|
||||
if (hz >= 1000) return '${(hz / 1000).toStringAsFixed(1)} kHz';
|
||||
return '${hz.round()} Hz';
|
||||
}
|
||||
|
||||
String _formatBitrate(int bitsPerSecond) {
|
||||
if (bitsPerSecond >= 1000000) {
|
||||
return '${(bitsPerSecond / 1000000).toStringAsFixed(2)} Mbps';
|
||||
|
||||
@@ -3,7 +3,7 @@ part of 'audio_analysis_widget.dart';
|
||||
// Analysis result models and per-run parameter records.
|
||||
|
||||
class AudioAnalysisData {
|
||||
static const cacheVersion = 7;
|
||||
static const cacheVersion = 8;
|
||||
|
||||
final String filePath;
|
||||
final int fileSize;
|
||||
|
||||
@@ -24,6 +24,19 @@ const int audioSpectrogramHeight = 800;
|
||||
const int audioSpectralAnalysisWidth = 400;
|
||||
const double audioSpectrogramDynamicRangeDb = 120;
|
||||
|
||||
String formatAudioAnalysisSpectralCutoff(
|
||||
double? cutoffHz, {
|
||||
required String notDetectedLabel,
|
||||
}) {
|
||||
if (cutoffHz == null || !cutoffHz.isFinite || cutoffHz <= 0) {
|
||||
return notDetectedLabel;
|
||||
}
|
||||
if (cutoffHz >= 1000) {
|
||||
return '${(cutoffHz / 1000).toStringAsFixed(1)} kHz';
|
||||
}
|
||||
return '${cutoffHz.round()} Hz';
|
||||
}
|
||||
|
||||
String _buildShowspectrumOptions({required int width, required String color}) {
|
||||
return 'showspectrumpic='
|
||||
's=${width}x$audioSpectrogramHeight:'
|
||||
@@ -385,8 +398,10 @@ double? estimateEffectiveSpectralCutoffHz({
|
||||
}
|
||||
|
||||
// A genuinely broadband signal with no internal falling edge reaches the
|
||||
// analysis ceiling. Report Nyquist only when both its baseband and top band
|
||||
// are populated; silence or an isolated high-frequency line returns null.
|
||||
// analysis ceiling. Natural music has a pronounced spectral tilt, so the
|
||||
// top band does not need to be almost as loud as the baseband. It must still
|
||||
// sit clearly above the measured low-level floor; silence or an isolated
|
||||
// high-frequency line therefore continues to return null.
|
||||
final basebandLevel = _spectralMedian(
|
||||
smoothed,
|
||||
(height * 0.05).floor(),
|
||||
@@ -397,7 +412,8 @@ double? estimateEffectiveSpectralCutoffHz({
|
||||
(height * 0.90).floor(),
|
||||
math.max(1, (height * 0.98).floor()),
|
||||
);
|
||||
if (basebandLevel >= 24 && topBandLevel >= basebandLevel - minimumDrop) {
|
||||
final populatedTopFloor = math.max(24.0, lowLevel * 0.60);
|
||||
if (basebandLevel >= 24 && topBandLevel >= populatedTopFloor) {
|
||||
return maxFrequencyHz;
|
||||
}
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user