started implementing the right quantizer

This commit is contained in:
Weird Constructor 2021-08-28 08:09:17 +02:00
parent b2570f5484
commit d24809112f
4 changed files with 156 additions and 11 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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
View 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,
]);
}