1
0
Fork 0

Add some pointers for getting started to the docs

This commit is contained in:
Robbert van der Helm 2022-05-13 15:08:05 +02:00
parent bbb73c557d
commit 8239169aaf
5 changed files with 98 additions and 19 deletions

View file

@ -5,18 +5,18 @@
[![Docs](https://github.com/robbert-vdh/nih-plug/actions/workflows/docs.yml/badge.svg?branch=master)](https://nih-plug.robbertvanderhelm.nl/) [![Docs](https://github.com/robbert-vdh/nih-plug/actions/workflows/docs.yml/badge.svg?branch=master)](https://nih-plug.robbertvanderhelm.nl/)
This is a work in progress API-agnostic audio plugin framework written in Rust This is a work in progress API-agnostic audio plugin framework written in Rust
to do some experiments with, as well as a small collection of plugins. The idea as well as a small collection of plugins. The idea is to have a statefull but
is to have a statefull but simple plugin API that gets rid of as much simple plugin API that gets rid of as much unnecessary ceremony wherever
unnecessary ceremony wherever possible, while also keeping the amount of magic possible, while also keeping the amount of magic to minimum. Since this is not
to minimum. Since this is not quite meant for general use just yet, the plugin quite meant for general use just yet, the plugin API surface is currently
API surface is currently limited to the functionality that I either needed limited to the functionality that I either needed myself or that was requested
myself or that was requested by others. See the [current by others. See the [current features](#current-features) section for more
features](#current-features) section for more information on the project's information on the project's current status.
current status.
Come join us on the [Rust Audio Discord](https://discord.gg/ykxU3rt4Cb), or Come join us on the [Rust Audio Discord](https://discord.gg/ykxU3rt4Cb), or
check out the [documentation](https://nih-plug.robbertvanderhelm.nl/) (work in check out the work in progress
progress). [documentation](https://nih-plug.robbertvanderhelm.nl/) for some pointers on how
to get started.
### Table of contents ### Table of contents

View file

@ -1,5 +1,83 @@
//! Documentation is currently a work in progress. Import everything from the [`prelude`] module and //! Documentation is still a work in progress. The best way to learn right now is to browse through
//! check out the example plugins to get started. //! the examples and to browse through these docs. There is no full guide yet, but here are some
//! pointers to get started:
//!
//! - All useful functionality is exported through the [`prelude`] module. Add
//! `use nih_plug::prelude::*;` to the top of your `lib.rs` file to get started.
//! - Make sure to check out the macros from the [`debug`] module. These should be used instead of,
//! `println!()`/`eprint!()`, `dbg!()` and similar macros, and they are re-exported from the
//! prelude. NIH-plug sets up a flexible logger for you that all of these functions will output
//! to. By default, the output is logged to STDERR unless you're running Windows and a Windows
//! debugger is attached, in which case the output is logged to the debug console instead. The
//! `NIH_LOG` environment variable controls whether output is logged to STDERR, the Windows debug
//! console, or to a file. Check the [`nih_log!()`] macro for more information.
//! - The abovementioned debug module also contains non-fatal debug-assertions macros that are only
//! evaluated during debug builds. The framework uses these all over the place to check for
//! invariants, so it's important to test your plugins using debug builds while developing.
//! - Check out the features list in NIH-plug's `Cargo.toml` file for optional features you can
//! enable. This includes things like SIMD support for the buffer adapters and panicking on
//! allocations during DSP code in debug mode.
//!
//! - An NIH-plug plugin consists of an implementation of the [`Plugin`][prelude::Plugin] trait and
//! a call to [`nih_export_vst3!()`] and/or [`nih_export_clap!()`] in your `lib.rs` file to expose
//! the plugin functionality. Some of these traits will require you to implement an additional
//! trait containing API-specific information for the plugin.
//! - NIH-plug comes with a bundler that creates plugin bundles for you based on the exported plugin
//! formats and the operating system and architecture you're compiling for. Check out the
//! readme for
//! [`nih_plug_xtask`](https://github.com/robbert-vdh/nih-plug/tree/master/nih_plug_xtask) for
//! instructions on how to use this within your own project.
//! - It's also possible to export a standalone application from a plugin using the
//! [`nih_export_standalone()`][prelude::nih_export_standalone()] function. Check that function's
//! documentation to learn how to do this. This requires enabling the `standalone` crate feature.
//! - Everything is described in more detail on the [`Plugin`][prelude::Plugin] trait and everything
//! linked from there, but a plugin's general lifecycle involves the following function calls.
//!
//! 1. When the host loads the plugin, your plugin object will be instantiated using its
//! [`Default`] implementation. The plugin should refrain from performing expensive
//! calculations or IO at this point.
//! 2. The host or the plugin wrapper will call
//! [`Plugin::accepts_bus_config()`][prelude::Plugin::accepts_bus_config()] several times with
//! different IO configuratinos to poll whether your plugin supports certain IO configurations.
//! The plugin should not do any work at this point and just reply with boolean whether it
//! supports the configuration or not.
//! 3. After that, [`Plugin::initialize()`][prelude::Plugin::initialize()] will be called with the
//! the selected IO configuration and the audio buffer settings. Here you should allocate any
//! data structures you need or precompute data that depends on the sample rate or maximum
//! buffer size. This is the only place where you can safely allocate memory.
//! 4. The [`Plugin::reset()`][prelude::Plugin::reset()] function is always called immediately
//! after `initialize()`. This is where you should clear out coefficients, envelopes, phases,
//! and other runtime data. The reason for this split is that this function may be called at
//! any time by the host from the audio thread, and it thus needs to be realtime safe.
//!
//! Whenever a preset is loaded, both of these functions will be called again.
//! 5. After that the [`Plugin::process()`][prelude::Plugin::process()] function will be called
//! repeatedly until the plugin is deactivated. Here the plugin receives a
//! [`Buffer`][prelude::Buffer] object that contains the input audio (if the plugin has inputs)
//! which the plugin should overwrite with output audio. Check the documentation on the
//! `Buffer` object for all of the ways you can use this API. You can access note events,
//! transport data, and more through the [`ProcessContext`][prelude::ProcessContext] that's
//! also passed to the process function.
//!
//! - Plugin parameters are managed automatically by creating a struct deriving the
//! [`Params`][prelude::Params] trait and returning a handle to it from the
//! [`Plugin::params()`][prelude::Plugin::params()] function. Any
//! [`FloatParam`][prelude::FloatParam], [`IntParam`][prelude::IntParam],
//! [`BoolParam`][prelude::BoolParam] or [`EnumParam`][prelude::EnumParam] fields on that struct
//! will automatically be registered as a parameter if they have an `#[id = "foobar"]` attribute.
//! The string `"foobar"` here uniquely identifies the parameter, making it possible to reorder
//! and rename parameters as long as this string stays constant. You can also store persistent
//! non-parameter data and other parameter objects in a `Params` struct. Check out the trait's
//! documentation for more details, and also be sure to take a look at the [example
//! plugins](https://github.com/robbert-vdh/nih-plug/tree/master/plugins).
//! - After calling `.with_smoother()` during an integer or floating point parameter's creation,
//! you can use `param.smoothed` to access smoothed values for that parameter. Be sure to check
//! out the [`Smoother`][prelude::Smoother] API for more details. If you want to generate entire
//! blocks of smoothed values, be sure to call the predefined
//! `[Plugin::initialize_block_smoothers()]` method from your plugin's `initialize()` function.
//!
//! There's a whole lot more to discuss, but once you understand the above you should be able to
//! figure out the rest by reading through the examples and the API documetnation. Good luck!
#![cfg_attr(feature = "docs", feature(doc_auto_cfg))] #![cfg_attr(feature = "docs", feature(doc_auto_cfg))]
#![cfg_attr(feature = "simd", feature(portable_simd))] #![cfg_attr(feature = "simd", feature(portable_simd))]

View file

@ -309,16 +309,17 @@ impl FloatParam {
} }
/// Display a unit when rendering this parameter to a string. Appended after the /// Display a unit when rendering this parameter to a string. Appended after the
/// [`value_to_string`][Self::value_to_string] function if that is also set. NIH-plug will not /// [`value_to_string`][Self::with_value_to_string()] function if that is also set. NIH-plug
/// automatically add a space before the unit. /// will not automatically add a space before the unit.
pub fn with_unit(mut self, unit: &'static str) -> Self { pub fn with_unit(mut self, unit: &'static str) -> Self {
self.unit = unit; self.unit = unit;
self self
} }
/// Set the distance between steps of a [FloatParam]. Mostly useful for quantizing GUI input. If /// Set the distance between steps of a [FloatParam]. Mostly useful for quantizing GUI input. If
/// this is set and if [`value_to_string`][Self::value_to_string] is not set, then this is also /// this is set and a [`value_to_string`][Self::with_value_to_string()] function is not set,
/// used when formatting the parameter. This must be a positive, nonzero number. /// then this is also used when formatting the parameter. This must be a positive, nonzero
/// number.
pub fn with_step_size(mut self, step_size: f32) -> Self { pub fn with_step_size(mut self, step_size: f32) -> Self {
self.step_size = Some(step_size); self.step_size = Some(step_size);
self self

View file

@ -270,8 +270,8 @@ impl IntParam {
} }
/// Display a unit when rendering this parameter to a string. Appended after the /// Display a unit when rendering this parameter to a string. Appended after the
/// [`value_to_string`][Self::value_to_string] function if that is also set. NIH-plug will not /// [`value_to_string`][Self::with_value_to_string()] function if that is also set. NIH-plug
/// automatically add a space before the unit. /// will not automatically add a space before the unit.
pub fn with_unit(mut self, unit: &'static str) -> Self { pub fn with_unit(mut self, unit: &'static str) -> Self {
self.unit = unit; self.unit = unit;
self self

View file

@ -262,7 +262,7 @@ impl<const NUM_SIDECHAIN_INPUTS: usize> StftHelper<NUM_SIDECHAIN_INPUTS> {
/// next block before `process_cb()` is called. /// next block before `process_cb()` is called.
/// ///
/// Since there are a couple different ways to do it, any window functions needs to be applied /// Since there are a couple different ways to do it, any window functions needs to be applied
/// in the callbacks. Check the [`nih_plug::util::window`] module for more information. /// in the callbacks. Check the [`nih_plug::util::window`][crate::util::window] module for more information.
/// ///
/// For efficiency's sake this function will reuse the same vector for all calls to /// For efficiency's sake this function will reuse the same vector for all calls to
/// `process_cb`. This means you can only access a single channel's worth of windowed data at a /// `process_cb`. This means you can only access a single channel's worth of windowed data at a