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:
Paul Lietar 2016-03-13 15:15:15 +00:00
parent 32fe895105
commit ac5b34927f
5 changed files with 55 additions and 9 deletions

View file

@ -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
View file

@ -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"

View file

@ -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"]

View file

@ -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;

View file

@ -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
}); });