implemented interpolation in the sample player
This commit is contained in:
parent
0c3d5e99fa
commit
1890e9ed90
2 changed files with 42 additions and 10 deletions
|
@ -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() {
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue