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 $[
|
||||
$t, $f, $f, $f, $f, $t,
|
||||
$t, $f, $f, $f, $f, $t,
|
||||
$f, $f, $f, $f, $f, $f,
|
||||
$f, $f, $f, $t, $t, $t,
|
||||
];
|
||||
|
||||
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)]
|
||||
pub struct CtrlPitchQuantizer {
|
||||
/// All keys, containing the min/max octave!
|
||||
|
@ -2189,15 +2305,7 @@ impl CtrlPitchQuantizer {
|
|||
|
||||
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;
|
||||
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;
|
||||
|
|
|
@ -382,10 +382,12 @@ macro_rules! define_exp6 {
|
|||
}
|
||||
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! n_pit { ($x: expr) => {
|
||||
0.1 * (($x as f32).max(0.01) / 440.0).log2()
|
||||
} }
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! d_pit { ($x: expr) => {
|
||||
{
|
||||
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