-
Notifications
You must be signed in to change notification settings - Fork 9
Optional standalone format #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 9 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
fbfa75c
Add new standalone plugin format
emuell a0e463e
Add standalone target for the gain example
emuell 60fe046
Add justfile
emuell ecb61fc
Don't send Start/EndParameterChange events to plugins
emuell eef5489
Revert xtask changes and remove/ignore justfile
emuell fb8f4e3
Log (for events) or assert (for audio buffers) allocations on the aud…
emuell 7bc59ae
Add README for the gain example to make clear how to build it
emuell d2738ba
Add TODO for StandaloneParameterEventIterator's next impl
emuell 6625f0f
Add audio and MIDI configs and enumerate functions to allow selecting…
emuell 0408af6
Removed some logging & fixed some comments
emuell 2b92145
Remove `export_standalone` macro & add new `run_standalone` and `run_…
emuell File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| .DS_Store | ||
| .vscode | ||
| .zed | ||
| justfile | ||
| Cargo.lock | ||
| target |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # Gain Plugin Example | ||
|
|
||
| A minimal example audio effect plugin demonstrating the `plugin-things` framework. | ||
|
|
||
| ## Building | ||
|
|
||
| > Append `--release` to any command below for a release build. | ||
|
|
||
| ### Plugin Bundles (CLAP & VST3) | ||
|
|
||
| ```sh | ||
| cargo xtask bundle gain-plugin | ||
| ``` | ||
|
|
||
| ### Standalone App | ||
|
|
||
| ```sh | ||
| cargo run -p gain-plugin --features standalone | ||
| ``` | ||
|
|
||
| ### Standalone App with Live Preview | ||
|
|
||
| Hot-reload the Slint UI when modifying .slint UI files without recompiling the app. | ||
|
|
||
| ```sh | ||
| SLINT_LIVE_PREVIEW=1 cargo run -p gain-plugin --features=standalone,slint/live-preview | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,3 +3,5 @@ mod parameters; | |
| mod plugin; | ||
| mod processor; | ||
| mod view; | ||
|
|
||
| pub use plugin::GainPlugin; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| use gain_plugin::GainPlugin; | ||
|
|
||
| plinth_plugin::export_standalone!(GainPlugin); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| mod audio; | ||
| mod config; | ||
| mod host; | ||
| mod macros; | ||
| mod midi; | ||
| mod parameters; | ||
| mod plugin; | ||
| mod runner; | ||
|
|
||
| pub use config::{AudioDeviceDriver, AudioOutputConfig, MidiInputConfig}; | ||
| pub use plugin::StandalonePlugin; | ||
| pub use runner::run_standalone; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| use std::sync::{Arc, mpsc::Receiver}; | ||
|
|
||
| use cpal::{FromSample, Sample}; | ||
| use plinth_core::{ buffers::buffer::Buffer, signals::{ signal::{Signal, SignalMut}, signal_base::SignalBase } }; | ||
|
|
||
| use super::parameters::StandaloneParameterEventMap; | ||
| use super::plugin::StandalonePlugin; | ||
| use crate::{Event, Processor}; | ||
|
|
||
| /// Push events to a event list vec, printing a warning when preallocated memory exceeded. | ||
| trait EventListPush { | ||
| type EventType; | ||
| fn push_event(&mut self, event: Self::EventType); | ||
| } | ||
|
|
||
| impl EventListPush for Vec<Event> { | ||
| type EventType = Event; | ||
| fn push_event(&mut self, event: Event) { | ||
| if self.len() == self.capacity() { | ||
| log::warn!( | ||
| "Event queue exceeded preallocated capacity of {} - allocating more. \ | ||
| Increase EVENT_QUEUE_LEN to avoid allocation on the audio thread.", | ||
| self.capacity() | ||
| ); | ||
| self.reserve(128); | ||
| } | ||
| self.push(event); | ||
| } | ||
| } | ||
|
|
||
| /// Runs a plinth processor on a CPAL audio stream | ||
| pub struct AudioState<P: StandalonePlugin> { | ||
| pub processor: P::Processor, | ||
| pub buffer: Buffer, | ||
| pub channels: usize, | ||
| pub midi_receiver: Receiver<Event>, | ||
| pub parameter_event_map: Arc<StandaloneParameterEventMap>, | ||
| pending_events: Vec<Event>, | ||
| } | ||
|
|
||
| impl<P: StandalonePlugin> AudioState<P> { | ||
| pub fn new( | ||
| processor: P::Processor, | ||
| channels: usize, | ||
| midi_receiver: Receiver<Event>, | ||
| parameter_event_map: Arc<StandaloneParameterEventMap>, | ||
| ) -> Self { | ||
| Self { | ||
| processor, | ||
| buffer: Buffer::new(channels, P::MAX_BLOCK_SIZE), | ||
| channels, | ||
| midi_receiver, | ||
| parameter_event_map, | ||
| pending_events: Vec::with_capacity(P::EVENT_QUEUE_LEN), | ||
| } | ||
| } | ||
|
|
||
| pub fn process<T>(&mut self, data: &mut [T], channels: usize) | ||
| where | ||
| T: Sample + FromSample<f32>, | ||
| f32: FromSample<T>, | ||
| { | ||
| let frame_count = data.len() / channels; | ||
|
|
||
| // Drain MIDI events | ||
| self.pending_events.clear(); | ||
| while let Ok(event) = self.midi_receiver.try_recv() { | ||
| self.pending_events.push_event(event); | ||
| } | ||
|
|
||
| // Collect pending parameter change events | ||
| for event in self.parameter_event_map.iter_events() { | ||
| self.pending_events.push_event(event); | ||
| } | ||
|
|
||
| // Process audio, ensuring we don't call process with more than P::MAX_BLOCK_SIZE frames | ||
| debug_assert!( | ||
| self.buffer.capacity() == P::MAX_BLOCK_SIZE, | ||
| "Buffer must be preallocated to avoid allocation on the saudio thread" | ||
| ); | ||
|
|
||
| let mut frame_offset = 0; | ||
| while frame_offset < frame_count { | ||
| let chunk_size = (frame_count - frame_offset).min(P::MAX_BLOCK_SIZE); | ||
|
|
||
| // Truncate or extend buffer to fit the chunk | ||
| if self.buffer.len() != chunk_size { | ||
| self.buffer.resize(chunk_size); | ||
|
ilmai marked this conversation as resolved.
|
||
| } | ||
|
|
||
| // Deinterleave chunk from CPAL buffer | ||
| for frame in 0..chunk_size { | ||
| for ch in 0..self.channels { | ||
| self.buffer.channel_mut(ch)[frame] = | ||
| f32::from_sample(data[(frame_offset + frame) * self.channels + ch]); | ||
| } | ||
| } | ||
|
|
||
| // Process and drain all events on first run, assuming they have no time tags | ||
| let aux: Option<&Buffer> = None; | ||
| self.processor | ||
| .process(&mut self.buffer, aux, None, self.pending_events.drain(..)); | ||
|
|
||
| // Reinterleave chunk back into CPAL buffer | ||
| for frame in 0..chunk_size { | ||
| for ch in 0..self.channels { | ||
| data[(frame_offset + frame) * self.channels + ch] = | ||
| T::from_sample(self.buffer.channel(ch)[frame]); | ||
| } | ||
| } | ||
|
|
||
| frame_offset += chunk_size; | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.