From 08e64c1b9d622026bcbe1f80d2d5d64dd80af8f9 Mon Sep 17 00:00:00 2001 From: Eskil Q Date: Sat, 2 Jan 2021 09:47:14 +0100 Subject: add streaming version of NoiseGate --- mumd/src/audio.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-) (limited to 'mumd/src/audio.rs') diff --git a/mumd/src/audio.rs b/mumd/src/audio.rs index 828dbc5..0a2465e 100644 --- a/mumd/src/audio.rs +++ b/mumd/src/audio.rs @@ -21,7 +21,7 @@ use futures::Stream; use futures::task::{Context, Poll}; use std::pin::Pin; use tokio_stream::StreamExt; -use std::future::Future; +use std::future::{Future}; use std::mem; //TODO? move to mumlib @@ -373,7 +373,11 @@ struct NoiseGate { } impl NoiseGate { - pub fn new(signal: S, activate_threshold: <::Sample as Sample>::Float, deactivate_threshold: <::Sample as Sample>::Float) -> NoiseGate { + pub fn new( + signal: S, + activate_threshold: <::Sample as Sample>::Float, + deactivate_threshold: <::Sample as Sample>::Float + ) -> NoiseGate { Self { open: false, signal, @@ -417,6 +421,72 @@ impl Signal for NoiseGate { } } +struct StreamingNoiseGate { + open: bool, + signal: S, + buffer: dasp_ring_buffer::Fixed>, + activate_threshold: <::Sample as Sample>::Float, + deactivate_threshold: <::Sample as Sample>::Float, +} + +impl StreamingNoiseGate { + pub fn new( + signal: S, + activate_threshold: <::Sample as Sample>::Float, + deactivate_threshold: <::Sample as Sample>::Float + ) -> StreamingNoiseGate { + Self { + open: false, + signal, + buffer: Fixed::from(vec![::EQUILIBRIUM; 4096]), + activate_threshold, + deactivate_threshold, + } + } +} + +impl StreamingSignal for StreamingNoiseGate + where + S: StreamingSignal + Unpin, + <<::Frame as Frame>::Sample as Sample>::Float: Unpin, + ::Frame: Unpin { + type Frame = S::Frame; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let s = self.get_mut(); + + let frame = match S::poll_next(Pin::new(&mut s.signal), cx) { + Poll::Ready(v) => v, + Poll::Pending => return Poll::Pending, + }; + s.buffer.push(frame); + + if s.open && s.buffer + .iter() + .all(|f| f.to_float_frame() + .channels() + .all(|sample| abs(sample - <<::Sample as Sample>::Float as Sample>::EQUILIBRIUM) <= s.deactivate_threshold)) { + s.open = false; + } else if !s.open && s.buffer + .iter() + .any(|f| f.to_float_frame() + .channels() + .any(|sample| abs(sample - <<::Sample as Sample>::Float as Sample>::EQUILIBRIUM) >= s.activate_threshold)) { + s.open = true; + } + + if s.open { + Poll::Ready(frame) + } else { + Poll::Ready(S::Frame::EQUILIBRIUM) + } + } + + fn is_exhausted(&self) -> bool { + self.signal.is_exhausted() + } +} + fn abs(sample: S) -> S { let zero = S::EQUILIBRIUM; if sample >= zero { -- cgit v1.2.1