Преглед изворни кода

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.
Paul Lietar пре 9 година
родитељ
комит
ac5b34927f
5 измењених фајлова са 55 додато и 9 уклоњено
  1. 1 0
      .travis.yml
  2. 20 0
      Cargo.lock
  3. 2 0
      Cargo.toml
  4. 4 0
      src/lib.rs
  5. 28 9
      src/player.rs

+ 1 - 0
.travis.yml

@@ -12,6 +12,7 @@ addons:
 
 script:
     - cargo build
+    - cargo build --features with-tremor
     # Building without syntex only works on nightly
     - if [[ $(rustc --version) == *"nightly"* ]]; then
         cargo build --no-default-features;

+ 20 - 0
Cargo.lock

@@ -23,6 +23,7 @@ dependencies = [
  "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)",
  "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)",
  "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)",
@@ -449,6 +450,25 @@ dependencies = [
  "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]]
 name = "unicode-bidi"
 version = "0.2.3"

+ 2 - 0
Cargo.toml

@@ -41,6 +41,7 @@ portaudio       = { git = "https://github.com/mvdnes/portaudio-rs" }
 json_macros     = { git = "https://github.com/plietar/json_macros" }
 protobuf_macros = { git = "https://github.com/plietar/rust-protobuf-macros" }
 shannon         = { git = "https://github.com/plietar/rust-shannon" }
+tremor          = { git = "https://github.com/plietar/rust-tremor", optional = true }
 
 [build-dependencies]
 vergen          = "~0.1.0"
@@ -51,4 +52,5 @@ json_macros     = { git = "https://github.com/plietar/json_macros" }
 [features]
 discovery = ["dns-sd"]
 with-syntex = ["syntex", "protobuf_macros/with-syntex", "json_macros/with-syntex"]
+with-tremor = ["tremor"]
 default = ["with-syntex"]

+ 4 - 0
src/lib.rs

@@ -21,7 +21,11 @@ extern crate time;
 extern crate tiny_http;
 extern crate tempfile;
 extern crate url;
+
+#[cfg(not(feature = "with-tremor"))]
 extern crate vorbis;
+#[cfg(feature = "with-tremor")]
+extern crate tremor as vorbis;
 
 #[cfg(feature = "dns-sd")]
 extern crate dns_sd;

+ 28 - 9
src/player.rs

@@ -3,6 +3,7 @@ use portaudio;
 use std::borrow::Cow;
 use std::sync::{mpsc, Mutex, Arc, MutexGuard};
 use std::thread;
+use std::io::{Read, Seek};
 use vorbis;
 
 use metadata::{FileFormat, Track, TrackRef};
@@ -11,6 +12,26 @@ use audio_decrypt::AudioDecrypt;
 use util::{self, SpotifyId, Subfile};
 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 struct Player {
@@ -195,7 +216,8 @@ impl PlayerInternal {
                         Subfile::new(
                         AudioDecrypt::new(key,
                         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| {
                         state.status = if play {
@@ -211,11 +233,10 @@ impl PlayerInternal {
                     });
                     println!("Load Done");
                 }
-                Some(PlayerCommand::Seek(ms)) => {
-                    decoder.as_mut().unwrap().time_seek(ms as f64 / 1000f64).unwrap();
+                Some(PlayerCommand::Seek(position)) => {
+                    vorbis_time_seek_ms(decoder.as_mut().unwrap(), position as i64).unwrap()
                     self.update(|state| {
-                        state.position_ms =
-                            (decoder.as_mut().unwrap().time_tell().unwrap() * 1000f64) as u32;
+                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                         state.position_measured_at = util::now_ms();
 
                         true
@@ -224,8 +245,7 @@ impl PlayerInternal {
                 Some(PlayerCommand::Play) => {
                     self.update(|state| {
                         state.status = PlayStatus::kPlayStatusPlay;
-                        state.position_ms =
-                            (decoder.as_mut().unwrap().time_tell().unwrap() * 1000f64) as u32;
+                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                         state.position_measured_at = util::now_ms();
                         true
                     });
@@ -236,8 +256,7 @@ impl PlayerInternal {
                     self.update(|state| {
                         state.status = PlayStatus::kPlayStatusPause;
                         state.update_time = util::now_ms();
-                        state.position_ms =
-                            (decoder.as_mut().unwrap().time_tell().unwrap() * 1000f64) as u32;
+                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                         state.position_measured_at = util::now_ms();
                         true
                     });