fix(player): stabilize equalizer and visualizer
This commit is contained in:
@@ -40,7 +40,9 @@ class _VisualizadorAudioState extends State<VisualizadorAudio>
|
||||
late final AnimationController _controller;
|
||||
bool _activo = false;
|
||||
int? _sessionId;
|
||||
List<double> _ondaReal = const [];
|
||||
List<double> _ondaObjetivo = const [];
|
||||
List<double> _ondaVisual = const [];
|
||||
DateTime? _ultimaOndaReal;
|
||||
StreamSubscription<EstadoReproduccion>? _estadoSubscription;
|
||||
StreamSubscription<int?>? _sessionSubscription;
|
||||
StreamSubscription<dynamic>? _ondaSubscription;
|
||||
@@ -52,7 +54,10 @@ class _VisualizadorAudioState extends State<VisualizadorAudio>
|
||||
vsync: this,
|
||||
duration: const Duration(seconds: 2),
|
||||
)..addListener(() {
|
||||
if (mounted) setState(() {});
|
||||
if (mounted) {
|
||||
_actualizarOndaVisual();
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
_estadoSubscription = widget.estadoStream.listen(_onEstado);
|
||||
_sessionSubscription = widget.androidAudioSessionIdStream?.listen(
|
||||
@@ -87,9 +92,7 @@ class _VisualizadorAudioState extends State<VisualizadorAudio>
|
||||
if (!puedeCapturar) {
|
||||
unawaited(_ondaSubscription?.cancel());
|
||||
_ondaSubscription = null;
|
||||
if (_ondaReal.isNotEmpty && mounted) {
|
||||
setState(() => _ondaReal = const []);
|
||||
}
|
||||
_ultimaOndaReal = null;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -107,18 +110,66 @@ class _VisualizadorAudioState extends State<VisualizadorAudio>
|
||||
.map((v) => v.toDouble().clamp(0.0, 1.0))
|
||||
.toList(growable: false);
|
||||
if (muestras.isNotEmpty) {
|
||||
setState(() => _ondaReal = muestras);
|
||||
_ultimaOndaReal = DateTime.now();
|
||||
_ondaObjetivo = _normalizar(muestras);
|
||||
}
|
||||
},
|
||||
onError: (_) {
|
||||
unawaited(_ondaSubscription?.cancel());
|
||||
_ondaSubscription = null;
|
||||
if (mounted) setState(() => _ondaReal = const []);
|
||||
_ultimaOndaReal = null;
|
||||
},
|
||||
cancelOnError: false,
|
||||
);
|
||||
}
|
||||
|
||||
void _actualizarOndaVisual() {
|
||||
final objetivo = _objetivoActual();
|
||||
if (_ondaVisual.length != objetivo.length) {
|
||||
_ondaVisual = List<double>.from(objetivo);
|
||||
return;
|
||||
}
|
||||
_ondaVisual = List<double>.generate(objetivo.length, (i) {
|
||||
final suavizado = _ondaVisual[i] + (objetivo[i] - _ondaVisual[i]) * 0.16;
|
||||
return suavizado.clamp(0.0, 1.0);
|
||||
}, growable: false);
|
||||
}
|
||||
|
||||
List<double> _objetivoActual() {
|
||||
final ahora = DateTime.now();
|
||||
final tieneReal =
|
||||
_ultimaOndaReal != null &&
|
||||
ahora.difference(_ultimaOndaReal!) <
|
||||
const Duration(milliseconds: 900) &&
|
||||
_ondaObjetivo.isNotEmpty;
|
||||
if (tieneReal) return _ondaObjetivo;
|
||||
return _ondaOrganica();
|
||||
}
|
||||
|
||||
List<double> _ondaOrganica() {
|
||||
final count = widget.barras.clamp(8, 96);
|
||||
final phase = _controller.value * pi * 2;
|
||||
final intensidad = _activo ? 1.0 : 0.18;
|
||||
return List<double>.generate(count, (i) {
|
||||
final p = count <= 1 ? 0.0 : i / (count - 1);
|
||||
final envelope = sin(pi * p).clamp(0.10, 1.0);
|
||||
final flow =
|
||||
sin(phase + p * pi * 2.2) * 0.24 +
|
||||
sin(phase * 0.63 - p * pi * 5.1) * 0.18 +
|
||||
sin(phase * 1.37 + p * pi * 9.0) * 0.08;
|
||||
final value = 0.5 + flow * envelope * intensidad;
|
||||
return value.clamp(0.12, 0.88);
|
||||
}, growable: false);
|
||||
}
|
||||
|
||||
List<double> _normalizar(List<double> muestras) {
|
||||
final maximo = muestras.fold<double>(0, (max, v) => v > max ? v : max);
|
||||
if (maximo <= 0.001) return muestras;
|
||||
return muestras
|
||||
.map((v) => (0.08 + (v / maximo) * 0.84).clamp(0.0, 1.0))
|
||||
.toList(growable: false);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_estadoSubscription?.cancel();
|
||||
@@ -141,7 +192,7 @@ class _VisualizadorAudioState extends State<VisualizadorAudio>
|
||||
color: color,
|
||||
phase: t,
|
||||
active: _activo,
|
||||
waveform: _ondaReal,
|
||||
waveform: _ondaVisual,
|
||||
),
|
||||
child: const SizedBox.expand(),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user