xsynth-core 0.4.0

A fast Rust-based SoundFont synthesizer designed for high voice counts and low latency.
Documentation
use std::marker::PhantomData;

use simdeez::prelude::*;

use crate::voice::{ReleaseType, VoiceControlData};

use super::{SIMDSampleMono, SIMDVoiceGenerator, VoiceGeneratorBase};

pub struct SIMDSquareWaveGenerator<S: Simd, Pitch: SIMDVoiceGenerator<S, SIMDSampleMono<S>>> {
    phase: f32,

    pitch_gen: Pitch,

    _s: PhantomData<S>,
}

impl<S, Pitch> SIMDSquareWaveGenerator<S, Pitch>
where
    S: Simd,
    Pitch: SIMDVoiceGenerator<S, SIMDSampleMono<S>>,
{
    pub fn new(pitch_gen: Pitch) -> Self {
        Self {
            phase: 0.0,
            pitch_gen,
            _s: PhantomData,
        }
    }

    fn next_phase(&mut self, step: f32) -> f32 {
        self.phase += step;
        self.phase %= 1.0;
        self.phase
    }
}

impl<S, Pitch> VoiceGeneratorBase for SIMDSquareWaveGenerator<S, Pitch>
where
    S: Simd,
    Pitch: SIMDVoiceGenerator<S, SIMDSampleMono<S>>,
{
    #[inline(always)]
    fn ended(&self) -> bool {
        false
    }

    #[inline(always)]
    fn signal_release(&mut self, rel_type: ReleaseType) {
        self.pitch_gen.signal_release(rel_type);
    }

    #[inline(always)]
    fn process_controls(&mut self, control: &VoiceControlData) {
        self.pitch_gen.process_controls(control);
    }
}

impl<S, Pitch> SIMDVoiceGenerator<S, SIMDSampleMono<S>> for SIMDSquareWaveGenerator<S, Pitch>
where
    S: Simd,
    Pitch: SIMDVoiceGenerator<S, SIMDSampleMono<S>>,
{
    #[inline(always)]
    fn next_sample(&mut self) -> SIMDSampleMono<S> {
        simd_invoke!(S, {
            let mut values = S::Vf32::zeroes();
            let pitch_step = self.pitch_gen.next_sample().0;
            for i in 0..S::Vf32::WIDTH {
                let phase = self.next_phase(pitch_step[i]);
                let val = if phase > 0.5 { 1.0 } else { -1.0 };
                values[i] = val;
            }

            SIMDSampleMono(values)
        })
    }
}