summaryrefslogtreecommitdiff
path: root/src/audio.rs
diff options
context:
space:
mode:
authorozpv <39195175+ozpv@users.noreply.github.com>2026-06-20 03:11:03 -0500
committerozpv <39195175+ozpv@users.noreply.github.com>2026-06-20 03:11:03 -0500
commit029fc9d3cf4768d94a6e37380e1dcc1e758ae876 (patch)
treee38d6533ac8a08fca1109e6e4ee92fe2e227e274 /src/audio.rs
parent15452d1352dc01e4618a54c8159d8f049225d4fd (diff)
add vst3 support
Diffstat (limited to 'src/audio.rs')
-rw-r--r--src/audio.rs204
1 files changed, 0 insertions, 204 deletions
diff --git a/src/audio.rs b/src/audio.rs
deleted file mode 100644
index 4aaac9f..0000000
--- a/src/audio.rs
+++ /dev/null
@@ -1,204 +0,0 @@
-use crate::{
- RetainPluginMainThread, RetainPluginShared, params::RetainParams,
- retain::retain_top_n_magnitudes, window_size::WindowSize, window_type::WindowType,
- windowed_fft::WindowedRealFft,
-};
-use clack_extensions::{
- audio_ports::{
- AudioPortFlags, AudioPortInfo, AudioPortInfoWriter, AudioPortType, PluginAudioPortsImpl,
- },
- latency::HostLatency,
- params::PluginAudioProcessorParams,
-};
-use clack_plugin::prelude::*;
-use std::sync::Arc;
-
-/// Our plugin's audio processor. It lives in the audio thread.
-///
-/// It receives parameter events, and process a stereo audio signal by operating on the given audio
-/// buffer.
-pub struct RetainPluginAudioProcessor<'a> {
- /// The local state of the parameters
- params: Arc<RetainParams>,
- /// A reference to the plugin's shared data.
- shared: &'a RetainPluginShared<'a>,
- /// Our handle to the host
- host: HostAudioProcessorHandle<'a>,
- /// Fft for the left channel
- fft_left: WindowedRealFft,
- /// Fft for the right channel
- fft_right: WindowedRealFft,
- /// Previous window type
- prev_window_type: Option<WindowType>,
- /// Previous window size
- prev_window_size: Option<WindowSize>,
-}
-
-impl<'a> PluginAudioProcessor<'a, RetainPluginShared<'a>, RetainPluginMainThread<'a>>
- for RetainPluginAudioProcessor<'a>
-{
- fn activate(
- host: HostAudioProcessorHandle<'a>,
- _main_thread: &mut RetainPluginMainThread,
- shared: &'a RetainPluginShared<'a>,
- _audio_config: PluginAudioConfiguration,
- ) -> Result<Self, PluginError> {
- let params = Arc::clone(&shared.params);
-
- let fft_left = WindowedRealFft::new(params.get_window_size());
- let fft_right = WindowedRealFft::new(params.get_window_size());
-
- // This is where we would allocate intermediate buffers and such if we needed them.
- Ok(Self {
- params,
- shared,
- host,
- fft_left,
- fft_right,
- prev_window_size: None,
- prev_window_type: None,
- })
- }
-
- fn process(
- &mut self,
- _process: Process,
- mut audio: Audio,
- events: Events,
- ) -> Result<ProcessStatus, PluginError> {
- // Ensure at least a single input/output port pair, which contains channels of `f32`
- // audio sample data.
- let mut port_pair = audio
- .port_pair(0)
- .ok_or(PluginError::Message("No input/output ports found"))?;
-
- let mut output_channels = port_pair
- .channels()?
- .into_f32()
- .ok_or(PluginError::Message("Expected f32 input/output"))?;
-
- // Extract the buffer slices that we need, while making sure they are paired correctly and
- // check for either in-place or separate buffers.
- let mut output_buffers = [None, None];
-
- for (pair, buf) in output_channels.iter_mut().zip(&mut output_buffers) {
- *buf = match pair {
- ChannelPair::InputOnly(_) | ChannelPair::OutputOnly(_) => None,
- ChannelPair::InPlace(b) => Some(b),
- ChannelPair::InputOutput(i, o) => {
- o.copy_from_slice(i);
- Some(o)
- }
- }
- }
-
- // update window size and latency if it has changed
- // updates fft window sizes only if necessary
- let window_size = self.params.get_window_size();
- if self.prev_window_size != Some(window_size.clone()) {
- self.fft_left.window_size(window_size.clone());
- self.fft_right.window_size(window_size.clone());
-
- if let Some(latency) = self.shared.host.get_extension::<HostLatency>() {
- // SAFETY: should be safe as self.shared.host is a shared
- // version of the main thread handle
- // no reason to propagate it through all these layers
- let mut main = unsafe { self.shared.host.as_main_thread_unchecked() };
-
- latency.changed(&mut main);
- // self.shared.host.request_restart();
- }
-
- self.prev_window_size = Some(window_size);
- }
-
- // update change in window type if needed
- let window_type = self.params.get_window_type();
- if self.prev_window_type != Some(window_type.clone()) {
- self.fft_left.window_function(&window_type);
- self.fft_right.window_function(&window_type);
- self.prev_window_type = Some(window_type);
- }
-
- // process the audio
- for event_batch in events.input.batch() {
- for event in event_batch.events() {
- self.params.handle_event(event);
- }
-
- // Get the parameters after all changes have been handled.
- let order = self.params.get_order();
-
- // this parameter is read-only and can only be changed in the UI
- let complement = self.params.get_complement();
-
- // process samples in place here
- if let [Some(left), Some(right)] = &mut output_buffers {
- let range = event_batch.sample_bounds();
-
- for sample in &mut left[range] {
- if self.fft_left.push_back_input(*sample) {
- self.fft_left.forward();
-
- retain_top_n_magnitudes(self.fft_left.get_spectrum(), order, complement);
-
- self.fft_left.inverse();
- self.fft_left.clear_input();
- }
-
- *sample = self.fft_left.pop_front_output();
- }
-
- for sample in &mut right[range] {
- if self.fft_right.push_back_input(*sample) {
- self.fft_right.forward();
-
- retain_top_n_magnitudes(self.fft_right.get_spectrum(), order, complement);
-
- self.fft_right.inverse();
- self.fft_right.clear_input();
- }
-
- *sample = self.fft_right.pop_front_output();
- }
- }
- }
-
- // Publish any parameter changes we may have received back to the GUI.
- // Request the on-main-thread callback, which we use to refresh the UI if it is open
- self.host.request_callback();
-
- Ok(ProcessStatus::ContinueIfNotQuiet)
- }
-}
-
-impl PluginAudioPortsImpl for RetainPluginMainThread<'_> {
- fn count(&mut self, _is_input: bool) -> u32 {
- 1
- }
-
- fn get(&mut self, index: u32, _is_input: bool, writer: &mut AudioPortInfoWriter) {
- if index == 0 {
- writer.set(&AudioPortInfo {
- id: ClapId::new(0),
- name: b"main",
- channel_count: 2,
- flags: AudioPortFlags::IS_MAIN,
- port_type: Some(AudioPortType::STEREO),
- in_place_pair: None,
- });
- }
- }
-}
-
-impl PluginAudioProcessorParams for RetainPluginAudioProcessor<'_> {
- fn flush(
- &mut self,
- input_parameter_changes: &InputEvents,
- _output_parameter_changes: &mut OutputEvents,
- ) {
- for event in input_parameter_changes {
- self.params.handle_event(event);
- }
- }
-}