implemented untested DSP part of Delay
This commit is contained in:
parent
9e752fe3f1
commit
cbc69f3ca3
3 changed files with 47 additions and 17 deletions
|
@ -160,10 +160,12 @@ impl SplitMix64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mix(v1: f32, v2: f32, mix: f32) -> f32 {
|
#[inline]
|
||||||
|
pub fn crossfade(v1: f32, v2: f32, mix: f32) -> f32 {
|
||||||
v1 * (1.0 - mix) + v2 * mix
|
v1 * (1.0 - mix) + v2 * mix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn clamp(f: f32, min: f32, max: f32) -> f32 {
|
pub fn clamp(f: f32, min: f32, max: f32) -> f32 {
|
||||||
if f < min { min }
|
if f < min { min }
|
||||||
else if f > max { max }
|
else if f > max { max }
|
||||||
|
@ -482,7 +484,8 @@ impl TriggerClock {
|
||||||
/// Default size of the delay buffer: 5 seconds at 8 times 48kHz
|
/// Default size of the delay buffer: 5 seconds at 8 times 48kHz
|
||||||
const DEFAULT_DELAY_BUFFER_SAMPLES : usize = 8 * 48000 * 5;
|
const DEFAULT_DELAY_BUFFER_SAMPLES : usize = 8 * 48000 * 5;
|
||||||
|
|
||||||
struct DelayBuffer {
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct DelayBuffer {
|
||||||
data: Vec<f32>,
|
data: Vec<f32>,
|
||||||
wr: usize,
|
wr: usize,
|
||||||
srate: f32,
|
srate: f32,
|
||||||
|
|
|
@ -363,10 +363,11 @@ define_exp!{n_declick d_declick 0.0, 50.0}
|
||||||
|
|
||||||
define_exp!{n_env d_env 0.0, 1000.0}
|
define_exp!{n_env d_env 0.0, 1000.0}
|
||||||
|
|
||||||
|
define_exp!{n_time d_time 0.0, 5000.0}
|
||||||
|
|
||||||
// Special linear gain factor for the Out node, to be able
|
// Special linear gain factor for the Out node, to be able
|
||||||
// to reach more exact "1.0".
|
// to reach more exact "1.0".
|
||||||
define_lin!{n_ogin d_ogin 0.0, 2.0}
|
define_lin!{n_ogin d_ogin 0.0, 2.0}
|
||||||
define_lin!{n_time d_time 0.0, 5000.0}
|
|
||||||
|
|
||||||
// A note about the input-indicies:
|
// A note about the input-indicies:
|
||||||
//
|
//
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
// See README.md and COPYING for details.
|
// See README.md and COPYING for details.
|
||||||
|
|
||||||
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
||||||
use crate::dsp::{NodeId, SAtom, ProcBuf, GraphFun, GraphAtomData, DspNode, LedPhaseVals};
|
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals};
|
||||||
|
use crate::dsp::helpers::{DelayBuffer, crossfade};
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! fa_dly_s { ($formatter: expr, $v: expr, $denorm_v: expr) => { {
|
macro_rules! fa_dly_s { ($formatter: expr, $v: expr, $denorm_v: expr) => { {
|
||||||
|
@ -28,11 +29,15 @@ macro_rules! fa_dly_s { ($formatter: expr, $v: expr, $denorm_v: expr) => { {
|
||||||
/// A simple amplifier
|
/// A simple amplifier
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Delay {
|
pub struct Delay {
|
||||||
|
buffer: Box<DelayBuffer>,
|
||||||
|
fb_sample: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Delay {
|
impl Delay {
|
||||||
pub fn new(_nid: &NodeId) -> Self {
|
pub fn new(_nid: &NodeId) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
buffer: Box::new(DelayBuffer::new()),
|
||||||
|
fb_sample: 0.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,27 +80,48 @@ For other kinds of delay/feedback please see also the 'FbWr'/'FbRd' nodes.
|
||||||
impl DspNode for Delay {
|
impl DspNode for Delay {
|
||||||
fn outputs() -> usize { 1 }
|
fn outputs() -> usize { 1 }
|
||||||
|
|
||||||
fn set_sample_rate(&mut self, _srate: f32) { }
|
fn set_sample_rate(&mut self, srate: f32) {
|
||||||
fn reset(&mut self) { }
|
self.buffer.set_sample_rate(srate);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset(&mut self) {
|
||||||
|
self.buffer.reset();
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn process<T: NodeAudioContext>(
|
fn process<T: NodeAudioContext>(
|
||||||
&mut self, ctx: &mut T, _ectx: &mut NodeExecContext,
|
&mut self, ctx: &mut T, _ectx: &mut NodeExecContext,
|
||||||
atoms: &[SAtom], _params: &[ProcBuf], _inputs: &[ProcBuf],
|
_atoms: &[SAtom], _params: &[ProcBuf], inputs: &[ProcBuf],
|
||||||
outputs: &mut [ProcBuf], _led: LedPhaseVals)
|
outputs: &mut [ProcBuf], _led: LedPhaseVals)
|
||||||
{
|
{
|
||||||
use crate::dsp::{out, at};
|
use crate::dsp::{out, inp, denorm};
|
||||||
|
|
||||||
// let p = at::Delay::p(atoms);
|
let buffer = &mut *self.buffer;
|
||||||
|
|
||||||
|
let inp = inp::Delay::inp(inputs);
|
||||||
|
let time = inp::Delay::time(inputs);
|
||||||
|
let fb = inp::Delay::fb(inputs);
|
||||||
|
let mix = inp::Delay::mix(inputs);
|
||||||
let out = out::Delay::sig(outputs);
|
let out = out::Delay::sig(outputs);
|
||||||
for frame in 0..ctx.nframes() {
|
|
||||||
out.write(frame, 0.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn graph_fun() -> Option<GraphFun> {
|
let mut fb_s = self.fb_sample;
|
||||||
Some(Box::new(|_gd: &dyn GraphAtomData, _init: bool, x: f32| -> f32 {
|
|
||||||
x
|
for frame in 0..ctx.nframes() {
|
||||||
}))
|
let dry = inp.read(frame);
|
||||||
|
buffer.feed(
|
||||||
|
dry + fb_s * denorm::Delay::fb(fb, frame));
|
||||||
|
|
||||||
|
let out_sample =
|
||||||
|
buffer.cubic_interpolate_at(
|
||||||
|
denorm::Delay::time(time, frame));
|
||||||
|
|
||||||
|
out.write(frame,
|
||||||
|
crossfade(dry, out_sample,
|
||||||
|
denorm::Delay::mix(mix, frame).clamp(0.0, 1.0)));
|
||||||
|
|
||||||
|
fb_s = out_sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.fb_sample = fb_s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue