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 /// A simple amplifier
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Sampl { pub struct Sampl {
sample_idx: usize, phase: f64,
srate: f64,
} }
impl Sampl { impl Sampl {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
sample_idx: 0, phase: 0.0,
srate: 44100.0,
} }
} }
pub const freq : &'static str = pub const freq : &'static str =
@ -29,7 +31,7 @@ impl Sampl {
impl DspNode for Sampl { impl DspNode for Sampl {
fn outputs() -> usize { 1 } 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) { } fn reset(&mut self) { }
#[inline] #[inline]
@ -44,14 +46,44 @@ impl DspNode for Sampl {
let out = out::Sampl::sig(outputs); let out = out::Sampl::sig(outputs);
if let SAtom::AudioSample((_, Some(sample_data))) = sample { 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() { 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]; let i = self.phase.floor() as usize + sd_len;
out.write(frame, sd);
self.sample_idx += (1.0 * speed).ceil() as usize; // 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 { } else {
for frame in 0..ctx.nframes() { 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)); matrix.set_param(freq_p, SAtom::param(0.1));
let fft = run_and_get_fft4096(&mut node_exec, 800, 0.0); 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)); matrix.set_param(freq_p, SAtom::param(-0.1));
let fft = run_and_get_fft4096(&mut node_exec, 800, 0.0); let fft = run_and_get_fft4096(&mut node_exec, 800, 0.0);
assert_eq!(fft[0], (220, 988)); assert_eq!(fft[0], (226, 965));
} }