use xmrs::fixed::fixed::{Q15, Q8_8};
use xmrs::fixed::units::PitchDelta;
use xmrs::{prelude::Waveform, waveform::WaveformState};
#[derive(Default, Clone, Copy, Debug)]
pub struct VibratoTremolo {
pub waveform: WaveformState,
pub speed: Q8_8,
pub depth: i16,
}
#[derive(Default, Clone, Copy, Debug)]
pub struct EffectVibratoTremolo {
pub data: VibratoTremolo,
in_progress: bool,
pos: u16,
value: i16,
}
impl EffectVibratoTremolo {
pub fn new(wf: Waveform) -> Self {
let mut evt = Self::default();
evt.data.waveform = WaveformState::new(wf);
evt
}
pub fn clear_output(&mut self) {
self.in_progress = false;
self.value = 0;
}
#[inline]
pub fn tick0_q(&mut self, speed: Q8_8, depth: i16) -> i16 {
self.data.speed = speed;
self.data.depth = depth;
self.retrigger_q()
}
#[inline]
pub fn retrigger_q(&mut self) -> i16 {
self.in_progress = false;
self.pos = 0;
self.value = 0;
0
}
#[inline]
pub fn tick_q(&mut self) -> i16 {
self.in_progress = true;
let wave = self
.data
.waveform
.value_q15(xmrs::fixed::units::Phase::from_raw(self.pos));
let product = ((self.data.depth as i32) * (wave.raw() as i32)) >> 15;
self.value = product.clamp(i16::MIN as i32, i16::MAX as i32) as i16;
let speed_pos = self.data.speed.raw().max(0) as u32;
let phase_delta = speed_pos.wrapping_mul(256) as u16;
self.pos = self.pos.wrapping_add(phase_delta);
self.value
}
#[inline]
pub fn value_q15(&self) -> Q15 {
Q15::from_raw(self.value)
}
#[inline]
pub fn value_pitch_delta(&self) -> PitchDelta {
PitchDelta::from_q8_8_i16(self.value)
}
pub fn in_progress(&self) -> bool {
self.in_progress
}
}