Work on the gate length mode for MidiP

This commit is contained in:
Weird Constructor 2022-08-16 03:52:45 +02:00
parent 5be2c93c45
commit 3b4e8a36f5
2 changed files with 80 additions and 3 deletions

View file

@ -2,9 +2,9 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later. // This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details. // See README.md and COPYING for details.
use crate::dsp::{at, inp, out_idx, DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom}; use crate::dsp::{at, inp, denorm, out_idx, DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom};
use crate::nodes::{HxMidiEvent, MidiEventPointer, NodeAudioContext, NodeExecContext}; use crate::nodes::{HxMidiEvent, MidiEventPointer, NodeAudioContext, NodeExecContext};
use synfx_dsp::TrigSignal; use synfx_dsp::{GateSignal, TrigSignal};
#[macro_export] #[macro_export]
macro_rules! fa_midip_chan { macro_rules! fa_midip_chan {
@ -34,11 +34,19 @@ pub struct MidiP {
cur_gate: u8, cur_gate: u8,
cur_vel: f32, cur_vel: f32,
trig_sig: TrigSignal, trig_sig: TrigSignal,
gate_sig: GateSignal,
} }
impl MidiP { impl MidiP {
pub fn new(_nid: &NodeId) -> Self { pub fn new(_nid: &NodeId) -> Self {
Self { next_gate: 0, cur_note: 0, cur_gate: 0, cur_vel: 0.0, trig_sig: TrigSignal::new() } Self {
next_gate: 0,
cur_note: 0,
cur_gate: 0,
cur_vel: 0.0,
trig_sig: TrigSignal::new(),
gate_sig: GateSignal::new(),
}
} }
pub const chan: &'static str = "MidiP chan\nMIDI Channel 0 to 15\n"; pub const chan: &'static str = "MidiP chan\nMIDI Channel 0 to 15\n";
@ -91,9 +99,11 @@ impl DspNode for MidiP {
fn set_sample_rate(&mut self, srate: f32) { fn set_sample_rate(&mut self, srate: f32) {
self.trig_sig.set_sample_rate(srate); self.trig_sig.set_sample_rate(srate);
self.gate_sig.set_sample_rate(srate);
} }
fn reset(&mut self) { fn reset(&mut self) {
self.trig_sig.reset(); self.trig_sig.reset();
self.gate_sig.reset();
} }
#[inline] #[inline]
@ -108,6 +118,7 @@ impl DspNode for MidiP {
ctx_vals: LedPhaseVals, ctx_vals: LedPhaseVals,
) { ) {
let det = inp::MidiP::det(inputs); let det = inp::MidiP::det(inputs);
let glen = inp::MidiP::glen(inputs);
let chan = at::MidiP::chan(atoms); let chan = at::MidiP::chan(atoms);
let gmode = at::MidiP::gmode(atoms); let gmode = at::MidiP::gmode(atoms);
let out_i = out_idx::MidiP::gate(); let out_i = out_idx::MidiP::gate();
@ -124,6 +135,8 @@ impl DspNode for MidiP {
let gmode = gmode.i(); let gmode = gmode.i();
for frame in 0..ctx.nframes() { for frame in 0..ctx.nframes() {
let gate_len = denorm::MidiP::glen(glen, frame);
if self.next_gate > 0 { if self.next_gate > 0 {
self.cur_gate = 1; self.cur_gate = 1;
} else if self.next_gate < 0 { } else if self.next_gate < 0 {
@ -144,11 +157,14 @@ impl DspNode for MidiP {
} else { } else {
self.cur_gate = 1; self.cur_gate = 1;
} }
println!("NOTE ON");
self.trig_sig.trigger(); self.trig_sig.trigger();
self.gate_sig.trigger();
self.cur_note = note; self.cur_note = note;
self.cur_vel = vel; self.cur_vel = vel;
} }
HxMidiEvent::NoteOff { channel, note } => { HxMidiEvent::NoteOff { channel, note } => {
println!("NOTE OFF");
if channel != midip_channel { if channel != midip_channel {
continue; continue;
} }
@ -165,6 +181,14 @@ impl DspNode for MidiP {
1 => { 1 => {
gate.write(frame, self.trig_sig.next()); gate.write(frame, self.trig_sig.next());
} }
2 => {
println!("GOGOGO {} {}", gate_len, self.next_gate);
if self.next_gate > 0 {
gate.write(frame, 0.0);
} else {
gate.write(frame, self.gate_sig.next(gate_len));
}
}
_ => { _ => {
gate.write(frame, if self.cur_gate > 0 { 1.0 } else { 0.0 }); gate.write(frame, if self.cur_gate > 0 { 1.0 } else { 0.0 });
} }

View file

@ -189,3 +189,56 @@ fn check_node_midip_trigger_test() {
// As expected, now end of note at 106: // As expected, now end of note at 106:
assert_eq!(changes, vec![(100, 100), (106, -100)]); assert_eq!(changes, vec![(100, 100), (106, -100)]);
} }
#[test]
fn check_node_midip_gate_test() {
let (node_conf, mut node_exec) = new_node_engine();
let mut matrix = Matrix::new(node_conf, 3, 3);
let mut chain = MatrixCellChain::new(CellDir::B);
chain
.node_out("midip", "gate")
.set_denorm("det", 0.1)
.set_atom("gmode", SAtom::setting(2))
.set_denorm("glen", 1.0)
.node_inp("out", "ch1")
.place(&mut matrix, 0, 0)
.unwrap();
matrix.sync().unwrap();
let (ch1, _) = node_exec.test_run(
0.015,
false,
&[HxTimedEvent::note_on(100, 0, 69, 1.0), HxTimedEvent::note_off(105, 0, 69)],
);
let changes = collect_signal_changes_both_edges(&ch1[..], 1);
assert_eq!(changes, vec![(100, 100), (145, -100)]);
// Check double trigger:
let (ch1, _) = node_exec.test_run(
0.015,
false,
&[
HxTimedEvent::note_on(100, 0, 69, 1.0),
HxTimedEvent::note_off(105, 0, 69),
HxTimedEvent::note_on(120, 0, 69, 1.0),
],
);
let changes = collect_signal_changes_both_edges(&ch1[..], 1);
assert_eq!(changes, vec![(100, 100), (145, -100)]);
// // Now test without the trigger signal:
// node_pset_s(&mut matrix, "midip", 0, "gmode", 0);
//
// let (ch1, _) = node_exec.test_run(
// 0.015,
// false,
// &[HxTimedEvent::note_on(100, 0, 69, 1.0), HxTimedEvent::note_off(105, 0, 69)],
// );
//
// let changes = collect_signal_changes_both_edges(&ch1[..], 1);
// // As expected, now end of note at 106:
// assert_eq!(changes, vec![(100, 100), (106, -100)]);
}