mirror of
https://github.com/RustAudio/rodio
synced 2024-11-10 14:14:21 +00:00
Make silence more efficient
This commit is contained in:
parent
2c7d171670
commit
9c874b7690
2 changed files with 36 additions and 19 deletions
|
@ -206,7 +206,7 @@ where
|
|||
if next.len() == 0 {
|
||||
if self.input.keep_alive_if_empty.load(Ordering::Acquire) {
|
||||
// Play a short silence in order to avoid spinlocking.
|
||||
let silence = Zero::<S>::new(1, 44000); // TODO: meh
|
||||
let silence = Zero::<S>::new(1, 44100); // TODO: meh
|
||||
(
|
||||
Box::new(silence.take_duration(Duration::from_millis(10))) as Box<_>,
|
||||
None,
|
||||
|
|
|
@ -4,8 +4,14 @@ use Sample;
|
|||
use Source;
|
||||
|
||||
/// Internal function that builds a `TakeDuration` object.
|
||||
pub fn take_duration<I>(input: I, duration: Duration) -> TakeDuration<I> {
|
||||
pub fn take_duration<I>(input: I, duration: Duration) -> TakeDuration<I>
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
TakeDuration {
|
||||
current_frame_len: input.current_frame_len(),
|
||||
duration_per_sample: TakeDuration::get_duration_per_sample(&input),
|
||||
input: input,
|
||||
remaining_duration: duration,
|
||||
requested_duration: duration,
|
||||
|
@ -35,6 +41,8 @@ impl DurationFilter
|
|||
}
|
||||
}
|
||||
|
||||
const NANOS_PER_SEC: u64 = 1_000_000_000;
|
||||
|
||||
/// A source that repeats the given source.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TakeDuration<I> {
|
||||
|
@ -42,6 +50,10 @@ pub struct TakeDuration<I> {
|
|||
remaining_duration: Duration,
|
||||
requested_duration: Duration,
|
||||
filter: Option<DurationFilter>,
|
||||
// Remaining samples in current frame.
|
||||
current_frame_len: Option<usize>,
|
||||
// Only updated when the current frame len is exausted.
|
||||
duration_per_sample: Duration,
|
||||
}
|
||||
|
||||
impl<I> TakeDuration<I>
|
||||
|
@ -51,8 +63,8 @@ where
|
|||
{
|
||||
/// Returns the duration elapsed for each sample extracted.
|
||||
#[inline]
|
||||
fn get_duration_per_sample(&self) -> Duration {
|
||||
let ns = 1000000000 / (self.input.sample_rate() as u64 * self.channels() as u64);
|
||||
fn get_duration_per_sample(input: &I) -> Duration {
|
||||
let ns = NANOS_PER_SEC / input.sample_rate() as u64 * input.channels() as u64;
|
||||
// \|/ the maximum value of `ns` is one billion, so this can't fail
|
||||
Duration::new(0, ns as u32)
|
||||
}
|
||||
|
@ -92,9 +104,17 @@ where
|
|||
type Item = <I as Iterator>::Item;
|
||||
|
||||
fn next(&mut self) -> Option<<I as Iterator>::Item> {
|
||||
let duration_per_sample = self.get_duration_per_sample();
|
||||
if let Some(frame_len) = self.current_frame_len.take() {
|
||||
if frame_len > 0 {
|
||||
self.current_frame_len = Some(frame_len - 1);
|
||||
} else {
|
||||
self.current_frame_len = self.input.current_frame_len();
|
||||
// Sample rate might have changed
|
||||
self.duration_per_sample = Self::get_duration_per_sample(&self.input);
|
||||
}
|
||||
}
|
||||
|
||||
if self.remaining_duration <= duration_per_sample {
|
||||
if self.remaining_duration <= self.duration_per_sample {
|
||||
None
|
||||
} else {
|
||||
if let Some(sample) = self.input.next() {
|
||||
|
@ -102,7 +122,9 @@ where
|
|||
Some(filter) => filter.apply(sample, &self),
|
||||
None => sample,
|
||||
};
|
||||
self.remaining_duration = self.remaining_duration - duration_per_sample;
|
||||
|
||||
self.remaining_duration = self.remaining_duration - self.duration_per_sample;
|
||||
|
||||
Some(sample)
|
||||
} else {
|
||||
None
|
||||
|
@ -120,20 +142,15 @@ where
|
|||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
let remaining_nanosecs = self.remaining_duration.as_secs() * 1000000000
|
||||
let remaining_nanos = self.remaining_duration.as_secs() * NANOS_PER_SEC
|
||||
+ self.remaining_duration.subsec_nanos() as u64;
|
||||
let remaining_samples = remaining_nanosecs * self.input.sample_rate() as u64
|
||||
* self.channels() as u64 / 1000000000;
|
||||
let nanos_per_sample = self.duration_per_sample.as_secs() * NANOS_PER_SEC
|
||||
+ self.duration_per_sample.subsec_nanos() as u64;
|
||||
let remaining_samples = (remaining_nanos / nanos_per_sample) as usize;
|
||||
|
||||
if let Some(value) = self.input.current_frame_len() {
|
||||
if (value as u64) < remaining_samples {
|
||||
Some(value)
|
||||
} else {
|
||||
Some(remaining_samples as usize)
|
||||
}
|
||||
} else {
|
||||
Some(remaining_samples as usize)
|
||||
}
|
||||
self.input.current_frame_len()
|
||||
.filter(|value| *value < remaining_samples)
|
||||
.or(Some(remaining_samples))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
Loading…
Reference in a new issue