I am trying to play a WAV file using rust-sdl2
.
I found AudioSpecWAV
, but none of the audio initialisation methods seem to take it as a type, and it doesn't implement AudioCallback
. I tried implementing this myself with my own callback looking something like:
struct MyWav {
wav: AudioSpecWAV,
volume: f32,
pos: usize,
}
impl AudioCallback for MyWav {
type Channel = f32;
fn callback(&mut self, out: &mut [f32]) {
for x in out.iter_mut() {
*x = match self.wav.buffer().get(self.pos) {
Some(v) => { self.pos += 1; v as f32 },
None => { 0.0 }
}
}
}
}
... but I don't know how to work around the following error I get:
the traitcore::marker::Sync is not implemented for the type *mut u8
This seems to be the audio_buf
field of AudioSpecWAV
, but if that's not Sync
how am I supposed to pass a buffer to the callback?
(for reference, here is an example of playing a generated sound)
AudioCallback
requires implementers to be Send
. You could do that by wrapping AudioSpecWAV
in a struct and doing an unsafe impl
for Send
on that struct, or you could copy the data. Since you shouldn't typically use unsafe unless you know what you are doing is actually safe, you may want to look at the copy approach.
Here is an example of both approaches:
extern crate sdl2;
use std::thread::{self};
use sdl2::{Sdl};
use sdl2::audio::{self, AudioSpecDesired, AudioSpecWAV, AudioCallback, AudioDevice};
//----------------------------------------------------------------------------//
struct CopiedData {
bytes: Vec<u8>,
position: usize
}
impl AudioCallback for CopiedData {
type Channel = u8;
fn callback(&mut self, data: &mut [u8]) {
let (start, end) = (self.position, self.position + data.len());
self.position += data.len();
let audio_data = &self.bytes[start..end];
for (src, dst) in audio_data.iter().zip(data.iter_mut()) {
*dst = *src;
}
}
}
//----------------------------------------------------------------------------//
struct WrappedData {
audio: AudioSpecWAV,
position: usize
}
impl AudioCallback for WrappedData {
type Channel = u8;
fn callback(&mut self, data: &mut [u8]) {
let (start, end) = (self.position, self.position + data.len());
self.position += data.len();
let audio_data = &self.audio.buffer()[start..end];
for (src, dst) in audio_data.iter().zip(data.iter_mut()) {
*dst = *src;
}
}
}
unsafe impl Send for WrappedData { }
//----------------------------------------------------------------------------//
pub fn main() {
let sdl_context = sdl2::init().unwrap();
let audio_system = sdl_context.audio().unwrap();
let audio_spec = AudioSpecDesired{ freq: None, channels: None, samples: None };
let audio_wav = AudioSpecWAV::load_wav("test.wav").unwrap();
let copied_data = CopiedData{ bytes: audio_wav.buffer().to_vec(), position: 0 };
//let wrapped_data = WrappedData{ audio: audio_wav, position: 0 };
let audio_device = audio_system.open_playback(None, audio_spec, move |spec| {
copied_data
}).unwrap();
audio_device.resume();
thread::sleep_ms(5000);
}
Note: The WAV I was playing was quite loud (to the point where it sounded distorted) and I am not a sound guy so I am not sure if that had something to do with my code or the WAV file I was using in general.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With