ruffle/desktop/src/audio.rs

78 lines
2.4 KiB
Rust

use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use ruffle_core::backend::audio::{
swf, AudioBackend, AudioMixer, SoundHandle, SoundInstanceHandle, SoundTransform,
};
use ruffle_core::impl_audio_mixer_backend;
pub struct CpalAudioBackend {
#[allow(dead_code)]
device: cpal::Device,
#[allow(dead_code)]
config: cpal::StreamConfig,
stream: cpal::Stream,
mixer: AudioMixer,
}
type Error = Box<dyn std::error::Error>;
impl CpalAudioBackend {
pub fn new() -> Result<Self, Error> {
// Create CPAL audio device.
let host = cpal::default_host();
let device = host
.default_output_device()
.ok_or("No audio devices available")?;
// Create audio stream for device.
let config = device.default_output_config()?;
let sample_format = config.sample_format();
let config = cpal::StreamConfig::from(config);
let mixer = AudioMixer::new(config.channels.try_into()?, config.sample_rate.0);
// Start the audio stream.
let stream = {
let mixer = mixer.proxy();
let error_handler = move |err| log::error!("Audio stream error: {}", err);
match sample_format {
cpal::SampleFormat::F32 => device.build_output_stream(
&config,
move |buffer, _| mixer.mix::<f32>(buffer),
error_handler,
),
cpal::SampleFormat::I16 => device.build_output_stream(
&config,
move |buffer, _| mixer.mix::<i16>(buffer),
error_handler,
),
cpal::SampleFormat::U16 => device.build_output_stream(
&config,
move |buffer, _| mixer.mix::<u16>(buffer),
error_handler,
),
}?
};
stream.play()?;
Ok(Self {
device,
config,
stream,
mixer,
})
}
}
impl AudioBackend for CpalAudioBackend {
impl_audio_mixer_backend!(mixer);
fn play(&mut self) {
self.stream.play().expect("Error trying to resume CPAL audio stream. This feature may not be supported by your audio device.");
}
fn pause(&mut self) {
self.stream.pause().expect("Error trying to pause CPAL audio stream. This feature may not be supported by your audio device.");
}
}