librespot/audio/src/lib.rs

124 lines
3.3 KiB
Rust
Raw Normal View History

2018-02-26 01:50:41 +00:00
#[macro_use]
extern crate futures;
#[macro_use]
extern crate log;
2017-08-03 19:37:04 +00:00
2019-11-11 07:22:41 +00:00
extern crate aes_ctr;
2017-08-03 19:37:04 +00:00
extern crate bit_set;
extern crate byteorder;
2019-11-01 19:46:28 +00:00
extern crate bytes;
2017-08-03 19:37:04 +00:00
extern crate num_bigint;
2018-02-26 01:50:41 +00:00
extern crate num_traits;
2017-08-03 19:37:04 +00:00
extern crate tempfile;
2019-09-16 19:00:09 +00:00
extern crate librespot_core;
2017-08-03 19:37:04 +00:00
mod decrypt;
2018-02-26 01:50:41 +00:00
mod fetch;
2017-08-03 19:37:04 +00:00
#[cfg(not(any(feature = "with-tremor", feature = "with-vorbis")))]
mod lewton_decoder;
#[cfg(any(feature = "with-tremor", feature = "with-vorbis"))]
mod libvorbis_decoder;
2021-01-07 06:42:38 +00:00
mod passthrough_decoder;
2019-11-01 19:46:28 +00:00
mod range_set;
2017-08-03 19:37:04 +00:00
pub use decrypt::AudioDecrypt;
2019-11-01 19:46:28 +00:00
pub use fetch::{AudioFile, AudioFileOpen, StreamLoaderController};
2019-11-11 07:22:41 +00:00
pub use fetch::{
READ_AHEAD_BEFORE_PLAYBACK_ROUNDTRIPS, READ_AHEAD_BEFORE_PLAYBACK_SECONDS,
READ_AHEAD_DURING_PLAYBACK_ROUNDTRIPS, READ_AHEAD_DURING_PLAYBACK_SECONDS,
};
2021-01-07 06:42:38 +00:00
use std::fmt;
pub enum AudioPacket {
Samples(Vec<f32>),
2021-01-07 06:42:38 +00:00
OggData(Vec<u8>),
}
// Losslessly represent [-1.0, 1.0] to [$type::MIN, $type::MAX] while maintaining DC linearity.
macro_rules! convert_samples_to {
($type: ident, $samples: expr) => {
$samples
.iter()
.map(|sample| {
if *sample == 0.0 {
0 as $type
} else {
(*sample as f64 * (std::$type::MAX as f64 + 0.5) - 0.5) as $type
}
})
.collect()
};
}
2021-01-07 06:42:38 +00:00
impl AudioPacket {
pub fn samples(&self) -> &[f32] {
2021-01-07 06:42:38 +00:00
match self {
AudioPacket::Samples(s) => s,
AudioPacket::OggData(_) => panic!("can't return OggData on samples"),
}
}
pub fn oggdata(&self) -> &[u8] {
match self {
AudioPacket::Samples(_) => panic!("can't return samples on OggData"),
AudioPacket::OggData(d) => d,
}
}
pub fn is_empty(&self) -> bool {
match self {
AudioPacket::Samples(s) => s.is_empty(),
AudioPacket::OggData(d) => d.is_empty(),
}
}
pub fn f32_to_s32(samples: &[f32]) -> Vec<i32> {
convert_samples_to!(i32, samples)
}
pub fn f32_to_s16(samples: &[f32]) -> Vec<i16> {
convert_samples_to!(i16, samples)
}
2021-01-07 06:42:38 +00:00
}
#[cfg(not(any(feature = "with-tremor", feature = "with-vorbis")))]
2021-01-07 06:42:38 +00:00
pub use crate::lewton_decoder::{VorbisDecoder, VorbisError};
#[cfg(any(feature = "with-tremor", feature = "with-vorbis"))]
2021-01-07 06:42:38 +00:00
pub use libvorbis_decoder::{VorbisDecoder, VorbisError};
pub use passthrough_decoder::{PassthroughDecoder, PassthroughError};
#[derive(Debug)]
pub enum AudioError {
PassthroughError(PassthroughError),
VorbisError(VorbisError),
}
impl fmt::Display for AudioError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
AudioError::PassthroughError(err) => write!(f, "PassthroughError({})", err),
AudioError::VorbisError(err) => write!(f, "VorbisError({})", err),
}
}
}
impl From<VorbisError> for AudioError {
fn from(err: VorbisError) -> AudioError {
AudioError::VorbisError(VorbisError::from(err))
}
}
impl From<PassthroughError> for AudioError {
fn from(err: PassthroughError) -> AudioError {
AudioError::PassthroughError(PassthroughError::from(err))
}
}
pub trait AudioDecoder {
fn seek(&mut self, ms: i64) -> Result<(), AudioError>;
fn next_packet(&mut self) -> Result<Option<AudioPacket>, AudioError>;
}