Skip to content

Commit

Permalink
Update.
Browse files Browse the repository at this point in the history
  • Loading branch information
SamiPerttu committed Dec 29, 2023
1 parent c990d2e commit 05eb91e
Show file tree
Hide file tree
Showing 9 changed files with 184 additions and 116 deletions.
14 changes: 14 additions & 0 deletions benches/benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use fundsp::hacker32::*;

fn resynth_bench(_dummy: usize) -> Wave32 {
Wave32::render(
44100.0,
1.0,
&mut (noise()
>> resynth::<U1, U1, _>(1024, |fft| {
for i in 0..fft.bins() {
fft.set(0, i, fft.at(0, i));
}
})),
)
}

fn pass_bench(_dummy: usize) -> Wave32 {
Wave32::render(
44100.0,
Expand Down Expand Up @@ -66,6 +79,7 @@ fn phaser_bench(_dummy: usize) -> Wave32 {
}

fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("resynth", |b| b.iter(|| resynth_bench(black_box(0))));
c.bench_function("pass", |b| b.iter(|| pass_bench(black_box(0))));
c.bench_function("wavetable", |b| b.iter(|| wavetable_bench(black_box(0))));
c.bench_function("envelope", |b| b.iter(|| envelope_bench(black_box(0))));
Expand Down
4 changes: 2 additions & 2 deletions src/delay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl<N: Size<T>, T: Float> AudioNode for Tick<N, T> {
}

/// Fixed delay.
/// Allocates: the delay line.
/// - Allocates: the delay line.
/// - Input 0: input
/// - Output 0: delayed input
#[derive(Clone)]
Expand Down Expand Up @@ -136,7 +136,7 @@ impl<T: Float> AudioNode for Delay<T> {

/// Variable delay line using cubic interpolation.
/// The number of taps is `N`.
/// Allocates: the delay line.
/// - Allocates: the delay line.
/// - Input 0: input
/// - Inputs 1...N: delay amount in seconds.
/// - Output 0: delayed input
Expand Down
58 changes: 30 additions & 28 deletions src/hacker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -900,7 +900,7 @@ pub fn multitick<N: Size<f64>>() -> An<Tick<N, f64>> {

/// Fixed delay of `t` seconds.
/// Delay time is rounded to the nearest sample.
/// Allocates: the delay line.
/// - Allocates: the delay line.
/// - Input 0: signal.
/// - Output 0: delayed signal.
///
Expand All @@ -915,7 +915,7 @@ pub fn delay(t: f64) -> An<Delay<f64>> {

/// Tapped delay line with cubic interpolation.
/// Minimum and maximum delay times are in seconds.
/// Allocates: the delay line.
/// - Allocates: the delay line.
/// - Input 0: signal.
/// - Input 1: delay time in seconds.
/// - Output 0: delayed signal.
Expand All @@ -932,7 +932,7 @@ pub fn tap(min_delay: f64, max_delay: f64) -> An<Tap<U1, f64>> {
/// Tapped delay line with cubic interpolation.
/// The number of taps is `N`.
/// Minimum and maximum delay times are in seconds.
/// Allocates: the delay line.
/// - Allocates: the delay line.
/// - Input 0: signal.
/// - Inputs 1...N: delay time in seconds.
/// - Output 0: delayed signal.
Expand Down Expand Up @@ -1175,7 +1175,7 @@ pub fn follow<S: ScalarOrPair<Sample = f64>>(t: S) -> An<AFollow<f64, f64, S>> {

/// Look-ahead limiter with `(attack, release)` times in seconds.
/// Look-ahead is equal to the attack time.
/// Allocates: look-ahead buffers.
/// - Allocates: look-ahead buffers.
/// - Input 0: signal
/// - Output 0: signal limited to -1...1
pub fn limiter<S: ScalarOrPair<Sample = f64>>(time: S) -> An<Limiter<f64, U1, S>> {
Expand All @@ -1184,7 +1184,7 @@ pub fn limiter<S: ScalarOrPair<Sample = f64>>(time: S) -> An<Limiter<f64, U1, S>

/// Stereo look-ahead limiter with `(attack, release)` times in seconds.
/// Look-ahead is equal to the attack time.
/// Allocates: look-ahead buffers.
/// - Allocates: look-ahead buffers.
/// - Input 0: left signal
/// - Input 1: right signal
/// - Output 0: left signal limited to -1...1
Expand Down Expand Up @@ -1532,7 +1532,7 @@ pub fn dsf_square_r(roughness: f64) -> An<Dsf<f64, U1>> {

/// Karplus-Strong plucked string oscillator with `frequency` in Hz.
/// High frequency damping is in 0...1.
/// Allocates: pluck buffer.
/// - Allocates: pluck buffer.
/// - Input 0: string excitation
/// - Output 0: oscillator output
///
Expand All @@ -1550,31 +1550,31 @@ pub fn pluck(frequency: f64, gain_per_second: f64, high_frequency_damping: f64)
}

/// Saw wavetable oscillator.
/// Allocates: global saw wavetable.
/// - Allocates: global saw wavetable.
/// - Input 0: frequency in Hz
/// - Output 0: saw wave
pub fn saw() -> An<WaveSynth<'static, f64, U1>> {
An(WaveSynth::new(DEFAULT_SR, &SAW_TABLE))
}

/// Square wavetable oscillator.
/// Allocates: global square wavetable.
/// - Allocates: global square wavetable.
/// - Input 0: frequency in Hz
/// - Output 0: square wave
pub fn square() -> An<WaveSynth<'static, f64, U1>> {
An(WaveSynth::new(DEFAULT_SR, &SQUARE_TABLE))
}

/// Triangle wavetable oscillator.
/// Allocates: global triangle wavetable.
/// - Allocates: global triangle wavetable.
/// - Input 0: frequency in Hz
/// - Output 0: triangle wave
pub fn triangle() -> An<WaveSynth<'static, f64, U1>> {
An(WaveSynth::new(DEFAULT_SR, &TRIANGLE_TABLE))
}

/// Organ wavetable oscillator. Emphasizes octave partials.
/// Allocates: global organ wavetable.
/// - Allocates: global organ wavetable.
/// - Input 0: frequency in Hz
/// - Output 0: organ wave
pub fn organ() -> An<WaveSynth<'static, f64, U1>> {
Expand All @@ -1583,59 +1583,59 @@ pub fn organ() -> An<WaveSynth<'static, f64, U1>> {

/// Soft saw wavetable oscillator.
/// Contains all partials, falls off like a triangle wave.
/// Allocates: global soft saw wavetable.
/// - Allocates: global soft saw wavetable.
/// - Input 0: frequency in Hz
/// - Output 0: soft saw wave
pub fn soft_saw() -> An<WaveSynth<'static, f64, U1>> {
An(WaveSynth::new(DEFAULT_SR, &SOFT_SAW_TABLE))
}

/// Hammond wavetable oscillator. Emphasizes first three partials.
/// Allocates: global Hammond wavetable.
/// - Allocates: global Hammond wavetable.
/// - Input 0: frequency in Hz
/// - Output 0: Hammond wave
pub fn hammond() -> An<WaveSynth<'static, f64, U1>> {
An(WaveSynth::new(DEFAULT_SR, &HAMMOND_TABLE))
}

/// Fixed saw wavetable oscillator at `f` Hz.
/// Allocates: global saw wavetable.
/// - Allocates: global saw wavetable.
/// - Output 0: saw wave
pub fn saw_hz(f: f64) -> An<Pipe<f64, Constant<U1, f64>, WaveSynth<'static, f64, U1>>> {
super::prelude::saw_hz(f)
}

/// Fixed square wavetable oscillator at `f` Hz.
/// Allocates: global square wavetable.
/// - Allocates: global square wavetable.
/// - Output 0: square wave
pub fn square_hz(f: f64) -> An<Pipe<f64, Constant<U1, f64>, WaveSynth<'static, f64, U1>>> {
super::prelude::square_hz(f)
}

/// Fixed triangle wavetable oscillator at `f` Hz.
/// Allocates: global triangle wavetable.
/// - Allocates: global triangle wavetable.
/// - Output 0: triangle wave
pub fn triangle_hz(f: f64) -> An<Pipe<f64, Constant<U1, f64>, WaveSynth<'static, f64, U1>>> {
super::prelude::triangle_hz(f)
}

/// Fixed organ wavetable oscillator at `f` Hz. Emphasizes octave partials.
/// Allocates: global organ wavetable.
/// - Allocates: global organ wavetable.
/// - Output 0: organ wave
pub fn organ_hz(f: f64) -> An<Pipe<f64, Constant<U1, f64>, WaveSynth<'static, f64, U1>>> {
constant(f) >> organ()
}

/// Fixed soft saw wavetable oscillator at `f` Hz.
/// Contains all partials, falls off like a triangle wave.
/// Allocates: global soft saw wavetable.
/// - Allocates: global soft saw wavetable.
/// - Output 0: soft saw wave
pub fn soft_saw_hz(f: f64) -> An<Pipe<f64, Constant<U1, f64>, WaveSynth<'static, f64, U1>>> {
constant(f) >> soft_saw()
}

/// Fixed Hammond wavetable oscillator at `f` Hz. Emphasizes first three partials.
/// Allocates: global Hammond wavetable.
/// - Allocates: global Hammond wavetable.
/// - Output 0: Hammond wave
pub fn hammond_hz(f: f64) -> An<Pipe<f64, Constant<U1, f64>, WaveSynth<'static, f64, U1>>> {
constant(f) >> hammond()
Expand Down Expand Up @@ -2172,22 +2172,24 @@ pub fn snoop(capacity: usize) -> (Snoop<f64>, An<SnoopBackend<f64>>) {
(snoop, An(backend))
}

/// Frequency domain resynthesizer. The number of inputs is `I` and the number of outputs is `O`.
/// Frequency domain resynthesizer.
/// The number of inputs is `I` and the number of outputs is `O`.
/// The window length (in samples) must be a power of two and at least four.
/// Processes windows of input samples transformed into the frequency domain.
/// The processing function is issued arguments (time, window).
/// It processes frequency domain inputs into frequency domain outputs.
/// The resynthesizer processes windows of input samples transformed into the frequency domain.
/// The user supplied processing function processes frequency domain inputs into frequency domain outputs.
/// The outputs are inverse transformed and overlap-added.
/// The latency in samples is equal to window length.
/// If any output is a copy of an input, then the input will be reconstructed exactly
/// once all windows are overlapping, which takes `window_length` samples.
/// -Input(s): input signals.
/// -Output(s): processed signals.
/// once all windows are overlapping, which takes `window_length` extra samples.
/// - Allocates: all needed buffers when created.
/// - Input(s): `I` input signals.
/// - Output(s): `O` processed signals.
///
/// ### Example: FFT Lowpass Filter
/// ### Example: FFT Brickwall Lowpass Filter
/// ```
/// use fundsp::hacker::*;
/// let cutoff = 1000.0;
/// let resynth = resynth::<U1, U1, _>(1024, |_time, fft|
/// let synth = resynth::<U1, U1, _>(1024, |fft|
/// for i in 0..fft.bins() {
/// if fft.frequency(i) <= cutoff {
/// fft.set(0, i, fft.at(0, i));
Expand All @@ -2198,7 +2200,7 @@ pub fn resynth<I, O, F>(window_length: usize, processing: F) -> An<Resynth<I, O,
where
I: Size<f64>,
O: Size<f64>,
F: FnMut(f32, &mut FftWindow) + Clone + Send + Sync,
F: FnMut(&mut FftWindow) + Clone + Send + Sync,
{
An(Resynth::new(window_length, processing))
}
Loading

0 comments on commit 05eb91e

Please sign in to comment.