added missing file and implemented gate output ports to the sequencer
This commit is contained in:
parent
d069c4aafa
commit
1b22ab623a
6 changed files with 406 additions and 141 deletions
|
@ -309,7 +309,13 @@ macro_rules! node_list {
|
||||||
[2 trk3]
|
[2 trk3]
|
||||||
[3 trk4]
|
[3 trk4]
|
||||||
[4 trk5]
|
[4 trk5]
|
||||||
[5 trk6],
|
[5 trk6]
|
||||||
|
[6 gat1]
|
||||||
|
[7 gat2]
|
||||||
|
[8 gat3]
|
||||||
|
[9 gat4]
|
||||||
|
[10 gat5]
|
||||||
|
[11 gat6],
|
||||||
sampl => Sampl UIType::Generic UICategory::Osc
|
sampl => Sampl UIType::Generic UICategory::Osc
|
||||||
(0 freq n_pit d_pit r_id f_def -1.0, 1.0, 440.0)
|
(0 freq n_pit d_pit r_id f_def -1.0, 1.0, 440.0)
|
||||||
(1 trig n_id n_id r_id f_def -1.0, 1.0, 0.0)
|
(1 trig n_id n_id r_id f_def -1.0, 1.0, 0.0)
|
||||||
|
@ -495,7 +501,7 @@ macro_rules! make_node_info_enum {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(&self, f: &mut std::io::Write, v: f32) -> Option<std::io::Result<()>> {
|
pub fn format(&self, f: &mut dyn std::io::Write, v: f32) -> Option<std::io::Result<()>> {
|
||||||
match self.node {
|
match self.node {
|
||||||
NodeId::$v1 => None,
|
NodeId::$v1 => None,
|
||||||
$(NodeId::$variant(_) => {
|
$(NodeId::$variant(_) => {
|
||||||
|
|
97
src/dsp/node_fbwr_fbrd.rs
Normal file
97
src/dsp/node_fbwr_fbrd.rs
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
// Copyright (c) 2021 Weird Constructor <weirdconstructor@gmail.com>
|
||||||
|
// This is a part of HexoDSP. Released under (A)GPLv3 or any later.
|
||||||
|
// See README.md and COPYING for details.
|
||||||
|
|
||||||
|
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
||||||
|
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals};
|
||||||
|
|
||||||
|
/// A simple amplifier
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct FbWr {
|
||||||
|
fb_index: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FbWr {
|
||||||
|
pub fn new(nid: &NodeId) -> Self {
|
||||||
|
Self {
|
||||||
|
fb_index: nid.instance() as u8,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub const inp : &'static str =
|
||||||
|
"FbWr inp\nSignal input\nRange: (-1..1)\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DspNode for FbWr {
|
||||||
|
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,
|
||||||
|
atoms: &[SAtom], _params: &[ProcBuf], inputs: &[ProcBuf],
|
||||||
|
outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals)
|
||||||
|
{
|
||||||
|
use crate::dsp::{inp};
|
||||||
|
|
||||||
|
let inp = inp::FbWr::inp(inputs);
|
||||||
|
|
||||||
|
for frame in 0..ctx.nframes() {
|
||||||
|
ectx.feedback_delay_buffers[self.fb_index as usize]
|
||||||
|
.write(inp.read(frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx_vals[0].set(inp.read(ctx.nframes() - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// A simple amplifier
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct FbRd {
|
||||||
|
fb_index: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FbRd {
|
||||||
|
pub fn new(nid: &NodeId) -> Self {
|
||||||
|
Self {
|
||||||
|
fb_index: nid.instance() as u8,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub const atv : &'static str =
|
||||||
|
"FbRd atv\nAttenuate or invert input.\n\
|
||||||
|
Use this to adjust the feedback amount.\nRange: (0..1)\n";
|
||||||
|
pub const sig : &'static str =
|
||||||
|
"FbRd sig\nFeedback signal output.\nRange: (-1..1)\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DspNode for FbRd {
|
||||||
|
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,
|
||||||
|
atoms: &[SAtom], _params: &[ProcBuf], inputs: &[ProcBuf],
|
||||||
|
outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals)
|
||||||
|
{
|
||||||
|
use crate::dsp::{out, inp, denorm};
|
||||||
|
|
||||||
|
let atv = inp::FbRd::atv(inputs);
|
||||||
|
let sig = out::FbRd::sig(outputs);
|
||||||
|
|
||||||
|
let mut last_val = 0.0;
|
||||||
|
for frame in 0..ctx.nframes() {
|
||||||
|
last_val =
|
||||||
|
ectx.feedback_delay_buffers[self.fb_index as usize]
|
||||||
|
.read();
|
||||||
|
last_val *= denorm::FbRd::atv(atv, frame);
|
||||||
|
sig.write(frame, last_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx_vals[0].set(last_val);
|
||||||
|
}
|
||||||
|
}
|
|
@ -67,6 +67,19 @@ impl TSeq {
|
||||||
"TSeq trk5\nTrack 5 signal output\nRange: (-1..1)\n";
|
"TSeq trk5\nTrack 5 signal output\nRange: (-1..1)\n";
|
||||||
pub const trk6 : &'static str =
|
pub const trk6 : &'static str =
|
||||||
"TSeq trk6\nTrack 6 signal output\nRange: (-1..1)\n";
|
"TSeq trk6\nTrack 6 signal output\nRange: (-1..1)\n";
|
||||||
|
|
||||||
|
pub const gat1 : &'static str =
|
||||||
|
"TSeq gat1\nTrack 1 gate output\nRange: (-1..1)\n";
|
||||||
|
pub const gat2 : &'static str =
|
||||||
|
"TSeq gat2\nTrack 2 gate output\nRange: (-1..1)\n";
|
||||||
|
pub const gat3 : &'static str =
|
||||||
|
"TSeq gat3\nTrack 3 gate output\nRange: (-1..1)\n";
|
||||||
|
pub const gat4 : &'static str =
|
||||||
|
"TSeq gat4\nTrack 4 gate output\nRange: (-1..1)\n";
|
||||||
|
pub const gat5 : &'static str =
|
||||||
|
"TSeq gat5\nTrack 5 gate output\nRange: (-1..1)\n";
|
||||||
|
pub const gat6 : &'static str =
|
||||||
|
"TSeq gat6\nTrack 6 gate output\nRange: (-1..1)\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DspNode for TSeq {
|
impl DspNode for TSeq {
|
||||||
|
@ -136,41 +149,62 @@ impl DspNode for TSeq {
|
||||||
|
|
||||||
let mut col_out : [f32; MAX_BLOCK_SIZE] =
|
let mut col_out : [f32; MAX_BLOCK_SIZE] =
|
||||||
[0.0; MAX_BLOCK_SIZE];
|
[0.0; MAX_BLOCK_SIZE];
|
||||||
|
let mut col_out_gate : [f32; MAX_BLOCK_SIZE] =
|
||||||
|
[0.0; MAX_BLOCK_SIZE];
|
||||||
let col_out_slice = &mut col_out[ 0..ctx.nframes()];
|
let col_out_slice = &mut col_out[ 0..ctx.nframes()];
|
||||||
|
let col_out_gate_slice = &mut col_out_gate[0..ctx.nframes()];
|
||||||
let phase_out_slice = &phase_out[ 0..ctx.nframes()];
|
let phase_out_slice = &phase_out[ 0..ctx.nframes()];
|
||||||
|
|
||||||
let out_t1 = out::TSeq::trk1(outputs);
|
let out_t1 = out::TSeq::trk1(outputs);
|
||||||
backend.get_col_at_phase(
|
backend.get_col_at_phase(
|
||||||
0, phase_out_slice, col_out_slice);
|
0, phase_out_slice, col_out_slice, col_out_gate_slice);
|
||||||
out_t1.write_from(col_out_slice);
|
out_t1.write_from(col_out_slice);
|
||||||
|
|
||||||
|
let out_g1 = out::TSeq::gat1(outputs);
|
||||||
|
out_g1.write_from(col_out_gate_slice);
|
||||||
|
|
||||||
ctx_vals[0].set(col_out_slice[col_out_slice.len() - 1]);
|
ctx_vals[0].set(col_out_slice[col_out_slice.len() - 1]);
|
||||||
|
|
||||||
let out_t2 = out::TSeq::trk2(outputs);
|
let out_t2 = out::TSeq::trk2(outputs);
|
||||||
backend.get_col_at_phase(
|
backend.get_col_at_phase(
|
||||||
1, phase_out_slice, col_out_slice);
|
1, phase_out_slice, col_out_slice, col_out_gate_slice);
|
||||||
out_t2.write_from(col_out_slice);
|
out_t2.write_from(col_out_slice);
|
||||||
|
|
||||||
|
let out_g2 = out::TSeq::gat2(outputs);
|
||||||
|
out_g2.write_from(col_out_gate_slice);
|
||||||
|
|
||||||
let out_t3 = out::TSeq::trk3(outputs);
|
let out_t3 = out::TSeq::trk3(outputs);
|
||||||
backend.get_col_at_phase(
|
backend.get_col_at_phase(
|
||||||
2, phase_out_slice, col_out_slice);
|
2, phase_out_slice, col_out_slice, col_out_gate_slice);
|
||||||
out_t3.write_from(col_out_slice);
|
out_t3.write_from(col_out_slice);
|
||||||
|
|
||||||
|
let out_g3 = out::TSeq::gat3(outputs);
|
||||||
|
out_g3.write_from(col_out_gate_slice);
|
||||||
|
|
||||||
let out_t4 = out::TSeq::trk4(outputs);
|
let out_t4 = out::TSeq::trk4(outputs);
|
||||||
backend.get_col_at_phase(
|
backend.get_col_at_phase(
|
||||||
3, phase_out_slice, col_out_slice);
|
3, phase_out_slice, col_out_slice, col_out_gate_slice);
|
||||||
out_t4.write_from(col_out_slice);
|
out_t4.write_from(col_out_slice);
|
||||||
|
|
||||||
|
let out_g4 = out::TSeq::gat4(outputs);
|
||||||
|
out_g4.write_from(col_out_gate_slice);
|
||||||
|
|
||||||
let out_t5 = out::TSeq::trk5(outputs);
|
let out_t5 = out::TSeq::trk5(outputs);
|
||||||
backend.get_col_at_phase(
|
backend.get_col_at_phase(
|
||||||
4, phase_out_slice, col_out_slice);
|
4, phase_out_slice, col_out_slice, col_out_gate_slice);
|
||||||
out_t5.write_from(col_out_slice);
|
out_t5.write_from(col_out_slice);
|
||||||
|
|
||||||
|
let out_g5 = out::TSeq::gat5(outputs);
|
||||||
|
out_g5.write_from(col_out_gate_slice);
|
||||||
|
|
||||||
let out_t6 = out::TSeq::trk6(outputs);
|
let out_t6 = out::TSeq::trk6(outputs);
|
||||||
backend.get_col_at_phase(
|
backend.get_col_at_phase(
|
||||||
5, phase_out_slice, col_out_slice);
|
5, phase_out_slice, col_out_slice, col_out_gate_slice);
|
||||||
out_t6.write_from(col_out_slice);
|
out_t6.write_from(col_out_slice);
|
||||||
|
|
||||||
|
let out_g6 = out::TSeq::gat6(outputs);
|
||||||
|
out_g6.write_from(col_out_gate_slice);
|
||||||
|
|
||||||
ctx_vals[1].set(phase_out_slice[phase_out_slice.len() - 1]);
|
ctx_vals[1].set(phase_out_slice[phase_out_slice.len() - 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ pub enum PatternUpdateMsg {
|
||||||
col: usize,
|
col: usize,
|
||||||
col_type: PatternColType,
|
col_type: PatternColType,
|
||||||
pattern_len: usize,
|
pattern_len: usize,
|
||||||
data: [f32; MAX_PATTERN_LEN]
|
data: [(f32, u8); MAX_PATTERN_LEN]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,17 +143,21 @@ impl TrackerBackend {
|
||||||
|
|
||||||
pub fn pattern_len(&self) -> usize { self.seq.rows() }
|
pub fn pattern_len(&self) -> usize { self.seq.rows() }
|
||||||
|
|
||||||
pub fn get_col_at_phase(&mut self, col: usize, phase: &[f32], out: &mut [f32]) {
|
pub fn get_col_at_phase(
|
||||||
|
&mut self, col: usize, phase: &[f32],
|
||||||
|
out: &mut [f32], out_gate: &mut [f32])
|
||||||
|
{
|
||||||
if self.seq.rows() == 0 {
|
if self.seq.rows() == 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.col_types[col] {
|
match self.col_types[col] {
|
||||||
PatternColType::Note | PatternColType::Step => {
|
PatternColType::Note | PatternColType::Step =>
|
||||||
self.seq.col_get_at_phase(col, phase, out)
|
self.seq.col_get_at_phase( col, phase, out, out_gate),
|
||||||
},
|
PatternColType::Value =>
|
||||||
PatternColType::Value => self.seq.col_interpolate_at_phase(col, phase, out),
|
self.seq.col_interpolate_at_phase(col, phase, out, out_gate),
|
||||||
PatternColType::Gate => self.seq.col_gate_at_phase(col, phase, out),
|
PatternColType::Gate =>
|
||||||
|
self.seq.col_gate_at_phase( col, phase, out, out_gate),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,11 +191,17 @@ mod tests {
|
||||||
while backend.check_updates() { }
|
while backend.check_updates() { }
|
||||||
|
|
||||||
let mut out = [0.0; 16];
|
let mut out = [0.0; 16];
|
||||||
|
let mut out_gate = [0.0; 16];
|
||||||
|
|
||||||
|
backend.get_col_at_phase(
|
||||||
|
0, &[0.2, 0.5, 0.99], &mut out[..], &mut out_gate[..]);
|
||||||
|
|
||||||
backend.get_col_at_phase(0, &[0.2, 0.5, 0.99], &mut out[..]);
|
|
||||||
assert_float_eq!(out[0], 1.0);
|
assert_float_eq!(out[0], 1.0);
|
||||||
assert_float_eq!(out[1], 0.46666666);
|
assert_float_eq!(out[1], 0.46666666);
|
||||||
assert_float_eq!(out[2], 0.0);
|
assert_float_eq!(out[2], 0.0);
|
||||||
|
assert_float_eq!(out_gate[0], 0.0);
|
||||||
|
assert_float_eq!(out_gate[1], 1.0);
|
||||||
|
assert_float_eq!(out_gate[2], 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -209,11 +219,16 @@ mod tests {
|
||||||
while backend.check_updates() { }
|
while backend.check_updates() { }
|
||||||
|
|
||||||
let mut out = [0.0; 16];
|
let mut out = [0.0; 16];
|
||||||
|
let mut out_gate = [0.0; 16];
|
||||||
|
|
||||||
backend.get_col_at_phase(0, &[0.2, 0.5, 0.999999], &mut out[..]);
|
backend.get_col_at_phase(
|
||||||
|
0, &[0.2, 0.5, 0.999999], &mut out[..], &mut out_gate[..]);
|
||||||
assert_float_eq!(out[0], 0.83238);
|
assert_float_eq!(out[0], 0.83238);
|
||||||
assert_float_eq!(out[1], 0.46666666);
|
assert_float_eq!(out[1], 0.46666666);
|
||||||
assert_float_eq!(out[2], 0.0);
|
assert_float_eq!(out[2], 0.0);
|
||||||
|
assert_float_eq!(out_gate[0], 0.0);
|
||||||
|
assert_float_eq!(out_gate[1], 0.0);
|
||||||
|
assert_float_eq!(out_gate[2], 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -232,6 +247,7 @@ mod tests {
|
||||||
while backend.check_updates() { }
|
while backend.check_updates() { }
|
||||||
|
|
||||||
let mut out = [0.0; 64];
|
let mut out = [0.0; 64];
|
||||||
|
let mut out_gate = [0.0; 64];
|
||||||
|
|
||||||
let mut phase = [0.0; 64];
|
let mut phase = [0.0; 64];
|
||||||
for (i, p) in phase.iter_mut().enumerate() {
|
for (i, p) in phase.iter_mut().enumerate() {
|
||||||
|
@ -239,16 +255,23 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
//d// println!("----");
|
//d// println!("----");
|
||||||
backend.get_col_at_phase(0, &phase[..], &mut out[..]);
|
backend.get_col_at_phase(
|
||||||
|
0, &phase[..], &mut out[..], &mut out_gate[..]);
|
||||||
//d// println!("out: {:?}", &out[16..32]);
|
//d// println!("out: {:?}", &out[16..32]);
|
||||||
|
|
||||||
assert_eq!(out[0..8], [1.0; 8]);
|
assert_eq!(out[0..8], [1.0; 8]);
|
||||||
assert_eq!(out[8..16], [0.0; 8]);
|
assert_eq!(out[8..16], [0.0; 8]);
|
||||||
assert_eq!(out[16..32],[0.0; 16]);
|
assert_eq!(out[16..32],[0.0; 16]);
|
||||||
|
assert_eq!(out_gate[0..8], [1.0; 8]);
|
||||||
|
assert_eq!(out_gate[8..16], [1.0; 8]);
|
||||||
|
assert_eq!(out_gate[16..32],[0.0; 16]);
|
||||||
|
|
||||||
assert_float_eq!(out[32], 1.0);
|
assert_float_eq!(out[32], 1.0);
|
||||||
assert_eq!(out[33..48],[0.0; 15]);
|
assert_eq!(out[33..48],[0.0; 15]);
|
||||||
|
assert_float_eq!(out_gate[32], 1.0);
|
||||||
|
assert_eq!(out_gate[33..48],[1.0; 15]);
|
||||||
|
|
||||||
assert_eq!(out[48..64],[1.0; 16]);
|
assert_eq!(out[48..64],[1.0; 16]);
|
||||||
|
assert_eq!(out_gate[48..64],[1.0; 16]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use crate::matrix_repr::PatternRepr;
|
||||||
pub struct PatternData {
|
pub struct PatternData {
|
||||||
col_types: [PatternColType; MAX_COLS],
|
col_types: [PatternColType; MAX_COLS],
|
||||||
data: Vec<Vec<Option<u16>>>,
|
data: Vec<Vec<Option<u16>>>,
|
||||||
out_data: Vec<[f32; MAX_PATTERN_LEN]>,
|
out_data: Vec<[(f32, u8); MAX_PATTERN_LEN]>,
|
||||||
strings: Vec<Vec<Option<String>>>,
|
strings: Vec<Vec<Option<String>>>,
|
||||||
cursor: (usize, usize),
|
cursor: (usize, usize),
|
||||||
rows: usize,
|
rows: usize,
|
||||||
|
@ -24,7 +24,7 @@ impl PatternData {
|
||||||
Self {
|
Self {
|
||||||
col_types: [PatternColType::Value; MAX_COLS],
|
col_types: [PatternColType::Value; MAX_COLS],
|
||||||
data: vec![vec![None; MAX_COLS]; MAX_PATTERN_LEN],
|
data: vec![vec![None; MAX_COLS]; MAX_PATTERN_LEN],
|
||||||
out_data: vec![[0.0; MAX_PATTERN_LEN]; MAX_COLS],
|
out_data: vec![[(0.0, 0); MAX_PATTERN_LEN]; MAX_COLS],
|
||||||
strings: vec![vec![None; MAX_COLS]; MAX_PATTERN_LEN],
|
strings: vec![vec![None; MAX_COLS]; MAX_PATTERN_LEN],
|
||||||
cursor: (2, 2),
|
cursor: (2, 2),
|
||||||
edit_step: 4,
|
edit_step: 4,
|
||||||
|
@ -106,7 +106,7 @@ impl PatternData {
|
||||||
self.cursor = repr.cursor;
|
self.cursor = repr.cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_out_data(&self) -> &[[f32; MAX_PATTERN_LEN]] {
|
pub fn get_out_data(&self) -> &[[(f32, u8); MAX_PATTERN_LEN]] {
|
||||||
&self.out_data
|
&self.out_data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,8 +160,8 @@ impl PatternData {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(end_value) = cur_value {
|
if let Some(end_value) = cur_value {
|
||||||
out_col[start_idx] = start_value;
|
out_col[start_idx] = (start_value, 0);
|
||||||
out_col[end_idx] = end_value;
|
out_col[end_idx] = (end_value, 1);
|
||||||
|
|
||||||
let delta_rows = end_idx - start_idx;
|
let delta_rows = end_idx - start_idx;
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ impl PatternData {
|
||||||
(idx - start_idx) as f32
|
(idx - start_idx) as f32
|
||||||
/ (delta_rows as f32);
|
/ (delta_rows as f32);
|
||||||
out_col[idx] =
|
out_col[idx] =
|
||||||
start_value * (1.0 - x) + end_value * x;
|
(start_value * (1.0 - x) + end_value * x, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,23 +189,33 @@ impl PatternData {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
PatternColType::Note => {
|
PatternColType::Note => {
|
||||||
let mut cur_value = 0.0;
|
let mut cur_value = (0.0, 0);
|
||||||
|
|
||||||
for row in 0..self.rows {
|
for row in 0..self.rows {
|
||||||
if let Some(new_value) = self.data[row][col] {
|
if let Some(new_value) = self.data[row][col] {
|
||||||
cur_value =
|
cur_value = (
|
||||||
((new_value as i32 - 69) as f32 * 0.1) / 12.0;
|
((new_value as i32 - 69) as f32 * 0.1) / 12.0,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
cur_value.1 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
out_col[row] = cur_value.clamp(-1.0, 1.0);
|
out_col[row] =
|
||||||
|
(cur_value.0.clamp(-1.0, 1.0), cur_value.1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
PatternColType::Step => {
|
PatternColType::Step => {
|
||||||
let mut cur_value = 0.0;
|
let mut cur_value = (0.0, 0);
|
||||||
|
|
||||||
for row in 0..self.rows {
|
for row in 0..self.rows {
|
||||||
if let Some(new_value) = self.data[row][col] {
|
if let Some(new_value) = self.data[row][col] {
|
||||||
cur_value = ((new_value & 0xFFF) as f32) / (0xFFF as f32);
|
cur_value = (
|
||||||
|
((new_value & 0xFFF) as f32) / (0xFFF as f32),
|
||||||
|
1
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
cur_value.1 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
out_col[row] = cur_value;
|
out_col[row] = cur_value;
|
||||||
|
@ -215,9 +225,9 @@ impl PatternData {
|
||||||
for row in 0..self.rows {
|
for row in 0..self.rows {
|
||||||
out_col[row] =
|
out_col[row] =
|
||||||
if let Some(new_value) = self.data[row][col] {
|
if let Some(new_value) = self.data[row][col] {
|
||||||
f32::from_bits(new_value as u32)
|
(f32::from_bits(new_value as u32), 1)
|
||||||
} else {
|
} else {
|
||||||
f32::from_bits(0xF000 as u32)
|
(f32::from_bits(0xF000 as u32), 0)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -394,8 +404,8 @@ mod tests {
|
||||||
let inc = 1.0 / 2.0;
|
let inc = 1.0 / 2.0;
|
||||||
for i in 1..2 {
|
for i in 1..2 {
|
||||||
let delta =
|
let delta =
|
||||||
out_data[col][i]
|
out_data[col][i].0
|
||||||
- out_data[col][i - 1];
|
- out_data[col][i - 1].0;
|
||||||
assert_float_eq!(delta, inc);
|
assert_float_eq!(delta, inc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -416,8 +426,8 @@ mod tests {
|
||||||
let inc = 1.0 / 3.0;
|
let inc = 1.0 / 3.0;
|
||||||
for i in 1..3 {
|
for i in 1..3 {
|
||||||
let delta =
|
let delta =
|
||||||
out_data[col][i]
|
out_data[col][i].0
|
||||||
- out_data[col][i - 1];
|
- out_data[col][i - 1].0;
|
||||||
assert_float_eq!(delta, inc);
|
assert_float_eq!(delta, inc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -440,8 +450,8 @@ mod tests {
|
||||||
//d// println!("out: {:?}", &out_data[col][0..16]);
|
//d// println!("out: {:?}", &out_data[col][0..16]);
|
||||||
for i in 1..16 {
|
for i in 1..16 {
|
||||||
let delta =
|
let delta =
|
||||||
out_data[col][i]
|
out_data[col][i].0
|
||||||
- out_data[col][i - 1];
|
- out_data[col][i - 1].0;
|
||||||
assert_float_eq!(delta, inc);
|
assert_float_eq!(delta, inc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -462,8 +472,8 @@ mod tests {
|
||||||
|
|
||||||
for i in 1..16 {
|
for i in 1..16 {
|
||||||
let delta =
|
let delta =
|
||||||
out_data[col][i]
|
out_data[col][i].0
|
||||||
- out_data[col][i - 1];
|
- out_data[col][i - 1].0;
|
||||||
assert_float_eq!(delta.abs(), inc);
|
assert_float_eq!(delta.abs(), inc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -484,8 +494,8 @@ mod tests {
|
||||||
//d// println!("out: {:?}", &out_data[col][0..16]);
|
//d// println!("out: {:?}", &out_data[col][0..16]);
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
assert_float_eq!(
|
assert_float_eq!(
|
||||||
out_data[col][i],
|
out_data[col][i].0,
|
||||||
out_data[col][15 - i]);
|
out_data[col][15 - i].0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -505,8 +515,8 @@ mod tests {
|
||||||
//d// println!("out: {:?}", &out_data[col][0..16]);
|
//d// println!("out: {:?}", &out_data[col][0..16]);
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
assert_float_eq!(
|
assert_float_eq!(
|
||||||
out_data[col][i],
|
out_data[col][i].0,
|
||||||
out_data[col][15 - i]);
|
out_data[col][15 - i].0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -528,8 +538,8 @@ mod tests {
|
||||||
//d// println!("out: {:?}", &out_data[col][0..16]);
|
//d// println!("out: {:?}", &out_data[col][0..16]);
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
assert_float_eq!(
|
assert_float_eq!(
|
||||||
out_data[col][i],
|
out_data[col][i].0,
|
||||||
out_data[col][15 - i]);
|
out_data[col][15 - i].0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -550,13 +560,13 @@ mod tests {
|
||||||
|
|
||||||
//d// println!("out: {:?}", &out_data[col][0..16]);
|
//d// println!("out: {:?}", &out_data[col][0..16]);
|
||||||
|
|
||||||
assert_float_eq!(0.5, out_data[col][6]);
|
assert_float_eq!(0.5, out_data[col][6].0);
|
||||||
assert_float_eq!(0.5, out_data[col][9]);
|
assert_float_eq!(0.5, out_data[col][9].0);
|
||||||
|
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
assert_float_eq!(
|
assert_float_eq!(
|
||||||
out_data[col][i],
|
out_data[col][i].0,
|
||||||
out_data[col][15 - i]);
|
out_data[col][15 - i].0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -575,14 +585,14 @@ mod tests {
|
||||||
pats.sync_out_data(col);
|
pats.sync_out_data(col);
|
||||||
|
|
||||||
let out_data = pats.get_out_data();
|
let out_data = pats.get_out_data();
|
||||||
assert_float_eq!(out_data[col][0], 0.0);
|
assert_float_eq!(out_data[col][0].0, 0.0);
|
||||||
assert_float_eq!(out_data[col][4], 0.26959708);
|
assert_float_eq!(out_data[col][4].0, 0.26959708);
|
||||||
assert_float_eq!(out_data[col][5], 0.0);
|
assert_float_eq!(out_data[col][5].0, 0.0);
|
||||||
assert_float_eq!(out_data[col][7], 0.4998779);
|
assert_float_eq!(out_data[col][7].0, 0.4998779);
|
||||||
assert_float_eq!(out_data[col][8], 0.4998779);
|
assert_float_eq!(out_data[col][8].0, 0.4998779);
|
||||||
assert_float_eq!(out_data[col][9], 0.50012213);
|
assert_float_eq!(out_data[col][9].0, 0.50012213);
|
||||||
assert_float_eq!(out_data[col][10], 1.0);
|
assert_float_eq!(out_data[col][10].0, 1.0);
|
||||||
assert_float_eq!(out_data[col][15], 1.0);
|
assert_float_eq!(out_data[col][15].0, 1.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,13 +609,13 @@ mod tests {
|
||||||
pats.sync_out_data(col);
|
pats.sync_out_data(col);
|
||||||
|
|
||||||
let out_data = pats.get_out_data();
|
let out_data = pats.get_out_data();
|
||||||
assert_float_eq!(out_data[col][0], 0.0);
|
assert_float_eq!(out_data[col][0].0, 0.0);
|
||||||
assert_float_eq!(out_data[col][4], 0.0);
|
assert_float_eq!(out_data[col][4].0, 0.0);
|
||||||
assert_float_eq!(out_data[col][5], -0.575);
|
assert_float_eq!(out_data[col][5].0, -0.575);
|
||||||
assert_float_eq!(out_data[col][7], -0.1);
|
assert_float_eq!(out_data[col][7].0, -0.1);
|
||||||
assert_float_eq!(out_data[col][9], -0.1);
|
assert_float_eq!(out_data[col][9].0, -0.1);
|
||||||
assert_float_eq!(out_data[col][10], 0.1);
|
assert_float_eq!(out_data[col][10].0, 0.1);
|
||||||
assert_float_eq!(out_data[col][15], 0.1);
|
assert_float_eq!(out_data[col][15].0, 0.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::dsp::helpers::SplitMix64;
|
||||||
|
|
||||||
pub struct PatternSequencer {
|
pub struct PatternSequencer {
|
||||||
rows: usize,
|
rows: usize,
|
||||||
data: Vec<Vec<f32>>,
|
data: Vec<Vec<(f32, u8)>>,
|
||||||
rng: SplitMix64,
|
rng: SplitMix64,
|
||||||
rand_vals: [(usize, f64); MAX_COLS],
|
rand_vals: [(usize, f64); MAX_COLS],
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ impl PatternSequencer {
|
||||||
pub fn new_default_seed(rows: usize) -> Self {
|
pub fn new_default_seed(rows: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
rows,
|
rows,
|
||||||
data: vec![vec![0.0; MAX_PATTERN_LEN]; MAX_COLS],
|
data: vec![vec![(0.0, 0); MAX_PATTERN_LEN]; MAX_COLS],
|
||||||
rng: SplitMix64::new(0x91234),
|
rng: SplitMix64::new(0x91234),
|
||||||
rand_vals: [(99999, 0.0); MAX_COLS],
|
rand_vals: [(99999, 0.0); MAX_COLS],
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ impl PatternSequencer {
|
||||||
};
|
};
|
||||||
Self {
|
Self {
|
||||||
rows,
|
rows,
|
||||||
data: vec![vec![0.0; MAX_PATTERN_LEN]; MAX_COLS],
|
data: vec![vec![(0.0, 0); MAX_PATTERN_LEN]; MAX_COLS],
|
||||||
rng: SplitMix64::new_from_i64(seed),
|
rng: SplitMix64::new_from_i64(seed),
|
||||||
rand_vals: [(99999, 0.0); MAX_COLS],
|
rand_vals: [(99999, 0.0); MAX_COLS],
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ impl PatternSequencer {
|
||||||
|
|
||||||
pub fn rows(&self) -> usize { self.rows }
|
pub fn rows(&self) -> usize { self.rows }
|
||||||
|
|
||||||
pub fn set_col(&mut self, col: usize, col_data: &[f32]) {
|
pub fn set_col(&mut self, col: usize, col_data: &[(f32, u8)]) {
|
||||||
for (out_cell, in_cell) in
|
for (out_cell, in_cell) in
|
||||||
self.data[col]
|
self.data[col]
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
|
@ -76,21 +76,26 @@ impl PatternSequencer {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn col_interpolate_at_phase(
|
pub fn col_interpolate_at_phase(
|
||||||
&self, col: usize, phase: &[f32], out: &mut [f32])
|
&self, col: usize, phase: &[f32], out: &mut [f32], out_gate: &mut [f32])
|
||||||
{
|
{
|
||||||
let col = &self.data[col][..];
|
let col = &self.data[col][..];
|
||||||
|
|
||||||
let last_row_idx : f32 = (self.rows as f32) - 0.000001;
|
let last_row_idx : f32 = (self.rows as f32) - 0.000001;
|
||||||
let rows = self.rows;
|
let rows = self.rows;
|
||||||
|
|
||||||
for (phase, out) in phase.iter().zip(out.iter_mut()) {
|
for ((phase, out), out_gate) in
|
||||||
|
phase.iter()
|
||||||
|
.zip(out.iter_mut())
|
||||||
|
.zip(out_gate.iter_mut())
|
||||||
|
{
|
||||||
let row_phase = phase * last_row_idx;
|
let row_phase = phase * last_row_idx;
|
||||||
let phase_frac = row_phase.fract();
|
let phase_frac = row_phase.fract();
|
||||||
let line = row_phase.floor() as usize % rows;
|
let line = row_phase.floor() as usize % rows;
|
||||||
let prev_line = if line == 0 { self.rows - 1 } else { line - 1 };
|
let prev_line = if line == 0 { self.rows - 1 } else { line - 1 };
|
||||||
|
|
||||||
let prev = col[prev_line];
|
let prev = col[prev_line].0;
|
||||||
let next = col[line];
|
let next = col[line].0;
|
||||||
|
let gate = col[line].1;
|
||||||
|
|
||||||
// println!("INTERP: {}={:9.7}, {}={:9.7} | {:9.7}",
|
// println!("INTERP: {}={:9.7}, {}={:9.7} | {:9.7}",
|
||||||
// prev_line, prev,
|
// prev_line, prev,
|
||||||
|
@ -98,39 +103,51 @@ impl PatternSequencer {
|
||||||
// phase_frac);
|
// phase_frac);
|
||||||
|
|
||||||
*out = prev * (1.0 - phase_frac) + next * phase_frac;
|
*out = prev * (1.0 - phase_frac) + next * phase_frac;
|
||||||
|
*out_gate = gate as f32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn col_get_at_phase(
|
pub fn col_get_at_phase(
|
||||||
&self, col: usize, phase: &[f32], out: &mut [f32])
|
&self, col: usize, phase: &[f32], out: &mut [f32], out_gate: &mut [f32])
|
||||||
{
|
{
|
||||||
let col = &self.data[col][..];
|
let col = &self.data[col][..];
|
||||||
|
|
||||||
let last_row_idx : f32 = (self.rows as f32) - 0.000001;
|
let last_row_idx : f32 = (self.rows as f32) - 0.000001;
|
||||||
let rows = self.rows;
|
let rows = self.rows;
|
||||||
|
|
||||||
for (phase, out) in phase.iter().zip(out.iter_mut()) {
|
for ((phase, out), out_gate) in
|
||||||
|
phase.iter()
|
||||||
|
.zip(out.iter_mut())
|
||||||
|
.zip(out_gate.iter_mut())
|
||||||
|
{
|
||||||
let row_phase = phase * last_row_idx;
|
let row_phase = phase * last_row_idx;
|
||||||
let line = row_phase.floor() as usize % rows;
|
let line = row_phase.floor() as usize % rows;
|
||||||
|
|
||||||
*out = col[line];
|
let (val, gate) = col[line];
|
||||||
|
*out = val;
|
||||||
|
*out_gate = gate as f32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn col_gate_at_phase(
|
pub fn col_gate_at_phase(
|
||||||
&mut self, col_idx: usize, phase: &[f32], out: &mut [f32])
|
&mut self, col_idx: usize, phase: &[f32], out: &mut [f32], out_gate: &mut [f32])
|
||||||
{
|
{
|
||||||
let col = &self.data[col_idx][..];
|
let col = &self.data[col_idx][..];
|
||||||
|
|
||||||
let last_row_idx : f32 = (self.rows as f32) - 0.000001;
|
let last_row_idx : f32 = (self.rows as f32) - 0.000001;
|
||||||
let rows = self.rows;
|
let rows = self.rows;
|
||||||
|
|
||||||
for (phase, out) in phase.iter().zip(out.iter_mut()) {
|
for ((phase, out), out_gate) in
|
||||||
|
phase.iter()
|
||||||
|
.zip(out.iter_mut())
|
||||||
|
.zip(out_gate.iter_mut())
|
||||||
|
{
|
||||||
let row_phase = phase.clamp(0.0, 1.0) * last_row_idx;
|
let row_phase = phase.clamp(0.0, 1.0) * last_row_idx;
|
||||||
let line = row_phase.floor() as usize % rows;
|
let line = row_phase.floor() as usize % rows;
|
||||||
let phase_frac = row_phase.fract();
|
let phase_frac = row_phase.fract();
|
||||||
|
|
||||||
let gate : u32 = col[line].to_bits();
|
let gate : u32 = col[line].0.to_bits();
|
||||||
|
let ggate : u8 = col[line].1;
|
||||||
|
|
||||||
// pulse_width:
|
// pulse_width:
|
||||||
// 0xF - Gate is on for full row
|
// 0xF - Gate is on for full row
|
||||||
|
@ -164,16 +181,21 @@ impl PatternSequencer {
|
||||||
|
|
||||||
if rand_val > (FRACT_16THS[probability as usize] as f64) {
|
if rand_val > (FRACT_16THS[probability as usize] as f64) {
|
||||||
*out = 0.0;
|
*out = 0.0;
|
||||||
|
if (gate & 0xF000) > 0 {
|
||||||
|
*out_gate = 0.0;
|
||||||
|
} else {
|
||||||
|
*out_gate = ggate as f32;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("GATE: {:0X}", gate);
|
|
||||||
|
|
||||||
if (gate & 0xF000) > 0 {
|
if (gate & 0xF000) > 0 {
|
||||||
*out = 0.0;
|
*out = 0.0;
|
||||||
|
*out_gate = 0.0;
|
||||||
} else {
|
} else {
|
||||||
*out = if sub_frac <= pulse_width { 1.0 } else { 0.0 };
|
*out = if sub_frac <= pulse_width { 1.0 } else { 0.0 };
|
||||||
|
*out_gate = ggate as f32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,74 +218,109 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn check_seq_interpolate_1() {
|
fn check_seq_interpolate_1() {
|
||||||
let mut ps = PatternSequencer::new(2);
|
let mut ps = PatternSequencer::new(2);
|
||||||
ps.set_col(0, &[0.0, 1.0]);
|
ps.set_col(0, &[(0.0, 0), (1.0, 1)]);
|
||||||
|
|
||||||
let mut out = [0.0; 6];
|
let mut out = [0.0; 6];
|
||||||
ps.col_interpolate_at_phase(0, &[0.0, 0.1, 0.50, 0.51, 0.9, 0.99999], &mut out[..]);
|
let mut out_gate = [0.0; 6];
|
||||||
|
ps.col_interpolate_at_phase(
|
||||||
|
0, &[0.0, 0.1, 0.50, 0.51, 0.9, 0.99999],
|
||||||
|
&mut out[..], &mut out_gate[..]);
|
||||||
assert_float_eq!(out[0], 1.0);
|
assert_float_eq!(out[0], 1.0);
|
||||||
assert_float_eq!(out[1], 0.8);
|
assert_float_eq!(out[1], 0.8);
|
||||||
assert_float_eq!(out[2], 0.0);
|
assert_float_eq!(out[2], 0.0);
|
||||||
assert_float_eq!(out[3], 0.02);
|
assert_float_eq!(out[3], 0.02);
|
||||||
assert_float_eq!(out[4], 0.8);
|
assert_float_eq!(out[4], 0.8);
|
||||||
assert_float_eq!(out[5], 0.99999);
|
assert_float_eq!(out[5], 0.99999);
|
||||||
|
|
||||||
|
assert_float_eq!(out_gate[0], 0.0);
|
||||||
|
assert_float_eq!(out_gate[1], 0.0);
|
||||||
|
assert_float_eq!(out_gate[2], 0.0);
|
||||||
|
assert_float_eq!(out_gate[3], 1.0);
|
||||||
|
assert_float_eq!(out_gate[4], 1.0);
|
||||||
|
assert_float_eq!(out_gate[5], 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_seq_interpolate_buffer_end() {
|
fn check_seq_interpolate_buffer_end() {
|
||||||
let mut ps = PatternSequencer::new(256);
|
let mut ps = PatternSequencer::new(256);
|
||||||
ps.set_col(0, &[f32::from_bits(0xF000); 256]);
|
ps.set_col(0, &[(f32::from_bits(0xF000), 0); 256]);
|
||||||
|
|
||||||
let mut out = [0.0; 1];
|
let mut out = [0.0; 1];
|
||||||
ps.col_gate_at_phase(0, &[0.9999999999], &mut out[..]);
|
let mut out_gate = [0.0; 1];
|
||||||
|
ps.col_gate_at_phase(
|
||||||
|
0, &[0.9999999999], &mut out[..], &mut out_gate[..]);
|
||||||
assert_float_eq!(out[0], 0.0);
|
assert_float_eq!(out[0], 0.0);
|
||||||
|
assert_float_eq!(out_gate[0], 0.0);
|
||||||
|
|
||||||
let mut ps = PatternSequencer::new(256);
|
let mut ps = PatternSequencer::new(256);
|
||||||
ps.set_col(0, &[0.0; 256]);
|
ps.set_col(0, &[(0.0, 0); 256]);
|
||||||
|
|
||||||
ps.col_get_at_phase(0, &[0.9999999999], &mut out[..]);
|
ps.col_get_at_phase(
|
||||||
|
0, &[0.9999999999], &mut out[..], &mut out_gate[..]);
|
||||||
assert_float_eq!(out[0], 0.0);
|
assert_float_eq!(out[0], 0.0);
|
||||||
|
assert_float_eq!(out_gate[0], 0.0);
|
||||||
|
|
||||||
ps.col_interpolate_at_phase(0, &[0.9999999999], &mut out[..]);
|
ps.col_interpolate_at_phase(
|
||||||
|
0, &[0.9999999999], &mut out[..], &mut out_gate[..]);
|
||||||
assert_float_eq!(out[0], 0.0);
|
assert_float_eq!(out[0], 0.0);
|
||||||
|
assert_float_eq!(out_gate[0], 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_seq_step_1() {
|
fn check_seq_step_1() {
|
||||||
let mut ps = PatternSequencer::new(2);
|
let mut ps = PatternSequencer::new(2);
|
||||||
ps.set_col(0, &[0.0, 1.0]);
|
ps.set_col(0, &[(0.0, 0), (1.0, 1)]);
|
||||||
|
|
||||||
let mut out = [0.0; 3];
|
let mut out = [0.0; 3];
|
||||||
ps.col_get_at_phase(0, &[0.1, 0.51, 0.9], &mut out[..]);
|
let mut out_gate = [0.0; 3];
|
||||||
|
ps.col_get_at_phase(
|
||||||
|
0, &[0.1, 0.51, 0.9], &mut out[..], &mut out_gate[..]);
|
||||||
assert_float_eq!(out[0], 0.0);
|
assert_float_eq!(out[0], 0.0);
|
||||||
assert_float_eq!(out[1], 1.0);
|
assert_float_eq!(out[1], 1.0);
|
||||||
assert_float_eq!(out[2], 1.0);
|
assert_float_eq!(out[2], 1.0);
|
||||||
|
assert_float_eq!(out_gate[0], 0.0);
|
||||||
|
assert_float_eq!(out_gate[1], 1.0);
|
||||||
|
assert_float_eq!(out_gate[2], 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_seq_step_2() {
|
fn check_seq_step_2() {
|
||||||
let mut ps = PatternSequencer::new(3);
|
let mut ps = PatternSequencer::new(3);
|
||||||
ps.set_col(0, &[0.0, 0.3, 1.0]);
|
ps.set_col(0, &[(0.0, 0), (0.3, 1), (1.0, 1)]);
|
||||||
|
|
||||||
let mut out = [0.0; 6];
|
let mut out = [0.0; 6];
|
||||||
ps.col_get_at_phase(0, &[0.1, 0.5, 0.51, 0.6, 0.9, 0.99], &mut out[..]);
|
let mut out_gate = [0.0; 6];
|
||||||
|
ps.col_get_at_phase(
|
||||||
|
0, &[0.1, 0.5, 0.51, 0.6, 0.9, 0.99],
|
||||||
|
&mut out[..], &mut out_gate[..]);
|
||||||
assert_float_eq!(out[0], 0.0);
|
assert_float_eq!(out[0], 0.0);
|
||||||
assert_float_eq!(out[1], 0.3);
|
assert_float_eq!(out[1], 0.3);
|
||||||
assert_float_eq!(out[2], 0.3);
|
assert_float_eq!(out[2], 0.3);
|
||||||
assert_float_eq!(out[3], 0.3);
|
assert_float_eq!(out[3], 0.3);
|
||||||
assert_float_eq!(out[4], 1.0);
|
assert_float_eq!(out[4], 1.0);
|
||||||
assert_float_eq!(out[5], 1.0);
|
assert_float_eq!(out[5], 1.0);
|
||||||
|
|
||||||
|
assert_float_eq!(out_gate[0], 0.0);
|
||||||
|
assert_float_eq!(out_gate[1], 1.0);
|
||||||
|
assert_float_eq!(out_gate[2], 1.0);
|
||||||
|
assert_float_eq!(out_gate[3], 1.0);
|
||||||
|
assert_float_eq!(out_gate[4], 1.0);
|
||||||
|
assert_float_eq!(out_gate[5], 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_seq_gate_1() {
|
fn check_seq_gate_1() {
|
||||||
let mut ps = PatternSequencer::new(2);
|
let mut ps = PatternSequencer::new(2);
|
||||||
ps.set_col(0, &[
|
ps.set_col(0, &[
|
||||||
f32::from_bits(0x0FFF),
|
(f32::from_bits(0x0FFF), 1),
|
||||||
f32::from_bits(0xF000),
|
(f32::from_bits(0xF000), 0),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let mut out = [0.0; 6];
|
let mut out = [0.0; 6];
|
||||||
ps.col_gate_at_phase(0, &[0.1, 0.5, 0.5001, 0.6, 0.9, 0.99], &mut out[..]);
|
let mut out_gate = [0.0; 6];
|
||||||
|
ps.col_gate_at_phase(
|
||||||
|
0, &[0.1, 0.5, 0.5001, 0.6, 0.9, 0.99],
|
||||||
|
&mut out[..], &mut out_gate[..]);
|
||||||
//d// println!("out: {:?}", out);
|
//d// println!("out: {:?}", out);
|
||||||
|
|
||||||
assert_float_eq!(out[0], 1.0);
|
assert_float_eq!(out[0], 1.0);
|
||||||
|
@ -272,6 +329,13 @@ mod tests {
|
||||||
assert_float_eq!(out[3], 0.0);
|
assert_float_eq!(out[3], 0.0);
|
||||||
assert_float_eq!(out[4], 0.0);
|
assert_float_eq!(out[4], 0.0);
|
||||||
assert_float_eq!(out[5], 0.0);
|
assert_float_eq!(out[5], 0.0);
|
||||||
|
|
||||||
|
assert_float_eq!(out_gate[0], 1.0);
|
||||||
|
assert_float_eq!(out_gate[1], 1.0);
|
||||||
|
assert_float_eq!(out_gate[2], 0.0);
|
||||||
|
assert_float_eq!(out_gate[3], 0.0);
|
||||||
|
assert_float_eq!(out_gate[4], 0.0);
|
||||||
|
assert_float_eq!(out_gate[5], 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn count_high(slice: &[f32]) -> usize {
|
fn count_high(slice: &[f32]) -> usize {
|
||||||
|
@ -298,9 +362,9 @@ mod tests {
|
||||||
fn check_seq_gate_2() {
|
fn check_seq_gate_2() {
|
||||||
let mut ps = PatternSequencer::new(3);
|
let mut ps = PatternSequencer::new(3);
|
||||||
ps.set_col(0, &[
|
ps.set_col(0, &[
|
||||||
f32::from_bits(0x0FF0),
|
(f32::from_bits(0x0FF0), 1),
|
||||||
f32::from_bits(0x0FF7),
|
(f32::from_bits(0x0FF7), 0),
|
||||||
f32::from_bits(0x0FFF),
|
(f32::from_bits(0x0FFF), 1),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let mut phase = vec![0.0; 96];
|
let mut phase = vec![0.0; 96];
|
||||||
|
@ -314,25 +378,33 @@ mod tests {
|
||||||
//d// println!("PHASE: {:?}", phase);
|
//d// println!("PHASE: {:?}", phase);
|
||||||
|
|
||||||
let mut out = [0.0; 96];
|
let mut out = [0.0; 96];
|
||||||
ps.col_gate_at_phase(0, &phase[..], &mut out[..]);
|
let mut out_gate = [0.0; 96];
|
||||||
|
ps.col_gate_at_phase(
|
||||||
|
0, &phase[..], &mut out[..], &mut out_gate[..]);
|
||||||
//d// println!("out: {:?}", &out[0..32]);
|
//d// println!("out: {:?}", &out[0..32]);
|
||||||
|
|
||||||
assert_eq!(count_high(&out[0..32]), 2);
|
assert_eq!(count_high(&out[0..32]), 2);
|
||||||
assert_eq!(count_high(&out[32..64]), 16);
|
assert_eq!(count_high(&out[32..64]), 16);
|
||||||
assert_eq!(count_high(&out[64..96]), 32);
|
assert_eq!(count_high(&out[64..96]), 32);
|
||||||
|
assert_eq!(count_high(&out_gate[0..32]), 32);
|
||||||
|
assert_eq!(count_high(&out_gate[32..64]), 0);
|
||||||
|
assert_eq!(count_high(&out_gate[64..96]), 32);
|
||||||
|
|
||||||
assert_eq!(count_up(&out[0..32]), 1);
|
assert_eq!(count_up(&out[0..32]), 1);
|
||||||
assert_eq!(count_up(&out[32..64]), 1);
|
assert_eq!(count_up(&out[32..64]), 1);
|
||||||
assert_eq!(count_up(&out[64..96]), 1);
|
assert_eq!(count_up(&out[64..96]), 1);
|
||||||
|
assert_eq!(count_up(&out_gate[0..32]), 1);
|
||||||
|
assert_eq!(count_up(&out_gate[32..64]), 0);
|
||||||
|
assert_eq!(count_up(&out_gate[64..96]), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_seq_gate_div_1() {
|
fn check_seq_gate_div_1() {
|
||||||
let mut ps = PatternSequencer::new(3);
|
let mut ps = PatternSequencer::new(3);
|
||||||
ps.set_col(0, &[
|
ps.set_col(0, &[
|
||||||
f32::from_bits(0x0F80),
|
(f32::from_bits(0x0F80), 1),
|
||||||
f32::from_bits(0x0F87),
|
(f32::from_bits(0x0F87), 0),
|
||||||
f32::from_bits(0x0F8F),
|
(f32::from_bits(0x0F8F), 1),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let mut phase = vec![0.0; 3 * 64];
|
let mut phase = vec![0.0; 3 * 64];
|
||||||
|
@ -346,25 +418,33 @@ mod tests {
|
||||||
//d// println!("PHASE: {:?}", phase);
|
//d// println!("PHASE: {:?}", phase);
|
||||||
|
|
||||||
let mut out = [0.0; 3 * 64];
|
let mut out = [0.0; 3 * 64];
|
||||||
ps.col_gate_at_phase(0, &phase[..], &mut out[..]);
|
let mut out_gate = [0.0; 3 * 64];
|
||||||
|
ps.col_gate_at_phase(
|
||||||
|
0, &phase[..], &mut out[..], &mut out_gate[..]);
|
||||||
|
|
||||||
assert_eq!(count_high(&out[0..64]), 8);
|
assert_eq!(count_high(&out[0..64]), 8);
|
||||||
assert_eq!(count_up( &out[0..64]), 8);
|
assert_eq!(count_up( &out[0..64]), 8);
|
||||||
|
assert_eq!(count_high(&out_gate[0..64]), 64);
|
||||||
|
assert_eq!(count_up( &out_gate[0..64]), 1);
|
||||||
|
|
||||||
assert_eq!(count_high(&out[64..128]), 32);
|
assert_eq!(count_high(&out[64..128]), 32);
|
||||||
assert_eq!(count_up( &out[64..128]), 8);
|
assert_eq!(count_up( &out[64..128]), 8);
|
||||||
|
assert_eq!(count_high(&out_gate[64..128]), 0);
|
||||||
|
assert_eq!(count_up( &out_gate[64..128]), 0);
|
||||||
|
|
||||||
assert_eq!(count_high(&out[128..192]), 64);
|
assert_eq!(count_high(&out[128..192]), 64);
|
||||||
assert_eq!(count_up( &out[128..192]), 1);
|
assert_eq!(count_up( &out[128..192]), 1);
|
||||||
|
assert_eq!(count_high(&out_gate[128..192]), 64);
|
||||||
|
assert_eq!(count_up( &out_gate[128..192]), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_seq_gate_div_2() {
|
fn check_seq_gate_div_2() {
|
||||||
let mut ps = PatternSequencer::new(3);
|
let mut ps = PatternSequencer::new(3);
|
||||||
ps.set_col(0, &[
|
ps.set_col(0, &[
|
||||||
f32::from_bits(0x0F00),
|
(f32::from_bits(0x0F00), 1),
|
||||||
f32::from_bits(0x0F07),
|
(f32::from_bits(0x0F07), 0),
|
||||||
f32::from_bits(0x0F0F),
|
(f32::from_bits(0x0F0F), 1),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let mut phase = vec![0.0; 6 * 64];
|
let mut phase = vec![0.0; 6 * 64];
|
||||||
|
@ -378,25 +458,32 @@ mod tests {
|
||||||
//d// println!("PHASE: {:?}", phase);
|
//d// println!("PHASE: {:?}", phase);
|
||||||
|
|
||||||
let mut out = [0.0; 6 * 64];
|
let mut out = [0.0; 6 * 64];
|
||||||
ps.col_gate_at_phase(0, &phase[..], &mut out[..]);
|
let mut out_gate = [0.0; 6 * 64];
|
||||||
|
ps.col_gate_at_phase(0, &phase[..], &mut out[..], &mut out_gate[..]);
|
||||||
|
|
||||||
assert_eq!(count_high(&out[0..128]), 16);
|
assert_eq!(count_high(&out[0..128]), 16);
|
||||||
assert_eq!(count_up( &out[0..128]), 16);
|
assert_eq!(count_up( &out[0..128]), 16);
|
||||||
|
assert_eq!(count_high(&out_gate[0..128]), 128);
|
||||||
|
assert_eq!(count_up( &out_gate[0..128]), 1);
|
||||||
|
|
||||||
assert_eq!(count_high(&out[128..256]), 64);
|
assert_eq!(count_high(&out[128..256]), 64);
|
||||||
assert_eq!(count_up( &out[128..256]), 16);
|
assert_eq!(count_up( &out[128..256]), 16);
|
||||||
|
assert_eq!(count_high(&out_gate[128..256]), 0);
|
||||||
|
assert_eq!(count_up( &out_gate[128..256]), 0);
|
||||||
|
|
||||||
assert_eq!(count_high(&out[256..384]), 128);
|
assert_eq!(count_high(&out[256..384]), 128);
|
||||||
assert_eq!(count_up( &out[256..384]), 1);
|
assert_eq!(count_up( &out[256..384]), 1);
|
||||||
|
assert_eq!(count_high(&out_gate[256..384]), 128);
|
||||||
|
assert_eq!(count_up( &out_gate[256..384]), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_seq_gate_div_3() {
|
fn check_seq_gate_div_3() {
|
||||||
let mut ps = PatternSequencer::new(3);
|
let mut ps = PatternSequencer::new(3);
|
||||||
ps.set_col(0, &[
|
ps.set_col(0, &[
|
||||||
f32::from_bits(0x0FE0),
|
(f32::from_bits(0x0FE0), 1),
|
||||||
f32::from_bits(0x0FE7),
|
(f32::from_bits(0x0FE7), 0),
|
||||||
f32::from_bits(0x0FEF),
|
(f32::from_bits(0x0FEF), 1),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let mut phase = vec![0.0; 6 * 64];
|
let mut phase = vec![0.0; 6 * 64];
|
||||||
|
@ -410,25 +497,32 @@ mod tests {
|
||||||
//d// println!("PHASE: {:?}", phase);
|
//d// println!("PHASE: {:?}", phase);
|
||||||
|
|
||||||
let mut out = [0.0; 6 * 64];
|
let mut out = [0.0; 6 * 64];
|
||||||
ps.col_gate_at_phase(0, &phase[..], &mut out[..]);
|
let mut out_gate = [0.0; 6 * 64];
|
||||||
|
ps.col_gate_at_phase(0, &phase[..], &mut out[..], &mut out_gate[..]);
|
||||||
|
|
||||||
assert_eq!(count_high(&out[0..128]), 8);
|
assert_eq!(count_high(&out[0..128]), 8);
|
||||||
assert_eq!(count_up( &out[0..128]), 2);
|
assert_eq!(count_up( &out[0..128]), 2);
|
||||||
|
assert_eq!(count_high(&out_gate[0..128]), 128);
|
||||||
|
assert_eq!(count_up( &out_gate[0..128]), 1);
|
||||||
|
|
||||||
assert_eq!(count_high(&out[128..256]), 64);
|
assert_eq!(count_high(&out[128..256]), 64);
|
||||||
assert_eq!(count_up( &out[128..256]), 2);
|
assert_eq!(count_up( &out[128..256]), 2);
|
||||||
|
assert_eq!(count_high(&out_gate[128..256]), 0);
|
||||||
|
assert_eq!(count_up( &out_gate[128..256]), 0);
|
||||||
|
|
||||||
assert_eq!(count_high(&out[256..384]), 128);
|
assert_eq!(count_high(&out[256..384]), 128);
|
||||||
assert_eq!(count_up( &out[256..384]), 1);
|
assert_eq!(count_up( &out[256..384]), 1);
|
||||||
|
assert_eq!(count_high(&out_gate[256..384]), 128);
|
||||||
|
assert_eq!(count_up( &out_gate[256..384]), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_probability_test_for(prob: u32) -> (usize, usize) {
|
fn run_probability_test_for(prob: u32) -> (usize, usize) {
|
||||||
let rows = 100;
|
let rows = 100;
|
||||||
|
|
||||||
let mut ps = PatternSequencer::new_default_seed(rows);
|
let mut ps = PatternSequencer::new_default_seed(rows);
|
||||||
let mut coldata = vec![0.0; rows];
|
let mut coldata = vec![(0.0, 0); rows];
|
||||||
for i in 0..coldata.len() {
|
for i in 0..coldata.len() {
|
||||||
coldata[i] = f32::from_bits(0x00FF | prob);
|
coldata[i] = (f32::from_bits(0x00FF | prob), 1);
|
||||||
}
|
}
|
||||||
ps.set_col(0, &coldata[..]);
|
ps.set_col(0, &coldata[..]);
|
||||||
|
|
||||||
|
@ -442,7 +536,8 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut out = vec![0.0; samples];
|
let mut out = vec![0.0; samples];
|
||||||
ps.col_gate_at_phase(0, &phase[..], &mut out[..]);
|
let mut out_gate = vec![0.0; samples];
|
||||||
|
ps.col_gate_at_phase(0, &phase[..], &mut out[..], &mut out_gate[..]);
|
||||||
|
|
||||||
(count_high(&out[..]), count_up(&out[..]))
|
(count_high(&out[..]), count_up(&out[..]))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue