Could someone explain how to get access to the data source which is a ring buffer within the audio callback. I have a simple requirement which is to stream to the default output device. I chose to use cpal for this module. I think the answer may be to use a closure but not sure how to do that.
use cpal::{Data, Sample, SampleFormat};
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use std::vec;
use crate::app::common::ringb;
//==================================================================================
// Audio output
pub struct AudioData<'a> {
rb_audio : &'a ringb::SyncByteRingBuf,
}
impl AudioData<'_> {
// Create a new instance and initialise the default data
pub fn new(rb_audio : & ringb::SyncByteRingBuf) -> AudioData {
AudioData {
rb_audio : rb_audio,
}
}
// Create an audio output stream
pub fn init_audio(&mut self) {
let host = cpal::default_host();
let device = host.default_output_device().expect("no output device available");
let mut supported_configs_range = device.supported_output_configs()
.expect("error while querying configs");
let supported_config = supported_configs_range.next()
.expect("no supported config?!")
.with_max_sample_rate();
let err_fn = |err| eprintln!("an error occurred on the output audio stream: {}", err);
let sample_format = supported_config.sample_format();
let config = supported_config.into();
let stream = match sample_format {
SampleFormat::F32 => device.build_output_stream(&config, write_audio::<f32>, err_fn),
SampleFormat::I16 => device.build_output_stream(&config, write_audio::<i16>, err_fn),
SampleFormat::U16 => device.build_output_stream(&config, write_audio::<u16>, err_fn),
}.unwrap();
// Start the default stream
stream.play().unwrap();
}
}
// Callback when the audio output needs more data
fn write_audio<T: Sample>(data: &mut [T], _: &cpal::OutputCallbackInfo) {
let mut data: Vec<f32> = vec![0.0; data.len()];
let mut i = 0;
// Check the ring buffer for data
let audio_data = self.rb_audio.read().read(&mut data);
match audio_data {
Ok(_sz) => {
for sample in data.iter_mut() {
*sample = data[i];
i += 1;
}
}
Err(e) => println!("Read error on rb_iq {:?}. Skipping cycle.", e),
}
}