Added linear gain filter

This commit is contained in:
Jamie Hardt 2023-05-23 12:15:12 -07:00
parent 8f949a81c8
commit fe912a829e
3 changed files with 130 additions and 1 deletions

View file

@ -84,7 +84,7 @@ where
impl<I> Source for FadeIn<I>
where
I: Source,
I::Item: Sample,
I::Item: Sample,
{
#[inline]
fn current_frame_len(&self) -> Option<usize> {

117
src/source/linear_ramp.rs Normal file
View file

@ -0,0 +1,117 @@
use std::time::Duration;
use crate::{Sample, Source};
/// Internal function that builds a `LinearRamp` object.
pub fn linear_gain_ramp<I>(input: I,
duration: Duration,
start_gain: f32,
end_gain: f32) -> LinearGainRamp<I>
where
I: Source,
I::Item: Sample,
{
let duration = duration.as_secs() * 1000000000 + duration.subsec_nanos() as u64;
LinearGainRamp {
input,
remaining_ns: duration as f32,
total_ns: duration as f32,
start_gain,
end_gain
}
}
/// Filter that adds a linear gain ramp to the source over a given time range.
#[derive(Clone, Debug)]
pub struct LinearGainRamp<I> {
input: I,
remaining_ns: f32,
total_ns: f32,
start_gain: f32,
end_gain: f32
}
impl<I> LinearGainRamp<I>
where
I: Source,
I::Item: Sample
{
/// Returns a reference to the innner source.
#[inline]
pub fn inner(&self) -> &I {
&self.input
}
/// Returns a mutable reference to the inner source.
#[inline]
pub fn inner_mut(&mut self) -> &mut I {
&mut self.input
}
/// Returns the inner source.
#[inline]
pub fn into_inner(self) -> I {
self.input
}
}
impl<I> Iterator for LinearGainRamp<I>
where
I: Source,
I::Item: Sample,
{
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<I::Item> {
if self.remaining_ns <= 0.0 {
return self.input.next();
}
let factor : f32 = f32::lerp(self.start_gain, self.end_gain, self.remaining_ns as u32, self.total_ns as u32);
self.remaining_ns -=
1000000000.0 / (self.input.sample_rate() as f32 * self.channels() as f32);
self.input.next().map(|value| value.amplify(factor))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.input.size_hint()
}
}
impl<I> ExactSizeIterator for LinearGainRamp<I>
where
I: Source + ExactSizeIterator,
I::Item: Sample,
{
}
impl<I> Source for LinearGainRamp<I>
where
I: Source,
I::Item: Sample,
{
#[inline]
fn current_frame_len(&self) -> Option<usize> {
self.input.current_frame_len()
}
#[inline]
fn channels(&self) -> u16 {
self.input.channels()
}
#[inline]
fn sample_rate(&self) -> u32 {
self.input.sample_rate()
}
#[inline]
fn total_duration(&self) -> Option<Duration> {
self.input.total_duration()
}
}

View file

@ -18,6 +18,7 @@ pub use self::empty_callback::EmptyCallback;
pub use self::fadein::FadeIn;
pub use self::from_factory::{from_factory, FromFactoryIter};
pub use self::from_iter::{from_iter, FromIter};
pub use self::linear_ramp::LinearGainRamp;
pub use self::mix::Mix;
pub use self::pausable::Pausable;
pub use self::periodic::PeriodicAccess;
@ -45,6 +46,7 @@ mod empty_callback;
mod fadein;
mod from_factory;
mod from_iter;
mod linear_ramp;
mod mix;
mod pausable;
mod periodic;
@ -245,6 +247,16 @@ where
{
fadein::fadein(self, duration)
}
/// Applies a linear gain ramp to the sound
#[inline]
fn linear_gain_ramp(self, duration: Duration, start_value: f32, end_value: f32) -> LinearGainRamp<Self>
where
Self: Sized
{
linear_ramp::linear_gain_ramp(self, duration, start_value, end_value)
}
/// Calls the `access` closure on `Self` the first time the source is iterated and every
/// time `period` elapses.