use crate::buffer::AudioBuffer;
pub use naad::oscillator::{Oscillator, Waveform, polyblep};
pub use naad::filter::{BiquadFilter, FilterType, StateVariableFilter, SvfOutput};
pub use naad::envelope::{Adsr, EnvelopeSegment, EnvelopeState, MultiStageEnvelope};
pub use naad::wavetable::{MorphWavetable, Wavetable, WavetableOscillator};
pub use naad::modulation::{Lfo, LfoMode, LfoShape};
pub use naad::noise::{NoiseGenerator, NoiseType};
pub use naad::mod_matrix::{ModDestination, ModMatrix, ModRouting, ModSource};
pub use naad::voice::{PolyMode, StealMode, Voice, VoiceManager};
pub use naad::smoothing::ParamSmoother;
pub use naad::tuning::{
TuningSystem, TuningTable, cents, equal_temperament_freq, freq_to_midi, midi_to_freq,
};
pub use naad::panning::{PanGains, PanLaw, pan_gains, pan_mono, stereo_balance};
pub use naad::dsp_util;
pub use naad::delay::{CombFilter, DelayLine as SynthDelayLine};
pub use naad::dynamics::{
Compressor as SynthCompressor, EnvelopeDetector, Limiter as SynthLimiter, NoiseGate,
};
pub use naad::eq::{EqBand, ParametricEq as SynthParametricEq};
pub use naad::reverb::Reverb as SynthReverb;
pub use naad::effects::{Chorus, Distortion, DistortionType, Flanger, Phaser};
pub use naad::flush_denormal;
pub use naad::NaadError;
pub use naad::synth::subtractive::SubtractiveSynth;
pub use naad::synth::fm::{FmAlgorithm, FmOperator, FmSynthEngine as FmSynth};
pub use naad::synth::additive::{AdditiveSynth, Partial};
pub use naad::synth::drum::{HiHat, KickDrum, SnareDrum};
pub use naad::synth::formant::{FormantFilter as SynthFormantFilter, Vowel as SynthVowel};
pub use naad::synth::vocoder::Vocoder;
pub use naad::synth::granular::{GrainWindow, GranularEngine};
pub use naad::synth::physical::KarplusStrong;
pub fn render_to_buffer(
mut sample_fn: impl FnMut() -> f32,
channels: u32,
frames: usize,
sample_rate: u32,
) -> AudioBuffer {
let ch = channels as usize;
let mut samples = Vec::with_capacity(frames * ch);
for _ in 0..frames {
let s = sample_fn();
for _ in 0..ch {
samples.push(s);
}
}
AudioBuffer::from_interleaved(samples, channels, sample_rate)
.unwrap_or_else(|_| AudioBuffer::silence(channels.max(1), frames, sample_rate.max(1)))
}
pub fn render_stereo_to_buffer(
mut sample_fn: impl FnMut() -> (f32, f32),
frames: usize,
sample_rate: u32,
) -> AudioBuffer {
let mut samples = Vec::with_capacity(frames * 2);
for _ in 0..frames {
let (l, r) = sample_fn();
samples.push(l);
samples.push(r);
}
AudioBuffer::from_interleaved(samples, 2, sample_rate)
.unwrap_or_else(|_| AudioBuffer::silence(2, frames, sample_rate.max(1)))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn render_sine_to_buffer() {
let mut osc = Oscillator::new(Waveform::Sine, 440.0, 44100.0).unwrap();
let buf = render_to_buffer(|| osc.next_sample(), 2, 4410, 44100);
assert_eq!(buf.channels(), 2);
assert_eq!(buf.frames(), 4410);
assert!(buf.peak() > 0.9);
assert!(buf.samples().iter().all(|s| s.is_finite()));
}
#[test]
fn render_fm_synth() {
let mut fm = FmSynth::new(2, 44100.0).unwrap();
fm.set_algorithm(FmAlgorithm::Serial2);
fm.operator_mut(0).unwrap().set_frequency(440.0);
fm.operator_mut(0).unwrap().set_level(1.0);
fm.operator_mut(1).unwrap().set_frequency(880.0);
fm.operator_mut(1).unwrap().set_level(0.5);
fm.note_on();
let buf = render_to_buffer(|| fm.next_sample(), 1, 4410, 44100);
assert!(buf.rms() > 0.0);
}
#[test]
fn render_stereo_panned() {
let mut osc = Oscillator::new(Waveform::Saw, 220.0, 44100.0).unwrap();
let buf = render_stereo_to_buffer(
|| {
let s = osc.next_sample();
let gains = pan_gains(0.7, PanLaw::EqualPower);
(s * gains.left, s * gains.right)
},
4410,
44100,
);
assert_eq!(buf.channels(), 2);
assert!(buf.peak() > 0.5);
}
#[test]
fn subtractive_synth_works() {
let mut synth = SubtractiveSynth::new(Waveform::Saw, 440.0, 2000.0, 0.7, 44100.0).unwrap();
synth.note_on();
let buf = render_to_buffer(|| synth.next_sample(), 1, 4410, 44100);
assert!(buf.rms() > 0.0);
}
#[test]
fn granular_engine_works() {
let source: Vec<f32> = (0..44100)
.map(|i| (2.0 * std::f32::consts::PI * 440.0 * i as f32 / 44100.0).sin())
.collect();
let mut engine = GranularEngine::new(44100.0);
engine.set_source(source);
engine.set_grain_rate(20.0);
engine.set_grain_duration(50.0);
let buf = render_to_buffer(|| engine.next_sample(), 1, 4410, 44100);
assert!(buf.samples().iter().all(|s| s.is_finite()));
}
#[test]
fn karplus_strong_works() {
let mut ks = KarplusStrong::new(440.0, 0.99, 0.5, 44100.0).unwrap();
ks.pluck();
let buf = render_to_buffer(|| ks.next_sample(), 1, 4410, 44100);
assert!(buf.peak() > 0.0);
}
#[test]
fn drum_kick_works() {
let mut kick = KickDrum::new(150.0, 40.0, 200.0, 0.8, 44100.0).unwrap();
kick.trigger();
let buf = render_to_buffer(|| kick.next_sample(), 1, 4410, 44100);
assert!(buf.peak() > 0.0);
}
}