Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

144
vendor/rodio/src/decoder/flac.rs vendored Normal file
View File

@@ -0,0 +1,144 @@
use std::cmp::Ordering;
use std::io::{Read, Seek, SeekFrom};
use std::mem;
use std::time::Duration;
use crate::source::SeekError;
use crate::Source;
use claxon::FlacReader;
/// Decoder for the Flac format.
pub struct FlacDecoder<R>
where
R: Read + Seek,
{
reader: FlacReader<R>,
current_block: Vec<i32>,
current_block_channel_len: usize,
current_block_off: usize,
bits_per_sample: u32,
sample_rate: u32,
channels: u16,
samples: Option<u64>,
}
impl<R> FlacDecoder<R>
where
R: Read + Seek,
{
/// Attempts to decode the data as Flac.
pub fn new(mut data: R) -> Result<FlacDecoder<R>, R> {
if !is_flac(data.by_ref()) {
return Err(data);
}
let reader = FlacReader::new(data).unwrap();
let spec = reader.streaminfo();
Ok(FlacDecoder {
reader,
current_block: Vec::with_capacity(
spec.max_block_size as usize * spec.channels as usize,
),
current_block_channel_len: 1,
current_block_off: 0,
bits_per_sample: spec.bits_per_sample,
sample_rate: spec.sample_rate,
channels: spec.channels as u16,
samples: spec.samples,
})
}
pub fn into_inner(self) -> R {
self.reader.into_inner()
}
}
impl<R> Source for FlacDecoder<R>
where
R: Read + Seek,
{
#[inline]
fn current_frame_len(&self) -> Option<usize> {
None
}
#[inline]
fn channels(&self) -> u16 {
self.channels
}
#[inline]
fn sample_rate(&self) -> u32 {
self.sample_rate
}
#[inline]
fn total_duration(&self) -> Option<Duration> {
// `samples` in FLAC means "inter-channel samples" aka frames
// so we do not divide by `self.channels` here.
self.samples
.map(|s| Duration::from_micros(s * 1_000_000 / self.sample_rate as u64))
}
#[inline]
fn try_seek(&mut self, _: Duration) -> Result<(), SeekError> {
Err(SeekError::NotSupported {
underlying_source: std::any::type_name::<Self>(),
})
}
}
impl<R> Iterator for FlacDecoder<R>
where
R: Read + Seek,
{
type Item = i16;
#[inline]
fn next(&mut self) -> Option<i16> {
loop {
if self.current_block_off < self.current_block.len() {
// Read from current block.
let real_offset = (self.current_block_off % self.channels as usize)
* self.current_block_channel_len
+ self.current_block_off / self.channels as usize;
let raw_val = self.current_block[real_offset];
self.current_block_off += 1;
let real_val = match self.bits_per_sample.cmp(&16) {
Ordering::Less => (raw_val << (16 - self.bits_per_sample)) as i16,
Ordering::Equal => raw_val as i16,
Ordering::Greater => (raw_val >> (self.bits_per_sample - 16)) as i16,
};
return Some(real_val);
}
// Load the next block.
self.current_block_off = 0;
let buffer = mem::take(&mut self.current_block);
match self.reader.blocks().read_next_or_eof(buffer) {
Ok(Some(block)) => {
self.current_block_channel_len = (block.len() / block.channels()) as usize;
self.current_block = block.into_buffer();
}
_ => return None,
}
}
}
}
/// Returns true if the stream contains Flac data, then resets it to where it was.
fn is_flac<R>(mut data: R) -> bool
where
R: Read + Seek,
{
let stream_pos = data.stream_position().unwrap();
if FlacReader::new(data.by_ref()).is_err() {
data.seek(SeekFrom::Start(stream_pos)).unwrap();
return false;
}
data.seek(SeekFrom::Start(stream_pos)).unwrap();
true
}

585
vendor/rodio/src/decoder/mod.rs vendored Normal file
View File

@@ -0,0 +1,585 @@
//! Decodes samples from an audio file.
use std::error::Error;
use std::fmt;
#[allow(unused_imports)]
use std::io::{Read, Seek, SeekFrom};
use std::mem;
use std::str::FromStr;
use std::time::Duration;
use crate::source::SeekError;
use crate::Source;
#[cfg(feature = "symphonia")]
use self::read_seek_source::ReadSeekSource;
#[cfg(feature = "symphonia")]
use ::symphonia::core::io::{MediaSource, MediaSourceStream};
#[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
mod flac;
#[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
mod mp3;
#[cfg(feature = "symphonia")]
mod read_seek_source;
#[cfg(feature = "symphonia")]
/// Symphonia decoders types
pub mod symphonia;
#[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
mod vorbis;
#[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
mod wav;
/// Source of audio samples from decoding a file.
///
/// Supports MP3, WAV, Vorbis and Flac.
pub struct Decoder<R>(DecoderImpl<R>)
where
R: Read + Seek;
/// Source of audio samples from decoding a file that never ends. When the
/// end of the file is reached the decoder starts again from the beginning.
///
/// Supports MP3, WAV, Vorbis and Flac.
pub struct LoopedDecoder<R>(DecoderImpl<R>)
where
R: Read + Seek;
// Cannot really reduce the size of the VorbisDecoder. There are not any
// arrays just a lot of struct fields.
#[allow(clippy::large_enum_variant)]
enum DecoderImpl<R>
where
R: Read + Seek,
{
#[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
Wav(wav::WavDecoder<R>),
#[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
Vorbis(vorbis::VorbisDecoder<R>),
#[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
Flac(flac::FlacDecoder<R>),
#[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
Mp3(mp3::Mp3Decoder<R>),
#[cfg(feature = "symphonia")]
Symphonia(symphonia::SymphoniaDecoder),
None(::std::marker::PhantomData<R>),
}
impl<R: Read + Seek> DecoderImpl<R> {
#[inline]
fn next(&mut self) -> Option<i16> {
match self {
#[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
DecoderImpl::Wav(source) => source.next(),
#[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
DecoderImpl::Vorbis(source) => source.next(),
#[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
DecoderImpl::Flac(source) => source.next(),
#[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
DecoderImpl::Mp3(source) => source.next(),
#[cfg(feature = "symphonia")]
DecoderImpl::Symphonia(source) => source.next(),
DecoderImpl::None(_) => None,
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match self {
#[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
DecoderImpl::Wav(source) => source.size_hint(),
#[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
DecoderImpl::Vorbis(source) => source.size_hint(),
#[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
DecoderImpl::Flac(source) => source.size_hint(),
#[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
DecoderImpl::Mp3(source) => source.size_hint(),
#[cfg(feature = "symphonia")]
DecoderImpl::Symphonia(source) => source.size_hint(),
DecoderImpl::None(_) => (0, None),
}
}
#[inline]
fn current_frame_len(&self) -> Option<usize> {
match self {
#[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
DecoderImpl::Wav(source) => source.current_frame_len(),
#[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
DecoderImpl::Vorbis(source) => source.current_frame_len(),
#[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
DecoderImpl::Flac(source) => source.current_frame_len(),
#[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
DecoderImpl::Mp3(source) => source.current_frame_len(),
#[cfg(feature = "symphonia")]
DecoderImpl::Symphonia(source) => source.current_frame_len(),
DecoderImpl::None(_) => Some(0),
}
}
#[inline]
fn channels(&self) -> u16 {
match self {
#[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
DecoderImpl::Wav(source) => source.channels(),
#[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
DecoderImpl::Vorbis(source) => source.channels(),
#[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
DecoderImpl::Flac(source) => source.channels(),
#[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
DecoderImpl::Mp3(source) => source.channels(),
#[cfg(feature = "symphonia")]
DecoderImpl::Symphonia(source) => source.channels(),
DecoderImpl::None(_) => 0,
}
}
#[inline]
fn sample_rate(&self) -> u32 {
match self {
#[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
DecoderImpl::Wav(source) => source.sample_rate(),
#[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
DecoderImpl::Vorbis(source) => source.sample_rate(),
#[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
DecoderImpl::Flac(source) => source.sample_rate(),
#[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
DecoderImpl::Mp3(source) => source.sample_rate(),
#[cfg(feature = "symphonia")]
DecoderImpl::Symphonia(source) => source.sample_rate(),
DecoderImpl::None(_) => 1,
}
}
#[inline]
fn total_duration(&self) -> Option<Duration> {
match self {
#[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
DecoderImpl::Wav(source) => source.total_duration(),
#[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
DecoderImpl::Vorbis(source) => source.total_duration(),
#[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
DecoderImpl::Flac(source) => source.total_duration(),
#[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
DecoderImpl::Mp3(source) => source.total_duration(),
#[cfg(feature = "symphonia")]
DecoderImpl::Symphonia(source) => source.total_duration(),
DecoderImpl::None(_) => Some(Duration::default()),
}
}
#[inline]
fn try_seek(&mut self, pos: Duration) -> Result<(), SeekError> {
match self {
#[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
DecoderImpl::Wav(source) => source.try_seek(pos),
#[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
DecoderImpl::Vorbis(source) => source.try_seek(pos),
#[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
DecoderImpl::Flac(source) => source.try_seek(pos),
#[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
DecoderImpl::Mp3(source) => source.try_seek(pos),
#[cfg(feature = "symphonia")]
DecoderImpl::Symphonia(source) => source.try_seek(pos),
DecoderImpl::None(_) => Err(SeekError::NotSupported {
underlying_source: "DecoderImpl::None",
}),
}
}
}
impl<R> Decoder<R>
where
R: Read + Seek + Send + Sync + 'static,
{
/// Builds a new decoder.
///
/// Attempts to automatically detect the format of the source of data.
#[allow(unused_variables)]
pub fn new(data: R) -> Result<Decoder<R>, DecoderError> {
#[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
let data = match wav::WavDecoder::new(data) {
Err(data) => data,
Ok(decoder) => {
return Ok(Decoder(DecoderImpl::Wav(decoder)));
}
};
#[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
let data = match flac::FlacDecoder::new(data) {
Err(data) => data,
Ok(decoder) => {
return Ok(Decoder(DecoderImpl::Flac(decoder)));
}
};
#[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
let data = match vorbis::VorbisDecoder::new(data) {
Err(data) => data,
Ok(decoder) => {
return Ok(Decoder(DecoderImpl::Vorbis(decoder)));
}
};
#[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
let data = match mp3::Mp3Decoder::new(data) {
Err(data) => data,
Ok(decoder) => {
return Ok(Decoder(DecoderImpl::Mp3(decoder)));
}
};
#[cfg(feature = "symphonia")]
{
let mss = MediaSourceStream::new(
Box::new(ReadSeekSource::new(data)) as Box<dyn MediaSource>,
Default::default(),
);
match symphonia::SymphoniaDecoder::new(mss, None) {
Err(e) => Err(e),
Ok(decoder) => Ok(Decoder(DecoderImpl::Symphonia(decoder))),
}
}
#[cfg(not(feature = "symphonia"))]
Err(DecoderError::UnrecognizedFormat)
}
/// Builds a new looped decoder.
///
/// Attempts to automatically detect the format of the source of data.
pub fn new_looped(data: R) -> Result<LoopedDecoder<R>, DecoderError> {
Self::new(data).map(LoopedDecoder::new)
}
/// Builds a new decoder from wav data.
#[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
pub fn new_wav(data: R) -> Result<Decoder<R>, DecoderError> {
match wav::WavDecoder::new(data) {
Err(_) => Err(DecoderError::UnrecognizedFormat),
Ok(decoder) => Ok(Decoder(DecoderImpl::Wav(decoder))),
}
}
/// Builds a new decoder from wav data.
#[cfg(feature = "symphonia-wav")]
pub fn new_wav(data: R) -> Result<Decoder<R>, DecoderError> {
Decoder::new_symphonia(data, "wav")
}
/// Builds a new decoder from flac data.
#[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
pub fn new_flac(data: R) -> Result<Decoder<R>, DecoderError> {
match flac::FlacDecoder::new(data) {
Err(_) => Err(DecoderError::UnrecognizedFormat),
Ok(decoder) => Ok(Decoder(DecoderImpl::Flac(decoder))),
}
}
/// Builds a new decoder from flac data.
#[cfg(feature = "symphonia-flac")]
pub fn new_flac(data: R) -> Result<Decoder<R>, DecoderError> {
Decoder::new_symphonia(data, "flac")
}
/// Builds a new decoder from vorbis data.
#[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
pub fn new_vorbis(data: R) -> Result<Decoder<R>, DecoderError> {
match vorbis::VorbisDecoder::new(data) {
Err(_) => Err(DecoderError::UnrecognizedFormat),
Ok(decoder) => Ok(Decoder(DecoderImpl::Vorbis(decoder))),
}
}
/// Builds a new decoder from vorbis data.
#[cfg(feature = "symphonia-vorbis")]
pub fn new_vorbis(data: R) -> Result<Decoder<R>, DecoderError> {
Decoder::new_symphonia(data, "ogg")
}
/// Builds a new decoder from mp3 data.
#[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
pub fn new_mp3(data: R) -> Result<Decoder<R>, DecoderError> {
match mp3::Mp3Decoder::new(data) {
Err(_) => Err(DecoderError::UnrecognizedFormat),
Ok(decoder) => Ok(Decoder(DecoderImpl::Mp3(decoder))),
}
}
/// Builds a new decoder from mp3 data.
#[cfg(feature = "symphonia-mp3")]
pub fn new_mp3(data: R) -> Result<Decoder<R>, DecoderError> {
Decoder::new_symphonia(data, "mp3")
}
/// Builds a new decoder from aac data.
#[cfg(feature = "symphonia-aac")]
pub fn new_aac(data: R) -> Result<Decoder<R>, DecoderError> {
Decoder::new_symphonia(data, "aac")
}
/// Builds a new decoder from mp4 data.
#[cfg(feature = "symphonia-isomp4")]
pub fn new_mp4(data: R, hint: Mp4Type) -> Result<Decoder<R>, DecoderError> {
Decoder::new_symphonia(data, &hint.to_string())
}
#[cfg(feature = "symphonia")]
fn new_symphonia(data: R, hint: &str) -> Result<Decoder<R>, DecoderError> {
let mss = MediaSourceStream::new(
Box::new(ReadSeekSource::new(data)) as Box<dyn MediaSource>,
Default::default(),
);
match symphonia::SymphoniaDecoder::new(mss, Some(hint)) {
Err(e) => Err(e),
Ok(decoder) => Ok(Decoder(DecoderImpl::Symphonia(decoder))),
}
}
}
#[allow(missing_docs)] // Reason: will be removed, see: #612
#[derive(Debug)]
pub enum Mp4Type {
Mp4,
M4a,
M4p,
M4b,
M4r,
M4v,
Mov,
}
impl FromStr for Mp4Type {
type Err = String;
fn from_str(input: &str) -> Result<Mp4Type, Self::Err> {
match &input.to_lowercase()[..] {
"mp4" => Ok(Mp4Type::Mp4),
"m4a" => Ok(Mp4Type::M4a),
"m4p" => Ok(Mp4Type::M4p),
"m4b" => Ok(Mp4Type::M4b),
"m4r" => Ok(Mp4Type::M4r),
"m4v" => Ok(Mp4Type::M4v),
"mov" => Ok(Mp4Type::Mov),
_ => Err(format!("{input} is not a valid mp4 extension")),
}
}
}
impl fmt::Display for Mp4Type {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let text = match self {
Mp4Type::Mp4 => "mp4",
Mp4Type::M4a => "m4a",
Mp4Type::M4p => "m4p",
Mp4Type::M4b => "m4b",
Mp4Type::M4r => "m4r",
Mp4Type::M4v => "m4v",
Mp4Type::Mov => "mov",
};
write!(f, "{text}")
}
}
impl<R> LoopedDecoder<R>
where
R: Read + Seek,
{
fn new(decoder: Decoder<R>) -> LoopedDecoder<R> {
Self(decoder.0)
}
}
impl<R> Iterator for Decoder<R>
where
R: Read + Seek,
{
type Item = i16;
#[inline]
fn next(&mut self) -> Option<i16> {
self.0.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<R> Source for Decoder<R>
where
R: Read + Seek,
{
#[inline]
fn current_frame_len(&self) -> Option<usize> {
self.0.current_frame_len()
}
#[inline]
fn channels(&self) -> u16 {
self.0.channels()
}
fn sample_rate(&self) -> u32 {
self.0.sample_rate()
}
#[inline]
fn total_duration(&self) -> Option<Duration> {
self.0.total_duration()
}
#[inline]
fn try_seek(&mut self, pos: Duration) -> Result<(), SeekError> {
self.0.try_seek(pos)
}
}
impl<R> Iterator for LoopedDecoder<R>
where
R: Read + Seek,
{
type Item = i16;
#[inline]
fn next(&mut self) -> Option<i16> {
if let Some(sample) = self.0.next() {
Some(sample)
} else {
let decoder = mem::replace(&mut self.0, DecoderImpl::None(Default::default()));
let (decoder, sample) = match decoder {
#[cfg(all(feature = "wav", not(feature = "symphonia-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(all(feature = "vorbis", not(feature = "symphonia-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(all(feature = "flac", not(feature = "symphonia-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(all(feature = "minimp3", not(feature = "symphonia-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)
}
#[cfg(feature = "symphonia")]
DecoderImpl::Symphonia(source) => {
let mut reader = source.into_inner();
reader.seek(SeekFrom::Start(0)).ok()?;
let mut source = symphonia::SymphoniaDecoder::new(reader, None).ok()?;
let sample = source.next();
(DecoderImpl::Symphonia(source), sample)
}
none @ DecoderImpl::None(_) => (none, None),
};
self.0 = decoder;
sample
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<R> Source for LoopedDecoder<R>
where
R: Read + Seek,
{
#[inline]
fn current_frame_len(&self) -> Option<usize> {
self.0.current_frame_len()
}
#[inline]
fn channels(&self) -> u16 {
self.0.channels()
}
#[inline]
fn sample_rate(&self) -> u32 {
self.0.sample_rate()
}
#[inline]
fn total_duration(&self) -> Option<Duration> {
None
}
fn try_seek(&mut self, pos: Duration) -> Result<(), SeekError> {
self.0.try_seek(pos)
}
}
/// Error that can happen when creating a decoder.
#[derive(Debug, Clone)]
pub enum DecoderError {
/// The format of the data has not been recognized.
UnrecognizedFormat,
/// An IO error occurred while reading, writing, or seeking the stream.
#[cfg(feature = "symphonia")]
IoError(String),
/// The stream contained malformed data and could not be decoded or demuxed.
#[cfg(feature = "symphonia")]
DecodeError(&'static str),
/// A default or user-defined limit was reached while decoding or demuxing the stream. Limits
/// are used to prevent denial-of-service attacks from malicious streams.
#[cfg(feature = "symphonia")]
LimitError(&'static str),
/// The demuxer or decoder needs to be reset before continuing.
#[cfg(feature = "symphonia")]
ResetRequired,
/// No streams were found by the decoder
#[cfg(feature = "symphonia")]
NoStreams,
}
impl fmt::Display for DecoderError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let text = match self {
DecoderError::UnrecognizedFormat => "Unrecognized format",
#[cfg(feature = "symphonia")]
DecoderError::IoError(msg) => &msg[..],
#[cfg(feature = "symphonia")]
DecoderError::DecodeError(msg) => msg,
#[cfg(feature = "symphonia")]
DecoderError::LimitError(msg) => msg,
#[cfg(feature = "symphonia")]
DecoderError::ResetRequired => "Reset required",
#[cfg(feature = "symphonia")]
DecoderError::NoStreams => "No streams",
};
write!(f, "{text}")
}
}
impl Error for DecoderError {}

125
vendor/rodio/src/decoder/mp3.rs vendored Normal file
View File

@@ -0,0 +1,125 @@
use std::io::{Read, Seek, SeekFrom};
use std::time::Duration;
use crate::source::SeekError;
use crate::Source;
use minimp3::Decoder;
use minimp3::Frame;
use minimp3_fixed as minimp3;
pub struct Mp3Decoder<R>
where
R: Read + Seek,
{
// decoder: SeekDecoder<R>,
decoder: Decoder<R>,
current_frame: Frame,
current_frame_offset: usize,
}
impl<R> Mp3Decoder<R>
where
R: Read + Seek,
{
pub fn new(mut data: R) -> Result<Self, R> {
if !is_mp3(data.by_ref()) {
return Err(data);
}
// let mut decoder = SeekDecoder::new(data)
let mut decoder = Decoder::new(data);
// parameters are correct and minimp3 is used correctly
// thus if we crash here one of these invariants is broken:
// .expect("should be able to allocate memory, perform IO");
// let current_frame = decoder.decode_frame()
let current_frame = decoder.next_frame()
// the reader makes enough data available therefore
// if we crash here the invariant broken is:
.expect("data should not corrupt");
Ok(Mp3Decoder {
decoder,
current_frame,
current_frame_offset: 0,
})
}
pub fn into_inner(self) -> R {
self.decoder.into_inner()
}
}
impl<R> Source for Mp3Decoder<R>
where
R: Read + Seek,
{
#[inline]
fn current_frame_len(&self) -> Option<usize> {
Some(self.current_frame.data.len())
}
#[inline]
fn channels(&self) -> u16 {
self.current_frame.channels as _
}
#[inline]
fn sample_rate(&self) -> u32 {
self.current_frame.sample_rate as _
}
#[inline]
fn total_duration(&self) -> Option<Duration> {
None
}
fn try_seek(&mut self, pos: Duration) -> Result<(), SeekError> {
// TODO waiting for PR in minimp3_fixed or minimp3
// let pos = (pos.as_secs_f32() * self.sample_rate() as f32) as u64;
// // do not trigger a sample_rate, channels and frame len update
// // as the seek only takes effect after the current frame is done
// self.decoder.seek_samples(pos)?;
// Ok(())
Err(SeekError::NotSupported {
underlying_source: std::any::type_name::<Self>(),
})
}
}
impl<R> Iterator for Mp3Decoder<R>
where
R: Read + Seek,
{
type Item = i16;
fn next(&mut self) -> Option<i16> {
if self.current_frame_offset == self.current_frame_len().unwrap() {
if let Ok(frame) = self.decoder.next_frame() {
// if let Ok(frame) = self.decoder.decode_frame() {
self.current_frame = frame;
self.current_frame_offset = 0;
} else {
return None;
}
}
let v = self.current_frame.data[self.current_frame_offset];
self.current_frame_offset += 1;
Some(v)
}
}
/// Returns true if the stream contains mp3 data, then resets it to where it was.
fn is_mp3<R>(mut data: R) -> bool
where
R: Read + Seek,
{
let stream_pos = data.seek(SeekFrom::Current(0)).unwrap();
let mut decoder = Decoder::new(data.by_ref());
let ok = decoder.next_frame().is_ok();
data.seek(SeekFrom::Start(stream_pos)).unwrap();
ok
}

View File

@@ -0,0 +1,37 @@
use std::io::{Read, Result, Seek, SeekFrom};
use symphonia::core::io::MediaSource;
pub struct ReadSeekSource<T: Read + Seek + Send + Sync> {
inner: T,
}
impl<T: Read + Seek + Send + Sync> ReadSeekSource<T> {
/// Instantiates a new `ReadSeekSource<T>` by taking ownership and wrapping the provided
/// `Read + Seek`er.
pub fn new(inner: T) -> Self {
ReadSeekSource { inner }
}
}
impl<T: Read + Seek + Send + Sync> MediaSource for ReadSeekSource<T> {
fn is_seekable(&self) -> bool {
true
}
fn byte_len(&self) -> Option<u64> {
None
}
}
impl<T: Read + Seek + Send + Sync> Read for ReadSeekSource<T> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
self.inner.read(buf)
}
}
impl<T: Read + Seek + Send + Sync> Seek for ReadSeekSource<T> {
fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
self.inner.seek(pos)
}
}

333
vendor/rodio/src/decoder/symphonia.rs vendored Normal file
View File

@@ -0,0 +1,333 @@
use core::fmt;
use core::time::Duration;
use symphonia::{
core::{
audio::{AudioBufferRef, SampleBuffer, SignalSpec},
codecs::{Decoder, DecoderOptions, CODEC_TYPE_NULL},
errors::Error,
formats::{FormatOptions, FormatReader, SeekedTo},
io::MediaSourceStream,
meta::MetadataOptions,
probe::Hint,
units::{self, Time},
},
default::get_probe,
};
use crate::{source, Source};
use super::DecoderError;
// Decoder errors are not considered fatal.
// The correct action is to just get a new packet and try again.
// But a decode error in more than 3 consecutive packets is fatal.
const MAX_DECODE_RETRIES: usize = 3;
pub(crate) struct SymphoniaDecoder {
decoder: Box<dyn Decoder>,
current_frame_offset: usize,
format: Box<dyn FormatReader>,
total_duration: Option<Time>,
buffer: SampleBuffer<i16>,
spec: SignalSpec,
}
impl SymphoniaDecoder {
pub(crate) fn new(
mss: MediaSourceStream,
extension: Option<&str>,
) -> Result<Self, DecoderError> {
match SymphoniaDecoder::init(mss, extension) {
Err(e) => match e {
Error::IoError(e) => Err(DecoderError::IoError(e.to_string())),
Error::DecodeError(e) => Err(DecoderError::DecodeError(e)),
Error::SeekError(_) => {
unreachable!("Seek errors should not occur during initialization")
}
Error::Unsupported(_) => Err(DecoderError::UnrecognizedFormat),
Error::LimitError(e) => Err(DecoderError::LimitError(e)),
Error::ResetRequired => Err(DecoderError::ResetRequired),
},
Ok(Some(decoder)) => Ok(decoder),
Ok(None) => Err(DecoderError::NoStreams),
}
}
pub(crate) fn into_inner(self) -> MediaSourceStream {
self.format.into_inner()
}
fn init(
mss: MediaSourceStream,
extension: Option<&str>,
) -> symphonia::core::errors::Result<Option<SymphoniaDecoder>> {
let mut hint = Hint::new();
if let Some(ext) = extension {
hint.with_extension(ext);
}
let format_opts: FormatOptions = FormatOptions {
enable_gapless: true,
..Default::default()
};
let metadata_opts: MetadataOptions = Default::default();
let mut probed = get_probe().format(&hint, mss, &format_opts, &metadata_opts)?;
let stream = match probed.format.default_track() {
Some(stream) => stream,
None => return Ok(None),
};
// Select the first supported track
let track_id = probed
.format
.tracks()
.iter()
.find(|t| t.codec_params.codec != CODEC_TYPE_NULL)
.ok_or(symphonia::core::errors::Error::Unsupported(
"No track with supported codec",
))?
.id;
let track = probed
.format
.tracks()
.iter()
.find(|track| track.id == track_id)
.unwrap();
let mut decoder = symphonia::default::get_codecs()
.make(&track.codec_params, &DecoderOptions::default())?;
let total_duration = stream
.codec_params
.time_base
.zip(stream.codec_params.n_frames)
.map(|(base, frames)| base.calc_time(frames));
let mut decode_errors: usize = 0;
let decoded = loop {
let current_frame = match probed.format.next_packet() {
Ok(packet) => packet,
Err(Error::IoError(_)) => break decoder.last_decoded(),
Err(e) => return Err(e),
};
// If the packet does not belong to the selected track, skip over it
if current_frame.track_id() != track_id {
continue;
}
match decoder.decode(&current_frame) {
Ok(decoded) => break decoded,
Err(e) => match e {
Error::DecodeError(_) => {
decode_errors += 1;
if decode_errors > MAX_DECODE_RETRIES {
return Err(e);
} else {
continue;
}
}
_ => return Err(e),
},
}
};
let spec = decoded.spec().to_owned();
let buffer = SymphoniaDecoder::get_buffer(decoded, &spec);
Ok(Some(SymphoniaDecoder {
decoder,
current_frame_offset: 0,
format: probed.format,
total_duration,
buffer,
spec,
}))
}
#[inline]
fn get_buffer(decoded: AudioBufferRef, spec: &SignalSpec) -> SampleBuffer<i16> {
let duration = units::Duration::from(decoded.capacity() as u64);
let mut buffer = SampleBuffer::<i16>::new(duration, *spec);
buffer.copy_interleaved_ref(decoded);
buffer
}
}
impl Source for SymphoniaDecoder {
#[inline]
fn current_frame_len(&self) -> Option<usize> {
Some(self.buffer.samples().len())
}
#[inline]
fn channels(&self) -> u16 {
self.spec.channels.count() as u16
}
#[inline]
fn sample_rate(&self) -> u32 {
self.spec.rate
}
#[inline]
fn total_duration(&self) -> Option<Duration> {
self.total_duration
.map(|Time { seconds, frac }| Duration::new(seconds, (1f64 / frac) as u32))
}
fn try_seek(&mut self, pos: Duration) -> Result<(), source::SeekError> {
use symphonia::core::formats::{SeekMode, SeekTo};
let seek_beyond_end = self
.total_duration()
.is_some_and(|dur| dur.saturating_sub(pos).as_millis() < 1);
let time = if seek_beyond_end {
let time = self.total_duration.expect("if guarantees this is Some");
skip_back_a_tiny_bit(time) // some decoders can only seek to just before the end
} else {
pos.as_secs_f64().into()
};
// make sure the next sample is for the right channel
let to_skip = self.current_frame_offset % self.channels() as usize;
let seek_res = self
.format
.seek(
SeekMode::Accurate,
SeekTo::Time {
time,
track_id: None,
},
)
.map_err(SeekError::BaseSeek)?;
self.refine_position(seek_res)?;
self.current_frame_offset += to_skip;
Ok(())
}
}
/// Error returned when the try_seek implementation of the symphonia decoder fails.
#[derive(Debug)]
pub enum SeekError {
/// Could not get next packet while refining seek position
Refining(symphonia::core::errors::Error),
/// Format reader failed to seek
BaseSeek(symphonia::core::errors::Error),
/// Decoding failed retrying on the next packet failed
Retrying(symphonia::core::errors::Error),
/// Decoding failed on multiple consecutive packets
Decoding(symphonia::core::errors::Error),
}
impl fmt::Display for SeekError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SeekError::Refining(err) => {
write!(
f,
"Could not get next packet while refining seek position: {:?}",
err
)
}
SeekError::BaseSeek(err) => {
write!(f, "Format reader failed to seek: {:?}", err)
}
SeekError::Retrying(err) => {
write!(
f,
"Decoding failed retrying on the next packet failed: {:?}",
err
)
}
SeekError::Decoding(err) => {
write!(
f,
"Decoding failed on multiple consecutive packets: {:?}",
err
)
}
}
}
}
impl std::error::Error for SeekError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
SeekError::Refining(err) => Some(err),
SeekError::BaseSeek(err) => Some(err),
SeekError::Retrying(err) => Some(err),
SeekError::Decoding(err) => Some(err),
}
}
}
impl SymphoniaDecoder {
/// Note frame offset must be set after
fn refine_position(&mut self, seek_res: SeekedTo) -> Result<(), source::SeekError> {
let mut samples_to_pass = seek_res.required_ts - seek_res.actual_ts;
let packet = loop {
let candidate = self.format.next_packet().map_err(SeekError::Refining)?;
if candidate.dur() > samples_to_pass {
break candidate;
} else {
samples_to_pass -= candidate.dur();
}
};
let mut decoded = self.decoder.decode(&packet);
for _ in 0..MAX_DECODE_RETRIES {
if decoded.is_err() {
let packet = self.format.next_packet().map_err(SeekError::Retrying)?;
decoded = self.decoder.decode(&packet);
}
}
let decoded = decoded.map_err(SeekError::Decoding)?;
decoded.spec().clone_into(&mut self.spec);
self.buffer = SymphoniaDecoder::get_buffer(decoded, &self.spec);
self.current_frame_offset = samples_to_pass as usize * self.channels() as usize;
Ok(())
}
}
fn skip_back_a_tiny_bit(
Time {
mut seconds,
mut frac,
}: Time,
) -> Time {
frac -= 0.0001;
if frac < 0.0 {
seconds = seconds.saturating_sub(1);
frac = 1.0 - frac;
}
Time { seconds, frac }
}
impl Iterator for SymphoniaDecoder {
type Item = i16;
#[inline]
fn next(&mut self) -> Option<i16> {
if self.current_frame_offset >= self.buffer.len() {
let packet = self.format.next_packet().ok()?;
let mut decoded = self.decoder.decode(&packet);
for _ in 0..MAX_DECODE_RETRIES {
if decoded.is_err() {
let packet = self.format.next_packet().ok()?;
decoded = self.decoder.decode(&packet);
}
}
let decoded = decoded.ok()?;
decoded.spec().clone_into(&mut self.spec);
self.buffer = SymphoniaDecoder::get_buffer(decoded, &self.spec);
self.current_frame_offset = 0;
}
let sample = *self.buffer.samples().get(self.current_frame_offset)?;
self.current_frame_offset += 1;
Some(sample)
}
}

144
vendor/rodio/src/decoder/vorbis.rs vendored Normal file
View File

@@ -0,0 +1,144 @@
use std::io::{Read, Seek, SeekFrom};
use std::time::Duration;
use crate::source::SeekError;
use crate::Source;
use lewton::inside_ogg::OggStreamReader;
/// Decoder for an OGG file that contains Vorbis sound format.
pub struct VorbisDecoder<R>
where
R: Read + Seek,
{
stream_reader: OggStreamReader<R>,
current_data: Vec<i16>,
next: usize,
}
impl<R> VorbisDecoder<R>
where
R: Read + Seek,
{
/// Attempts to decode the data as ogg/vorbis.
pub fn new(mut data: R) -> Result<VorbisDecoder<R>, R> {
if !is_vorbis(data.by_ref()) {
return Err(data);
}
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(Some(d)) => d,
_ => Vec::new(),
};
// The first packet is always empty, therefore
// we need to read the second frame to get some data
if let Ok(Some(mut d)) = stream_reader.read_dec_packet_itl() {
data.append(&mut d);
}
VorbisDecoder {
stream_reader,
current_data: data,
next: 0,
}
}
pub fn into_inner(self) -> OggStreamReader<R> {
self.stream_reader
}
}
impl<R> Source for VorbisDecoder<R>
where
R: Read + Seek,
{
#[inline]
fn current_frame_len(&self) -> Option<usize> {
Some(self.current_data.len())
}
#[inline]
fn channels(&self) -> u16 {
self.stream_reader.ident_hdr.audio_channels as u16
}
#[inline]
fn sample_rate(&self) -> u32 {
self.stream_reader.ident_hdr.audio_sample_rate
}
#[inline]
fn total_duration(&self) -> Option<Duration> {
None
}
/// seek is broken, https://github.com/RustAudio/lewton/issues/73.
// We could work around it by:
// - using unsafe to create an instance of Self
// - use mem::swap to turn the &mut self into a mut self
// - take out the underlying Read+Seek
// - make a new self and seek
//
// If this issue is fixed use the implementation in
// commit: 3bafe32388b4eb7a48c6701e6c65044dc8c555e6
#[inline]
fn try_seek(&mut self, _: Duration) -> Result<(), SeekError> {
Err(SeekError::NotSupported {
underlying_source: std::any::type_name::<Self>(),
})
}
}
impl<R> Iterator for VorbisDecoder<R>
where
R: Read + Seek,
{
type Item = i16;
#[inline]
fn next(&mut self) -> Option<i16> {
if let Some(sample) = self.current_data.get(self.next).copied() {
self.next += 1;
if self.current_data.is_empty() {
if let Ok(Some(data)) = self.stream_reader.read_dec_packet_itl() {
self.current_data = data;
self.next = 0;
}
}
Some(sample)
} else {
if let Ok(Some(data)) = self.stream_reader.read_dec_packet_itl() {
self.current_data = data;
self.next = 0;
}
let sample = self.current_data.get(self.next).copied();
self.next += 1;
sample
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.current_data.len(), None)
}
}
/// Returns true if the stream contains Vorbis data, then resets it to where it was.
fn is_vorbis<R>(mut data: R) -> bool
where
R: Read + Seek,
{
let stream_pos = data.stream_position().unwrap();
if OggStreamReader::new(data.by_ref()).is_err() {
data.seek(SeekFrom::Start(stream_pos)).unwrap();
return false;
}
data.seek(SeekFrom::Start(stream_pos)).unwrap();
true
}

221
vendor/rodio/src/decoder/wav.rs vendored Normal file
View File

@@ -0,0 +1,221 @@
use std::io::{Read, Seek, SeekFrom};
use std::time::Duration;
use crate::source::SeekError;
use crate::Source;
use hound::{SampleFormat, WavReader};
/// Decoder for the WAV format.
pub struct WavDecoder<R>
where
R: Read + Seek,
{
reader: SamplesIterator<R>,
total_duration: Duration,
sample_rate: u32,
channels: u16,
}
impl<R> WavDecoder<R>
where
R: Read + Seek,
{
/// Attempts to decode the data as WAV.
pub fn new(mut data: R) -> Result<WavDecoder<R>, R> {
if !is_wave(data.by_ref()) {
return Err(data);
}
let reader = WavReader::new(data).unwrap();
let spec = reader.spec();
let len = reader.len() as u64;
let reader = SamplesIterator {
reader,
samples_read: 0,
};
let sample_rate = spec.sample_rate;
let channels = spec.channels;
let total_duration =
Duration::from_micros((1_000_000 * len) / (sample_rate as u64 * channels as u64));
Ok(WavDecoder {
reader,
total_duration,
sample_rate,
channels,
})
}
pub fn into_inner(self) -> R {
self.reader.reader.into_inner()
}
}
struct SamplesIterator<R>
where
R: Read + Seek,
{
reader: WavReader<R>,
samples_read: u32, // wav header is u32 so this suffices
}
impl<R> Iterator for SamplesIterator<R>
where
R: Read + Seek,
{
type Item = i16;
#[inline]
fn next(&mut self) -> Option<i16> {
let spec = self.reader.spec();
match (spec.sample_format, spec.bits_per_sample) {
(SampleFormat::Float, 32) => self.reader.samples().next().map(|value| {
self.samples_read += 1;
f32_to_i16(value.unwrap_or(0.0))
}),
(SampleFormat::Int, 8) => self.reader.samples().next().map(|value| {
self.samples_read += 1;
i8_to_i16(value.unwrap_or(0))
}),
(SampleFormat::Int, 16) => self.reader.samples().next().map(|value| {
self.samples_read += 1;
value.unwrap_or(0)
}),
(SampleFormat::Int, 24) => self.reader.samples().next().map(|value| {
self.samples_read += 1;
i24_to_i16(value.unwrap_or(0))
}),
(SampleFormat::Int, 32) => self.reader.samples().next().map(|value| {
self.samples_read += 1;
i32_to_i16(value.unwrap_or(0))
}),
(sample_format, bits_per_sample) => {
panic!("Unimplemented wav spec: {sample_format:?}, {bits_per_sample}")
}
}
}
#[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 {}
impl<R> Source for WavDecoder<R>
where
R: Read + Seek,
{
#[inline]
fn current_frame_len(&self) -> Option<usize> {
None
}
#[inline]
fn channels(&self) -> u16 {
self.channels
}
#[inline]
fn sample_rate(&self) -> u32 {
self.sample_rate
}
#[inline]
fn total_duration(&self) -> Option<Duration> {
Some(self.total_duration)
}
#[inline]
fn try_seek(&mut self, pos: Duration) -> Result<(), SeekError> {
let file_len = self.reader.reader.duration();
let new_pos = pos.as_secs_f32() * self.sample_rate() as f32;
let new_pos = new_pos as u32;
let new_pos = new_pos.min(file_len); // saturate pos at the end of the source
// make sure the next sample is for the right channel
let to_skip = self.reader.samples_read % self.channels() as u32;
self.reader
.reader
.seek(new_pos)
.map_err(SeekError::HoundDecoder)?;
self.reader.samples_read = new_pos * self.channels() as u32;
for _ in 0..to_skip {
self.next();
}
Ok(())
}
}
impl<R> Iterator for WavDecoder<R>
where
R: Read + Seek,
{
type Item = i16;
#[inline]
fn next(&mut self) -> Option<i16> {
self.reader.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.reader.size_hint()
}
}
impl<R> ExactSizeIterator for WavDecoder<R> where R: Read + Seek {}
/// 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.stream_position().unwrap();
if WavReader::new(data.by_ref()).is_err() {
data.seek(SeekFrom::Start(stream_pos)).unwrap();
return false;
}
data.seek(SeekFrom::Start(stream_pos)).unwrap();
true
}
/// Returns a 32 bit WAV float as an i16. WAV floats are typically in the range of
/// [-1.0, 1.0] while i16s are in the range [-32768, 32767]. Note that this
/// function definitely causes precision loss but hopefully this isn't too
/// audiable when actually playing?
fn f32_to_i16(f: f32) -> i16 {
// prefer to clip the input rather than be excessively loud.
(f.clamp(-1.0, 1.0) * i16::MAX as f32) as i16
}
/// Returns an 8-bit WAV int as an i16. This scales the sample value by a factor
/// of 256.
fn i8_to_i16(i: i8) -> i16 {
i as i16 * 256
}
/// Returns a 24 bit WAV int as an i16. Note that this is a 24 bit integer, not a
/// 32 bit one. 24 bit ints are in the range [8,388,608, 8,388,607] while i16s
/// are in the range [-32768, 32767]. Note that this function definitely causes
/// precision loss but hopefully this isn't too audiable when actually playing?
fn i24_to_i16(i: i32) -> i16 {
(i >> 8) as i16
}
/// Returns a 32 bit WAV int as an i16. 32 bit ints are in the range
/// [-2,147,483,648, 2,147,483,647] while i16s are in the range [-32768, 32767].
/// Note that this function definitely causes precision loss but hopefully this
/// isn't too audiable when actually playing?
fn i32_to_i16(i: i32) -> i16 {
(i >> 16) as i16
}