2021-06-30 20:15:32 +00:00
|
|
|
// Copyright (c) 2021 Weird Constructor <weirdconstructor@gmail.com>
|
2021-08-04 01:58:43 +00:00
|
|
|
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
|
2021-06-30 20:15:32 +00:00
|
|
|
// See README.md and COPYING for details.
|
|
|
|
|
|
|
|
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
2021-07-10 19:27:18 +00:00
|
|
|
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals, NodeContext};
|
2021-07-01 03:06:46 +00:00
|
|
|
use crate::dsp::helpers::Rng;
|
2021-06-30 20:15:32 +00:00
|
|
|
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! fa_noise_mode { ($formatter: expr, $v: expr, $denorm_v: expr) => { {
|
|
|
|
let s =
|
|
|
|
match ($v.round() as usize) {
|
|
|
|
0 => "Bipolar",
|
|
|
|
1 => "Unipolar",
|
|
|
|
_ => "?",
|
|
|
|
};
|
|
|
|
write!($formatter, "{}", s)
|
|
|
|
} } }
|
|
|
|
|
|
|
|
/// A simple amplifier
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct Noise {
|
2021-07-01 03:06:46 +00:00
|
|
|
seed: u64,
|
|
|
|
rng: Rng,
|
2021-06-30 20:15:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Noise {
|
2021-07-01 03:06:46 +00:00
|
|
|
pub fn new(nid: &NodeId) -> Self {
|
|
|
|
let mut rng = Rng::new();
|
|
|
|
rng.seed(
|
|
|
|
(0x193a67f4a8a6d769_u64).wrapping_add(
|
|
|
|
0x131415 * (nid.instance() as u64 + 1)));
|
|
|
|
|
2021-06-30 20:15:32 +00:00
|
|
|
Self {
|
2021-07-01 03:06:46 +00:00
|
|
|
seed: nid.instance() as u64,
|
|
|
|
rng,
|
2021-06-30 20:15:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub const atv : &'static str =
|
2021-07-10 20:16:55 +00:00
|
|
|
"Noise atv\n.Attenuverter input, to attenuate or invert \
|
2021-07-01 03:06:46 +00:00
|
|
|
the noise.\nRange: (-1..1)";
|
2021-06-30 20:15:32 +00:00
|
|
|
pub const offs : &'static str =
|
2021-07-01 03:06:46 +00:00
|
|
|
"Noise offs\n.Offset input, that is added to the output \
|
|
|
|
signal after attenuvertig it.\nRange: (-1..1)";
|
2021-06-30 20:15:32 +00:00
|
|
|
pub const mode : &'static str =
|
2021-07-01 03:06:46 +00:00
|
|
|
"Noise mode\nYou can switch between 'Bipolar' noise, which \
|
|
|
|
uses the full range from -1 to 1, or 'Unipolar' noise that \
|
|
|
|
only uses the range from 0 to 1.";
|
2021-06-30 20:15:32 +00:00
|
|
|
pub const sig : &'static str =
|
2021-07-01 03:06:46 +00:00
|
|
|
"Noise sig\nThe noise output.\nRange: (-1..1)";
|
2021-06-30 20:15:32 +00:00
|
|
|
|
|
|
|
pub const DESC : &'static str =
|
2021-07-24 18:30:23 +00:00
|
|
|
r#"Noise Oscillator
|
2021-06-30 20:15:32 +00:00
|
|
|
|
|
|
|
This is a very simple noise oscillator, which can be used for any kind of audio rate noise.
|
|
|
|
And as a source for sample & hold like nodes to generate low frequency modulation.
|
|
|
|
"#;
|
|
|
|
pub const HELP : &'static str =
|
|
|
|
r#"Noise - A Simple Noise Oscillator
|
|
|
|
|
|
|
|
This is a very simple noise oscillator, which can be used for
|
|
|
|
any kind of audio rate noise. And as a source for sample & hold
|
|
|
|
like nodes to generate low frequency modulation.
|
|
|
|
|
|
|
|
The 'atv' attenuverter and 'offs' parameters control the value range
|
|
|
|
of the noise, and the 'mode' allows to switch the oscillator between
|
|
|
|
unipolar and bipolar output.
|
|
|
|
"#;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DspNode for Noise {
|
|
|
|
fn outputs() -> usize { 1 }
|
|
|
|
|
2021-07-01 03:06:46 +00:00
|
|
|
fn set_sample_rate(&mut self, _srate: f32) {
|
2021-06-30 20:15:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn reset(&mut self) {
|
2021-07-01 03:06:46 +00:00
|
|
|
self.rng.seed(
|
|
|
|
(0x193a67f4a8a6d769_u64).wrapping_add(
|
|
|
|
0x131415 * (self.seed + 1)));
|
2021-06-30 20:15:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn process<T: NodeAudioContext>(
|
|
|
|
&mut self, ctx: &mut T, _ectx: &mut NodeExecContext,
|
2021-07-10 19:27:18 +00:00
|
|
|
_nctx: &NodeContext,
|
|
|
|
atoms: &[SAtom], inputs: &[ProcBuf],
|
2021-06-30 20:15:32 +00:00
|
|
|
outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals)
|
|
|
|
{
|
|
|
|
use crate::dsp::{at, out, inp, denorm};
|
|
|
|
|
2021-07-01 03:06:46 +00:00
|
|
|
let mode = at::Noise::mode(atoms);
|
|
|
|
let atv = inp::Noise::atv(inputs);
|
|
|
|
let offs = inp::Noise::offs(inputs);
|
|
|
|
let out = out::Noise::sig(outputs);
|
|
|
|
|
|
|
|
let rng = &mut self.rng;
|
|
|
|
|
|
|
|
if mode.i() == 0 {
|
|
|
|
for frame in 0..ctx.nframes() {
|
|
|
|
let s = (rng.next() * 2.0) - 1.0;
|
|
|
|
let s = s
|
|
|
|
* denorm::Noise::atv(atv, frame)
|
|
|
|
+ denorm::Noise::offs(offs, frame);
|
|
|
|
out.write(frame, s);
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
for frame in 0..ctx.nframes() {
|
|
|
|
let s = rng.next()
|
|
|
|
* denorm::Noise::atv(atv, frame)
|
|
|
|
+ denorm::Noise::offs(offs, frame);
|
|
|
|
out.write(frame, s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let last_frame = ctx.nframes() - 1;
|
|
|
|
ctx_vals[0].set(out.read(last_frame));
|
2021-06-30 20:15:32 +00:00
|
|
|
}
|
|
|
|
}
|