2022-07-25 03:55:54 +00:00
|
|
|
// Copyright (c) 2022 Weird Constructor <weirdconstructor@gmail.com>
|
|
|
|
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
|
|
|
|
// See README.md and COPYING for details.
|
|
|
|
|
|
|
|
//use super::helpers::{sqrt4_to_pow4, TrigSignal, Trigger};
|
2022-07-25 04:15:48 +00:00
|
|
|
use crate::dsp::{DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom};
|
2022-07-25 04:36:07 +00:00
|
|
|
use crate::nodes::SCOPE_SAMPLES;
|
2022-07-25 03:55:54 +00:00
|
|
|
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
2022-07-25 04:36:07 +00:00
|
|
|
use crate::ScopeHandle;
|
|
|
|
use std::sync::Arc;
|
2022-07-25 03:55:54 +00:00
|
|
|
|
|
|
|
/// A simple signal scope
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct Scope {
|
2022-07-25 04:36:07 +00:00
|
|
|
handle: Arc<ScopeHandle>,
|
2022-07-25 03:55:54 +00:00
|
|
|
idx: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Scope {
|
|
|
|
pub fn new(_nid: &NodeId) -> Self {
|
2022-07-25 04:36:07 +00:00
|
|
|
Self { handle: ScopeHandle::new_shared(), idx: 0 }
|
2022-07-25 03:55:54 +00:00
|
|
|
}
|
2022-07-25 04:15:48 +00:00
|
|
|
pub const in1: &'static str = "Scope in1\nSignal input 1.\nRange: (-1..1)\n";
|
|
|
|
pub const in2: &'static str = "Scope in2\nSignal input 2.\nRange: (-1..1)\n";
|
|
|
|
pub const in3: &'static str = "Scope in3\nSignal input 3.\nRange: (-1..1)\n";
|
2022-07-25 03:55:54 +00:00
|
|
|
pub const DESC: &'static str = r#"Signal Oscilloscope Probe
|
|
|
|
|
2022-07-25 04:15:48 +00:00
|
|
|
This is a signal oscilloscope probe node, you can capture up to 3 signals.
|
2022-07-25 03:55:54 +00:00
|
|
|
"#;
|
|
|
|
pub const HELP: &'static str = r#"Scope - Signal Oscilloscope Probe
|
|
|
|
|
2022-07-25 04:15:48 +00:00
|
|
|
You can have up to 8 different scopes in your patch. That means you can in theory
|
|
|
|
record up to 24 signals. The received signal will be forwarded to the GUI and
|
|
|
|
you can inspect the waveform there.
|
2022-07-25 03:55:54 +00:00
|
|
|
"#;
|
|
|
|
|
2022-07-25 04:36:07 +00:00
|
|
|
pub fn set_scope_handle(&mut self, handle: Arc<ScopeHandle>) {
|
|
|
|
self.handle = handle;
|
2022-07-25 03:55:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DspNode for Scope {
|
|
|
|
fn outputs() -> usize {
|
|
|
|
1
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set_sample_rate(&mut self, _srate: f32) {}
|
|
|
|
|
|
|
|
fn reset(&mut self) {}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn process<T: NodeAudioContext>(
|
|
|
|
&mut self,
|
|
|
|
ctx: &mut T,
|
|
|
|
_ectx: &mut NodeExecContext,
|
2022-07-25 04:36:07 +00:00
|
|
|
nctx: &NodeContext,
|
2022-07-25 03:55:54 +00:00
|
|
|
_atoms: &[SAtom],
|
|
|
|
inputs: &[ProcBuf],
|
2022-07-25 04:36:07 +00:00
|
|
|
_outputs: &mut [ProcBuf],
|
2022-07-25 03:55:54 +00:00
|
|
|
ctx_vals: LedPhaseVals,
|
|
|
|
) {
|
2022-07-25 04:36:07 +00:00
|
|
|
use crate::dsp::inp;
|
2022-07-25 03:55:54 +00:00
|
|
|
|
2022-07-25 04:15:48 +00:00
|
|
|
let in1 = inp::Scope::in1(inputs);
|
|
|
|
let in2 = inp::Scope::in2(inputs);
|
|
|
|
let in3 = inp::Scope::in3(inputs);
|
|
|
|
let inputs = [in1, in2, in3];
|
2022-07-25 03:55:54 +00:00
|
|
|
|
2022-07-25 04:36:07 +00:00
|
|
|
self.handle.set_active_from_mask(nctx.in_connected);
|
|
|
|
|
2022-07-25 03:55:54 +00:00
|
|
|
for frame in 0..ctx.nframes() {
|
2022-07-25 04:15:48 +00:00
|
|
|
for (i, input) in inputs.iter().enumerate() {
|
|
|
|
let in_val = input.read(frame);
|
2022-07-25 04:36:07 +00:00
|
|
|
self.handle.write(i, self.idx, in_val);
|
2022-07-25 04:15:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
self.idx = (self.idx + 1) % SCOPE_SAMPLES;
|
2022-07-25 03:55:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let last_frame = ctx.nframes() - 1;
|
2022-07-25 04:15:48 +00:00
|
|
|
ctx_vals[0].set(
|
|
|
|
(in1.read(last_frame) + in2.read(last_frame) + in3.read(last_frame)).clamp(-1.0, 1.0),
|
|
|
|
);
|
2022-07-25 03:55:54 +00:00
|
|
|
}
|
|
|
|
}
|