mirror of
https://github.com/transistorfet/moa.git
synced 2024-09-27 16:57:32 +00:00
64 lines
1.9 KiB
Rust
64 lines
1.9 KiB
Rust
|
|
||
|
use std::sync::{Arc, Mutex};
|
||
|
use cpal::{Stream, SampleRate, SampleFormat, StreamConfig, traits::{DeviceTrait, HostTrait, StreamTrait}};
|
||
|
|
||
|
use moa_core::{warn, error};
|
||
|
|
||
|
use crate::audio::{AudioOutput, SAMPLE_RATE};
|
||
|
|
||
|
#[allow(dead_code)]
|
||
|
pub struct CpalAudioOutput {
|
||
|
stream: Stream,
|
||
|
}
|
||
|
|
||
|
impl CpalAudioOutput {
|
||
|
pub fn create_audio_output(output: Arc<Mutex<AudioOutput>>) -> CpalAudioOutput {
|
||
|
let device = cpal::default_host()
|
||
|
.default_output_device()
|
||
|
.expect("No sound output device available");
|
||
|
|
||
|
let config: StreamConfig = device
|
||
|
.supported_output_configs()
|
||
|
.expect("error while querying configs")
|
||
|
.find(|config| config.sample_format() == SampleFormat::F32 && config.channels() == 2)
|
||
|
.expect("no supported config?!")
|
||
|
.with_sample_rate(SampleRate(SAMPLE_RATE as u32))
|
||
|
.into();
|
||
|
|
||
|
let data_callback = move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
|
||
|
let result = if let Ok(mut output) = output.lock() {
|
||
|
output.set_frame_size(data.len() / 2);
|
||
|
output.pop_next()
|
||
|
} else {
|
||
|
return;
|
||
|
};
|
||
|
|
||
|
if let Some(frame) = result {
|
||
|
let (start, middle, end) = unsafe { frame.data.align_to::<f32>() };
|
||
|
if !start.is_empty() || !end.is_empty() {
|
||
|
warn!("audio: frame wasn't aligned");
|
||
|
}
|
||
|
let length = middle.len().min(data.len());
|
||
|
data[..length].copy_from_slice(&middle[..length]);
|
||
|
} else {
|
||
|
warn!("missed an audio frame");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
let stream = device.build_output_stream(
|
||
|
&config,
|
||
|
data_callback,
|
||
|
move |err| {
|
||
|
error!("ERROR: {:?}", err);
|
||
|
},
|
||
|
).unwrap();
|
||
|
|
||
|
stream.play().unwrap();
|
||
|
|
||
|
CpalAudioOutput {
|
||
|
stream,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|