use super::LinearMode;
impl super::LinearModel {
#[inline(always)]
pub(crate) unsafe fn process_sample(&mut self, input: f32) -> f32 {
self.history[self.write_pos] = input;
self.write_pos += 1;
if self.write_pos >= self.double_limit {
self.write_pos -= self.history.size();
}
match &mut self.mode {
LinearMode::Direct => {
let start = self.write_pos - self.receptive_field;
let window = &self.history[start..self.write_pos];
let dot = unsafe {
crate::math::dsp::stereo::convolve_mono(
self.weights.as_ptr(),
window.as_ptr(),
self.receptive_field,
)
};
self.bias + dot
}
LinearMode::Fft(state) => {
let p = state.p;
let head_weights_ptr =
unsafe { self.weights.as_ptr().add(self.receptive_field - p) };
let head_start = self.write_pos - p;
let head_window = &self.history[head_start..self.write_pos];
let head_dot = unsafe {
crate::math::dsp::stereo::convolve_mono(
head_weights_ptr,
head_window.as_ptr(),
p,
)
};
let y_tail = state.tail_output_buf[state.sample_counter];
state.sample_counter += 1;
if state.sample_counter >= p {
let block_start = self.write_pos - 2 * p;
let block_window = &self.history[block_start..self.write_pos];
state.process_tail_block(block_window);
state.sample_counter = 0;
}
self.bias + head_dot + y_tail
}
}
}
#[inline(always)]
pub unsafe fn process(&mut self, input: &[f32], output: &mut [f32]) {
let n = core::cmp::min(input.len(), output.len());
for i in 0..n {
unsafe {
output[i] = self.process_sample(input[i]);
}
}
}
#[cold]
pub fn prewarm(&mut self, _num_samples: usize) {
let size = self.history.size();
for i in 0..(size * 2) {
self.history[i] = 0.0;
}
self.write_pos = size;
if let LinearMode::Fft(ref mut state) = self.mode {
state.reset();
}
}
#[cold]
pub fn reset(&mut self, _sample_rate: u32, _max_buffer_size: usize) {
let size = self.history.size();
for i in 0..(size * 2) {
self.history[i] = 0.0;
}
self.write_pos = size;
if let LinearMode::Fft(ref mut state) = self.mode {
state.reset();
}
}
}