mirror of
https://github.com/librespot-org/librespot.git
synced 2025-10-06 03:50:06 +02:00
Add support for lewton as an Vorbis decoder.
This commit is contained in:
parent
ec8f80df75
commit
d1447d2bfb
10 changed files with 250 additions and 151 deletions
77
audio/src/lewton_decoder.rs
Normal file
77
audio/src/lewton_decoder.rs
Normal file
|
@ -0,0 +1,77 @@
|
|||
extern crate lewton;
|
||||
|
||||
use self::lewton::inside_ogg::OggStreamReader;
|
||||
|
||||
use std::io::{Read, Seek};
|
||||
use std::fmt;
|
||||
use std::error;
|
||||
|
||||
pub struct VorbisDecoder<R: Read + Seek>(OggStreamReader<R>);
|
||||
pub struct VorbisPacket(Vec<i16>);
|
||||
pub struct VorbisError(lewton::VorbisError);
|
||||
|
||||
impl <R> VorbisDecoder<R>
|
||||
where R: Read + Seek
|
||||
{
|
||||
pub fn new(input: R) -> Result<VorbisDecoder<R>, VorbisError> {
|
||||
Ok(VorbisDecoder(OggStreamReader::new(input)?))
|
||||
}
|
||||
|
||||
pub fn seek(&mut self, ms: i64) -> Result<(), VorbisError> {
|
||||
let absgp = ms * 44100 / 1000;
|
||||
self.0.seek_absgp_pg(absgp as u64)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn next_packet(&mut self) -> Result<Option<VorbisPacket>, VorbisError> {
|
||||
use self::lewton::VorbisError::BadAudio;
|
||||
use self::lewton::audio::AudioReadError::AudioIsHeader;
|
||||
loop {
|
||||
match self.0.read_dec_packet_itl() {
|
||||
Ok(Some(packet)) => return Ok(Some(VorbisPacket(packet))),
|
||||
Ok(None) => return Ok(None),
|
||||
|
||||
Err(BadAudio(AudioIsHeader)) => (),
|
||||
Err(err) => return Err(err.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VorbisPacket {
|
||||
pub fn data(&self) -> &[i16] {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn data_mut(&mut self) -> &mut [i16] {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<lewton::VorbisError> for VorbisError {
|
||||
fn from(err: lewton::VorbisError) -> VorbisError {
|
||||
VorbisError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for VorbisError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for VorbisError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for VorbisError {
|
||||
fn description(&self) -> &str {
|
||||
error::Error::description(&self.0)
|
||||
}
|
||||
|
||||
fn cause(&self) -> Option<&error::Error> {
|
||||
error::Error::cause(&self.0)
|
||||
}
|
||||
}
|
|
@ -13,5 +13,15 @@ extern crate librespot_core as core;
|
|||
mod fetch;
|
||||
mod decrypt;
|
||||
|
||||
#[cfg(not(feature = "with-lewton"))]
|
||||
mod libvorbis_decoder;
|
||||
#[cfg(feature = "with-lewton")]
|
||||
mod lewton_decoder;
|
||||
|
||||
pub use fetch::{AudioFile, AudioFileOpen};
|
||||
pub use decrypt::AudioDecrypt;
|
||||
|
||||
#[cfg(not(feature = "with-lewton"))]
|
||||
pub use libvorbis_decoder::{VorbisDecoder, VorbisPacket, VorbisError};
|
||||
#[cfg(feature = "with-lewton")]
|
||||
pub use lewton_decoder::{VorbisDecoder, VorbisPacket, VorbisError};
|
||||
|
|
80
audio/src/libvorbis_decoder.rs
Normal file
80
audio/src/libvorbis_decoder.rs
Normal file
|
@ -0,0 +1,80 @@
|
|||
#[cfg(not(feature = "with-tremor"))] extern crate vorbis;
|
||||
#[cfg(feature = "with-tremor")] extern crate tremor as vorbis;
|
||||
|
||||
use std::io::{Read, Seek};
|
||||
use std::fmt;
|
||||
use std::error;
|
||||
|
||||
pub struct VorbisDecoder<R: Read + Seek>(vorbis::Decoder<R>);
|
||||
pub struct VorbisPacket(vorbis::Packet);
|
||||
pub struct VorbisError(vorbis::VorbisError);
|
||||
|
||||
impl <R> VorbisDecoder<R>
|
||||
where R: Read + Seek
|
||||
{
|
||||
pub fn new(input: R) -> Result<VorbisDecoder<R>, VorbisError> {
|
||||
Ok(VorbisDecoder(vorbis::Decoder::new(input)?))
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "with-tremor"))]
|
||||
pub fn seek(&mut self, ms: i64) -> Result<(), VorbisError> {
|
||||
self.0.time_seek(ms as f64 / 1000f64)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-tremor")]
|
||||
pub fn seek(&mut self, ms: i64) -> Result<(), VorbisError> {
|
||||
self.0.time_seek(ms)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn next_packet(&mut self) -> Result<Option<VorbisPacket>, VorbisError> {
|
||||
loop {
|
||||
match self.0.packets().next() {
|
||||
Some(Ok(packet)) => return Ok(Some(VorbisPacket(packet))),
|
||||
None => return Ok(None),
|
||||
|
||||
Some(Err(vorbis::VorbisError::Hole)) => (),
|
||||
Some(Err(err)) => return Err(err.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VorbisPacket {
|
||||
pub fn data(&self) -> &[i16] {
|
||||
&self.0.data
|
||||
}
|
||||
|
||||
pub fn data_mut(&mut self) -> &mut [i16] {
|
||||
&mut self.0.data
|
||||
}
|
||||
}
|
||||
|
||||
impl From<vorbis::VorbisError> for VorbisError {
|
||||
fn from(err: vorbis::VorbisError) -> VorbisError {
|
||||
VorbisError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for VorbisError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for VorbisError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for VorbisError {
|
||||
fn description(&self) -> &str {
|
||||
error::Error::description(&self.0)
|
||||
}
|
||||
|
||||
fn cause(&self) -> Option<&error::Error> {
|
||||
error::Error::cause(&self.0)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue