Skip to content

Commit

Permalink
Anti aliased wavetable
Browse files Browse the repository at this point in the history
  • Loading branch information
ErikNatanael committed Sep 3, 2024
1 parent 5457342 commit 92eec5b
Show file tree
Hide file tree
Showing 9 changed files with 621 additions and 24 deletions.
4 changes: 2 additions & 2 deletions knyst/benches/micro_benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,14 @@ pub fn wavetable_vs_sin(c: &mut Criterion) {
let mut phase = WavetablePhase(0);
c.bench_function("wavetable sin linear", |b| {
b.iter(|| {
black_box(w.get_linear_interp(phase));
black_box(w.get_linear_interp(phase, frequency));
phase.increase(integer_phase_increase);
});
});
let mut phase = WavetablePhase(0);
c.bench_function("wavetable sin no interpolation", |b| {
b.iter(|| {
black_box(w.get(phase));
black_box(w.get(phase, frequency));
phase.increase(integer_phase_increase);
});
});
Expand Down
2 changes: 1 addition & 1 deletion knyst/src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::{
inspection::GraphInspection,
knyst_commands,
resources::{BufferId, ResourcesCommand, ResourcesResponse, WavetableId},
wavetable::Wavetable,
wavetable_aa::Wavetable,
};
use crate::{
graph::{
Expand Down
10 changes: 7 additions & 3 deletions knyst/src/gen/osc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use crate::{
gen::{Gen, GenContext, GenState, StopAction},
prelude::Seconds,
resources::{BufferId, IdOrKey, WavetableId, WavetableKey},
wavetable::{Wavetable, WavetablePhase, FRACTIONAL_PART, TABLE_SIZE},
wavetable::{WavetablePhase, FRACTIONAL_PART, TABLE_SIZE},
wavetable_aa::Wavetable,
Resources, Sample, SampleRate,
};
use knyst_macro::impl_gen;
Expand Down Expand Up @@ -70,7 +71,7 @@ impl Oscillator {
};
if let Some(wt) = resources.wavetable(wt_key) {
for (&f, o) in freq.iter().zip(sig.iter_mut()) {
*o = wt.get_linear_interp(self.phase);
*o = wt.get_linear_interp(self.phase, f);
self.set_freq(f);
self.phase.increase(self.step);
// TODO: Set a buffer of phase values and request them all from the wavetable all at the same time. Should enable SIMD in the wavetable lookup.
Expand Down Expand Up @@ -440,12 +441,14 @@ pub struct WavetableOscillatorOwned {
wavetable: Wavetable,
amp: Sample,
freq_to_phase_inc: f64,
freq: Sample,
}

impl WavetableOscillatorOwned {
/// Set the frequency of the oscillation. This will be overwritten by the
/// input frequency if used as a Gen.
pub fn set_freq(&mut self, freq: Sample) {
self.freq = freq;
self.step = (freq as f64 * self.freq_to_phase_inc) as u32;
}
/// Set the amplitude of the signal.
Expand All @@ -463,7 +466,7 @@ impl WavetableOscillatorOwned {
pub fn next_sample(&mut self) -> Sample {
// Use the phase to index into the wavetable
// self.wavetable.get_linear_interp(temp_phase) * self.amp
let sample = self.wavetable.get(self.phase) * self.amp;
let sample = self.wavetable.get(self.phase, self.freq) * self.amp;
self.phase.increase(self.step);
sample
}
Expand All @@ -480,6 +483,7 @@ impl WavetableOscillatorOwned {
wavetable,
amp: 1.0,
freq_to_phase_inc: 0.0, // set to a real value in init
freq: 0.,
}
}
fn process(&mut self, freq: &[Sample], sig: &mut [Sample]) -> GenState {
Expand Down
13 changes: 8 additions & 5 deletions knyst/src/gen/smoothing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ pub struct Lag {
sample_rate: Sample,
}

impl Lag {}
#[impl_gen]
impl Lag {
#[new]
Expand All @@ -27,7 +26,8 @@ impl Lag {
Self::default()
}
#[process]
fn process(
#[allow(missing_docs)]
pub fn process(
&mut self,
value: &[Sample],
time: &[Sample],
Expand All @@ -48,7 +48,8 @@ impl Lag {
GenState::Continue
}
#[init]
fn init(&mut self, sample_rate: SampleRate) {
#[allow(missing_docs)]
pub fn init(&mut self, sample_rate: SampleRate) {
self.sample_rate = *sample_rate;
}
}
Expand Down Expand Up @@ -80,7 +81,8 @@ impl Ramp {
}
}
#[process]
fn process(
#[allow(missing_docs)]
pub fn process(
&mut self,
value: &[Sample],
time: &[Sample],
Expand Down Expand Up @@ -118,7 +120,8 @@ impl Ramp {
}

#[init]
fn init(&mut self) {
#[allow(missing_docs)]
pub fn init(&mut self) {
self.num_steps_to_go = 0;
}
}
5 changes: 3 additions & 2 deletions knyst/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ pub mod sphere;
pub mod time;
pub mod trig;
pub mod wavetable;
pub mod wavetable_aa;
pub mod xorrng;

/// Combined error type for Knyst, containing any other error in the library.
Expand Down Expand Up @@ -147,7 +148,7 @@ pub type Trig = Sample;

/// Newtype for a sample rate to identify it in function signatures. Derefs to a `Sample` for easy use on the audio thread.
#[derive(Copy, Clone, Debug)]
pub struct SampleRate(Sample);
pub struct SampleRate(pub Sample);

impl SampleRate {
#[inline(always)]
Expand Down Expand Up @@ -197,7 +198,7 @@ impl From<f64> for SampleRate {
/// BlockSize.
///
/// Can be an unorthodox block size value in the event of a partial block at the beginning of a node's existence in the graph.
pub struct BlockSize(usize);
pub struct BlockSize(pub usize);

impl From<BlockSize> for usize {
#[inline(always)]
Expand Down
12 changes: 3 additions & 9 deletions knyst/src/modal_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use crate::graph::{GraphSettings, NodeId, Time};
use crate::handles::{GraphHandle, Handle};
use crate::prelude::{CallbackHandle, MultiThreadedKnystCommands};
use crate::sphere::KnystSphere;
use crate::wavetable_aa::{self, Wavetable};

/// A unique id for a KnystSphere.
#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)]
Expand Down Expand Up @@ -212,10 +213,7 @@ impl KnystCommands for UnifiedKnystCommands {
}
}

fn insert_wavetable(
&mut self,
wavetable: crate::wavetable::Wavetable,
) -> crate::resources::WavetableId {
fn insert_wavetable(&mut self, wavetable: Wavetable) -> crate::resources::WavetableId {
match self {
UnifiedKnystCommands::Real(kc) => kc.borrow_mut().insert_wavetable(wavetable),
UnifiedKnystCommands::Dummy(kc) => {
Expand All @@ -232,11 +230,7 @@ impl KnystCommands for UnifiedKnystCommands {
}
}

fn replace_wavetable(
&mut self,
id: crate::resources::WavetableId,
wavetable: crate::wavetable::Wavetable,
) {
fn replace_wavetable(&mut self, id: crate::resources::WavetableId, wavetable: Wavetable) {
match self {
UnifiedKnystCommands::Real(kc) => kc.borrow_mut().replace_wavetable(id, wavetable),
UnifiedKnystCommands::Dummy(kc) => kc.report_dummy(),
Expand Down
3 changes: 2 additions & 1 deletion knyst/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub use crate::resources::{IdOrKey, WavetableId, WavetableKey};
pub use crate::resources::{Resources, ResourcesSettings};
pub use crate::sphere::{KnystSphere, SphereSettings};
pub use crate::time::{Beats, Seconds};
pub use crate::wavetable::{Wavetable, TABLE_POWER, TABLE_SIZE};
pub use crate::wavetable::{TABLE_POWER, TABLE_SIZE};
pub use crate::wavetable_aa::Wavetable;
pub use crate::{BlockSize, Sample, SampleRate, Trig};
pub use knyst_macro::impl_gen;
2 changes: 1 addition & 1 deletion knyst/src/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use std::{collections::HashMap, hash::Hash, sync::atomic::AtomicU64};
use crate::{
buffer::{Buffer, BufferKey},
prelude::Seconds,
wavetable::Wavetable,
wavetable_aa::Wavetable,
};

#[derive(Copy, Clone, Debug)]
Expand Down
Loading

0 comments on commit 92eec5b

Please sign in to comment.