use std::sync::{Arc, Mutex}; use std::sync::atomic::{AtomicBool, Ordering}; use std::thread::JoinHandle; use std::time::Instant; use cpal::{default_host, BufferSize, Device, SampleRate, Stream, StreamConfig, SupportedStreamConfig}; use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; use crate::core::mixer::AudioMixer; use crate::domain::event::{Event, EventBus}; use crate::utils::real_time_event::RealTimeEvent; #[derive(Clone)] pub struct Speaker { device: Device } pub struct AudioPlayback { event_bus: EventBus, speaker: Speaker, running: Arc, stream: Option, worker: Option>, mixer: AudioMixer } impl Speaker { pub fn new(device: Device) -> Self { Speaker { device } } pub fn default() -> Self { let host = default_host(); let device = host.default_output_device().unwrap(); Speaker::new(device) } pub fn get_output_config(&self) -> SupportedStreamConfig { self.device.default_output_config().unwrap() } pub fn get_stream_config(&self) -> StreamConfig { // Lister toutes les configurations supportées self.print_supported_configs(); self.get_output_config().into() } pub fn print_supported_configs(&self) { println!("\n=== CONFIGURATIONS AUDIO DISPONIBLES ==="); // Configuration par défaut match self.device.default_output_config() { Ok(config) => { println!("📌 Configuration par défaut:"); println!(" Canaux: {}", config.channels()); println!(" Sample Rate: {} Hz", config.sample_rate().0); println!(" Format: {:?}", config.sample_format()); println!(" Buffer Size: {:?}", config.buffer_size()); }, Err(e) => println!("❌ Impossible d'obtenir la config par défaut: {}", e) } // Toutes les configurations supportées println!("\n📋 Toutes les configurations supportées:"); match self.device.supported_output_configs() { Ok(configs) => { for (i, config_range) in configs.enumerate() { println!("\n Config #{}", i + 1); println!(" Canaux: {}", config_range.channels()); println!(" Sample Rate: {} - {} Hz", config_range.min_sample_rate().0, config_range.max_sample_rate().0); println!(" Format: {:?}", config_range.sample_format()); println!(" Buffer Size: {:?}", config_range.buffer_size()); // Suggestions de sample rates courants let common_rates = [8000, 11025, 16000, 22050, 44100, 48000, 88200, 96000]; let mut supported_common = Vec::new(); for rate in common_rates { if rate >= config_range.min_sample_rate().0 && rate <= config_range.max_sample_rate().0 { supported_common.push(rate); } } if !supported_common.is_empty() { println!(" Sample rates courants supportés: {:?}", supported_common); } } }, Err(e) => println!("❌ Impossible de lister les configs: {}", e) } // Informations sur le device println!("\n🎧 Informations du device:"); if let Ok(name) = self.device.name() { println!(" Nom: {}", name); } // Test de configurations spécifiques println!("\n🧪 Test de configurations spécifiques:"); let test_configs = [ (44100, 1, "Mono 44.1kHz"), (44100, 2, "Stéréo 44.1kHz"), (48000, 1, "Mono 48kHz"), (48000, 2, "Stéréo 48kHz"), (22050, 2, "Stéréo 22.05kHz"), ]; for (sample_rate, channels, description) in test_configs { let test_config = StreamConfig { channels, sample_rate: SampleRate(sample_rate), buffer_size: BufferSize::Default }; // Test si cette config est supportée (tentative de création d'un stream fictif) let dummy_callback = |_: &mut [f32], _: &cpal::OutputCallbackInfo| {}; match self.device.build_output_stream(&test_config, dummy_callback, |_| {}, None) { Ok(_) => println!(" ✅ {} - SUPPORTÉ", description), Err(_) => println!(" ❌ {} - NON SUPPORTÉ", description), } } println!("\n===========================================\n"); } pub fn build_stream(&self, callback: F) -> Stream where F: FnMut(&mut [i16], &cpal::OutputCallbackInfo) + Send + 'static, { let config = self.get_stream_config(); self.device.build_output_stream( &config, callback, |err| println!("Error output stream: {err}"), None ).unwrap() } } impl AudioPlayback { pub fn new(event_bus: EventBus, speaker: Speaker, mixer: AudioMixer) -> Self { Self { event_bus, speaker, running: Arc::new(AtomicBool::new(false)), stream: None, worker: None, mixer } } pub fn default(event_bus: EventBus, mixer: AudioMixer) -> Self { let speaker = Speaker::default(); AudioPlayback::new(event_bus, speaker, mixer) } pub async fn start(&mut self) { self.running.store(true, Ordering::SeqCst); let stream_running = self.running.clone(); let event_bus = self.event_bus.clone(); let mixer = self.mixer.clone(); // stream cpal println!("Setting up audio playback stream..."); let last_time = Mutex::new(Instant::now()); let stream = self.speaker.build_stream(move |data, info| { println!( "CALLBACK : reçu {} samples, type info = {:?}", data.len(), info ); let now = Instant::now(); let mut last = last_time.lock().unwrap(); let dt = now.duration_since(*last); println!("Callback audio appelée chaque {:?} ms (≈ {:.1} Hz)", dt.as_millis(), 1000.0 / dt.as_millis().max(1) as f32); *last = now; if !stream_running.load(Ordering::Relaxed){ return; } let audio_mixer = mixer.read(data.len()); data.copy_from_slice(&audio_mixer); // println!("data content : {:?}", data); let _ = event_bus.emit_sync(Event::PlaybackTick(data.len())); }); stream.play().unwrap(); self.stream = Some(stream); println!("Audio playback stream started"); } pub async fn stop(&mut self) { self.running.store(false, Ordering::SeqCst); } }