master_audio 0.0.1
master_audio: ^0.0.1 copied to clipboard
Emissão de som de baixo nível controlando frequência volume e duração.
example/lib/main.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:master_audio/master_audio.dart'; // Ajuste o caminho se necessário
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
// Variáveis para controlar o áudio
double _currentFrequency = 200.0; // Não usado diretamente para emitTone neste exemplo, mas mantido
double _currentVolume = 1.0; // Não usado diretamente para emitTone neste exemplo, mas mantido
// Timer para agendamento do próximo tom (uso único)
Timer? _toneSchedulerTimer;
// Flag para controlar se a emissão de tons está ativa
bool _isEmitting = false;
// Variável para controlar o intervalo entre os tons, dinamicamente
double _currentEmissionIntervalMs = 50.0; // Intervalo inicial em milissegundos
@override
void initState() {
super.initState();
_initAudio();
}
Future<void> _initAudio() async {
try {
await MasterAudio.createAudioGenerator();
await MasterAudio.startAudio(); // Inicia o stream de áudio ao iniciar o app
print('AudioGenerator criado e stream iniciado.');
} catch (e) {
print('Erro ao inicializar áudio: $e');
}
}
@override
void dispose() {
_stopEmission(); // Garante que o timer seja parado
MasterAudio.stopAudio(); // Para o stream de áudio
MasterAudio.destroyAudioGenerator(); // Destrói o gerador de áudio
super.dispose();
}
/// Agenda a próxima emissão de tom com base no _currentEmissionIntervalMs.
void _scheduleNextTone() {
// Se a emissão não deve continuar ou o widget foi descartado, para a recursão.
if (!_isEmitting || !mounted) {
_toneSchedulerTimer?.cancel();
_toneSchedulerTimer = null;
print('Emissão de tom interrompida.');
return;
}
// Garante que o atraso seja um valor inteiro e não menor que 1ms
final int effectiveDelay = _currentEmissionIntervalMs.toInt().clamp(1, 2000);
// Cria um Timer de uso único que dispara após 'effectiveDelay' milissegundos
_toneSchedulerTimer = Timer(Duration(milliseconds: effectiveDelay), () {
// Verifica novamente o estado após o atraso (caso _isEmitting tenha mudado)
if (!_isEmitting || !mounted) {
_toneSchedulerTimer?.cancel();
_toneSchedulerTimer = null;
return;
}
// Emite o tom. Frequência, duração e volume podem ser dinâmicos também.
MasterAudio.emitTone(_currentFrequency, 20, _currentVolume);
print('Tom emitido. Próximo em $effectiveDelay ms.');
// Agenda a próxima emissão recursivamente
_scheduleNextTone();
});
}
/// Inicia a emissão de tons.
void _startEmission() {
if (_isEmitting) {
print('Emissão já está em andamento.');
return;
}
setState(() {
_isEmitting = true;
});
print('Iniciando emissão de tom com intervalo de ${_currentEmissionIntervalMs.toInt()}ms');
_scheduleNextTone(); // Inicia a primeira emissão e o ciclo de agendamento
}
/// Para a emissão de tons.
void _stopEmission() {
if (!_isEmitting) {
print('Emissão já está parada.');
return;
}
setState(() {
_isEmitting = false;
});
_toneSchedulerTimer?.cancel(); // Cancela o timer atual para interromper a cadeia
_toneSchedulerTimer = null;
print('Emissão de tom parada.');
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Plugin MasterAudio Exemplo')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Botão para controlar o início/parada da emissão
ElevatedButton(
onPressed: _isEmitting ? _stopEmission : _startEmission,
child: Text(_isEmitting ? 'Parar Emissão' : 'Iniciar Emissão'),
),
const SizedBox(height: 30),
// Slider para controlar o intervalo dinamicamente
Text('Intervalo de Emissão: ${_currentEmissionIntervalMs.toInt()} ms'),
Slider(
value: _currentEmissionIntervalMs,
min: 50.0,
max: 1000.0,
divisions: 95,
label: _currentEmissionIntervalMs.toInt().toString(),
onChanged: (newValue) {
setState(() {
_currentEmissionIntervalMs = newValue;
});
// A mudança de intervalo será aplicada no PRÓXIMO tom agendado.
// Se você quiser que a mudança seja *imediata* (cancelar o atual e agendar um novo),
// descomente o bloco abaixo:
// if (_isEmitting) {
// _toneSchedulerTimer?.cancel();
// _scheduleNextTone();
// }
},
),
const SizedBox(height: 30),
Text('Frequência de Emissão: ${_currentFrequency.toInt()} Hz'),
Slider(
value: _currentFrequency,
min: 0,
max: 10000.0,
divisions: 9900,
label: _currentFrequency.toInt().toString(),
onChanged: (newValue) {
setState(() {
_currentFrequency = newValue;
});
},
),
const SizedBox(height: 30),
Text('Volume de Emissão: ${_currentVolume.toInt()}'),
Slider(
value: _currentVolume,
min: 0.0,
max: 1.0,
divisions: 9,
label: _currentVolume.toDouble().toString(),
onChanged: (newValue) {
setState(() {
_currentVolume = newValue;
});
},
),
],
),
),
),
);
}
}