From dee0e194669a6afafe4b1a0d7e3a6b8018922efa Mon Sep 17 00:00:00 2001 From: Yesterday17 Date: Sun, 22 Sep 2024 18:42:56 +0800 Subject: [PATCH] feat(playback): allow to specify sample rate and skip useless resample --- anni-playback/examples/gapless.rs | 2 +- anni-playback/examples/player.rs | 2 +- anni-playback/examples/tui.rs | 2 +- anni-playback/src/cpal_output.rs | 19 ++++++++++++------- anni-playback/src/decoder/decoder.rs | 5 ++--- anni-playback/src/player.rs | 14 ++++++++++++-- 6 files changed, 29 insertions(+), 15 deletions(-) diff --git a/anni-playback/examples/gapless.rs b/anni-playback/examples/gapless.rs index 9608eb3..0af1c62 100644 --- a/anni-playback/examples/gapless.rs +++ b/anni-playback/examples/gapless.rs @@ -15,7 +15,7 @@ impl Player { thread::spawn({ let controls = controls.clone(); move || { - let decoder = Decoder::new(controls, thread_killer.1.clone()); + let decoder = Decoder::new(controls, 48000, thread_killer.1.clone()); decoder.start(); } }); diff --git a/anni-playback/examples/player.rs b/anni-playback/examples/player.rs index b7264ce..01e85b3 100644 --- a/anni-playback/examples/player.rs +++ b/anni-playback/examples/player.rs @@ -15,7 +15,7 @@ impl Player { thread::spawn({ let controls = controls.clone(); move || { - let decoder = Decoder::new(controls, thread_killer.1.clone()); + let decoder = Decoder::new(controls, 48000, thread_killer.1.clone()); decoder.start(); } }); diff --git a/anni-playback/examples/tui.rs b/anni-playback/examples/tui.rs index 9de900d..b27c4e6 100644 --- a/anni-playback/examples/tui.rs +++ b/anni-playback/examples/tui.rs @@ -27,7 +27,7 @@ impl Player { thread::spawn({ let controls = controls.clone(); move || { - let decoder = Decoder::new(controls, thread_killer.1.clone()); + let decoder = Decoder::new(controls, 48000, thread_killer.1.clone()); decoder.start(); } }); diff --git a/anni-playback/src/cpal_output.rs b/anni-playback/src/cpal_output.rs index 3159b13..951b932 100644 --- a/anni-playback/src/cpal_output.rs +++ b/anni-playback/src/cpal_output.rs @@ -256,13 +256,18 @@ impl CpalOutput { return; } - let mut samples = if let Some(resampler) = &mut self.resampler { - // If there is a resampler, then write resampled values - // instead of the normal `samples`. - resampler.resample(decoded).unwrap_or(&[]) - } else { - self.sample_buffer.copy_interleaved_ref(decoded); - self.sample_buffer.samples() + let need_resample = decoded.spec().rate != self.spec.rate; + let mut samples = match (need_resample, &mut self.resampler) { + (true, Some(resampler)) => { + // If there is a resampler, then write resampled values + // instead of the normal `samples`. + resampler.resample(decoded).unwrap_or(&[]) + } + _ => { + // no resampler, or the target sampe rate is the same as the input + self.sample_buffer.copy_interleaved_ref(decoded); + self.sample_buffer.samples() + } }; if self.controls.is_normalizing() { diff --git a/anni-playback/src/decoder/decoder.rs b/anni-playback/src/decoder/decoder.rs index a622952..df421dd 100644 --- a/anni-playback/src/decoder/decoder.rs +++ b/anni-playback/src/decoder/decoder.rs @@ -75,9 +75,8 @@ pub struct Decoder { impl Decoder { /// Creates a new decoder. - pub fn new(controls: Controls, thread_killer: Receiver) -> Self { - // TODO: allow specifying sample rate by user - let spec = SignalSpec::new_with_layout(44100, Layout::Stereo); + pub fn new(controls: Controls, sample_rate: u32, thread_killer: Receiver) -> Self { + let spec = SignalSpec::new_with_layout(sample_rate, Layout::Stereo); Decoder { thread_killer, diff --git a/anni-playback/src/player.rs b/anni-playback/src/player.rs index df27bcf..6cfe253 100644 --- a/anni-playback/src/player.rs +++ b/anni-playback/src/player.rs @@ -33,11 +33,21 @@ pub struct AnniPlayer { cache_store: CacheStore, // root of cache } +pub struct AnniPlayerOptions { + pub sample_rate: u32, + pub cache_path: PathBuf, +} + impl AnniPlayer { pub fn new( provider: TypedPriorityProvider, - cache_path: PathBuf, + options: AnniPlayerOptions, ) -> (Self, Receiver) { + let AnniPlayerOptions { + sample_rate, + cache_path, + } = options; + let (controls, receiver, killer) = { let (sender, receiver) = mpsc::channel(); let controls = Controls::new(sender); @@ -48,7 +58,7 @@ impl AnniPlayer { .spawn({ let controls = controls.clone(); move || { - let decoder = Decoder::new(controls, thread_killer.1); + let decoder = Decoder::new(controls, sample_rate, thread_killer.1); decoder.start(); }