started implementing the right quantizer
This commit is contained in:
parent
b2570f5484
commit
d24809112f
4 changed files with 156 additions and 11 deletions
|
@ -184,8 +184,8 @@ iter f 0 => n {
|
||||||
};
|
};
|
||||||
|
|
||||||
!lkup = mk_pitch_lookup_table $[
|
!lkup = mk_pitch_lookup_table $[
|
||||||
$t, $f, $f, $f, $f, $t,
|
$f, $f, $f, $f, $f, $f,
|
||||||
$t, $f, $f, $f, $f, $t,
|
$f, $f, $f, $t, $t, $t,
|
||||||
];
|
];
|
||||||
|
|
||||||
std:displayln ~ eucMod -1 12;
|
std:displayln ~ eucMod -1 12;
|
||||||
|
|
|
@ -2134,6 +2134,122 @@ impl<F: Flt> TriSawLFO<F> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Quantizer {
|
||||||
|
old_mask: i64,
|
||||||
|
keys: [f32; 12],
|
||||||
|
lkup_tbl: [u8; 24],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Quantizer {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
old_mask: 0xFFFF_FFFF,
|
||||||
|
keys: [0.0; 12],
|
||||||
|
lkup_tbl: [0; 24]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_keys(&mut self, keys_mask: i64) {
|
||||||
|
if keys_mask == self.old_mask {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.old_mask = keys_mask;
|
||||||
|
|
||||||
|
for i in 0..12 {
|
||||||
|
self.keys[i] =
|
||||||
|
((i as f32 / 12.0) * 0.1) - QUANT_TUNE_TO_A4;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setup_lookup_table();
|
||||||
|
}
|
||||||
|
|
||||||
|
// mk_pitch_lookup_table = {!enabled = _;
|
||||||
|
// !any = $f;
|
||||||
|
// iter n enabled { if n { .any = $t } };
|
||||||
|
//
|
||||||
|
// !tbl = $[];
|
||||||
|
//
|
||||||
|
// iter i 0 => 24 {
|
||||||
|
// !minDistNote = 0;
|
||||||
|
// !minDist = 10000000000;
|
||||||
|
//
|
||||||
|
// iter note -12 => 25 {
|
||||||
|
// !dist = std:num:abs[ (i + 1) / 2 - note ];
|
||||||
|
//
|
||||||
|
// !idx = eucMod note 12;
|
||||||
|
// if any &and not[enabled.(idx)] {
|
||||||
|
// next[];
|
||||||
|
// };
|
||||||
|
// std:displayln "DIST" (i + 1) / 2 note idx "=>" dist;
|
||||||
|
// if dist < minDist {
|
||||||
|
// .minDistNote = idx;
|
||||||
|
// .minDist = dist;
|
||||||
|
// } { break[] };
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// tbl.(i) = minDistNote;
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// tbl
|
||||||
|
//};
|
||||||
|
//
|
||||||
|
#[inline]
|
||||||
|
fn setup_lookup_table(&mut self) {
|
||||||
|
let mask = self.old_mask;
|
||||||
|
let any_enabled = mask > 0x0;
|
||||||
|
|
||||||
|
for i in 0..24 {
|
||||||
|
let mut min_dist_note = 0;
|
||||||
|
let mut min_dist = 1000000000;
|
||||||
|
|
||||||
|
for note in -12..=24 {
|
||||||
|
let dist = ((i + 1_i64) / 2 - note).abs();
|
||||||
|
|
||||||
|
let note_idx = note.rem_euclid(12);
|
||||||
|
if any_enabled && (mask & (0x1 << note_idx)) == 0x0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if dist < min_dist {
|
||||||
|
min_dist_note = note_idx;
|
||||||
|
min_dist = dist;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.lkup_tbl[i as usize] = min_dist_note as u8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//# float pitch = inputs[PITCH_INPUT].getVoltage(c);
|
||||||
|
//# int range = std::floor(pitch * 24); // 1.1 => 26
|
||||||
|
//# int octave = eucDiv(range, 24); // 26 => 1
|
||||||
|
//# range -= octave * 24; // 26 => 2
|
||||||
|
|
||||||
|
//# int note = ranges[range] + octave * 12;
|
||||||
|
//# playingNotes[eucMod(note, 12)] = true;
|
||||||
|
//# pitch = float(note) / 12;
|
||||||
|
//# outputs[PITCH_OUTPUT].setVoltage(pitch, c);
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn process(&self, inp: f32) -> f32 {
|
||||||
|
let note_num = (inp * 240.0).floor() as i64;
|
||||||
|
let octave = note_num.div_euclid(240);
|
||||||
|
let note_idx = note_num - octave * 240;
|
||||||
|
|
||||||
|
println!("INP {:6.4} => octave={:2}, note_idx={:2}", inp, octave, note_idx);
|
||||||
|
println!("KEYS: {:?}", self.keys);
|
||||||
|
|
||||||
|
let note_idx = self.lkup_tbl[note_idx as usize % 24]; // + octave * 12;
|
||||||
|
let pitch = self.keys[note_idx as usize];
|
||||||
|
|
||||||
|
pitch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct CtrlPitchQuantizer {
|
pub struct CtrlPitchQuantizer {
|
||||||
/// All keys, containing the min/max octave!
|
/// All keys, containing the min/max octave!
|
||||||
|
@ -2189,15 +2305,7 @@ impl CtrlPitchQuantizer {
|
||||||
|
|
||||||
let mut mask_count = 0;
|
let mut mask_count = 0;
|
||||||
|
|
||||||
for i in 0..9 {
|
for i in 0..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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in 9..12 {
|
|
||||||
let key_pitch_idx = (i + 9 + 12) % 12;
|
|
||||||
if mask & (0x1 << i) > 0 {
|
if mask & (0x1 << i) > 0 {
|
||||||
self.used_keys[mask_count] = (i as f32 / 12.0) * 0.1 - QUANT_TUNE_TO_A4;
|
self.used_keys[mask_count] = (i as f32 / 12.0) * 0.1 - QUANT_TUNE_TO_A4;
|
||||||
mask_count += 1;
|
mask_count += 1;
|
||||||
|
|
|
@ -382,10 +382,12 @@ macro_rules! define_exp6 {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
macro_rules! n_pit { ($x: expr) => {
|
macro_rules! n_pit { ($x: expr) => {
|
||||||
0.1 * (($x as f32).max(0.01) / 440.0).log2()
|
0.1 * (($x as f32).max(0.01) / 440.0).log2()
|
||||||
} }
|
} }
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
macro_rules! d_pit { ($x: expr) => {
|
macro_rules! d_pit { ($x: expr) => {
|
||||||
{
|
{
|
||||||
let note : f32 = ($x as f32) * 10.0;
|
let note : f32 = ($x as f32) * 10.0;
|
||||||
|
|
35
tests/quant.rs
Normal file
35
tests/quant.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright (c) 2021 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.
|
||||||
|
|
||||||
|
mod common;
|
||||||
|
use common::*;
|
||||||
|
|
||||||
|
use hexodsp::dsp::helpers::Quantizer;
|
||||||
|
use hexodsp::d_pit;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_quant_1() {
|
||||||
|
let mut q = Quantizer::new();
|
||||||
|
q.set_keys(0x0);
|
||||||
|
|
||||||
|
let v =
|
||||||
|
(0..=12).map(|i|
|
||||||
|
d_pit!(q.process(i as f32 * (0.1 / 12.0)))
|
||||||
|
).collect::<Vec<f32>>();
|
||||||
|
|
||||||
|
assert_vec_feq!(v, vec![
|
||||||
|
440.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
]);
|
||||||
|
}
|
Loading…
Reference in a new issue