Add LoopedDecoder

LoopedDecoder works like the normal Decoder, but when the decoder
reaches the end of file it will restart playback from the beginning.
This has the advantage over Decoder::new().repeat_infinite() that it
will not buffer the entire uncompressed audio file into memory.

Update minimp3 to version 0.5 to use the `into_iter()` method
This commit is contained in:
Jacob Hughes 2020-08-27 12:38:54 -04:00
parent a80a90bae5
commit 95317f9b88
6 changed files with 170 additions and 5 deletions

View file

@ -14,7 +14,7 @@ cpal = "0.12"
claxon = { version = "0.4.2", optional = true }
hound = { version = "3.3.1", optional = true }
lewton = { version = "0.10", optional = true }
minimp3 = { version = "0.3.2", optional = true }
minimp3 = { version = "0.5.0", optional = true }
[features]
default = ["flac", "vorbis", "wav", "mp3"]

View file

@ -47,6 +47,9 @@ where
samples: spec.samples,
})
}
pub fn into_inner(self) -> R {
self.reader.into_inner()
}
}
impl<R> Source for FlacDecoder<R>

View file

@ -5,6 +5,7 @@ use std::fmt;
use std::io::{Read, Seek};
#[allow(unused_imports)]
use std::io::SeekFrom;
use std::mem;
use std::time::Duration;
use crate::Source;
@ -25,6 +26,10 @@ pub struct Decoder<R>(DecoderImpl<R>)
where
R: Read + Seek;
pub struct LoopedDecoder<R>(DecoderImpl<R>)
where
R: Read + Seek;
enum DecoderImpl<R>
where
R: Read + Seek,
@ -83,6 +88,18 @@ where
Err(DecoderError::UnrecognizedFormat)
}
pub fn new_looped(data: R) -> Result<LoopedDecoder<R>, DecoderError> {
Self::new(data).map(LoopedDecoder::new)
}
}
impl<R> LoopedDecoder<R>
where
R: Read + Seek + Send + 'static,
{
fn new(decoder: Decoder<R>) -> LoopedDecoder<R> {
Self(decoder.0)
}
}
impl<R> Iterator for Decoder<R>
@ -187,6 +204,140 @@ where
}
}
impl<R> Iterator for LoopedDecoder<R>
where
R: Read + Seek,
{
type Item = i16;
#[inline]
fn next(&mut self) -> Option<i16> {
if let Some(sample) = match self.0 {
#[cfg(feature = "wav")]
DecoderImpl::Wav(ref mut source) => source.next(),
#[cfg(feature = "vorbis")]
DecoderImpl::Vorbis(ref mut source) => source.next(),
#[cfg(feature = "flac")]
DecoderImpl::Flac(ref mut source) => source.next(),
#[cfg(feature = "mp3")]
DecoderImpl::Mp3(ref mut source) => source.next(),
DecoderImpl::None(_) => None,
} {
Some(sample)
} else {
let decoder = mem::replace(&mut self.0, DecoderImpl::None(Default::default()));
let (decoder, sample) = match decoder {
#[cfg(feature = "wav")]
DecoderImpl::Wav(source) => {
let mut reader = source.into_inner();
reader.seek(SeekFrom::Start(0)).ok()?;
let mut source = wav::WavDecoder::new(reader).ok()?;
let sample = source.next();
(DecoderImpl::Wav(source), sample)
}
#[cfg(feature = "vorbis")]
DecoderImpl::Vorbis(source) => {
use lewton::inside_ogg::OggStreamReader;
let mut reader = source.into_inner().into_inner();
reader.seek_bytes(SeekFrom::Start(0)).ok()?;
let mut source = vorbis::VorbisDecoder::from_stream_reader(OggStreamReader::from_ogg_reader(reader).ok()?);
let sample = source.next();
(DecoderImpl::Vorbis(source), sample)
}
#[cfg(feature = "flac")]
DecoderImpl::Flac(source) => {
let mut reader = source.into_inner();
reader.seek(SeekFrom::Start(0)).ok()?;
let mut source = flac::FlacDecoder::new(reader).ok()?;
let sample = source.next();
(DecoderImpl::Flac(source), sample)
}
#[cfg(feature = "mp3")]
DecoderImpl::Mp3(source) => {
let mut reader = source.into_inner();
reader.seek(SeekFrom::Start(0)).ok()?;
let mut source = mp3::Mp3Decoder::new(reader).ok()?;
let sample = source.next();
(DecoderImpl::Mp3(source), sample)
}
none @ DecoderImpl::None(_) => (none, None)
};
self.0 = decoder;
sample
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match self.0 {
#[cfg(feature = "wav")]
DecoderImpl::Wav(ref source) => (source.size_hint().0, None),
#[cfg(feature = "vorbis")]
DecoderImpl::Vorbis(ref source) => (source.size_hint().0, None),
#[cfg(feature = "flac")]
DecoderImpl::Flac(ref source) => (source.size_hint().0, None),
#[cfg(feature = "mp3")]
DecoderImpl::Mp3(ref source) => (source.size_hint().0, None),
DecoderImpl::None(_) => (0, None),
}
}
}
impl<R> Source for LoopedDecoder<R>
where
R: Read + Seek,
{
#[inline]
fn current_frame_len(&self) -> Option<usize> {
match self.0 {
#[cfg(feature = "wav")]
DecoderImpl::Wav(ref source) => source.current_frame_len(),
#[cfg(feature = "vorbis")]
DecoderImpl::Vorbis(ref source) => source.current_frame_len(),
#[cfg(feature = "flac")]
DecoderImpl::Flac(ref source) => source.current_frame_len(),
#[cfg(feature = "mp3")]
DecoderImpl::Mp3(ref source) => source.current_frame_len(),
DecoderImpl::None(_) => Some(0),
}
}
#[inline]
fn channels(&self) -> u16 {
match self.0 {
#[cfg(feature = "wav")]
DecoderImpl::Wav(ref source) => source.channels(),
#[cfg(feature = "vorbis")]
DecoderImpl::Vorbis(ref source) => source.channels(),
#[cfg(feature = "flac")]
DecoderImpl::Flac(ref source) => source.channels(),
#[cfg(feature = "mp3")]
DecoderImpl::Mp3(ref source) => source.channels(),
DecoderImpl::None(_) => 0,
}
}
#[inline]
fn sample_rate(&self) -> u32 {
match self.0 {
#[cfg(feature = "wav")]
DecoderImpl::Wav(ref source) => source.sample_rate(),
#[cfg(feature = "vorbis")]
DecoderImpl::Vorbis(ref source) => source.sample_rate(),
#[cfg(feature = "flac")]
DecoderImpl::Flac(ref source) => source.sample_rate(),
#[cfg(feature = "mp3")]
DecoderImpl::Mp3(ref source) => source.sample_rate(),
DecoderImpl::None(_) => 1,
}
}
#[inline]
fn total_duration(&self) -> Option<Duration> {
None
}
}
/// Error that can happen when creating a decoder.
#[derive(Debug, Clone)]
pub enum DecoderError {

View file

@ -28,6 +28,9 @@ where
current_frame_offset: 0,
})
}
pub fn into_inner(self) -> R {
self.decoder.into_inner()
}
}
impl<R> Source for Mp3Decoder<R>

View file

@ -25,8 +25,10 @@ where
return Err(data);
}
let mut stream_reader = OggStreamReader::new(data).unwrap();
let stream_reader = OggStreamReader::new(data).unwrap();
Ok(Self::from_stream_reader(stream_reader))
}
pub fn from_stream_reader(mut stream_reader: OggStreamReader<R>) -> Self {
let mut data = match stream_reader.read_dec_packet_itl().ok().and_then(|v| v) {
Some(d) => d,
None => Vec::new(),
@ -39,10 +41,13 @@ where
None => (),
};
Ok(VorbisDecoder {
VorbisDecoder {
stream_reader: stream_reader,
current_data: data.into_iter(),
})
}
}
pub fn into_inner(self) -> OggStreamReader<R> {
self.stream_reader
}
}

View file

@ -38,6 +38,9 @@ where
channels: spec.channels,
})
}
pub fn into_inner(self) -> R {
self.reader.reader.into_inner()
}
}
struct SamplesIterator<R>