implemented basic sample oscillator

This commit is contained in:
Weird Constructor 2021-05-22 09:19:11 +02:00
parent b11743442a
commit 0c3d5e99fa
4 changed files with 70 additions and 8 deletions

View file

@ -8,11 +8,13 @@ use crate::dsp::{SAtom, ProcBuf, DspNode, LedPhaseVals};
/// A simple amplifier /// A simple amplifier
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Sampl { pub struct Sampl {
sample_idx: usize,
} }
impl Sampl { impl Sampl {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
sample_idx: 0,
} }
} }
pub const freq : &'static str = pub const freq : &'static str =
@ -35,15 +37,26 @@ impl DspNode for Sampl {
&mut self, ctx: &mut T, atoms: &[SAtom], _params: &[ProcBuf], &mut self, ctx: &mut T, atoms: &[SAtom], _params: &[ProcBuf],
inputs: &[ProcBuf], outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals) inputs: &[ProcBuf], outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals)
{ {
use crate::dsp::{out}; //, inp, denorm, denorm_v, inp_dir, at}; use crate::dsp::{out, at, inp, denorm}; //, inp, denorm, denorm_v, inp_dir, at};
// let gain = inp::Amp::gain(inputs); let sample = at::Sampl::sample(atoms);
// let att = inp::Amp::att(inputs); let freq = inp::Sampl::freq(inputs);
// let inp = inp::Amp::inp(inputs); let out = out::Sampl::sig(outputs);
let out = out::Sampl::sig(outputs);
for frame in 0..ctx.nframes() { if let SAtom::AudioSample((_, Some(sample_data))) = sample {
out.write(frame, 0.0); let sd_len = sample_data.len() - 1;
for frame in 0..ctx.nframes() {
let speed = denorm::Sampl::freq(freq, frame) / 440.0;
let sd = sample_data[self.sample_idx % sd_len + 1];
out.write(frame, sd);
self.sample_idx += (1.0 * speed).ceil() as usize;
}
} else {
for frame in 0..ctx.nframes() {
out.write(frame, 0.0);
}
} }
ctx_vals[0].set(1.0); ctx_vals[0].set(1.0);

View file

@ -12,6 +12,7 @@ use super::{
}; };
use crate::nodes::drop_thread::DropThread; use crate::nodes::drop_thread::DropThread;
use crate::dsp::{NodeId, ParamId, NodeInfo, Node, SAtom, node_factory}; use crate::dsp::{NodeId, ParamId, NodeInfo, Node, SAtom, node_factory};
use crate::{SampleLibrary};
use crate::util::AtomicFloat; use crate::util::AtomicFloat;
use crate::monitor::{ use crate::monitor::{
Monitor, MON_SIG_CNT, new_monitor_processor, MinMaxMonitorSamples Monitor, MON_SIG_CNT, new_monitor_processor, MinMaxMonitorSamples
@ -142,6 +143,10 @@ pub struct NodeConfigurator {
feedback_filter: FeedbackFilter, feedback_filter: FeedbackFilter,
/// Loads and Caches audio samples that are set as parameters
/// for nodes.
sample_lib: SampleLibrary,
/// Contains (automateable) parameters /// Contains (automateable) parameters
params: std::collections::HashMap<ParamId, NodeInputParam>, params: std::collections::HashMap<ParamId, NodeInputParam>,
/// Stores the most recently set parameter values /// Stores the most recently set parameter values
@ -226,6 +231,7 @@ impl NodeConfigurator {
(NodeConfigurator { (NodeConfigurator {
nodes, nodes,
shared, shared,
sample_lib: SampleLibrary::new(),
feedback_filter: FeedbackFilter::new(), feedback_filter: FeedbackFilter::new(),
output_fb_values: vec![], output_fb_values: vec![],
output_fb_cons: None, output_fb_cons: None,
@ -292,6 +298,13 @@ impl NodeConfigurator {
/// then the value will be remembered until [NodeConfigurator::rebuild_node_ports] is called. /// then the value will be remembered until [NodeConfigurator::rebuild_node_ports] is called.
pub fn set_param(&mut self, param: ParamId, at: SAtom) { pub fn set_param(&mut self, param: ParamId, at: SAtom) {
if param.is_atom() { if param.is_atom() {
let at =
if let SAtom::AudioSample((path, None)) = at {
self.sample_lib.load(&path).unwrap().clone()
} else {
at
};
self.atom_values.insert(param, at.clone()); self.atom_values.insert(param, at.clone());
if let Some(nparam) = self.atoms.get_mut(&param) { if let Some(nparam) = self.atoms.get_mut(&param) {

View file

@ -64,7 +64,9 @@ impl SampleLibrary {
}, },
hound::SampleFormat::Int => { hound::SampleFormat::Int => {
for s in rd.samples::<i16>().step_by(channels) { for s in rd.samples::<i16>().step_by(channels) {
v.push(s? as f32 / (i16::MAX as f32)); let s = s?;
let s = s as f32 / (i16::MAX as f32);
v.push(s);
} }
}, },
}; };

View file

@ -1105,3 +1105,37 @@ fn check_matrix_output_feedback() {
assert_float_eq!(fo_amp.1, 0.11627); assert_float_eq!(fo_amp.1, 0.11627);
} }
#[test]
fn check_node_sampl_1() {
let (node_conf, mut node_exec) = new_node_engine();
let mut matrix = Matrix::new(node_conf, 3, 3);
let smpl = NodeId::Sampl(0);
let out = NodeId::Out(0);
matrix.place(0, 0, Cell::empty(smpl)
.out(None, None, smpl.out("sig")));
matrix.place(0, 1, Cell::empty(out)
.input(out.inp("ch1"), None, None));
matrix.sync().unwrap();
let sample_p = smpl.inp_param("sample").unwrap();
let freq_p = smpl.inp_param("freq").unwrap();
matrix.set_param(sample_p, SAtom::audio_unloaded("tests/sample_sin.wav"));
let (rms, min, max) = run_and_get_l_rms_mimax(&mut node_exec, 50.0);
assert_float_eq!(rms, 0.505);
assert_float_eq!(min, -0.9998);
assert_float_eq!(max, 1.0);
let fft = run_and_get_fft4096(&mut node_exec, 800, 0.0);
assert_eq!(fft[0], (441, 940));
matrix.set_param(freq_p, SAtom::param(0.1));
let fft = run_and_get_fft4096(&mut node_exec, 800, 0.0);
assert_eq!(fft[0], (894, 988));
matrix.set_param(freq_p, SAtom::param(-0.1));
let fft = run_and_get_fft4096(&mut node_exec, 800, 0.0);
assert_eq!(fft[0], (220, 988));
}