use crate::synthesis::spectral::{
FormantShifter as CoreFormantShifter, PhaseVocoder as CorePhaseVocoder,
SpectralBlur as CoreSpectralBlur, SpectralCompressor as CoreSpectralCompressor,
SpectralDynamics as CoreSpectralDynamics, SpectralFilter as CoreSpectralFilter,
SpectralFreeze as CoreSpectralFreeze, SpectralGate as CoreSpectralGate,
SpectralHarmonizer as CoreSpectralHarmonizer, SpectralPanner as CoreSpectralPanner,
SpectralResonator as CoreSpectralResonator, SpectralRobotize as CoreSpectralRobotize,
SpectralScramble as CoreSpectralScramble, WindowType,
};
pub use crate::synthesis::spectral::FilterType;
pub use crate::synthesis::spectral::HarmonyVoice;
pub use crate::synthesis::spectral::PanPoint;
pub use crate::synthesis::spectral::Resonance;
#[derive(Clone)]
pub struct PhaseVocoder {
core: CorePhaseVocoder,
pub priority: u8,
sample_rate: f32,
pub enabled: bool,
input_buffer: Vec<f32>,
}
impl PhaseVocoder {
pub fn new(time_stretch: f32, pitch_shift: f32, sample_rate: f32) -> Self {
Self::with_params(2048, 512, time_stretch, pitch_shift, sample_rate)
}
pub fn with_params(
fft_size: usize,
hop_size: usize,
time_stretch: f32,
pitch_shift: f32,
sample_rate: f32,
) -> Self {
let mut core = CorePhaseVocoder::new(fft_size, hop_size, sample_rate, WindowType::Hann);
core.set_time_stretch(time_stretch);
core.set_pitch_shift(pitch_shift);
Self {
core,
priority: 50, sample_rate,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn pitch_up() -> Self {
Self::new(1.0, 7.0, 44100.0)
}
pub fn pitch_down() -> Self {
Self::new(1.0, -7.0, 44100.0)
}
pub fn chipmunk() -> Self {
Self::new(1.0, 12.0, 44100.0)
}
pub fn slow_mo() -> Self {
Self::new(2.0, 0.0, 44100.0)
}
pub fn fast() -> Self {
Self::new(0.5, 0.0, 44100.0)
}
pub fn set_time_stretch(&mut self, ratio: f32) {
self.core.set_time_stretch(ratio);
}
pub fn set_pitch_shift(&mut self, semitones: f32) {
self.core.set_pitch_shift(semitones);
}
pub fn time_stretch(&self) -> f32 {
self.core.time_stretch()
}
pub fn pitch_shift(&self) -> f32 {
self.core.pitch_shift()
}
pub fn reset(&mut self) {
self.core.reset();
}
pub fn set_priority(&mut self, priority: u8) {
self.priority = priority;
}
pub fn process_block(
&mut self,
buffer: &mut [f32],
sample_rate: f32,
_time: f32,
_sample_count: u64,
) {
if !self.enabled {
return;
}
if (self.sample_rate - sample_rate).abs() > 0.1 {
self.sample_rate = sample_rate;
}
self.input_buffer.clear();
self.input_buffer.extend_from_slice(buffer);
self.core.process(buffer, &self.input_buffer);
}
}
impl std::fmt::Debug for PhaseVocoder {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PhaseVocoder")
.field("time_stretch", &self.core.time_stretch())
.field("pitch_shift", &self.core.pitch_shift())
.field("priority", &self.priority)
.field("enabled", &self.enabled)
.finish()
}
}
#[derive(Clone)]
pub struct SpectralFreeze {
core: CoreSpectralFreeze,
pub priority: u8,
pub enabled: bool,
input_buffer: Vec<f32>,
}
impl SpectralFreeze {
pub fn new(freeze: bool, mix: f32, _sample_rate: f32) -> Self {
Self::with_params(2048, 512, freeze, mix, _sample_rate)
}
pub fn with_params(
fft_size: usize,
hop_size: usize,
freeze: bool,
mix: f32,
_sample_rate: f32,
) -> Self {
let mut core = CoreSpectralFreeze::new(fft_size, hop_size, WindowType::Hann);
if freeze {
core.freeze();
}
core.set_mix(mix);
Self {
core,
priority: 50, enabled: true,
input_buffer: Vec::new(),
}
}
pub fn frozen() -> Self {
Self::new(true, 1.0, 44100.0)
}
pub fn shimmer() -> Self {
Self::new(true, 0.5, 44100.0)
}
pub fn glitch() -> Self {
Self::new(true, 0.3, 44100.0)
}
pub fn freeze(&mut self) {
self.core.freeze();
}
pub fn unfreeze(&mut self) {
self.core.unfreeze();
}
pub fn set_mix(&mut self, mix: f32) {
self.core.set_mix(mix);
}
pub fn is_frozen(&self) -> bool {
self.core.is_frozen()
}
pub fn mix(&self) -> f32 {
self.core.mix()
}
pub fn reset(&mut self) {
self.core.reset();
}
pub fn set_priority(&mut self, priority: u8) {
self.priority = priority;
}
pub fn process_block(
&mut self,
buffer: &mut [f32],
_sample_rate: f32,
_time: f32,
_sample_count: u64,
) {
if !self.enabled {
return;
}
self.input_buffer.clear();
self.input_buffer.extend_from_slice(buffer);
self.core.process(buffer, &self.input_buffer);
}
}
impl std::fmt::Debug for SpectralFreeze {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SpectralFreeze")
.field("is_frozen", &self.core.is_frozen())
.field("mix", &self.core.mix())
.field("priority", &self.priority)
.field("enabled", &self.enabled)
.finish()
}
}
#[derive(Clone)]
pub struct SpectralGate {
core: CoreSpectralGate,
pub priority: u8,
pub enabled: bool,
input_buffer: Vec<f32>,
}
impl SpectralGate {
pub fn new(threshold: f32, attack: f32, release: f32, ratio: f32, sample_rate: f32) -> Self {
Self::with_params(2048, 512, threshold, attack, release, ratio, sample_rate)
}
pub fn with_params(
fft_size: usize,
hop_size: usize,
threshold: f32,
attack: f32,
release: f32,
ratio: f32,
sample_rate: f32,
) -> Self {
let mut core = CoreSpectralGate::new(fft_size, hop_size, WindowType::Hann, sample_rate);
core.set_threshold(threshold);
core.set_attack(attack);
core.set_release(release);
core.set_ratio(ratio);
Self {
core,
priority: 50, enabled: true,
input_buffer: Vec::new(),
}
}
pub fn gentle() -> Self {
Self::new(-50.0, 10.0, 100.0, 0.2, 44100.0)
}
pub fn aggressive() -> Self {
Self::new(-35.0, 1.0, 50.0, 0.0, 44100.0)
}
pub fn denoise() -> Self {
Self::new(-60.0, 20.0, 150.0, 0.1, 44100.0)
}
pub fn tighten() -> Self {
Self::new(-40.0, 2.0, 80.0, 0.0, 44100.0)
}
pub fn set_threshold(&mut self, threshold_db: f32) {
self.core.set_threshold(threshold_db);
}
pub fn set_attack(&mut self, attack: f32) {
self.core.set_attack(attack);
}
pub fn set_release(&mut self, release: f32) {
self.core.set_release(release);
}
pub fn set_ratio(&mut self, ratio: f32) {
self.core.set_ratio(ratio);
}
pub fn threshold(&self) -> f32 {
self.core.threshold()
}
pub fn attack(&self) -> f32 {
self.core.attack()
}
pub fn release(&self) -> f32 {
self.core.release()
}
pub fn ratio(&self) -> f32 {
self.core.ratio()
}
pub fn reset(&mut self) {
self.core.reset();
}
pub fn set_priority(&mut self, priority: u8) {
self.priority = priority;
}
pub fn process_block(
&mut self,
buffer: &mut [f32],
_sample_rate: f32,
_time: f32,
_sample_count: u64,
) {
if !self.enabled {
return;
}
self.input_buffer.clear();
self.input_buffer.extend_from_slice(buffer);
self.core.process(buffer, &self.input_buffer);
}
}
impl std::fmt::Debug for SpectralGate {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SpectralGate")
.field("threshold", &self.core.threshold())
.field("attack", &self.core.attack())
.field("release", &self.core.release())
.field("ratio", &self.core.ratio())
.field("priority", &self.priority)
.field("enabled", &self.enabled)
.finish()
}
}
#[derive(Clone)]
pub struct SpectralCompressor {
core: CoreSpectralCompressor,
pub priority: u8,
pub enabled: bool,
input_buffer: Vec<f32>,
}
impl SpectralCompressor {
pub fn new(
threshold: f32,
ratio: f32,
attack: f32,
release: f32,
knee: f32,
sample_rate: f32,
) -> Self {
Self::with_params(
2048,
512,
threshold,
ratio,
attack,
release,
knee,
sample_rate,
)
}
#[allow(clippy::too_many_arguments)]
pub fn with_params(
fft_size: usize,
hop_size: usize,
threshold: f32,
ratio: f32,
attack: f32,
release: f32,
knee: f32,
sample_rate: f32,
) -> Self {
let mut core = CoreSpectralCompressor::new(
fft_size,
hop_size,
crate::synthesis::spectral::WindowType::Hann,
sample_rate,
);
core.set_threshold(threshold);
core.set_ratio(ratio);
core.set_attack(attack);
core.set_release(release);
core.set_knee(knee);
Self {
core,
priority: 50, enabled: true,
input_buffer: Vec::new(),
}
}
pub fn gentle() -> Self {
Self::new(-25.0, 2.0, 10.0, 80.0, 3.0, 44100.0)
}
pub fn aggressive() -> Self {
Self::new(-15.0, 6.0, 2.0, 40.0, 2.0, 44100.0)
}
pub fn glue() -> Self {
Self::new(-30.0, 3.0, 15.0, 100.0, 4.0, 44100.0)
}
pub fn tame_peaks() -> Self {
Self::new(-10.0, 8.0, 1.0, 30.0, 1.0, 44100.0)
}
pub fn set_threshold(&mut self, threshold_db: f32) {
self.core.set_threshold(threshold_db);
}
pub fn set_ratio(&mut self, ratio: f32) {
self.core.set_ratio(ratio);
}
pub fn set_attack(&mut self, attack_ms: f32) {
self.core.set_attack(attack_ms);
}
pub fn set_release(&mut self, release_ms: f32) {
self.core.set_release(release_ms);
}
pub fn set_knee(&mut self, knee_db: f32) {
self.core.set_knee(knee_db);
}
pub fn threshold(&self) -> f32 {
self.core.threshold()
}
pub fn ratio(&self) -> f32 {
self.core.ratio()
}
pub fn attack(&self) -> f32 {
self.core.attack()
}
pub fn release(&self) -> f32 {
self.core.release()
}
pub fn knee(&self) -> f32 {
self.core.knee()
}
pub fn process_block(
&mut self,
buffer: &mut [f32],
_sample_rate: f32,
_time: f32,
_sample_count: u64,
) {
if !self.enabled {
return;
}
self.input_buffer.clear();
self.input_buffer.extend_from_slice(buffer);
self.core.process(buffer, &self.input_buffer);
}
pub fn reset(&mut self) {
self.core.reset();
}
}
impl std::fmt::Debug for SpectralCompressor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SpectralCompressor")
.field("threshold", &self.core.threshold())
.field("ratio", &self.core.ratio())
.field("attack", &self.core.attack())
.field("release", &self.core.release())
.field("knee", &self.core.knee())
.field("priority", &self.priority)
.field("enabled", &self.enabled)
.finish()
}
}
#[derive(Clone)]
pub struct SpectralRobotize {
core: CoreSpectralRobotize,
pub priority: u8,
pub enabled: bool,
input_buffer: Vec<f32>,
}
impl SpectralRobotize {
pub fn new(target_phase: f32, mix: f32, _sample_rate: f32) -> Self {
Self::with_params(2048, 512, target_phase, mix, _sample_rate)
}
pub fn with_params(
fft_size: usize,
hop_size: usize,
target_phase: f32,
mix: f32,
_sample_rate: f32,
) -> Self {
let mut core = CoreSpectralRobotize::new(
fft_size,
hop_size,
crate::synthesis::spectral::WindowType::Hann,
);
core.set_target_phase(target_phase);
core.set_mix(mix);
Self {
core,
priority: 50, enabled: true,
input_buffer: Vec::new(),
}
}
pub fn robot() -> Self {
Self::new(0.0, 1.0, 44100.0)
}
pub fn vocoder() -> Self {
Self::new(0.0, 0.8, 44100.0)
}
pub fn metallic() -> Self {
Self::new(1.57, 0.9, 44100.0) }
pub fn set_target_phase(&mut self, phase: f32) {
self.core.set_target_phase(phase);
}
pub fn set_mix(&mut self, mix: f32) {
self.core.set_mix(mix);
}
pub fn target_phase(&self) -> f32 {
self.core.target_phase()
}
pub fn mix(&self) -> f32 {
self.core.mix()
}
pub fn process_block(
&mut self,
buffer: &mut [f32],
_sample_rate: f32,
_time: f32,
_sample_count: u64,
) {
if !self.enabled {
return;
}
self.input_buffer.clear();
self.input_buffer.extend_from_slice(buffer);
self.core.process(buffer, &self.input_buffer);
}
pub fn reset(&mut self) {
self.core.reset();
}
}
impl std::fmt::Debug for SpectralRobotize {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SpectralRobotize")
.field("target_phase", &self.core.target_phase())
.field("mix", &self.core.mix())
.field("priority", &self.priority)
.field("enabled", &self.enabled)
.finish()
}
}
pub struct SpectralDelay {
core: crate::synthesis::spectral::SpectralDelay,
pub priority: u8,
pub enabled: bool,
input_buffer: Vec<f32>,
}
impl SpectralDelay {
pub fn new(
delay_time: f32,
feedback: f32,
frequency_scale: f32,
mix: f32,
sample_rate: f32,
) -> Self {
Self::with_params(
2048,
512,
delay_time,
feedback,
frequency_scale,
mix,
sample_rate,
)
}
pub fn with_params(
fft_size: usize,
hop_size: usize,
delay_time: f32,
feedback: f32,
frequency_scale: f32,
mix: f32,
sample_rate: f32,
) -> Self {
Self {
core: crate::synthesis::spectral::SpectralDelay::with_params(
fft_size,
hop_size,
sample_rate,
delay_time,
feedback,
frequency_scale,
mix,
),
priority: 100,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn shimmer() -> Self {
Self::new(200.0, 0.4, 1.5, 0.6, 44100.0)
}
pub fn cascade() -> Self {
Self::new(150.0, 0.5, 0.5, 0.7, 44100.0)
}
pub fn echo() -> Self {
Self::new(250.0, 0.3, 1.0, 0.5, 44100.0)
}
pub fn harmonic() -> Self {
Self::new(100.0, 0.6, 2.0, 0.5, 44100.0)
}
pub fn set_delay_time(&mut self, delay_time: f32) {
self.core.set_delay_time(delay_time);
}
pub fn delay_time(&self) -> f32 {
self.core.delay_time()
}
pub fn set_feedback(&mut self, feedback: f32) {
self.core.set_feedback(feedback);
}
pub fn feedback(&self) -> f32 {
self.core.feedback()
}
pub fn set_frequency_scale(&mut self, scale: f32) {
self.core.set_frequency_scale(scale);
}
pub fn frequency_scale(&self) -> f32 {
self.core.frequency_scale()
}
pub fn set_mix(&mut self, mix: f32) {
self.core.set_mix(mix);
}
pub fn mix(&self) -> f32 {
self.core.mix()
}
pub fn clear_buffers(&mut self) {
self.core.clear_buffers();
}
pub fn process_block(
&mut self,
buffer: &mut [f32],
_sample_rate: f32,
_time: f32,
_sample_count: u64,
) {
if !self.enabled {
return;
}
self.input_buffer.clear();
self.input_buffer.extend_from_slice(buffer);
self.core.process(buffer, &self.input_buffer);
}
pub fn reset(&mut self) {
self.core.reset();
}
}
impl Clone for SpectralDelay {
fn clone(&self) -> Self {
Self {
core: self.core.clone(),
priority: self.priority,
enabled: self.enabled,
input_buffer: Vec::new(),
}
}
}
impl std::fmt::Debug for SpectralDelay {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SpectralDelay")
.field("delay_time", &self.core.delay_time())
.field("feedback", &self.core.feedback())
.field("frequency_scale", &self.core.frequency_scale())
.field("mix", &self.core.mix())
.field("priority", &self.priority)
.field("enabled", &self.enabled)
.finish()
}
}
#[derive(Clone)]
pub struct SpectralFilter {
core: CoreSpectralFilter,
pub priority: u8,
pub enabled: bool,
input_buffer: Vec<f32>,
}
impl SpectralFilter {
pub fn new(
filter_type: FilterType,
cutoff: f32,
resonance: f32,
mix: f32,
sample_rate: f32,
) -> Self {
Self::with_params(2048, 512, filter_type, cutoff, resonance, mix, sample_rate)
}
pub fn with_params(
fft_size: usize,
hop_size: usize,
filter_type: FilterType,
cutoff: f32,
resonance: f32,
mix: f32,
sample_rate: f32,
) -> Self {
let mut core = CoreSpectralFilter::new(fft_size, hop_size, WindowType::Hann, sample_rate);
core.set_filter_type(filter_type);
core.set_cutoff(cutoff);
core.set_resonance(resonance);
core.set_mix(mix);
Self {
core,
priority: 50,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn low_pass() -> Self {
Self::new(FilterType::LowPass, 1000.0, 1.0, 1.0, 44100.0)
}
pub fn high_pass() -> Self {
Self::new(FilterType::HighPass, 200.0, 1.0, 1.0, 44100.0)
}
pub fn band_pass() -> Self {
Self::new(FilterType::BandPass, 1000.0, 2.0, 1.0, 44100.0)
}
pub fn telephone() -> Self {
Self::new(FilterType::BandPass, 1200.0, 8.0, 1.0, 44100.0)
}
pub fn radio() -> Self {
Self::new(FilterType::BandPass, 2000.0, 5.0, 1.0, 44100.0)
}
pub fn rumble_cut() -> Self {
Self::new(FilterType::HighPass, 80.0, 1.5, 1.0, 44100.0)
}
pub fn air_cut() -> Self {
Self::new(FilterType::LowPass, 8000.0, 1.0, 1.0, 44100.0)
}
pub fn set_filter_type(&mut self, filter_type: FilterType) {
self.core.set_filter_type(filter_type);
}
pub fn set_cutoff(&mut self, cutoff: f32) {
self.core.set_cutoff(cutoff);
}
pub fn set_resonance(&mut self, resonance: f32) {
self.core.set_resonance(resonance);
}
pub fn set_mix(&mut self, mix: f32) {
self.core.set_mix(mix);
}
pub fn process_block(
&mut self,
buffer: &mut [f32],
_sample_rate: f32,
_time: f32,
_sample_count: u64,
) {
if !self.enabled {
return;
}
self.input_buffer.clear();
self.input_buffer.extend_from_slice(buffer);
self.core.process(buffer, &self.input_buffer);
}
pub fn reset(&mut self) {
self.core.reset();
}
pub fn boxed(self) -> Box<Self> {
Box::new(self)
}
pub fn priority(&self) -> u8 {
self.priority
}
pub fn set_priority(&mut self, priority: u8) {
self.priority = priority;
}
pub fn is_enabled(&self) -> bool {
self.enabled
}
pub fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
}
pub fn duplicate(&self) -> Self {
Self {
core: self.core.clone(),
priority: self.priority,
enabled: self.enabled,
input_buffer: Vec::new(),
}
}
}
impl std::fmt::Debug for SpectralFilter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SpectralFilter")
.field("priority", &self.priority)
.field("enabled", &self.enabled)
.finish()
}
}
#[derive(Clone)]
pub struct SpectralBlur {
core: CoreSpectralBlur,
pub priority: u8,
pub enabled: bool,
input_buffer: Vec<f32>,
}
impl SpectralBlur {
pub fn new(blur_amount: f32, feedback: f32, mix: f32, sample_rate: f32) -> Self {
Self::with_params(2048, 512, blur_amount, feedback, mix, sample_rate)
}
pub fn with_params(
fft_size: usize,
hop_size: usize,
blur_amount: f32,
feedback: f32,
mix: f32,
sample_rate: f32,
) -> Self {
let mut core = CoreSpectralBlur::new(fft_size, hop_size, WindowType::Hann, sample_rate);
core.set_blur_amount(blur_amount);
core.set_feedback(feedback);
core.set_mix(mix);
Self {
core,
priority: 50,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn subtle() -> Self {
Self::new(0.3, 0.2, 0.5, 44100.0)
}
pub fn gentle() -> Self {
Self::new(0.5, 0.3, 0.7, 44100.0)
}
pub fn dreamy() -> Self {
Self::new(0.7, 0.5, 0.8, 44100.0)
}
pub fn heavy() -> Self {
Self::new(0.9, 0.7, 1.0, 44100.0)
}
pub fn shimmer() -> Self {
Self::new(0.6, 0.8, 0.9, 44100.0)
}
pub fn set_blur_amount(&mut self, amount: f32) {
self.core.set_blur_amount(amount);
}
pub fn blur_amount(&self) -> f32 {
self.core.blur_amount()
}
pub fn set_feedback(&mut self, feedback: f32) {
self.core.set_feedback(feedback);
}
pub fn feedback(&self) -> f32 {
self.core.feedback()
}
pub fn set_mix(&mut self, mix: f32) {
self.core.set_mix(mix);
}
pub fn mix(&self) -> f32 {
self.core.mix()
}
pub fn process_block(
&mut self,
buffer: &mut [f32],
_sample_rate: f32,
_time: f32,
_sample_count: u64,
) {
if !self.enabled {
return;
}
self.input_buffer.clear();
self.input_buffer.extend_from_slice(buffer);
self.core.process(buffer, &self.input_buffer);
}
pub fn reset(&mut self) {
self.core.reset();
}
pub fn boxed(self) -> Box<Self> {
Box::new(self)
}
pub fn priority(&self) -> u8 {
self.priority
}
pub fn set_priority(&mut self, priority: u8) {
self.priority = priority;
}
pub fn is_enabled(&self) -> bool {
self.enabled
}
pub fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
}
pub fn duplicate(&self) -> Self {
Self {
core: self.core.clone(),
priority: self.priority,
enabled: self.enabled,
input_buffer: Vec::new(),
}
}
}
impl std::fmt::Debug for SpectralBlur {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SpectralBlur")
.field("blur_amount", &self.core.blur_amount())
.field("feedback", &self.core.feedback())
.field("mix", &self.core.mix())
.field("priority", &self.priority)
.field("enabled", &self.enabled)
.finish()
}
}
use crate::synthesis::spectral::SpectralShift as CoreSpectralShift;
#[derive(Clone)]
pub struct SpectralShift {
core: CoreSpectralShift,
pub priority: u8,
pub enabled: bool,
input_buffer: Vec<f32>,
}
impl SpectralShift {
pub fn new(shift_hz: f32, mix: f32, sample_rate: f32) -> Self {
Self::with_params(2048, 512, shift_hz, mix, sample_rate)
}
pub fn with_params(
fft_size: usize,
hop_size: usize,
shift_hz: f32,
mix: f32,
sample_rate: f32,
) -> Self {
let mut core = CoreSpectralShift::new(fft_size, hop_size, WindowType::Hann, sample_rate);
core.set_shift_hz(shift_hz);
core.set_mix(mix);
Self {
core,
priority: 145,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn subtle() -> Self {
Self::new(7.0, 0.5, 44100.0)
}
pub fn metallic() -> Self {
Self::new(75.0, 0.8, 44100.0)
}
pub fn bell() -> Self {
Self::new(150.0, 0.9, 44100.0)
}
pub fn alien() -> Self {
Self::new(300.0, 1.0, 44100.0)
}
pub fn down() -> Self {
Self::new(-100.0, 0.8, 44100.0)
}
pub fn set_shift_hz(&mut self, shift_hz: f32) {
self.core.set_shift_hz(shift_hz);
}
pub fn shift_hz(&self) -> f32 {
self.core.shift_hz()
}
pub fn set_mix(&mut self, mix: f32) {
self.core.set_mix(mix);
}
pub fn mix(&self) -> f32 {
self.core.mix()
}
pub fn process_block(
&mut self,
buffer: &mut [f32],
_sample_rate: f32,
_time: f32,
_sample_count: u64,
) {
if !self.enabled {
return;
}
self.input_buffer.clear();
self.input_buffer.extend_from_slice(buffer);
self.core.process(buffer, &self.input_buffer);
}
pub fn reset(&mut self) {
self.core.reset();
}
pub fn boxed(self) -> Box<Self> {
Box::new(self)
}
pub fn priority(&self) -> u8 {
self.priority
}
pub fn set_priority(&mut self, priority: u8) {
self.priority = priority;
}
pub fn is_enabled(&self) -> bool {
self.enabled
}
pub fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
}
pub fn duplicate(&self) -> Self {
Self {
core: self.core.clone(),
priority: self.priority,
enabled: self.enabled,
input_buffer: Vec::new(),
}
}
}
impl std::fmt::Debug for SpectralShift {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SpectralShift")
.field("shift_hz", &self.core.shift_hz())
.field("mix", &self.core.mix())
.field("priority", &self.priority)
.field("enabled", &self.enabled)
.finish()
}
}
use crate::synthesis::spectral::SpectralExciter as CoreSpectralExciter;
#[derive(Clone)]
pub struct SpectralExciter {
core: CoreSpectralExciter,
pub priority: u8,
pub enabled: bool,
input_buffer: Vec<f32>,
}
impl SpectralExciter {
pub fn new(frequency: f32, drive: f32, harmonics: f32, mix: f32, sample_rate: f32) -> Self {
Self::with_params(2048, 512, frequency, drive, harmonics, mix, sample_rate)
}
pub fn with_params(
fft_size: usize,
hop_size: usize,
frequency: f32,
drive: f32,
harmonics: f32,
mix: f32,
sample_rate: f32,
) -> Self {
let mut core = CoreSpectralExciter::new(fft_size, hop_size, WindowType::Hann, sample_rate);
core.set_frequency(frequency);
core.set_drive(drive);
core.set_harmonics(harmonics);
core.set_mix(mix);
Self {
core,
priority: 150,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn gentle() -> Self {
Self::new(5000.0, 1.5, 0.3, 0.25, 44100.0)
}
pub fn moderate() -> Self {
Self::new(3500.0, 2.5, 0.5, 0.4, 44100.0)
}
pub fn aggressive() -> Self {
Self::new(2500.0, 4.0, 0.7, 0.6, 44100.0)
}
pub fn air() -> Self {
Self::new(8000.0, 2.0, 0.8, 0.3, 44100.0)
}
pub fn presence() -> Self {
Self::new(2000.0, 3.0, 0.4, 0.5, 44100.0)
}
pub fn set_frequency(&mut self, frequency: f32) {
self.core.set_frequency(frequency);
}
pub fn frequency(&self) -> f32 {
self.core.frequency()
}
pub fn set_drive(&mut self, drive: f32) {
self.core.set_drive(drive);
}
pub fn drive(&self) -> f32 {
self.core.drive()
}
pub fn set_harmonics(&mut self, harmonics: f32) {
self.core.set_harmonics(harmonics);
}
pub fn harmonics(&self) -> f32 {
self.core.harmonics()
}
pub fn set_mix(&mut self, mix: f32) {
self.core.set_mix(mix);
}
pub fn mix(&self) -> f32 {
self.core.mix()
}
pub fn process_block(
&mut self,
buffer: &mut [f32],
_sample_rate: f32,
_time: f32,
_sample_count: u64,
) {
if !self.enabled {
return;
}
self.input_buffer.clear();
self.input_buffer.extend_from_slice(buffer);
self.core.process(buffer, &self.input_buffer);
}
pub fn reset(&mut self) {
self.core.reset();
}
pub fn boxed(self) -> Box<Self> {
Box::new(self)
}
pub fn priority(&self) -> u8 {
self.priority
}
pub fn set_priority(&mut self, priority: u8) {
self.priority = priority;
}
pub fn is_enabled(&self) -> bool {
self.enabled
}
pub fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
}
pub fn duplicate(&self) -> Self {
Self {
core: self.core.clone(),
priority: self.priority,
enabled: self.enabled,
input_buffer: Vec::new(),
}
}
}
impl std::fmt::Debug for SpectralExciter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SpectralExciter")
.field("frequency", &self.core.frequency())
.field("drive", &self.core.drive())
.field("harmonics", &self.core.harmonics())
.field("mix", &self.core.mix())
.field("priority", &self.priority)
.field("enabled", &self.enabled)
.finish()
}
}
use crate::synthesis::spectral::SpectralInvert as CoreSpectralInvert;
#[derive(Clone)]
pub struct SpectralInvert {
core: CoreSpectralInvert,
pub priority: u8,
pub enabled: bool,
input_buffer: Vec<f32>,
}
impl SpectralInvert {
pub fn new(mix: f32, sample_rate: f32) -> Self {
Self::with_params(2048, 512, mix, sample_rate)
}
pub fn with_params(fft_size: usize, hop_size: usize, mix: f32, sample_rate: f32) -> Self {
let mut core = CoreSpectralInvert::new(fft_size, hop_size, WindowType::Hann, sample_rate);
core.set_mix(mix);
Self {
core,
priority: 160,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn subtle() -> Self {
Self::new(0.3, 44100.0)
}
pub fn full() -> Self {
Self::new(1.0, 44100.0)
}
pub fn moderate() -> Self {
Self::new(0.6, 44100.0)
}
pub fn set_mix(&mut self, mix: f32) {
self.core.set_mix(mix);
}
pub fn mix(&self) -> f32 {
self.core.mix()
}
pub fn process_block(
&mut self,
buffer: &mut [f32],
_sample_rate: f32,
_time: f32,
_sample_count: u64,
) {
if !self.enabled {
return;
}
self.input_buffer.clear();
self.input_buffer.extend_from_slice(buffer);
self.core.process(buffer, &self.input_buffer);
}
pub fn reset(&mut self) {
self.core.reset();
}
pub fn boxed(self) -> Box<Self> {
Box::new(self)
}
pub fn priority(&self) -> u8 {
self.priority
}
pub fn set_priority(&mut self, priority: u8) {
self.priority = priority;
}
pub fn is_enabled(&self) -> bool {
self.enabled
}
pub fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
}
pub fn duplicate(&self) -> Self {
Self {
core: self.core.clone(),
priority: self.priority,
enabled: self.enabled,
input_buffer: Vec::new(),
}
}
}
impl std::fmt::Debug for SpectralInvert {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SpectralInvert")
.field("mix", &self.core.mix())
.field("priority", &self.priority)
.field("enabled", &self.enabled)
.finish()
}
}
use crate::synthesis::spectral::SpectralWiden as CoreSpectralWiden;
#[derive(Clone)]
pub struct SpectralWiden {
core: CoreSpectralWiden,
pub priority: u8,
pub enabled: bool,
input_buffer: Vec<f32>,
}
impl SpectralWiden {
pub fn new(width: f32, low_cutoff: f32, high_cutoff: f32, sample_rate: f32) -> Self {
Self::with_params(2048, 512, width, low_cutoff, high_cutoff, sample_rate)
}
pub fn with_params(
fft_size: usize,
hop_size: usize,
width: f32,
low_cutoff: f32,
high_cutoff: f32,
sample_rate: f32,
) -> Self {
let mut core = CoreSpectralWiden::new(fft_size, hop_size, WindowType::Hann, sample_rate);
core.set_width(width);
core.set_low_cutoff(low_cutoff);
core.set_high_cutoff(high_cutoff);
Self {
core,
priority: 165,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn subtle() -> Self {
Self::new(1.2, 250.0, 16000.0, 44100.0)
}
pub fn moderate() -> Self {
Self::new(1.5, 200.0, 16000.0, 44100.0)
}
pub fn wide() -> Self {
Self::new(2.0, 150.0, 16000.0, 44100.0)
}
pub fn ultra() -> Self {
Self::new(2.5, 200.0, 16000.0, 44100.0)
}
pub fn set_width(&mut self, width: f32) {
self.core.set_width(width);
}
pub fn width(&self) -> f32 {
self.core.width()
}
pub fn set_low_cutoff(&mut self, frequency: f32) {
self.core.set_low_cutoff(frequency);
}
pub fn low_cutoff(&self) -> f32 {
self.core.low_cutoff()
}
pub fn set_high_cutoff(&mut self, frequency: f32) {
self.core.set_high_cutoff(frequency);
}
pub fn high_cutoff(&self) -> f32 {
self.core.high_cutoff()
}
pub fn process_block(
&mut self,
buffer: &mut [f32],
_sample_rate: f32,
_time: f32,
_sample_count: u64,
) {
if !self.enabled {
return;
}
self.input_buffer.clear();
self.input_buffer.extend_from_slice(buffer);
self.core.process(buffer, &self.input_buffer);
}
pub fn reset(&mut self) {
self.core.reset();
}
pub fn boxed(self) -> Box<Self> {
Box::new(self)
}
pub fn priority(&self) -> u8 {
self.priority
}
pub fn set_priority(&mut self, priority: u8) {
self.priority = priority;
}
pub fn is_enabled(&self) -> bool {
self.enabled
}
pub fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
}
pub fn duplicate(&self) -> Self {
Self {
core: self.core.clone(),
priority: self.priority,
enabled: self.enabled,
input_buffer: Vec::new(),
}
}
}
impl std::fmt::Debug for SpectralWiden {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SpectralWiden")
.field("width", &self.core.width())
.field("low_cutoff", &self.core.low_cutoff())
.field("high_cutoff", &self.core.high_cutoff())
.field("priority", &self.priority)
.field("enabled", &self.enabled)
.finish()
}
}
use crate::synthesis::spectral::SpectralMorph as CoreSpectralMorph;
pub use crate::synthesis::spectral::MorphTarget as SpectralMorphTarget;
#[derive(Clone)]
pub struct SpectralMorph {
core: CoreSpectralMorph,
pub priority: u8,
pub enabled: bool,
input_buffer: Vec<f32>,
}
impl SpectralMorph {
pub fn new(
target: SpectralMorphTarget,
morph_amount: f32,
fundamental: f32,
sample_rate: f32,
) -> Self {
Self::with_params(2048, 512, target, morph_amount, fundamental, sample_rate)
}
pub fn with_params(
fft_size: usize,
hop_size: usize,
target: SpectralMorphTarget,
morph_amount: f32,
fundamental: f32,
sample_rate: f32,
) -> Self {
let mut core = CoreSpectralMorph::new(fft_size, hop_size, WindowType::Hann, sample_rate);
core.set_target(target);
core.set_morph_amount(morph_amount);
core.set_fundamental(fundamental);
Self {
core,
priority: 170,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn harmonic() -> Self {
Self::new(SpectralMorphTarget::Harmonic, 0.7, 110.0, 44100.0)
}
pub fn noise() -> Self {
Self::new(SpectralMorphTarget::Noise, 0.6, 110.0, 44100.0)
}
pub fn whisper() -> Self {
Self::new(SpectralMorphTarget::Whisper, 0.8, 110.0, 44100.0)
}
pub fn robot() -> Self {
Self::new(SpectralMorphTarget::Robot, 0.9, 220.0, 44100.0)
}
pub fn set_target(&mut self, target: SpectralMorphTarget) {
self.core.set_target(target);
}
pub fn target(&self) -> SpectralMorphTarget {
self.core.target()
}
pub fn set_morph_amount(&mut self, amount: f32) {
self.core.set_morph_amount(amount);
}
pub fn morph_amount(&self) -> f32 {
self.core.morph_amount()
}
pub fn set_fundamental(&mut self, frequency: f32) {
self.core.set_fundamental(frequency);
}
pub fn fundamental(&self) -> f32 {
self.core.fundamental()
}
pub fn process_block(
&mut self,
buffer: &mut [f32],
_sample_rate: f32,
_time: f32,
_sample_count: u64,
) {
if !self.enabled {
return;
}
self.input_buffer.clear();
self.input_buffer.extend_from_slice(buffer);
self.core.process(buffer, &self.input_buffer);
}
pub fn reset(&mut self) {
self.core.reset();
}
pub fn boxed(self) -> Box<Self> {
Box::new(self)
}
pub fn priority(&self) -> u8 {
self.priority
}
pub fn set_priority(&mut self, priority: u8) {
self.priority = priority;
}
pub fn is_enabled(&self) -> bool {
self.enabled
}
pub fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
}
pub fn duplicate(&self) -> Self {
Self {
core: self.core.clone(),
priority: self.priority,
enabled: self.enabled,
input_buffer: Vec::new(),
}
}
}
impl std::fmt::Debug for SpectralMorph {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SpectralMorph")
.field("target", &self.core.target())
.field("morph_amount", &self.core.morph_amount())
.field("fundamental", &self.core.fundamental())
.field("priority", &self.priority)
.field("enabled", &self.enabled)
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_phase_vocoder_creation() {
let vocoder = PhaseVocoder::new(1.0, 0.0, 44100.0);
assert_eq!(vocoder.time_stretch(), 1.0);
assert_eq!(vocoder.pitch_shift(), 0.0);
assert!(vocoder.enabled);
}
#[test]
fn test_phase_vocoder_time_stretch() {
let mut vocoder = PhaseVocoder::new(1.0, 0.0, 44100.0);
vocoder.set_time_stretch(2.0);
assert_eq!(vocoder.time_stretch(), 2.0);
}
#[test]
fn test_phase_vocoder_pitch_shift() {
let mut vocoder = PhaseVocoder::new(1.0, 0.0, 44100.0);
vocoder.set_pitch_shift(12.0);
assert_eq!(vocoder.pitch_shift(), 12.0);
}
#[test]
fn test_phase_vocoder_process_block() {
let mut vocoder = PhaseVocoder::new(1.0, 0.0, 44100.0);
let mut buffer = vec![0.0; 512];
vocoder.process_block(&mut buffer, 44100.0, 0.0, 0);
assert_eq!(buffer.len(), 512);
}
#[test]
fn test_phase_vocoder_reset() {
let mut vocoder = PhaseVocoder::new(1.0, 0.0, 44100.0);
vocoder.set_pitch_shift(7.0);
vocoder.reset();
assert_eq!(vocoder.pitch_shift(), 7.0);
}
#[test]
fn test_spectral_freeze_creation() {
let freeze = SpectralFreeze::new(false, 1.0, 44100.0);
assert!(!freeze.is_frozen());
assert_eq!(freeze.mix(), 1.0);
assert!(freeze.enabled);
}
#[test]
fn test_spectral_freeze_freeze_unfreeze() {
let mut freeze = SpectralFreeze::new(false, 1.0, 44100.0);
assert!(!freeze.is_frozen());
freeze.freeze();
assert!(freeze.is_frozen());
freeze.unfreeze();
assert!(!freeze.is_frozen());
}
#[test]
fn test_spectral_freeze_set_mix() {
let mut freeze = SpectralFreeze::new(false, 1.0, 44100.0);
freeze.set_mix(0.5);
assert_eq!(freeze.mix(), 0.5);
freeze.set_mix(0.0);
assert_eq!(freeze.mix(), 0.0);
freeze.set_mix(1.0);
assert_eq!(freeze.mix(), 1.0);
}
#[test]
fn test_spectral_freeze_process_block() {
let mut freeze = SpectralFreeze::new(true, 1.0, 44100.0);
let mut buffer = vec![0.0; 512];
freeze.process_block(&mut buffer, 44100.0, 0.0, 0);
assert_eq!(buffer.len(), 512);
}
#[test]
fn test_spectral_freeze_disabled() {
let mut freeze = SpectralFreeze::new(true, 1.0, 44100.0);
freeze.enabled = false;
let mut buffer = vec![1.0; 512];
freeze.process_block(&mut buffer, 44100.0, 0.0, 0);
assert_eq!(buffer[0], 1.0);
}
#[test]
fn test_spectral_freeze_reset() {
let mut freeze = SpectralFreeze::new(true, 1.0, 44100.0);
freeze.reset();
assert!(!freeze.is_frozen());
}
#[test]
fn test_spectral_freeze_with_params() {
let freeze = SpectralFreeze::with_params(4096, 1024, false, 1.0, 44100.0);
assert!(!freeze.is_frozen());
assert!(freeze.enabled);
}
#[test]
fn test_spectral_gate_creation() {
let gate = SpectralGate::new(-40.0, 1.0, 50.0, 0.0, 44100.0);
assert_eq!(gate.threshold(), -40.0);
assert!(gate.enabled);
}
#[test]
fn test_spectral_gate_set_threshold() {
let mut gate = SpectralGate::new(-40.0, 1.0, 50.0, 0.0, 44100.0);
gate.set_threshold(-30.0);
assert_eq!(gate.threshold(), -30.0);
gate.set_threshold(-60.0);
assert_eq!(gate.threshold(), -60.0);
}
#[test]
fn test_spectral_gate_set_attack() {
let mut gate = SpectralGate::new(-40.0, 1.0, 50.0, 0.0, 44100.0);
gate.set_attack(0.01);
assert_eq!(gate.attack(), 0.01);
}
#[test]
fn test_spectral_gate_set_release() {
let mut gate = SpectralGate::new(-40.0, 1.0, 50.0, 0.0, 44100.0);
gate.set_release(0.1);
assert_eq!(gate.release(), 0.1);
}
#[test]
fn test_spectral_gate_set_ratio() {
let mut gate = SpectralGate::new(-40.0, 1.0, 50.0, 0.0, 44100.0);
gate.set_ratio(0.5);
assert_eq!(gate.ratio(), 0.5);
}
#[test]
fn test_spectral_gate_process_block() {
let mut gate = SpectralGate::new(-40.0, 1.0, 50.0, 0.0, 44100.0);
gate.set_threshold(-40.0);
let mut buffer = vec![0.0; 512];
gate.process_block(&mut buffer, 44100.0, 0.0, 0);
assert_eq!(buffer.len(), 512);
}
#[test]
fn test_spectral_gate_disabled() {
let mut gate = SpectralGate::new(-40.0, 1.0, 50.0, 0.0, 44100.0);
gate.enabled = false;
let mut buffer = vec![1.0; 512];
gate.process_block(&mut buffer, 44100.0, 0.0, 0);
assert_eq!(buffer[0], 1.0);
}
#[test]
fn test_spectral_gate_reset() {
let mut gate = SpectralGate::new(-40.0, 1.0, 50.0, 0.0, 44100.0);
gate.reset();
let mut buffer = vec![0.0; 512];
gate.process_block(&mut buffer, 44100.0, 0.0, 0);
assert_eq!(buffer.len(), 512);
}
#[test]
fn test_spectral_gate_with_params() {
let gate = SpectralGate::with_params(4096, 1024, -40.0, 1.0, 50.0, 0.0, 44100.0);
assert!(gate.enabled);
}
#[test]
fn test_spectral_compressor_creation() {
let comp = SpectralCompressor::new(-20.0, 4.0, 5.0, 50.0, 6.0, 44100.0);
assert!(comp.enabled);
assert_eq!(comp.priority, 50);
}
#[test]
fn test_spectral_compressor_set_threshold() {
let mut comp = SpectralCompressor::new(-20.0, 4.0, 5.0, 50.0, 6.0, 44100.0);
comp.set_threshold(-30.0);
assert_eq!(comp.threshold(), -30.0);
}
#[test]
fn test_spectral_compressor_set_ratio() {
let mut comp = SpectralCompressor::new(-20.0, 4.0, 5.0, 50.0, 6.0, 44100.0);
comp.set_ratio(8.0);
assert_eq!(comp.ratio(), 8.0);
}
#[test]
fn test_spectral_compressor_set_attack() {
let mut comp = SpectralCompressor::new(-20.0, 4.0, 5.0, 50.0, 6.0, 44100.0);
comp.set_attack(10.0);
assert_eq!(comp.attack(), 10.0);
}
#[test]
fn test_spectral_compressor_set_release() {
let mut comp = SpectralCompressor::new(-20.0, 4.0, 5.0, 50.0, 6.0, 44100.0);
comp.set_release(100.0);
assert_eq!(comp.release(), 100.0);
}
#[test]
fn test_spectral_compressor_set_knee() {
let mut comp = SpectralCompressor::new(-20.0, 4.0, 5.0, 50.0, 6.0, 44100.0);
comp.set_knee(12.0);
assert_eq!(comp.knee(), 12.0);
}
#[test]
fn test_spectral_compressor_process_block() {
let mut comp = SpectralCompressor::new(-20.0, 4.0, 5.0, 50.0, 6.0, 44100.0);
let mut buffer = vec![0.0; 512];
comp.process_block(&mut buffer, 44100.0, 0.0, 0);
assert_eq!(buffer.len(), 512);
}
#[test]
fn test_spectral_compressor_disabled() {
let mut comp = SpectralCompressor::new(-20.0, 4.0, 5.0, 50.0, 6.0, 44100.0);
comp.enabled = false;
let mut buffer = vec![1.0; 512];
comp.process_block(&mut buffer, 44100.0, 0.0, 0);
assert_eq!(buffer[0], 1.0);
}
#[test]
fn test_spectral_compressor_reset() {
let mut comp = SpectralCompressor::new(-20.0, 4.0, 5.0, 50.0, 6.0, 44100.0);
comp.reset();
let mut buffer = vec![0.0; 512];
comp.process_block(&mut buffer, 44100.0, 0.0, 0);
assert_eq!(buffer.len(), 512);
}
#[test]
fn test_spectral_compressor_with_params() {
let comp = SpectralCompressor::with_params(4096, 1024, -20.0, 4.0, 5.0, 50.0, 6.0, 44100.0);
assert!(comp.enabled);
}
#[test]
fn test_spectral_robotize_creation() {
let robotize = SpectralRobotize::new(0.0, 1.0, 44100.0);
assert!(robotize.enabled);
assert_eq!(robotize.priority, 50);
assert_eq!(robotize.target_phase(), 0.0);
assert_eq!(robotize.mix(), 1.0);
}
#[test]
fn test_spectral_robotize_set_target_phase() {
let mut robotize = SpectralRobotize::new(0.0, 1.0, 44100.0);
robotize.set_target_phase(std::f32::consts::PI);
assert_eq!(robotize.target_phase(), std::f32::consts::PI);
}
#[test]
fn test_spectral_robotize_set_mix() {
let mut robotize = SpectralRobotize::new(0.0, 1.0, 44100.0);
robotize.set_mix(0.5);
assert_eq!(robotize.mix(), 0.5);
}
#[test]
fn test_spectral_robotize_process_block() {
let mut robotize = SpectralRobotize::new(0.0, 1.0, 44100.0);
let mut buffer = vec![0.0; 512];
robotize.process_block(&mut buffer, 44100.0, 0.0, 0);
assert_eq!(buffer.len(), 512);
}
#[test]
fn test_spectral_robotize_disabled() {
let mut robotize = SpectralRobotize::new(0.0, 1.0, 44100.0);
robotize.enabled = false;
let mut buffer = vec![1.0; 512];
robotize.process_block(&mut buffer, 44100.0, 0.0, 0);
assert_eq!(buffer[0], 1.0);
}
#[test]
fn test_spectral_robotize_reset() {
let mut robotize = SpectralRobotize::new(0.0, 1.0, 44100.0);
robotize.reset();
let mut buffer = vec![0.0; 512];
robotize.process_block(&mut buffer, 44100.0, 0.0, 0);
assert_eq!(buffer.len(), 512);
}
#[test]
fn test_spectral_robotize_with_params() {
let robotize = SpectralRobotize::with_params(4096, 1024, 0.0, 0.5, 44100.0);
assert!(robotize.enabled);
}
#[test]
fn test_spectral_delay_creation() {
let delay = SpectralDelay::new(100.0, 0.3, 0.0, 0.5, 44100.0);
assert_eq!(delay.priority, 100);
assert!(delay.enabled);
assert_eq!(delay.delay_time(), 100.0);
}
#[test]
fn test_spectral_delay_set_delay_time() {
let mut delay = SpectralDelay::new(100.0, 0.3, 0.0, 0.5, 44100.0);
delay.set_delay_time(200.0);
assert_eq!(delay.delay_time(), 200.0);
}
#[test]
fn test_spectral_delay_set_feedback() {
let mut delay = SpectralDelay::new(100.0, 0.3, 0.0, 0.5, 44100.0);
delay.set_feedback(0.7);
assert_eq!(delay.feedback(), 0.7);
}
#[test]
fn test_spectral_delay_set_frequency_scale() {
let mut delay = SpectralDelay::new(100.0, 0.3, 0.0, 0.5, 44100.0);
delay.set_frequency_scale(0.5);
assert_eq!(delay.frequency_scale(), 0.5);
}
#[test]
fn test_spectral_delay_set_mix() {
let mut delay = SpectralDelay::new(100.0, 0.3, 0.0, 0.5, 44100.0);
delay.set_mix(0.75);
assert_eq!(delay.mix(), 0.75);
}
#[test]
fn test_spectral_delay_process_block() {
let mut delay = SpectralDelay::new(100.0, 0.3, 0.0, 0.5, 44100.0);
let mut buffer = vec![0.5; 512];
delay.process_block(&mut buffer, 44100.0, 0.0, 0);
}
#[test]
fn test_spectral_delay_disabled() {
let mut delay = SpectralDelay::new(100.0, 0.3, 0.0, 0.5, 44100.0);
delay.enabled = false;
let original = vec![0.5; 512];
let mut buffer = original.clone();
delay.process_block(&mut buffer, 44100.0, 0.0, 0);
assert_eq!(buffer, original);
}
#[test]
fn test_spectral_delay_reset() {
let mut delay = SpectralDelay::new(100.0, 0.3, 0.0, 0.5, 44100.0);
let mut buffer = vec![0.5; 512];
delay.process_block(&mut buffer, 44100.0, 0.0, 0);
delay.reset();
}
#[test]
fn test_spectral_delay_clear_buffers() {
let mut delay = SpectralDelay::new(100.0, 0.3, 0.0, 0.5, 44100.0);
delay.clear_buffers();
}
#[test]
fn test_spectral_delay_with_params() {
let delay = SpectralDelay::with_params(4096, 1024, 200.0, 0.5, 0.8, 0.7, 44100.0);
assert!(delay.enabled);
}
}
#[derive(Clone)]
pub struct SpectralDynamics {
core: CoreSpectralDynamics,
pub priority: u8,
pub enabled: bool,
input_buffer: Vec<f32>,
}
impl SpectralDynamics {
pub fn new(
threshold: f32,
ratio: f32,
attack: f32,
release: f32,
knee: f32,
sample_rate: f32,
) -> Self {
Self::with_params(
2048,
512,
threshold,
ratio,
attack,
release,
knee,
sample_rate,
)
}
#[allow(clippy::too_many_arguments)]
pub fn with_params(
fft_size: usize,
hop_size: usize,
threshold: f32,
ratio: f32,
attack: f32,
release: f32,
knee: f32,
sample_rate: f32,
) -> Self {
let mut core = CoreSpectralDynamics::new(
fft_size,
hop_size,
crate::synthesis::spectral::WindowType::Hann,
sample_rate,
);
core.set_threshold(threshold);
core.set_ratio(ratio);
core.set_attack(attack);
core.set_release(release);
core.set_knee(knee);
Self {
core,
priority: 155, enabled: true,
input_buffer: Vec::new(),
}
}
pub fn gentle() -> Self {
let core = CoreSpectralDynamics::gentle();
Self {
core,
priority: 155,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn moderate() -> Self {
let core = CoreSpectralDynamics::moderate();
Self {
core,
priority: 155,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn aggressive() -> Self {
let core = CoreSpectralDynamics::aggressive();
Self {
core,
priority: 155,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn expander() -> Self {
let core = CoreSpectralDynamics::expander();
Self {
core,
priority: 155,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn gate_like() -> Self {
let core = CoreSpectralDynamics::gate_like();
Self {
core,
priority: 155,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn set_threshold(&mut self, threshold_db: f32) {
self.core.set_threshold(threshold_db);
}
pub fn set_ratio(&mut self, ratio: f32) {
self.core.set_ratio(ratio);
}
pub fn set_attack(&mut self, attack_ms: f32) {
self.core.set_attack(attack_ms);
}
pub fn set_release(&mut self, release_ms: f32) {
self.core.set_release(release_ms);
}
pub fn set_knee(&mut self, knee_db: f32) {
self.core.set_knee(knee_db);
}
pub fn set_mix(&mut self, mix: f32) {
self.core.set_mix(mix);
}
pub fn threshold(&self) -> f32 {
self.core.threshold()
}
pub fn ratio(&self) -> f32 {
self.core.ratio()
}
pub fn attack(&self) -> f32 {
self.core.attack()
}
pub fn release(&self) -> f32 {
self.core.release()
}
pub fn knee(&self) -> f32 {
self.core.knee()
}
pub fn mix(&self) -> f32 {
self.core.mix()
}
pub fn process_block(
&mut self,
buffer: &mut [f32],
_sample_rate: f32,
_time: f32,
_sample_count: u64,
) {
if !self.enabled {
return;
}
self.input_buffer.clear();
self.input_buffer.extend_from_slice(buffer);
self.core.process(buffer, &self.input_buffer);
}
pub fn reset(&mut self) {
self.core.reset();
}
}
impl std::fmt::Debug for SpectralDynamics {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SpectralDynamics")
.field("threshold", &self.core.threshold())
.field("ratio", &self.core.ratio())
.field("attack", &self.core.attack())
.field("release", &self.core.release())
.field("knee", &self.core.knee())
.field("mix", &self.core.mix())
.field("priority", &self.priority)
.field("enabled", &self.enabled)
.finish()
}
}
#[derive(Clone)]
pub struct SpectralScramble {
core: CoreSpectralScramble,
pub priority: u8,
pub enabled: bool,
input_buffer: Vec<f32>,
}
impl SpectralScramble {
pub fn new(
scramble_amount: f32,
low_freq: f32,
high_freq: f32,
mix: f32,
sample_rate: f32,
) -> Self {
Self::with_params(
2048,
512,
scramble_amount,
low_freq,
high_freq,
mix,
sample_rate,
)
}
pub fn with_params(
fft_size: usize,
hop_size: usize,
scramble_amount: f32,
low_freq: f32,
high_freq: f32,
mix: f32,
sample_rate: f32,
) -> Self {
let mut core = CoreSpectralScramble::new(
fft_size,
hop_size,
crate::synthesis::spectral::WindowType::Hann,
sample_rate,
);
core.set_scramble_amount(scramble_amount);
core.set_low_freq(low_freq);
core.set_high_freq(high_freq);
core.set_mix(mix);
Self {
core,
priority: 175, enabled: true,
input_buffer: Vec::new(),
}
}
pub fn subtle() -> Self {
let core = CoreSpectralScramble::subtle();
Self {
core,
priority: 175,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn moderate() -> Self {
let core = CoreSpectralScramble::moderate();
Self {
core,
priority: 175,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn chaos() -> Self {
let core = CoreSpectralScramble::chaos();
Self {
core,
priority: 175,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn glitch() -> Self {
let core = CoreSpectralScramble::glitch();
Self {
core,
priority: 175,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn digital() -> Self {
let core = CoreSpectralScramble::digital();
Self {
core,
priority: 175,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn set_scramble_amount(&mut self, amount: f32) {
self.core.set_scramble_amount(amount);
}
pub fn set_low_freq(&mut self, freq: f32) {
self.core.set_low_freq(freq);
}
pub fn set_high_freq(&mut self, freq: f32) {
self.core.set_high_freq(freq);
}
pub fn set_mix(&mut self, mix: f32) {
self.core.set_mix(mix);
}
pub fn scramble_amount(&self) -> f32 {
self.core.scramble_amount()
}
pub fn low_freq(&self) -> f32 {
self.core.low_freq()
}
pub fn high_freq(&self) -> f32 {
self.core.high_freq()
}
pub fn mix(&self) -> f32 {
self.core.mix()
}
pub fn process_block(
&mut self,
buffer: &mut [f32],
_sample_rate: f32,
_time: f32,
_sample_count: u64,
) {
if !self.enabled {
return;
}
self.input_buffer.clear();
self.input_buffer.extend_from_slice(buffer);
self.core.process(buffer, &self.input_buffer);
}
pub fn reset(&mut self) {
self.core.reset();
}
}
impl std::fmt::Debug for SpectralScramble {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SpectralScramble")
.field("scramble_amount", &self.core.scramble_amount())
.field("low_freq", &self.core.low_freq())
.field("high_freq", &self.core.high_freq())
.field("mix", &self.core.mix())
.field("priority", &self.priority)
.field("enabled", &self.enabled)
.finish()
}
}
#[derive(Clone)]
pub struct FormantShifter {
core: CoreFormantShifter,
pub priority: u8,
pub enabled: bool,
input_buffer: Vec<f32>,
}
impl FormantShifter {
pub fn new(shift_ratio: f32, mix: f32, sample_rate: f32) -> Self {
Self::with_params(2048, 512, shift_ratio, mix, sample_rate)
}
pub fn with_params(
fft_size: usize,
hop_size: usize,
shift_ratio: f32,
mix: f32,
sample_rate: f32,
) -> Self {
let mut core = CoreFormantShifter::new(fft_size, hop_size, WindowType::Hann, sample_rate);
core.set_shift_ratio(shift_ratio);
core.set_mix(mix);
Self {
core,
priority: 146, enabled: true,
input_buffer: Vec::new(),
}
}
pub fn male_to_female() -> Self {
let core = CoreFormantShifter::male_to_female();
Self {
core,
priority: 146,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn female_to_male() -> Self {
let core = CoreFormantShifter::female_to_male();
Self {
core,
priority: 146,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn adult_to_child() -> Self {
let core = CoreFormantShifter::adult_to_child();
Self {
core,
priority: 146,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn brighten() -> Self {
let core = CoreFormantShifter::brighten();
Self {
core,
priority: 146,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn darken() -> Self {
let core = CoreFormantShifter::darken();
Self {
core,
priority: 146,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn monster() -> Self {
let core = CoreFormantShifter::monster();
Self {
core,
priority: 146,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn chipmunk() -> Self {
let core = CoreFormantShifter::chipmunk();
Self {
core,
priority: 146,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn set_shift_ratio(&mut self, ratio: f32) {
self.core.set_shift_ratio(ratio);
}
pub fn set_mix(&mut self, mix: f32) {
self.core.set_mix(mix);
}
pub fn shift_ratio(&self) -> f32 {
self.core.shift_ratio()
}
pub fn mix(&self) -> f32 {
self.core.mix()
}
pub fn process_block(
&mut self,
buffer: &mut [f32],
_sample_rate: f32,
_time: f32,
_sample_count: u64,
) {
if !self.enabled {
return;
}
self.input_buffer.clear();
self.input_buffer.extend_from_slice(buffer);
self.core.process(buffer, &self.input_buffer);
}
pub fn reset(&mut self) {
self.core.reset();
}
}
impl std::fmt::Debug for FormantShifter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FormantShifter")
.field("shift_ratio", &self.core.shift_ratio())
.field("mix", &self.core.mix())
.field("priority", &self.priority)
.field("enabled", &self.enabled)
.finish()
}
}
#[derive(Clone)]
pub struct SpectralHarmonizer {
core: CoreSpectralHarmonizer,
pub priority: u8,
pub enabled: bool,
input_buffer: Vec<f32>,
}
impl SpectralHarmonizer {
pub fn new(voices: Vec<HarmonyVoice>, dry_mix: f32, sample_rate: f32) -> Self {
Self::with_params(2048, 512, voices, dry_mix, sample_rate)
}
pub fn with_params(
fft_size: usize,
hop_size: usize,
voices: Vec<HarmonyVoice>,
dry_mix: f32,
sample_rate: f32,
) -> Self {
let mut core = CoreSpectralHarmonizer::new(fft_size, hop_size, WindowType::Hann, sample_rate);
core.set_voices(voices);
core.set_dry_mix(dry_mix);
Self {
core,
priority: 147, enabled: true,
input_buffer: Vec::new(),
}
}
pub fn major_chord() -> Self {
let core = CoreSpectralHarmonizer::major_chord();
Self {
core,
priority: 147,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn minor_chord() -> Self {
let core = CoreSpectralHarmonizer::minor_chord();
Self {
core,
priority: 147,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn fifth() -> Self {
let core = CoreSpectralHarmonizer::fifth();
Self {
core,
priority: 147,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn octave_up() -> Self {
let core = CoreSpectralHarmonizer::octave_up();
Self {
core,
priority: 147,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn octave_down() -> Self {
let core = CoreSpectralHarmonizer::octave_down();
Self {
core,
priority: 147,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn octave_double() -> Self {
let core = CoreSpectralHarmonizer::octave_double();
Self {
core,
priority: 147,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn choir() -> Self {
let core = CoreSpectralHarmonizer::choir();
Self {
core,
priority: 147,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn barbershop() -> Self {
let core = CoreSpectralHarmonizer::barbershop();
Self {
core,
priority: 147,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn thick() -> Self {
let core = CoreSpectralHarmonizer::thick();
Self {
core,
priority: 147,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn add_voice(&mut self, voice: HarmonyVoice) {
self.core.add_voice(voice);
}
pub fn clear_voices(&mut self) {
self.core.clear_voices();
}
pub fn set_voices(&mut self, voices: Vec<HarmonyVoice>) {
self.core.set_voices(voices);
}
pub fn voices(&self) -> &[HarmonyVoice] {
self.core.voices()
}
pub fn set_dry_mix(&mut self, mix: f32) {
self.core.set_dry_mix(mix);
}
pub fn dry_mix(&self) -> f32 {
self.core.dry_mix()
}
pub fn process_block(
&mut self,
buffer: &mut [f32],
_sample_rate: f32,
_time: f32,
_sample_count: u64,
) {
if !self.enabled {
return;
}
self.input_buffer.clear();
self.input_buffer.extend_from_slice(buffer);
self.core.process(buffer, &self.input_buffer);
}
pub fn reset(&mut self) {
self.core.reset();
}
}
impl std::fmt::Debug for SpectralHarmonizer {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SpectralHarmonizer")
.field("voices", &self.core.voices().len())
.field("dry_mix", &self.core.dry_mix())
.field("priority", &self.priority)
.field("enabled", &self.enabled)
.finish()
}
}
#[derive(Clone)]
pub struct SpectralResonator {
core: CoreSpectralResonator,
pub priority: u8,
pub enabled: bool,
input_buffer: Vec<f32>,
}
impl SpectralResonator {
pub fn new(resonances: Vec<crate::synthesis::spectral::Resonance>, mix: f32, sample_rate: f32) -> Self {
Self::with_params(2048, 512, resonances, mix, sample_rate)
}
pub fn with_params(
fft_size: usize,
hop_size: usize,
resonances: Vec<crate::synthesis::spectral::Resonance>,
mix: f32,
sample_rate: f32,
) -> Self {
let mut core = CoreSpectralResonator::new(fft_size, hop_size, WindowType::Hann, sample_rate);
core.set_resonances(resonances);
core.set_mix(mix);
Self {
core,
priority: 148, enabled: true,
input_buffer: Vec::new(),
}
}
pub fn pitched_a440() -> Self {
let core = CoreSpectralResonator::pitched_a440();
Self {
core,
priority: 148,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn bell() -> Self {
let core = CoreSpectralResonator::bell();
Self {
core,
priority: 148,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn metallic() -> Self {
let core = CoreSpectralResonator::metallic();
Self {
core,
priority: 148,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn vowel_a() -> Self {
let core = CoreSpectralResonator::vowel_a();
Self {
core,
priority: 148,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn vowel_e() -> Self {
let core = CoreSpectralResonator::vowel_e();
Self {
core,
priority: 148,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn vowel_i() -> Self {
let core = CoreSpectralResonator::vowel_i();
Self {
core,
priority: 148,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn vowel_o() -> Self {
let core = CoreSpectralResonator::vowel_o();
Self {
core,
priority: 148,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn vowel_u() -> Self {
let core = CoreSpectralResonator::vowel_u();
Self {
core,
priority: 148,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn gentle() -> Self {
let core = CoreSpectralResonator::gentle();
Self {
core,
priority: 148,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn comb() -> Self {
let core = CoreSpectralResonator::comb();
Self {
core,
priority: 148,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn add_resonance(&mut self, resonance: crate::synthesis::spectral::Resonance) {
self.core.add_resonance(resonance);
}
pub fn clear_resonances(&mut self) {
self.core.clear_resonances();
}
pub fn set_resonances(&mut self, resonances: Vec<crate::synthesis::spectral::Resonance>) {
self.core.set_resonances(resonances);
}
pub fn resonances(&self) -> &[crate::synthesis::spectral::Resonance] {
self.core.resonances()
}
pub fn set_harmonic_series(&mut self, fundamental: f32, num_harmonics: usize, gain: f32, q: f32) {
self.core.set_harmonic_series(fundamental, num_harmonics, gain, q);
}
pub fn set_mix(&mut self, mix: f32) {
self.core.set_mix(mix);
}
pub fn mix(&self) -> f32 {
self.core.mix()
}
pub fn process_block(
&mut self,
buffer: &mut [f32],
_sample_rate: f32,
_time: f32,
_sample_count: u64,
) {
if !self.enabled {
return;
}
self.input_buffer.clear();
self.input_buffer.extend_from_slice(buffer);
self.core.process(buffer, &self.input_buffer);
}
pub fn reset(&mut self) {
self.core.reset();
}
}
impl std::fmt::Debug for SpectralResonator {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SpectralResonator")
.field("resonances", &self.core.resonances().len())
.field("mix", &self.core.mix())
.field("priority", &self.priority)
.field("enabled", &self.enabled)
.finish()
}
}
#[derive(Clone)]
pub struct SpectralPanner {
core: CoreSpectralPanner,
pub priority: u8,
pub enabled: bool,
input_buffer: Vec<f32>,
}
impl SpectralPanner {
pub fn new(pan_points: Vec<crate::synthesis::spectral::PanPoint>, mix: f32, sample_rate: f32) -> Self {
Self::with_params(2048, 512, pan_points, mix, sample_rate)
}
pub fn with_params(
fft_size: usize,
hop_size: usize,
pan_points: Vec<crate::synthesis::spectral::PanPoint>,
mix: f32,
sample_rate: f32,
) -> Self {
let mut core = CoreSpectralPanner::new(fft_size, hop_size, WindowType::Hann, sample_rate);
core.set_pan_points(pan_points);
core.set_mix(mix);
Self {
core,
priority: 149, enabled: true,
input_buffer: Vec::new(),
}
}
pub fn center() -> Self {
let core = CoreSpectralPanner::center();
Self {
core,
priority: 149,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn bass_center() -> Self {
let core = CoreSpectralPanner::bass_center();
Self {
core,
priority: 149,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn highs_wide() -> Self {
let core = CoreSpectralPanner::highs_wide();
Self {
core,
priority: 149,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn low_left_high_right() -> Self {
let core = CoreSpectralPanner::low_left_high_right();
Self {
core,
priority: 149,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn low_right_high_left() -> Self {
let core = CoreSpectralPanner::low_right_high_left();
Self {
core,
priority: 149,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn mid_wide() -> Self {
let core = CoreSpectralPanner::mid_wide();
Self {
core,
priority: 149,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn circular() -> Self {
let core = CoreSpectralPanner::circular();
Self {
core,
priority: 149,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn gentle() -> Self {
let core = CoreSpectralPanner::gentle();
Self {
core,
priority: 149,
enabled: true,
input_buffer: Vec::new(),
}
}
pub fn add_pan_point(&mut self, point: crate::synthesis::spectral::PanPoint) {
self.core.add_pan_point(point);
}
pub fn clear_pan_points(&mut self) {
self.core.clear_pan_points();
}
pub fn set_pan_points(&mut self, pan_points: Vec<crate::synthesis::spectral::PanPoint>) {
self.core.set_pan_points(pan_points);
}
pub fn pan_points(&self) -> &[crate::synthesis::spectral::PanPoint] {
self.core.pan_points()
}
pub fn set_mix(&mut self, mix: f32) {
self.core.set_mix(mix);
}
pub fn mix(&self) -> f32 {
self.core.mix()
}
pub fn process_block(
&mut self,
buffer: &mut [f32],
_sample_rate: f32,
_time: f32,
_sample_count: u64,
) {
if !self.enabled {
return;
}
self.input_buffer.clear();
self.input_buffer.extend_from_slice(buffer);
self.core.process(buffer, &self.input_buffer);
}
pub fn reset(&mut self) {
self.core.reset();
}
}
impl std::fmt::Debug for SpectralPanner {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SpectralPanner")
.field("pan_points", &self.core.pan_points().len())
.field("mix", &self.core.mix())
.field("priority", &self.priority)
.field("enabled", &self.enabled)
.finish()
}
}