Refactored the quantizer to it's own struct
This commit is contained in:
parent
46de4b442d
commit
a631240e64
3 changed files with 117 additions and 57 deletions
|
@ -2134,6 +2134,111 @@ impl<F: Flt> TriSawLFO<F> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Quantizer {
|
||||||
|
/// All keys, containing the min/max octave!
|
||||||
|
keys: Vec<f32>,
|
||||||
|
/// Only the used keys with their pitches from the UI
|
||||||
|
used_keys: [f32; 12],
|
||||||
|
/// A value combination of the arguments to `update_keys`.
|
||||||
|
input_params: u64,
|
||||||
|
/// The number of used keys from the mask.
|
||||||
|
mask_key_count: u16,
|
||||||
|
/// The last key for the pitch that was returned by `process`.
|
||||||
|
last_key: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
const QUANT_TUNE_TO_A4 : f32 = (9.0 / 12.0) * 0.1;
|
||||||
|
|
||||||
|
impl Quantizer {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
keys: vec![0.0; 12 * 10],
|
||||||
|
used_keys: [0.0; 12],
|
||||||
|
mask_key_count: 0,
|
||||||
|
input_params: 0,
|
||||||
|
last_key: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn last_key_pitch(&self) -> f32 {
|
||||||
|
self.used_keys[
|
||||||
|
self.last_key as usize
|
||||||
|
% (self.mask_key_count as usize)]
|
||||||
|
+ QUANT_TUNE_TO_A4
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn has_no_keys(&self) -> bool {
|
||||||
|
self.keys.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn update_keys(&mut self, mask: i64, min_oct: i64, max_oct: i64) {
|
||||||
|
let inp_params =
|
||||||
|
(mask as u64)
|
||||||
|
| ((min_oct as u64) << 8)
|
||||||
|
| ((max_oct as u64) << 16);
|
||||||
|
|
||||||
|
if self.input_params == inp_params {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.input_params = inp_params;
|
||||||
|
|
||||||
|
let mut mask_count = 0;
|
||||||
|
|
||||||
|
for i in 0..9 {
|
||||||
|
if mask & (0x1 << i) > 0 {
|
||||||
|
self.used_keys[mask_count] = ((i as f32 / 12.0) * 0.1) - QUANT_TUNE_TO_A4;
|
||||||
|
mask_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 9..12 {
|
||||||
|
let key_pitch_idx = (i + 9 + 12) % 12;
|
||||||
|
if mask & (0x1 << i) > 0 {
|
||||||
|
self.used_keys[mask_count] = (i as f32 / 12.0) * 0.1 - QUANT_TUNE_TO_A4;
|
||||||
|
mask_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.keys.clear();
|
||||||
|
|
||||||
|
let min_oct = min_oct as usize;
|
||||||
|
for o in 0..min_oct {
|
||||||
|
let o = min_oct - o;
|
||||||
|
|
||||||
|
for i in 0..mask_count {
|
||||||
|
self.keys.push(self.used_keys[i] - (o as f32) * 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..mask_count {
|
||||||
|
self.keys.push(self.used_keys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
let max_oct = max_oct as usize;
|
||||||
|
for o in 1..=max_oct {
|
||||||
|
for i in 0..mask_count {
|
||||||
|
self.keys.push(self.used_keys[i] + (o as f32) * 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.mask_key_count = mask_count as u16;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn signal_to_pitch(&mut self, inp: f32) -> f32 {
|
||||||
|
let len = self.keys.len();
|
||||||
|
let key = (inp.clamp(0.0, 0.9999) * (len as f32)).floor();
|
||||||
|
let key = key as usize % len;
|
||||||
|
self.last_key = key as u8;
|
||||||
|
self.keys[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! fa_distort { ($formatter: expr, $v: expr, $denorm_v: expr) => { {
|
macro_rules! fa_distort { ($formatter: expr, $v: expr, $denorm_v: expr) => { {
|
||||||
let s =
|
let s =
|
||||||
|
|
|
@ -739,7 +739,7 @@ macro_rules! node_list {
|
||||||
[0 sig],
|
[0 sig],
|
||||||
quant => Quant UIType::Generic UICategory::CV
|
quant => Quant UIType::Generic UICategory::CV
|
||||||
(0 inp n_id d_id r_id f_def stp_d 0.0, 1.0, 0.0)
|
(0 inp n_id d_id r_id f_def stp_d 0.0, 1.0, 0.0)
|
||||||
(1 oct n_id d_id r_id f_def stp_d -1.0, 1.0, 0.0)
|
(1 oct n_id d_id r_s f_def stp_d -1.0, 1.0, 0.0)
|
||||||
{2 0 keys setting(0) fa_quant 0 0}
|
{2 0 keys setting(0) fa_quant 0 0}
|
||||||
{3 1 omin setting(0) fa_quant_omin 0 4}
|
{3 1 omin setting(0) fa_quant_omin 0 4}
|
||||||
{4 2 omax setting(0) fa_quant_omax 0 4}
|
{4 2 omax setting(0) fa_quant_omax 0 4}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
||||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals, NodeContext};
|
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals, NodeContext};
|
||||||
use crate::dsp::helpers::{Trigger};
|
use crate::dsp::helpers::Quantizer;
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! fa_quant { ($formatter: expr, $v: expr, $denorm_v: expr) => { {
|
macro_rules! fa_quant { ($formatter: expr, $v: expr, $denorm_v: expr) => { {
|
||||||
|
@ -42,11 +42,13 @@ macro_rules! fa_quant_omax { ($formatter: expr, $v: expr, $denorm_v: expr) => {
|
||||||
/// A 9 channel signal multiplexer
|
/// A 9 channel signal multiplexer
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Quant {
|
pub struct Quant {
|
||||||
|
quant: Quantizer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Quant {
|
impl Quant {
|
||||||
pub fn new(_nid: &NodeId) -> Self {
|
pub fn new(_nid: &NodeId) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
quant: Quantizer::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub const inp : &'static str =
|
pub const inp : &'static str =
|
||||||
|
@ -93,53 +95,9 @@ impl DspNode for Quant {
|
||||||
let omin = at::Quant::omin(atoms);
|
let omin = at::Quant::omin(atoms);
|
||||||
let omax = at::Quant::omax(atoms);
|
let omax = at::Quant::omax(atoms);
|
||||||
|
|
||||||
let mut key_count = 0;
|
self.quant.update_keys(keys.i(), omin.i(), omax.i());
|
||||||
let mut used_keys = [0.0; 12];
|
|
||||||
|
|
||||||
let mask = keys.i();
|
if self.quant.has_no_keys() {
|
||||||
let tune_to_a4 = (9.0 / 12.0) * 0.1;
|
|
||||||
for i in 0..9 {
|
|
||||||
if mask & (0x1 << i) > 0 {
|
|
||||||
used_keys[key_count] = ((i as f32 / 12.0) * 0.1) - tune_to_a4;
|
|
||||||
key_count += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in 9..12 {
|
|
||||||
let key_pitch_idx = (i + 9 + 12) % 12;
|
|
||||||
if mask & (0x1 << i) > 0 {
|
|
||||||
used_keys[key_count] = (i as f32 / 12.0) * 0.1 - tune_to_a4;
|
|
||||||
key_count += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut all_keys = [0.0; 12 * 10]; // -4 and +4 octaves + 1 center
|
|
||||||
let mut max_all = 0;
|
|
||||||
|
|
||||||
let omin = omin.i() as usize;
|
|
||||||
for o in 0..omin {
|
|
||||||
let o = omin - o;
|
|
||||||
|
|
||||||
for i in 0..key_count {
|
|
||||||
all_keys[max_all] = used_keys[i] - (o as f32) * 0.1;
|
|
||||||
max_all += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in 0..key_count {
|
|
||||||
all_keys[max_all] = used_keys[i];
|
|
||||||
max_all += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let omax = omax.i() as usize;
|
|
||||||
for o in 1..=omax {
|
|
||||||
for i in 0..key_count {
|
|
||||||
all_keys[max_all] = used_keys[i] + (o as f32) * 0.1;
|
|
||||||
max_all += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if max_all == 0 {
|
|
||||||
for frame in 0..ctx.nframes() {
|
for frame in 0..ctx.nframes() {
|
||||||
out.write(
|
out.write(
|
||||||
frame,
|
frame,
|
||||||
|
@ -154,18 +112,15 @@ impl DspNode for Quant {
|
||||||
let mut last_key = 0;
|
let mut last_key = 0;
|
||||||
|
|
||||||
for frame in 0..ctx.nframes() {
|
for frame in 0..ctx.nframes() {
|
||||||
let key =
|
let pitch =
|
||||||
(denorm::Quant::inp(inp, frame) * (max_all as f32))
|
self.quant.signal_to_pitch(
|
||||||
.floor();
|
denorm::Quant::inp(inp, frame));
|
||||||
let key = key as usize % max_all;
|
|
||||||
let pitch = all_keys[key];
|
|
||||||
last_key = key;
|
|
||||||
out.write(frame, pitch + denorm::Quant::oct(oct, frame));
|
out.write(frame, pitch + denorm::Quant::oct(oct, frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
let last_pitch = used_keys[last_key as usize % key_count];
|
let last_pitch = self.quant.last_key_pitch();
|
||||||
ctx_vals[1].set((last_pitch + tune_to_a4) * 10.0 + 0.0001);
|
ctx_vals[1].set(last_pitch * 10.0 + 0.0001);
|
||||||
ctx_vals[0].set(((last_pitch + tune_to_a4) * 10.0 - 0.5) * 2.0);
|
ctx_vals[0].set((last_pitch * 10.0 - 0.5) * 2.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue