diff --git a/src/dsp/mod.rs b/src/dsp/mod.rs index d7aa25c..f091965 100644 --- a/src/dsp/mod.rs +++ b/src/dsp/mod.rs @@ -511,6 +511,8 @@ mod node_formfm; #[allow(non_upper_case_globals)] mod node_map; #[allow(non_upper_case_globals)] +mod node_midip; +#[allow(non_upper_case_globals)] mod node_mix3; #[allow(non_upper_case_globals)] mod node_mux9; @@ -519,8 +521,6 @@ mod node_noise; #[allow(non_upper_case_globals)] mod node_out; #[allow(non_upper_case_globals)] -mod node_midip; -#[allow(non_upper_case_globals)] mod node_pverb; #[allow(non_upper_case_globals)] mod node_quant; @@ -569,10 +569,10 @@ use crate::fa_cqnt_omax; use crate::fa_cqnt_omin; use crate::fa_delay_mode; use crate::fa_map_clip; +use crate::fa_midip_chan; use crate::fa_mux9_in_cnt; use crate::fa_noise_mode; use crate::fa_out_mono; -use crate::fa_midip_chan; use crate::fa_quant; use crate::fa_sampl_dclick; use crate::fa_sampl_dir; @@ -600,11 +600,11 @@ use node_fbwr_fbrd::FbRd; use node_fbwr_fbrd::FbWr; use node_formfm::FormFM; use node_map::Map; +use node_midip::MidiP; use node_mix3::Mix3; use node_mux9::Mux9; use node_noise::Noise; use node_out::Out; -use node_midip::MidiP; use node_pverb::PVerb; use node_quant::Quant; use node_rndwk::RndWk; diff --git a/src/dsp/node_midip.rs b/src/dsp/node_midip.rs index 5fc69cc..f6ee163 100644 --- a/src/dsp/node_midip.rs +++ b/src/dsp/node_midip.rs @@ -92,9 +92,8 @@ impl DspNode for MidiP { for frame in 0..ctx.nframes() { let chan = ectx.note_buffer.get_chan_at(0, frame as u8); - let note = (chan.note as f32 - 57.0) / 120.0; + let note = (chan.note as f32 - 69.0) / 120.0; freq.write(frame, note); - println!("FRAME: {}, gate={}, freq={}", frame, chan.gate, chan.note); if chan.gate > 0 { // insert a single sample of silence, for retriggering @@ -107,6 +106,7 @@ impl DspNode for MidiP { } else { gate.write(frame, 0.0); } + self.prev_gate = chan.gate; vel.write(frame, chan.vel as f32); } diff --git a/src/nodes/mod.rs b/src/nodes/mod.rs index d5de649..a85f3f5 100644 --- a/src/nodes/mod.rs +++ b/src/nodes/mod.rs @@ -31,7 +31,7 @@ pub use node_conf::*; pub use node_exec::*; pub use node_graph_ordering::NodeGraphOrdering; pub use node_prog::*; -pub use note_buffer::{NoteBuffer, NoteChannelState, HxTimedEvent, HxMidiEvent, EventWindowing}; +pub use note_buffer::{EventWindowing, HxMidiEvent, HxTimedEvent, NoteBuffer, NoteChannelState}; use crate::dsp::{Node, SAtom}; pub use crate::monitor::MinMaxMonitorSamples; diff --git a/src/nodes/node_exec.rs b/src/nodes/node_exec.rs index 014dd08..2a54166 100644 --- a/src/nodes/node_exec.rs +++ b/src/nodes/node_exec.rs @@ -4,8 +4,8 @@ use super::NoteBuffer; use super::{ - DropMsg, GraphMessage, NodeProg, FB_DELAY_TIME_US, MAX_ALLOCATED_NODES, MAX_FB_DELAY_SIZE, - MAX_SMOOTHERS, UNUSED_MONITOR_IDX, HxTimedEvent, EventWindowing, HxMidiEvent, + DropMsg, EventWindowing, GraphMessage, HxMidiEvent, HxTimedEvent, NodeProg, FB_DELAY_TIME_US, + MAX_ALLOCATED_NODES, MAX_FB_DELAY_SIZE, MAX_SMOOTHERS, UNUSED_MONITOR_IDX, }; use crate::dsp::{Node, NodeContext, NodeId, MAX_BLOCK_SIZE}; use crate::monitor::{MonitorBackend, MON_SIG_CNT}; @@ -521,7 +521,12 @@ impl NodeExecutor { /// /// You can use it's source as reference for your own audio /// DSP thread processing function. - pub fn test_run(&mut self, seconds: f32, realtime: bool, mut events: Vec) -> (Vec, Vec) { + pub fn test_run( + &mut self, + seconds: f32, + realtime: bool, + mut events: Vec, + ) -> (Vec, Vec) { const SAMPLE_RATE: f32 = 44100.0; self.set_sample_rate(SAMPLE_RATE); self.process_graph_updates(); @@ -552,10 +557,8 @@ impl NodeExecutor { } ev_win.feed(events.remove(0)); - println!("FEED {}", offs); } - println!("CHECK {}", offs); if let Some((timing, event)) = ev_win.next_event_in_range(offs + cur_nframes) { buf.step_to(timing); match event { @@ -567,7 +570,6 @@ impl NodeExecutor { buf.note_off(channel, note); } } - } else { break; } diff --git a/src/nodes/note_buffer.rs b/src/nodes/note_buffer.rs index 084e8f9..f52a52e 100644 --- a/src/nodes/note_buffer.rs +++ b/src/nodes/note_buffer.rs @@ -13,23 +13,17 @@ pub struct HxTimedEvent { impl HxTimedEvent { pub fn note_on(timing: usize, channel: u8, note: u8, vel: f32) -> Self { - Self { - timing, - kind: HxMidiEvent::NoteOn { channel, note, vel } - } + Self { timing, kind: HxMidiEvent::NoteOn { channel, note, vel } } } pub fn note_off(timing: usize, channel: u8, note: u8) -> Self { - Self { - timing, - kind: HxMidiEvent::NoteOff { channel, note } - } + Self { timing, kind: HxMidiEvent::NoteOff { channel, note } } } } #[derive(Debug, Clone, Copy)] pub enum HxMidiEvent { - NoteOn { channel: u8, note: u8, vel: f32 }, + NoteOn { channel: u8, note: u8, vel: f32 }, NoteOff { channel: u8, note: u8 }, } @@ -90,7 +84,6 @@ impl NoteBuffer { #[inline] pub fn note_on(&mut self, channel: u8, note: u8) { let mut chan = &mut self.interleaved_chans[(self.buf_idx * 16) + (channel as usize % 16)]; - println!("NOTE ON {}, GATE={}", note, chan.gate); chan.gate = chan.gate % 2 + 1; chan.note = note; } @@ -120,9 +113,7 @@ pub struct EventWindowing { impl EventWindowing { pub fn new() -> Self { - Self { - event: None, - } + Self { event: None } } #[inline] @@ -149,7 +140,6 @@ impl EventWindowing { } } - #[cfg(test)] mod tests { use super::*; diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 3999b39..13f6da5 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -5,9 +5,9 @@ pub use hexodsp::dsp::*; pub use hexodsp::matrix::*; pub use hexodsp::nodes::new_node_engine; +pub use hexodsp::nodes::{HxMidiEvent, HxTimedEvent}; pub use hexodsp::MatrixCellChain; pub use hexodsp::NodeExecutor; -pub use hexodsp::nodes::{HxTimedEvent, HxMidiEvent}; use hound; diff --git a/tests/node_midip.rs b/tests/node_midip.rs index e5b7822..a9c2daa 100644 --- a/tests/node_midip.rs +++ b/tests/node_midip.rs @@ -10,21 +10,32 @@ fn check_node_midip_gate_inserts() { let (node_conf, mut node_exec) = new_node_engine(); let mut matrix = Matrix::new(node_conf, 3, 3); + // Create a DSP matrix with a "MidiP" node and an Out node: let mut chain = MatrixCellChain::new(CellDir::B); chain.node_out("midip", "gate").node_inp("out", "ch1").place(&mut matrix, 0, 0).unwrap(); matrix.sync().unwrap(); - let (ch1, _) = node_exec.test_run(0.005, false, vec![ - HxTimedEvent::note_on(5, 0, 69, 1.0), - HxTimedEvent::note_on(10, 0, 68, 1.0), - HxTimedEvent::note_on(130, 0, 57, 1.0), - ]); + // Test run for 5ms with 3 Note On events at sample positions + // 5, 10 and 130 in this block of samples: + let (ch1, _) = node_exec.test_run( + 0.005, + false, + vec![ + HxTimedEvent::note_on(5, 0, 69, 1.0), + HxTimedEvent::note_on(10, 0, 68, 1.0), + HxTimedEvent::note_on(130, 0, 57, 1.0), + ], + ); + // Collect the signal changes (raising edges): let changes = collect_signal_changes(&ch1[..], 0); - assert_eq!(changes, vec![ - (5, 100), - (11, 100), - (131, 100), - ]); + assert_eq!( + changes, + vec![ + (5, 100), // First note triggers right + (11, 100), // Second note needs to shortly pause the gate, which has 1 sample delay + (131, 100), // Third note also shortly pauses one sample later. + ] + ); }