diff options
| author | ozpv <39195175+ozpv@users.noreply.github.com> | 2026-05-19 01:48:04 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-05-19 01:48:04 -0500 |
| commit | 0f0bc6b88fe8cb80b947e576cdfa4a7124982f54 (patch) | |
| tree | faa432745faa91a9d0583c05a7386c0d9d0a437c | |
| parent | 88bd6307ee43f3c3609d5b2f49d440d285185765 (diff) | |
add complement parameter
| -rw-r--r-- | src/audio.rs | 62 | ||||
| -rw-r--r-- | src/gui.rs | 26 | ||||
| -rw-r--r-- | src/lib.rs | 7 | ||||
| -rw-r--r-- | src/params.rs | 170 | ||||
| -rw-r--r-- | src/retain.rs | 28 | ||||
| -rw-r--r-- | src/window_function.rs | 15 | ||||
| -rw-r--r-- | src/window_type.rs | 27 | ||||
| -rw-r--r-- | src/windowed_fft.rs | 14 |
8 files changed, 151 insertions, 198 deletions
diff --git a/src/audio.rs b/src/audio.rs index 9e50465..64338a1 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -1,10 +1,8 @@ //! Contains all types and implementations related to audio processing and the audio thread. use crate::{ - RetainPluginMainThread, RetainPluginShared, - params::{GestureChange, RetainParamsLocal, RetainParamsShared}, - retain::retain_top_n_magnitudes, - windowed_fft::WindowedRealFft, + RetainPluginMainThread, RetainPluginShared, params::RetainParamsLocal, + retain::retain_top_n_magnitudes, windowed_fft::WindowedRealFft, }; use clack_extensions::{ audio_ports::{ @@ -13,10 +11,7 @@ use clack_extensions::{ latency::HostLatency, params::PluginAudioProcessorParams, }; -use clack_plugin::{ - events::event_types::{ParamGestureBeginEvent, ParamGestureEndEvent}, - prelude::*, -}; +use clack_plugin::prelude::*; /// Our plugin's audio processor. It lives in the audio thread. /// @@ -93,10 +88,10 @@ impl<'a> PluginAudioProcessor<'a, RetainPluginShared<'a>, RetainPluginMainThread } let prev_window_size = self.params.get_window_size(); - let prev_window_type = self.params.get_window_type().as_bits(); + let prev_window_type = self.params.get_window_type().as_byte(); // Receive any param updates from the main thread and/or the GUI. - let has_ui_param_updates = self.params.fetch_updates(&self.shared.params); + self.params.fetch_updates(&self.shared.params); // update window size and latency if it has changed // updates fft window sizes only if necessary @@ -116,9 +111,9 @@ impl<'a> PluginAudioProcessor<'a, RetainPluginShared<'a>, RetainPluginMainThread // update change in window type if needed let window_type = self.params.get_window_type(); - if prev_window_type != window_type.as_bits() { - self.fft_left.window_function(&window_type); - self.fft_right.window_function(&window_type); + if prev_window_type != window_type.as_byte() { + self.fft_left.window_function(window_type); + self.fft_right.window_function(window_type); } // Now let's process the audio, while splitting the processing in batches between each @@ -131,16 +126,7 @@ impl<'a> PluginAudioProcessor<'a, RetainPluginShared<'a>, RetainPluginMainThread // Get the parameters after all changes have been handled. let order = self.params.get_order(); - - if order == 0 { - for channel in channel_buffers.iter_mut().flatten() { - for sample in channel.iter_mut() { - *sample = 0.0; - } - } - - continue; - } + let complement = self.params.get_complement(); // process samples in place here if let [Some(left), Some(right)] = &mut channel_buffers { @@ -148,7 +134,7 @@ impl<'a> PluginAudioProcessor<'a, RetainPluginShared<'a>, RetainPluginMainThread if self.fft_left.push_back_input(*sample) { self.fft_left.forward(); - retain_top_n_magnitudes(self.fft_left.get_spectrum(), order); + retain_top_n_magnitudes(self.fft_left.get_spectrum(), order, complement); self.fft_left.inverse(); self.fft_left.clear_input(); @@ -161,7 +147,7 @@ impl<'a> PluginAudioProcessor<'a, RetainPluginShared<'a>, RetainPluginMainThread if self.fft_right.push_back_input(*sample) { self.fft_right.forward(); - retain_top_n_magnitudes(self.fft_right.get_spectrum(), order); + retain_top_n_magnitudes(self.fft_right.get_spectrum(), order, complement); self.fft_right.inverse(); self.fft_right.clear_input(); @@ -178,32 +164,6 @@ impl<'a> PluginAudioProcessor<'a, RetainPluginShared<'a>, RetainPluginMainThread self.host.request_callback(); } - // Fetch the latest gesture status - let current_gesture = self - .params - .fetch_gesture(&self.shared.params, has_ui_param_updates); - - // Send a Gesture Begin event, if we need to do so - if let Some(GestureChange::Begin | GestureChange::Both) = current_gesture { - let _ = events.output.try_push(ParamGestureBeginEvent::new( - 0, - RetainParamsShared::PARAM_ORDER_ID, - )); - } - - // If the UI sent us param updates, send them to the Host - if has_ui_param_updates { - self.params.send_param_events(events.output); - } - - // Send a Gesture End event, if we need to do so - if let Some(GestureChange::End | GestureChange::Both) = current_gesture { - let _ = events.output.try_push(ParamGestureEndEvent::new( - audio.frames_count(), - RetainParamsShared::PARAM_ORDER_ID, - )); - } - Ok(ProcessStatus::ContinueIfNotQuiet) } } @@ -85,11 +85,9 @@ impl RetainPluginGui { state.local_params.push_updates(&state.shared_params); } - state.local_params.has_gesture = slider.is_pointer_button_down_on(); - state.local_params.push_gesture(&state.shared_params); - let mut window_size = WindowSize::from(state.local_params.get_window_size()); + ComboBox::from_label("Window Size") .selected_text(window_size.as_str()) .show_ui(ui, |ui| { @@ -108,26 +106,34 @@ impl RetainPluginGui { }); }); - ui.with_layout(Layout::right_to_left(Align::RIGHT), |ui| { + ui.with_layout(Layout::top_down(Align::RIGHT), |ui| { + let mut complement = state.local_params.get_complement(); + + if ui.checkbox(&mut complement, "Complement").changed() { + state.local_params.set_complement(complement); + state.local_params.push_updates(&state.shared_params); + } + let window_type = state.local_params.get_window_type(); let selected = window_type.as_str(); - let mut window_type = window_type.as_bits(); + let mut window_type = window_type.as_byte(); + ComboBox::from_label("Window Function") .selected_text(selected) .show_ui(ui, |ui| { for function in WindowType::iter() { let display = function.as_str(); - let bits = function.as_bits(); + let bits = function.as_byte(); if ui .selectable_value( &mut window_type, - function.as_bits(), + function.as_byte(), display, ) .changed() { - state.local_params.set_window_type_from_bits(bits); + state.local_params.set_window_type_from_byte(bits); state.local_params.push_updates(&state.shared_params); } } @@ -206,6 +212,10 @@ impl PluginGuiImpl for RetainPluginMainThread<'_> { }) } + fn can_resize(&mut self) -> bool { + false + } + fn set_size(&mut self, _size: GuiSize) -> Result<(), PluginError> { Ok(()) } @@ -75,14 +75,14 @@ impl DefaultPluginFactory for RetainPlugin { pub struct RetainPluginShared<'a> { /// The plugin's parameter values. params: Arc<RetainParamsShared>, - host: Arc<HostSharedHandle<'a>>, + host: HostSharedHandle<'a>, } impl<'a> RetainPluginShared<'a> { fn new(host: HostSharedHandle<'a>) -> Self { RetainPluginShared { params: Arc::new(RetainParamsShared::new()), - host: Arc::new(host), + host, } } } @@ -109,7 +109,8 @@ impl<'a> PluginMainThread<'a, RetainPluginShared<'a>> for RetainPluginMainThread impl PluginLatencyImpl for RetainPluginMainThread<'_> { fn get(&mut self) -> u32 { - self.shared.params.get_window_size() as u32 + self.params.fetch_updates(&self.shared.params); + self.params.get_window_size() as u32 } } diff --git a/src/params.rs b/src/params.rs index 0762cd2..605e305 100644 --- a/src/params.rs +++ b/src/params.rs @@ -8,7 +8,7 @@ use clack_extensions::{ state::PluginStateImpl, }; use clack_plugin::{ - events::{event_types::ParamValueEvent, spaces::CoreEventSpace}, + events::spaces::CoreEventSpace, prelude::*, stream::{InputStream, OutputStream}, utils::Cookie, @@ -24,7 +24,8 @@ use std::{ /// The default value of the order parameter. const DEFAULT_ORDER: usize = 1; pub const DEFAULT_WINDOW_SIZE: WindowSize = WindowSize::Size4096; -const DEFAULT_WINDOW_TYPE: WindowType = WindowType::Hann; +pub const DEFAULT_WINDOW_TYPE: WindowType = WindowType::Hann; +const DEFAULT_COMPLEMENT: bool = false; /// A struct that manages the parameters for our plugin. /// @@ -38,8 +39,8 @@ pub struct RetainParamsShared { window_size: AtomicUsize, /// Type of window function of FFT window_type: AtomicU8, - /// Whether a gesture is currently active or not on the parameters - has_gesture: AtomicBool, + /// Whether it retains or removes the highest magnitudes + complement: AtomicBool, } impl RetainParamsShared { @@ -47,31 +48,17 @@ impl RetainParamsShared { pub const PARAM_ORDER_ID: ClapId = ClapId::new(1); pub const PARAM_WINDOW_SIZE_ID: ClapId = ClapId::new(2); pub const PARAM_WINDOW_TYPE_ID: ClapId = ClapId::new(3); + pub const PARAM_COMPLEMENT_ID: ClapId = ClapId::new(3); /// Initializes the shared parameter value. pub fn new() -> Self { Self { order: AtomicUsize::new(DEFAULT_ORDER), window_size: AtomicUsize::new(DEFAULT_WINDOW_SIZE.inner()), - window_type: AtomicU8::new(DEFAULT_WINDOW_TYPE.as_bits()), - has_gesture: AtomicBool::new(false), + window_type: AtomicU8::new(DEFAULT_WINDOW_TYPE.as_byte()), + complement: AtomicBool::new(DEFAULT_COMPLEMENT), } } - - pub fn get_window_size(&self) -> usize { - self.window_size.load(Ordering::Relaxed) - } -} - -/// A param gesture change type -#[derive(Copy, Clone, Eq, PartialEq)] -pub enum GestureChange { - /// User started changing a parameter - Begin, - /// User finished changing a parameter - End, - /// User both started and finished changing a parameter during the current block - Both, } /// The local-side of parameter state. @@ -88,8 +75,8 @@ pub struct RetainParamsLocal { window_size: usize, /// The local value of the type of window function parameter. window_type: WindowType, - /// Whether the user is currently changing the parameter, that we know of - pub has_gesture: bool, + /// The local value of the complement parameter. + complement: bool, } impl RetainParamsLocal { @@ -98,8 +85,8 @@ impl RetainParamsLocal { Self { order: shared.order.load(Ordering::Relaxed), window_size: shared.window_size.load(Ordering::Relaxed), - window_type: WindowType::from_bits(shared.window_type.load(Ordering::Relaxed)), - has_gesture: shared.has_gesture.load(Ordering::Relaxed), + window_type: WindowType::from_byte(shared.window_type.load(Ordering::Relaxed)), + complement: shared.complement.load(Ordering::Relaxed), } } @@ -137,8 +124,20 @@ impl RetainParamsLocal { /// Sets the current local window type from `bits`. #[inline] - pub fn set_window_type_from_bits(&mut self, bits: u8) { - self.window_type = WindowType::from_bits(bits); + pub fn set_window_type_from_byte(&mut self, bits: u8) { + self.window_type = WindowType::from_byte(bits); + } + + /// Returns the current local complement. + #[inline] + pub fn get_complement(&self) -> bool { + self.complement + } + + /// Sets the current local complement to `value`. + #[inline] + pub fn set_complement(&mut self, value: bool) { + self.complement = value; } /// Fetch updates from the `shared` state. @@ -148,15 +147,18 @@ impl RetainParamsLocal { pub fn fetch_updates(&mut self, shared: &RetainParamsShared) -> bool { let latest_order = shared.order.load(Ordering::Relaxed); let latest_window_size = shared.window_size.load(Ordering::Relaxed); - let latest_window_type = WindowType::from_bits(shared.window_type.load(Ordering::Relaxed)); + let latest_window_type = WindowType::from_byte(shared.window_type.load(Ordering::Relaxed)); + let latest_complement = shared.complement.load(Ordering::Relaxed); if latest_order != self.order || latest_window_size != self.order || latest_window_type != self.window_type + || latest_complement != self.complement { self.order = latest_order; self.window_size = latest_window_size; self.window_type = latest_window_type; + self.complement = latest_complement; true } else { @@ -173,48 +175,13 @@ impl RetainParamsLocal { let previous_window_size = shared.window_size.swap(self.window_size, Ordering::Relaxed); let previous_window_type = shared .window_type - .swap(self.window_type.as_bits(), Ordering::Relaxed); + .swap(self.window_type.as_byte(), Ordering::Relaxed); + let previous_complement = shared.complement.swap(self.complement, Ordering::Relaxed); previous_order != self.order || previous_window_size != self.window_size - || previous_window_type != self.window_type.as_bits() - } - - /// Pushes the local gesture state to the `shared` state. - #[inline] - pub fn push_gesture(&self, shared: &RetainParamsShared) { - shared - .has_gesture - .store(self.has_gesture, Ordering::Relaxed); - } - - /// Fetches updates to the gesture state. - /// - /// If a gesture state changed occurred, it is returned. - /// If the gesture did not change from the last update, `None` is returned. - #[inline] - pub fn fetch_gesture( - &mut self, - shared: &RetainParamsShared, - has_ui_param_updates: bool, - ) -> Option<GestureChange> { - let previous_gesture = self.has_gesture; - - self.has_gesture = shared.has_gesture.load(Ordering::Relaxed); - - if previous_gesture == self.has_gesture { - return if has_ui_param_updates && !self.has_gesture { - Some(GestureChange::Both) - } else { - None - }; - } - - if previous_gesture { - Some(GestureChange::End) - } else { - Some(GestureChange::Begin) - } + || previous_window_type != self.window_type.as_byte() + || previous_complement != self.complement } /// Handles incoming events. @@ -230,30 +197,15 @@ impl RetainParamsLocal { if event.param_id() == RetainParamsShared::PARAM_WINDOW_SIZE_ID { self.set_window_size(event.value() as usize); } - } - } - /// Sends the value of the parameters to the host, via a [`ParamValueEvent`]. - pub fn send_param_events(&self, output_events: &mut OutputEvents) { - let order_event = ParamValueEvent::new( - 0, - RetainParamsShared::PARAM_ORDER_ID, - Pckn::match_all(), - self.order as f64, - Cookie::empty(), - ); - - let _ = output_events.try_push(order_event); - - let window_size_event = ParamValueEvent::new( - 0, - RetainParamsShared::PARAM_ORDER_ID, - Pckn::match_all(), - self.window_size as f64, - Cookie::empty(), - ); - - let _ = output_events.try_push(window_size_event); + if event.param_id() == RetainParamsShared::PARAM_WINDOW_TYPE_ID { + self.set_window_type_from_byte(event.value() as u8); + } + + if event.param_id() == RetainParamsShared::PARAM_COMPLEMENT_ID { + self.set_complement(event.value() != 0.0); + } + } } } @@ -266,6 +218,8 @@ struct PluginState { window_size: u32, #[prost(uint32, tag = "3")] window_type: u32, + #[prost(bool, tag = "4")] + complement: bool, } impl PluginState { @@ -273,7 +227,8 @@ impl PluginState { Self { order: local_params.get_order() as u64, window_size: local_params.get_window_size() as u32, - window_type: local_params.get_window_type().as_bits() as u32, + window_type: local_params.get_window_type().as_byte() as u32, + complement: local_params.get_complement(), } } @@ -288,6 +243,10 @@ impl PluginState { fn get_window_type_bits(&self) -> u8 { self.window_type as u8 } + + fn get_complement(&self) -> bool { + self.complement + } } /// Implementation of the State extension. @@ -315,7 +274,8 @@ impl PluginStateImpl for RetainPluginMainThread<'_> { self.params.set_order(data.get_order() as usize); self.params.set_window_size(data.get_window_size() as usize); self.params - .set_window_type_from_bits(data.get_window_type_bits()); + .set_window_type_from_byte(data.get_window_type_bits()); + self.params.set_complement(data.get_complement()); self.params.push_updates(&self.shared.params); @@ -325,7 +285,7 @@ impl PluginStateImpl for RetainPluginMainThread<'_> { impl PluginMainThreadParams for RetainPluginMainThread<'_> { fn count(&mut self) -> u32 { - 2 + 4 } fn get_info(&mut self, param_index: u32, info: &mut ParamInfoWriter) { @@ -363,7 +323,18 @@ impl PluginMainThreadParams for RetainPluginMainThread<'_> { module: b"", min_value: 0.0, max_value: 4.0, - default_value: DEFAULT_WINDOW_TYPE.as_bits() as f64, + default_value: DEFAULT_WINDOW_TYPE.as_byte() as f64, + }); + + info.set(&ParamInfo { + id: RetainParamsShared::PARAM_COMPLEMENT_ID, + flags: ParamInfoFlags::IS_READONLY, + cookie: Cookie::default(), + name: b"Complement", + module: b"", + min_value: 0.0, + max_value: 1.0, + default_value: DEFAULT_COMPLEMENT as u8 as f64, }); } @@ -372,28 +343,33 @@ impl PluginMainThreadParams for RetainPluginMainThread<'_> { RetainParamsShared::PARAM_ORDER_ID => Some(self.params.get_order() as f64), RetainParamsShared::PARAM_WINDOW_SIZE_ID => Some(self.params.get_window_size() as f64), RetainParamsShared::PARAM_WINDOW_TYPE_ID => { - Some(self.params.get_window_type().as_bits() as f64) + Some(self.params.get_window_type().as_byte() as f64) + } + RetainParamsShared::PARAM_COMPLEMENT_ID => { + Some(self.params.get_complement() as u8 as f64) } _ => None, } } + // TODO: update for order fn value_to_text( &mut self, param_id: ClapId, value: f64, writer: &mut ParamDisplayWriter, ) -> std::fmt::Result { - if param_id == 1 { + if param_id == RetainParamsShared::PARAM_ORDER_ID { write!(writer, "{0:.2} %", value * 100.0) } else { Err(std::fmt::Error) } } + // TODO: update for order fn text_to_value(&mut self, param_id: ClapId, text: &CStr) -> Option<f64> { let text = text.to_str().ok()?; - if param_id == 1 { + if param_id == RetainParamsShared::PARAM_ORDER_ID { let text = text.strip_suffix('%').unwrap_or(text).trim(); let percentage: f64 = text.parse().ok()?; diff --git a/src/retain.rs b/src/retain.rs index 8c4c8eb..5c14246 100644 --- a/src/retain.rs +++ b/src/retain.rs @@ -2,12 +2,26 @@ use num_complex::Complex; use rustc_hash::FxHashSet; #[inline(always)] -pub fn retain_top_n_magnitudes(spectrum: &mut [Complex<f32>], n: usize) { +pub fn retain_top_n_magnitudes(spectrum: &mut [Complex<f32>], n: usize, complement: bool) { // you'd be keeping the entire signal - // or keeping nothing at all - if n >= spectrum.len() { + if n >= spectrum.len() && !complement { return; - } else if n == 0 { + } + + if n == 0 && complement { + return; + } + + // keeping nothing at all + if n == 0 && !complement { + for phasor in spectrum { + *phasor = Complex::ZERO; + } + + return; + } + + if n >= spectrum.len() && complement { for phasor in spectrum { *phasor = Complex::ZERO; } @@ -30,7 +44,11 @@ pub fn retain_top_n_magnitudes(spectrum: &mut [Complex<f32>], n: usize) { .collect::<FxHashSet<usize>>(); for (i, phasor) in spectrum.iter_mut().enumerate() { - if !top_indices.contains(&i) { + if top_indices.contains(&i) && complement { + *phasor = Complex::ZERO; + } + + if !top_indices.contains(&i) && !complement { *phasor = Complex::ZERO; } } diff --git a/src/window_function.rs b/src/window_function.rs index 3565ea7..9ae15f8 100644 --- a/src/window_function.rs +++ b/src/window_function.rs @@ -1,6 +1,3 @@ -#![allow(unused)] -#![allow(dead_code)] - use crate::window_size::WindowSize; use std::{collections::VecDeque, f32::consts::PI}; @@ -31,14 +28,14 @@ impl RectangularWindow { impl WindowFunction for RectangularWindow { fn apply(&mut self, _data: &mut VecDeque<f32>) {} - fn reverse(&mut self, data: &mut [f32]) {} + fn reverse(&mut self, _data: &mut [f32]) {} fn needed(&self) -> usize { self.window_size } fn resize(&mut self, window_size: &WindowSize) { - *self = Self::new(&window_size); + *self = Self::new(window_size); } } @@ -160,7 +157,7 @@ impl WindowFunction for HannWindow { } fn resize(&mut self, window_size: &WindowSize) { - *self = Self::new(&window_size); + *self = Self::new(window_size); } } @@ -270,7 +267,7 @@ impl WindowFunction for HammingWindow { } fn resize(&mut self, window_size: &WindowSize) { - *self = Self::new(&window_size); + *self = Self::new(window_size); } } @@ -394,7 +391,7 @@ impl WindowFunction for BlackmanHarrisWindow { } fn resize(&mut self, window_size: &WindowSize) { - *self = Self::new(&window_size); + *self = Self::new(window_size); } } @@ -516,6 +513,6 @@ impl WindowFunction for Sine4Window { } fn resize(&mut self, window_size: &WindowSize) { - *self = Self::new(&window_size); + *self = Self::new(window_size); } } diff --git a/src/window_type.rs b/src/window_type.rs index be0e4df..c181c6d 100644 --- a/src/window_type.rs +++ b/src/window_type.rs @@ -1,6 +1,3 @@ -#![allow(unused)] -#![allow(dead_code)] - use crate::{ window_function::{ BlackmanHarrisWindow, HammingWindow, HannWindow, RectangularWindow, Sine4Window, @@ -50,24 +47,24 @@ impl WindowType { .into_iter() } - pub fn from_bits(bits: u8) -> Self { + pub fn from_byte(bits: u8) -> Self { match bits { - 0b00000000 => Self::Rectangular, - 0b00000001 => Self::Hann, - 0b00000010 => Self::Hamming, - 0b00000011 => Self::BlackmanHarris, - 0b00000100 => Self::Sine4, + 0 => Self::Rectangular, + 1 => Self::Hann, + 2 => Self::Hamming, + 3 => Self::BlackmanHarris, + 4 => Self::Sine4, _ => panic!("Invalid window type"), } } - pub fn as_bits(&self) -> u8 { + pub fn as_byte(&self) -> u8 { match self { - Self::Rectangular => 0b00000000, - Self::Hann => 0b00000001, - Self::Hamming => 0b00000010, - Self::BlackmanHarris => 0b00000011, - Self::Sine4 => 0b00000100, + Self::Rectangular => 0, + Self::Hann => 1, + Self::Hamming => 2, + Self::BlackmanHarris => 3, + Self::Sine4 => 4, } } } diff --git a/src/windowed_fft.rs b/src/windowed_fft.rs index 2cdc471..e99f1c1 100644 --- a/src/windowed_fft.rs +++ b/src/windowed_fft.rs @@ -1,14 +1,8 @@ #![allow(clippy::must_use_candidate)] #![allow(clippy::return_self_not_must_use)] -#![allow(unused)] -#![allow(dead_code)] use crate::{ - window_function::{ - BlackmanHarrisWindow, HammingWindow, HannWindow, RectangularWindow, Sine4Window, - WindowFunction, - }, - window_size::WindowSize, + params::DEFAULT_WINDOW_TYPE, window_function::WindowFunction, window_size::WindowSize, window_type::WindowType, }; use num_complex::Complex; @@ -20,16 +14,16 @@ pub struct WindowedRealFft { planner: RealFftPlanner<f32>, forward: Arc<dyn RealToComplex<f32>>, inverse: Arc<dyn ComplexToReal<f32>>, + scratch: Vec<Complex<f32>>, window_function: Box<dyn WindowFunction>, input: VecDeque<f32>, output: VecDeque<f32>, spectrum: Vec<Complex<f32>>, - scratch: Vec<Complex<f32>>, } impl WindowedRealFft { pub fn new(window_size: WindowSize) -> Self { - let window_function = Box::new(HannWindow::new(&window_size)); + let window_function = DEFAULT_WINDOW_TYPE.new_function(&window_size); let window_size = window_size.inner(); let mut planner = RealFftPlanner::new(); @@ -49,11 +43,11 @@ impl WindowedRealFft { planner, forward, inverse, + scratch, window_function, input, output, spectrum, - scratch, } } |
