diff --git a/src/buffer.rs b/src/buffer.rs index 305f6b1f..ef84d9c2 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -73,7 +73,7 @@ impl SamplesBuffer { impl Source for SamplesBuffer { #[inline] fn current_span_len(&self) -> Option { - None + Some(self.data.len() - self.pos) } #[inline] @@ -126,7 +126,7 @@ impl Iterator for SamplesBuffer { #[inline] fn size_hint(&self) -> (usize, Option) { - (self.data.len(), Some(self.data.len())) + (self.data.len() - self.pos, Some(self.data.len() - self.pos)) } } diff --git a/src/queue.rs b/src/queue.rs index 495606b4..923fcd5e 100644 --- a/src/queue.rs +++ b/src/queue.rs @@ -113,6 +113,8 @@ pub struct SourcesQueueOutput { } const THRESHOLD: usize = 512; +const SILENCE_SAMPLE_RATE: SampleRate = nz!(44100); +const SILENCE_CHANNELS: ChannelCount = nz!(1); impl Source for SourcesQueueOutput { #[inline] @@ -154,12 +156,28 @@ impl Source for SourcesQueueOutput { #[inline] fn channels(&self) -> ChannelCount { - self.current.channels() + // current_span_len() should never return 0 unless the source is empty, so this is a cheeky hint + if self.current.current_span_len() != Some(0) { + self.current.channels() + } else if let Some((next, _)) = self.input.next_sounds.lock().unwrap().first() { + next.channels() + } else { + // If keep_alive_if_empty is true, then it'll be mono 44.1khz silence -- otherwise it doesn't matter what it is + SILENCE_CHANNELS + } } #[inline] fn sample_rate(&self) -> SampleRate { - self.current.sample_rate() + // current_span_len() should never return 0 unless the source is empty, so this is a cheeky hint + if self.current.current_span_len() != Some(0) { + self.current.sample_rate() + } else if let Some((next, _)) = self.input.next_sounds.lock().unwrap().first() { + next.sample_rate() + } else { + // If keep_alive_if_empty is true, then it'll be mono 44.1khz silence -- otherwise it doesn't matter what it is + SILENCE_SAMPLE_RATE + } } #[inline] @@ -221,7 +239,11 @@ impl SourcesQueueOutput { let mut next = self.input.next_sounds.lock().unwrap(); if next.is_empty() { - let silence = Box::new(Zero::new_samples(nz!(1), nz!(44100), THRESHOLD)) as Box<_>; + let silence = Box::new(Zero::new_samples( + SILENCE_CHANNELS, + SILENCE_SAMPLE_RATE, + THRESHOLD, + )) as Box<_>; if self.input.keep_alive_if_empty.load(Ordering::Acquire) { // Play a short silence in order to avoid spinlocking. (silence, None) @@ -247,7 +269,6 @@ mod tests { use crate::source::Source; #[test] - #[ignore] // FIXME: samples rate and channel not updated immediately after transition fn basic() { let (tx, mut rx) = queue::queue(false); diff --git a/src/source/skip.rs b/src/source/skip.rs index 36f8d210..d3c43857 100644 --- a/src/source/skip.rs +++ b/src/source/skip.rs @@ -39,18 +39,22 @@ where return; } - let ns_per_sample: u128 = - NS_PER_SECOND / input.sample_rate().get() as u128 / input.channels().get() as u128; + let sample_rate = input.sample_rate().get() as u128; + let channels = input.channels().get() as u128; + + let samples_per_channel = duration.as_nanos() * sample_rate / NS_PER_SECOND; + let samples_to_skip: u128 = samples_per_channel * channels; // Check if we need to skip only part of the current span. - if span_len as u128 * ns_per_sample > duration.as_nanos() { - skip_samples(input, (duration.as_nanos() / ns_per_sample) as usize); + if span_len as u128 > samples_to_skip { + skip_samples(input, samples_to_skip as usize); return; } + duration -= Duration::from_nanos( + (NS_PER_SECOND * span_len as u128 / channels / sample_rate) as u64, + ); skip_samples(input, span_len); - - duration -= Duration::from_nanos((span_len * ns_per_sample as usize) as u64); } }