implemented interpolation in the sample player

This commit is contained in:
Weird Constructor 2021-05-22 11:11:03 +02:00
parent 0c3d5e99fa
commit 1890e9ed90
2 changed files with 42 additions and 10 deletions

View file

@ -8,13 +8,15 @@ use crate::dsp::{SAtom, ProcBuf, DspNode, LedPhaseVals};
/// A simple amplifier
#[derive(Debug, Clone)]
pub struct Sampl {
sample_idx: usize,
phase: f64,
srate: f64,
}
impl Sampl {
pub fn new() -> Self {
Self {
sample_idx: 0,
phase: 0.0,
srate: 44100.0,
}
}
pub const freq : &'static str =
@ -29,7 +31,7 @@ impl Sampl {
impl DspNode for Sampl {
fn outputs() -> usize { 1 }
fn set_sample_rate(&mut self, _srate: f32) { }
fn set_sample_rate(&mut self, srate: f32) { self.srate = srate.into(); }
fn reset(&mut self) { }
#[inline]
@ -44,14 +46,44 @@ impl DspNode for Sampl {
let out = out::Sampl::sig(outputs);
if let SAtom::AudioSample((_, Some(sample_data))) = sample {
let sd_len = sample_data.len() - 1;
let sd_len = sample_data.len() - 1;
let sd_len_f = sd_len as f64;
let sample_srate = sample_data[0] as f64;
let sample_data = &sample_data[1..];
let sr_factor = sample_srate / self.srate;
for frame in 0..ctx.nframes() {
let speed = denorm::Sampl::freq(freq, frame) / 440.0;
let playback_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;
let i = self.phase.floor() as usize + sd_len;
// Hermite interpolation, take from
// https://github.com/eric-wood/delay/blob/main/src/delay.rs#L52
//
// Thanks go to Eric Wood!
//
// For the interpolation code:
// MIT License, Copyright (c) 2021 Eric Wood
let xm1 = sample_data[(i - 1) % sd_len];
let x0 = sample_data[i % sd_len];
let x1 = sample_data[(i + 1) % sd_len];
let x2 = sample_data[(i + 2) % sd_len];
let c = (x1 - xm1) * 0.5;
let v = x0 - x1;
let w = c + v;
let a = w + v + (x2 - x0) * 0.5;
let b_neg = w + a;
let f = self.phase.fract() as f32;
let out_sample = (((a * f) - b_neg) * f + c) * f + x0;
out.write(frame, out_sample);
self.phase += sr_factor * playback_speed as f64;
}
} else {
for frame in 0..ctx.nframes() {

View file

@ -1133,9 +1133,9 @@ fn check_node_sampl_1() {
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));
assert_eq!(fft[0], (894, 982));
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));
assert_eq!(fft[0], (226, 965));
}