mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Support using tremor instead of libvorbis for audio decoding.
Tremor is a fixed point / integer only Vorbis decoder. This should improve playback performances on embedded platforms lacking hardware floating point support.
This commit is contained in:
parent
32fe895105
commit
ac5b34927f
5 changed files with 55 additions and 9 deletions
|
@ -12,6 +12,7 @@ addons:
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- cargo build
|
- cargo build
|
||||||
|
- cargo build --features with-tremor
|
||||||
# Building without syntex only works on nightly
|
# Building without syntex only works on nightly
|
||||||
- if [[ $(rustc --version) == *"nightly"* ]]; then
|
- if [[ $(rustc --version) == *"nightly"* ]]; then
|
||||||
cargo build --no-default-features;
|
cargo build --no-default-features;
|
||||||
|
|
20
Cargo.lock
generated
20
Cargo.lock
generated
|
@ -23,6 +23,7 @@ dependencies = [
|
||||||
"tempfile 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tempfile 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tiny_http 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tiny_http 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"tremor 0.1.0 (git+https://github.com/plietar/rust-tremor)",
|
||||||
"url 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"vergen 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"vergen 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"vorbis 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"vorbis 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -449,6 +450,25 @@ dependencies = [
|
||||||
"url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tremor"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/plietar/rust-tremor#5ced876f3cffb041fcf31238da7f3273178029fe"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"tremor-sys 0.1.0 (git+https://github.com/plietar/rust-tremor)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tremor-sys"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/plietar/rust-tremor#5ced876f3cffb041fcf31238da7f3273178029fe"
|
||||||
|
dependencies = [
|
||||||
|
"gcc 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ogg-sys 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-bidi"
|
name = "unicode-bidi"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
|
|
|
@ -41,6 +41,7 @@ portaudio = { git = "https://github.com/mvdnes/portaudio-rs" }
|
||||||
json_macros = { git = "https://github.com/plietar/json_macros" }
|
json_macros = { git = "https://github.com/plietar/json_macros" }
|
||||||
protobuf_macros = { git = "https://github.com/plietar/rust-protobuf-macros" }
|
protobuf_macros = { git = "https://github.com/plietar/rust-protobuf-macros" }
|
||||||
shannon = { git = "https://github.com/plietar/rust-shannon" }
|
shannon = { git = "https://github.com/plietar/rust-shannon" }
|
||||||
|
tremor = { git = "https://github.com/plietar/rust-tremor", optional = true }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
vergen = "~0.1.0"
|
vergen = "~0.1.0"
|
||||||
|
@ -51,4 +52,5 @@ json_macros = { git = "https://github.com/plietar/json_macros" }
|
||||||
[features]
|
[features]
|
||||||
discovery = ["dns-sd"]
|
discovery = ["dns-sd"]
|
||||||
with-syntex = ["syntex", "protobuf_macros/with-syntex", "json_macros/with-syntex"]
|
with-syntex = ["syntex", "protobuf_macros/with-syntex", "json_macros/with-syntex"]
|
||||||
|
with-tremor = ["tremor"]
|
||||||
default = ["with-syntex"]
|
default = ["with-syntex"]
|
||||||
|
|
|
@ -21,7 +21,11 @@ extern crate time;
|
||||||
extern crate tiny_http;
|
extern crate tiny_http;
|
||||||
extern crate tempfile;
|
extern crate tempfile;
|
||||||
extern crate url;
|
extern crate url;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "with-tremor"))]
|
||||||
extern crate vorbis;
|
extern crate vorbis;
|
||||||
|
#[cfg(feature = "with-tremor")]
|
||||||
|
extern crate tremor as vorbis;
|
||||||
|
|
||||||
#[cfg(feature = "dns-sd")]
|
#[cfg(feature = "dns-sd")]
|
||||||
extern crate dns_sd;
|
extern crate dns_sd;
|
||||||
|
|
|
@ -3,6 +3,7 @@ use portaudio;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::sync::{mpsc, Mutex, Arc, MutexGuard};
|
use std::sync::{mpsc, Mutex, Arc, MutexGuard};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
use std::io::{Read, Seek};
|
||||||
use vorbis;
|
use vorbis;
|
||||||
|
|
||||||
use metadata::{FileFormat, Track, TrackRef};
|
use metadata::{FileFormat, Track, TrackRef};
|
||||||
|
@ -11,6 +12,26 @@ use audio_decrypt::AudioDecrypt;
|
||||||
use util::{self, SpotifyId, Subfile};
|
use util::{self, SpotifyId, Subfile};
|
||||||
use spirc::PlayStatus;
|
use spirc::PlayStatus;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "with-tremor"))]
|
||||||
|
fn vorbis_time_seek_ms<R>(decoder: &mut vorbis::Decoder<R>, ms: i64) -> Result<(), vorbis::VorbisError> where R: Read + Seek {
|
||||||
|
decoder.time_seek(ms as f64 / 1000f64)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "with-tremor"))]
|
||||||
|
fn vorbis_time_tell_ms<R>(decoder: &mut vorbis::Decoder<R>) -> Result<i64, vorbis::VorbisError> where R: Read + Seek {
|
||||||
|
decoder.time_tell().map(|t| (t / 1000f64) as i64)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "with-tremor")]
|
||||||
|
fn vorbis_time_seek_ms<R>(decoder: &mut vorbis::Decoder<R>, ms: i64) -> Result<(), vorbis::VorbisError> where R: Read + Seek {
|
||||||
|
decoder.time_seek(ms)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "with-tremor")]
|
||||||
|
fn vorbis_time_tell_ms<R>(decoder: &mut vorbis::Decoder<R>) -> Result<i64, vorbis::VorbisError> where R: Read + Seek {
|
||||||
|
decoder.time_tell()
|
||||||
|
}
|
||||||
|
|
||||||
pub type PlayerObserver = Box<Fn(&PlayerState) + Send>;
|
pub type PlayerObserver = Box<Fn(&PlayerState) + Send>;
|
||||||
|
|
||||||
pub struct Player {
|
pub struct Player {
|
||||||
|
@ -195,7 +216,8 @@ impl PlayerInternal {
|
||||||
Subfile::new(
|
Subfile::new(
|
||||||
AudioDecrypt::new(key,
|
AudioDecrypt::new(key,
|
||||||
self.session.audio_file(file_id)), 0xa7)).unwrap());
|
self.session.audio_file(file_id)), 0xa7)).unwrap());
|
||||||
decoder.as_mut().unwrap().time_seek(position as f64 / 1000f64).unwrap();
|
|
||||||
|
vorbis_time_seek_ms(decoder.as_mut().unwrap(), position as i64).unwrap()
|
||||||
|
|
||||||
self.update(|state| {
|
self.update(|state| {
|
||||||
state.status = if play {
|
state.status = if play {
|
||||||
|
@ -211,11 +233,10 @@ impl PlayerInternal {
|
||||||
});
|
});
|
||||||
println!("Load Done");
|
println!("Load Done");
|
||||||
}
|
}
|
||||||
Some(PlayerCommand::Seek(ms)) => {
|
Some(PlayerCommand::Seek(position)) => {
|
||||||
decoder.as_mut().unwrap().time_seek(ms as f64 / 1000f64).unwrap();
|
vorbis_time_seek_ms(decoder.as_mut().unwrap(), position as i64).unwrap()
|
||||||
self.update(|state| {
|
self.update(|state| {
|
||||||
state.position_ms =
|
state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
|
||||||
(decoder.as_mut().unwrap().time_tell().unwrap() * 1000f64) as u32;
|
|
||||||
state.position_measured_at = util::now_ms();
|
state.position_measured_at = util::now_ms();
|
||||||
|
|
||||||
true
|
true
|
||||||
|
@ -224,8 +245,7 @@ impl PlayerInternal {
|
||||||
Some(PlayerCommand::Play) => {
|
Some(PlayerCommand::Play) => {
|
||||||
self.update(|state| {
|
self.update(|state| {
|
||||||
state.status = PlayStatus::kPlayStatusPlay;
|
state.status = PlayStatus::kPlayStatusPlay;
|
||||||
state.position_ms =
|
state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
|
||||||
(decoder.as_mut().unwrap().time_tell().unwrap() * 1000f64) as u32;
|
|
||||||
state.position_measured_at = util::now_ms();
|
state.position_measured_at = util::now_ms();
|
||||||
true
|
true
|
||||||
});
|
});
|
||||||
|
@ -236,8 +256,7 @@ impl PlayerInternal {
|
||||||
self.update(|state| {
|
self.update(|state| {
|
||||||
state.status = PlayStatus::kPlayStatusPause;
|
state.status = PlayStatus::kPlayStatusPause;
|
||||||
state.update_time = util::now_ms();
|
state.update_time = util::now_ms();
|
||||||
state.position_ms =
|
state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
|
||||||
(decoder.as_mut().unwrap().time_tell().unwrap() * 1000f64) as u32;
|
|
||||||
state.position_measured_at = util::now_ms();
|
state.position_measured_at = util::now_ms();
|
||||||
true
|
true
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue