With rodio
, Is there anyway to play sound from a Vec<u8>
or similar? I want to be able to read data from a zip file (I'm using the zip
crate) into memory and then play it back later. I've tried just about everything but I can't figure it out.
I tried
let sound_data = self.sounds.clone();
let cursor = Cursor::new(sound_data.as_slice());
let source = Decoder::new(cursor).unwrap();
// Play the sound directly on the device
self.audio_output.1.play_raw(source.convert_samples());
where sound_data
is a Arc<Vec<u8>>
. This complains that sound_data
does not live long enough, and that play_raw
requires the 'static lifetime. I've also tried various similar configurations involving &[u8]
s, BufReaders
, etc but none of them work. I'm relatively new to Rust (have tried a few small projects before), and this is making me crazy.
The problem is that Cursor::new(sound_data.as_slice());
borrows sound_data
in the local scope, while play_raw
requires its argument to be 'static
(which the local scope is not). The error you get is due to the fact that sound_data
as it is can't guarantee to not be destroyed while play_raw
is processing it; the original Arc
doesn't help.
Two things:
Arc<[u8]>
instead of Arc<Vec<u8>>
; the latter has two pointer indirections where only one is needed, and is smaller. You're not going to modify the Vec<u8>
inside the Arc
anyway, so a Arc<[u8]>
will suffice.Arc<[u8]>
is AsRef<[u8]>
, and any std::io::Cursor<T> where T: AsRef<[u8]>
is std::io::Read
. So you can use the Arc
to create a Cursor
without borrowing. The following should work, although I haven't tried... // `sound_data` is an `Arc<[u8]>`, e.g. `Arc::from(vec![1,2,3])`
let source = Decoder::new(Cursor::new(Arc::clone(&sound_data))).unwrap();
self.audio_output.1.play_raw(source.convert_samples());