rodio/src/decoder/wav.rs

105 lines
3.4 KiB
Rust
Raw Normal View History

2015-07-22 12:23:03 +00:00
use std::io::{Read, Seek, SeekFrom};
2015-09-10 15:20:42 +00:00
use std::cmp::Ordering;
2015-07-22 10:14:11 +00:00
use super::Decoder;
2015-09-01 17:35:26 +00:00
use super::conversions;
2015-07-22 10:14:11 +00:00
2015-09-01 17:35:26 +00:00
use cpal::{self, Endpoint, Voice};
use hound::WavIntoSamples;
2015-07-22 10:14:11 +00:00
use hound::WavReader;
use hound::WavSpec;
2015-09-01 17:35:26 +00:00
pub struct WavDecoder {
reader: Box<Iterator<Item=i16> + Send>,
voice: Voice,
2015-07-22 10:14:11 +00:00
}
2015-09-01 17:35:26 +00:00
impl WavDecoder {
2015-09-10 15:20:42 +00:00
pub fn new<R>(endpoint: &Endpoint, mut data: R) -> Result<WavDecoder, R>
where R: Read + Seek + Send + 'static
{
2015-09-01 17:35:26 +00:00
if !is_wave(data.by_ref()) {
2015-07-22 12:23:03 +00:00
return Err(data);
}
let reader = WavReader::new(data).unwrap();
2015-07-22 10:14:11 +00:00
let spec = reader.spec();
2015-09-10 15:20:42 +00:00
// choosing a format amongst the ones available
let voice_format = {
let mut formats_list = endpoint.get_supported_formats_list().unwrap().collect::<Vec<_>>();
formats_list.sort_by(|f1, f2| {
if (f1.samples_rate.0 % spec.sample_rate) == 0 && (f2.samples_rate.0 % spec.sample_rate) != 0 {
return Ordering::Greater;
} else if (f2.samples_rate.0 % spec.sample_rate) == 0 && (f1.samples_rate.0 % spec.sample_rate) != 0 {
return Ordering::Less;
}
if f1.channels.len() >= spec.channels as usize && f1.channels.len() < f2.channels.len() {
return Ordering::Greater;
} else if f2.channels.len() >= spec.channels as usize && f2.channels.len() < f1.channels.len() {
return Ordering::Less;
}
if f1.data_type == cpal::SampleFormat::I16 && f2.data_type != cpal::SampleFormat::I16 {
return Ordering::Greater;
} else if f2.data_type == cpal::SampleFormat::I16 && f1.data_type != cpal::SampleFormat::I16 {
return Ordering::Less;
}
Ordering::Equal
});
formats_list.into_iter().next().unwrap()
};
2015-09-01 17:35:26 +00:00
let voice = Voice::new(endpoint, &voice_format).unwrap();
let reader = reader.into_samples().map(|s| s.unwrap_or(0));
let reader = conversions::ChannelsCountConverter::new(reader, spec.channels,
voice.get_channels());
let reader = conversions::SamplesRateConverter::new(reader, cpal::SamplesRate(spec.sample_rate),
voice.get_samples_rate());
2015-07-22 10:14:11 +00:00
Ok(WavDecoder {
2015-09-01 17:35:26 +00:00
reader: Box::new(reader),
voice: voice,
2015-07-22 10:14:11 +00:00
})
}
}
2015-09-01 17:35:26 +00:00
/// Returns true if the stream contains WAV data, then resets it to where it was.
fn is_wave<R>(mut data: R) -> bool where R: Read + Seek {
let stream_pos = data.seek(SeekFrom::Current(0)).unwrap();
2015-07-22 10:14:11 +00:00
2015-09-01 17:35:26 +00:00
if WavReader::new(data.by_ref()).is_err() {
data.seek(SeekFrom::Start(stream_pos)).unwrap();
return false;
}
2015-07-22 10:14:11 +00:00
2015-09-01 17:35:26 +00:00
data.seek(SeekFrom::Start(stream_pos)).unwrap();
true
}
impl Decoder for WavDecoder {
2015-09-10 19:27:16 +00:00
fn write(&mut self) -> u64 {
2015-09-01 17:35:26 +00:00
let (min, _) = self.reader.size_hint();
2015-07-22 10:14:11 +00:00
2015-09-01 17:35:26 +00:00
if min == 0 {
// finished
2015-09-10 19:27:16 +00:00
return 1000000000;
2015-07-22 10:14:11 +00:00
}
2015-09-01 17:35:26 +00:00
2015-09-10 19:27:16 +00:00
let len = {
2015-09-01 17:35:26 +00:00
let mut buffer = self.voice.append_data(min);
2015-09-10 19:27:16 +00:00
let len = buffer.len();
2015-09-01 17:35:26 +00:00
conversions::convert_and_write(self.reader.by_ref(), &mut buffer);
2015-09-10 19:27:16 +00:00
len
};
let duration = len as u64 * 1000000000 / self.voice.get_samples_rate().0 as u64;
2015-09-01 17:35:26 +00:00
self.voice.play();
2015-09-10 19:27:16 +00:00
duration
2015-07-22 10:14:11 +00:00
}
}