2015-07-22 12:23:03 +00:00
|
|
|
use std::io::{Read, Seek, SeekFrom};
|
2015-09-11 11:49:07 +00:00
|
|
|
use std::cmp;
|
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-11 13:43:00 +00:00
|
|
|
use conversions;
|
2015-07-22 10:14:11 +00:00
|
|
|
|
2015-09-01 17:35:26 +00:00
|
|
|
use cpal::{self, Endpoint, Voice};
|
2015-07-22 10:14:11 +00:00
|
|
|
use hound::WavReader;
|
|
|
|
|
2015-09-01 17:35:26 +00:00
|
|
|
pub struct WavDecoder {
|
2015-09-11 11:49:07 +00:00
|
|
|
reader: conversions::AmplifierIterator<Box<Iterator<Item=i16> + Send>>,
|
2015-09-01 17:35:26 +00:00
|
|
|
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
|
2015-09-22 14:49:36 +00:00
|
|
|
let voice_format = endpoint.get_supported_formats_list().unwrap().fold(None, |f1, f2| {
|
|
|
|
if f1.is_none() {
|
|
|
|
return Some(f2);
|
|
|
|
}
|
|
|
|
|
|
|
|
let f1 = f1.unwrap();
|
|
|
|
|
|
|
|
if f1.samples_rate.0 % spec.sample_rate == 0 {
|
|
|
|
return Some(f1);
|
|
|
|
}
|
|
|
|
|
2015-09-22 18:24:34 +00:00
|
|
|
if f2.samples_rate.0 % spec.sample_rate == 0 {
|
2015-09-22 14:49:36 +00:00
|
|
|
return Some(f2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if f1.channels.len() >= spec.channels as usize {
|
|
|
|
return Some(f1);
|
|
|
|
}
|
|
|
|
|
2015-09-22 18:24:34 +00:00
|
|
|
if f2.channels.len() >= spec.channels as usize {
|
2015-09-22 14:49:36 +00:00
|
|
|
return Some(f2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if f1.data_type == cpal::SampleFormat::I16 {
|
|
|
|
return Some(f1);
|
|
|
|
}
|
|
|
|
|
2015-09-22 18:24:34 +00:00
|
|
|
if f2.data_type == cpal::SampleFormat::I16 {
|
|
|
|
return Some(f2);
|
|
|
|
}
|
|
|
|
|
|
|
|
Some(f1)
|
2015-09-22 14:49:36 +00:00
|
|
|
}).unwrap();
|
2015-09-10 15:20:42 +00:00
|
|
|
|
2015-09-01 17:35:26 +00:00
|
|
|
let voice = Voice::new(endpoint, &voice_format).unwrap();
|
|
|
|
|
2015-09-10 18:25:13 +00:00
|
|
|
let reader = SamplesIterator { reader: reader, samples_read: 0 };
|
2015-09-01 17:35:26 +00:00
|
|
|
let reader = conversions::ChannelsCountConverter::new(reader, spec.channels,
|
|
|
|
voice.get_channels());
|
|
|
|
let reader = conversions::SamplesRateConverter::new(reader, cpal::SamplesRate(spec.sample_rate),
|
2015-09-22 09:19:52 +00:00
|
|
|
voice.get_samples_rate(), voice.get_channels());
|
2015-09-01 17:35:26 +00:00
|
|
|
|
2015-07-22 10:14:11 +00:00
|
|
|
Ok(WavDecoder {
|
2015-09-11 11:49:07 +00:00
|
|
|
reader: conversions::AmplifierIterator::new(Box::new(reader), 1.0),
|
2015-09-01 17:35:26 +00:00
|
|
|
voice: voice,
|
2015-07-22 10:14:11 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-10 18:25:13 +00:00
|
|
|
struct SamplesIterator<R> where R: Read + Seek {
|
|
|
|
reader: WavReader<R>,
|
|
|
|
samples_read: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<R> Iterator for SamplesIterator<R> where R: Read + Seek {
|
|
|
|
type Item = i16;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn next(&mut self) -> Option<i16> {
|
|
|
|
if let Some(value) = self.reader.samples().next() {
|
|
|
|
self.samples_read += 1;
|
|
|
|
Some(value.unwrap_or(0))
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
|
|
|
let len = (self.reader.len() - self.samples_read) as usize;
|
|
|
|
(len, Some(len))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<R> ExactSizeIterator for SamplesIterator<R> where R: Read + Seek {}
|
|
|
|
|
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-09-22 19:47:09 +00:00
|
|
|
let min = cmp::min(min, 10240); // using a maximal value so that filters get applied
|
2015-09-11 11:49:07 +00:00
|
|
|
// quickly
|
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-22 15:58:03 +00:00
|
|
|
{
|
2015-09-01 17:35:26 +00:00
|
|
|
let mut buffer = self.voice.append_data(min);
|
|
|
|
conversions::convert_and_write(self.reader.by_ref(), &mut buffer);
|
2015-09-22 15:58:03 +00:00
|
|
|
}
|
2015-09-10 19:27:16 +00:00
|
|
|
|
2015-09-22 15:58:03 +00:00
|
|
|
let duration = self.voice.get_pending_samples() as u64 * 1000000000 /
|
|
|
|
(self.voice.get_samples_rate().0 as u64 * self.voice.get_channels() 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
|
|
|
}
|
2015-09-11 11:49:07 +00:00
|
|
|
|
|
|
|
fn set_volume(&mut self, value: f32) {
|
|
|
|
self.reader.set_amplification(value);
|
|
|
|
}
|
2015-09-23 08:33:45 +00:00
|
|
|
|
|
|
|
fn get_remaining_duration_ms(&self) -> u32 {
|
|
|
|
let (num_samples, _) = self.reader.size_hint();
|
|
|
|
let num_samples = num_samples + self.voice.get_pending_samples();
|
|
|
|
|
|
|
|
num_samples as u32 * 1000 /
|
|
|
|
(self.voice.get_samples_rate().0 as u32 * self.voice.get_channels() as u32)
|
|
|
|
}
|
2015-07-22 10:14:11 +00:00
|
|
|
}
|