commit 0cfc6f61750cb346d739a04162f6f76577ffe206
Author: minerva-jupiter <ryouturn@gmail.com>
Date: Tue, 10 Mar 2026 01:23:35 +0900
init of `pipx run cookiecutter gh:robbert-vdh/nih-plug-template`
Diffstat:
8 files changed, 218 insertions(+), 0 deletions(-)
diff --git a/.cargo/config b/.cargo/config
@@ -0,0 +1,2 @@
+[alias]
+xtask = "run --package xtask --release --"
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/Cargo.toml b/Cargo.toml
@@ -0,0 +1,31 @@
+[package]
+name = "mooxide"
+version = "0.1.0"
+edition = "2021"
+authors = ["minerva-jupiter <ryouturn@gmail.com>"]
+license = "Other licenses can be set in Cargo.toml, but using the project needs to be GPLv3 compliant to be able to use the VST3 exporter. Check Cargo.toml for more information."
+homepage = "https://minervajuppiter.net"
+description = "simple synth"
+
+[workspace]
+members = ["xtask"]
+
+[lib]
+crate-type = ["cdylib"]
+
+[dependencies]
+# Remove the `assert_process_allocs` feature to allow allocations on the audio
+# thread in debug builds.
+nih_plug = { git = "https://github.com/robbert-vdh/nih-plug.git", features = ["assert_process_allocs"] }
+# Uncomment the below line to disable the on-by-default VST3 feature to remove
+# the GPL compatibility requirement
+# nih_plug = { git = "https://github.com/robbert-vdh/nih-plug.git", default-features = false, features = ["assert_process_allocs"] }
+
+[profile.release]
+lto = "thin"
+strip = "symbols"
+
+[profile.profiling]
+inherits = "release"
+debug = true
+strip = "none"
diff --git a/README.md b/README.md
@@ -0,0 +1,9 @@
+# Mooxide
+
+## Building
+
+After installing [Rust](https://rustup.rs/), you can compile Mooxide as follows:
+
+```shell
+cargo xtask bundle mooxide --release
+```
diff --git a/bundler.toml b/bundler.toml
@@ -0,0 +1,8 @@
+# This provides metadata for NIH-plug's `cargo xtask bundle <foo>` plugin
+# bundler. This file's syntax is as follows:
+#
+# [package_name]
+# name = "Human Readable Plugin Name" # defaults to <package_name>
+
+[mooxide]
+name = "Mooxide"
diff --git a/src/lib.rs b/src/lib.rs
@@ -0,0 +1,157 @@
+use nih_plug::prelude::*;
+use std::sync::Arc;
+
+// This is a shortened version of the gain example with most comments removed, check out
+// https://github.com/robbert-vdh/nih-plug/blob/master/plugins/examples/gain/src/lib.rs to get
+// started
+
+struct Mooxide {
+ params: Arc<MooxideParams>,
+}
+
+#[derive(Params)]
+struct MooxideParams {
+ /// The parameter's ID is used to identify the parameter in the wrappred plugin API. As long as
+ /// these IDs remain constant, you can rename and reorder these fields as you wish. The
+ /// parameters are exposed to the host in the same order they were defined. In this case, this
+ /// gain parameter is stored as linear gain while the values are displayed in decibels.
+ #[id = "gain"]
+ pub gain: FloatParam,
+}
+
+impl Default for Mooxide {
+ fn default() -> Self {
+ Self {
+ params: Arc::new(MooxideParams::default()),
+ }
+ }
+}
+
+impl Default for MooxideParams {
+ fn default() -> Self {
+ Self {
+ // This gain is stored as linear gain. NIH-plug comes with useful conversion functions
+ // to treat these kinds of parameters as if we were dealing with decibels. Storing this
+ // as decibels is easier to work with, but requires a conversion for every sample.
+ gain: FloatParam::new(
+ "Gain",
+ util::db_to_gain(0.0),
+ FloatRange::Skewed {
+ min: util::db_to_gain(-30.0),
+ max: util::db_to_gain(30.0),
+ // This makes the range appear as if it was linear when displaying the values as
+ // decibels
+ factor: FloatRange::gain_skew_factor(-30.0, 30.0),
+ },
+ )
+ // Because the gain parameter is stored as linear gain instead of storing the value as
+ // decibels, we need logarithmic smoothing
+ .with_smoother(SmoothingStyle::Logarithmic(50.0))
+ .with_unit(" dB")
+ // There are many predefined formatters we can use here. If the gain was stored as
+ // decibels instead of as a linear gain value, we could have also used the
+ // `.with_step_size(0.1)` function to get internal rounding.
+ .with_value_to_string(formatters::v2s_f32_gain_to_db(2))
+ .with_string_to_value(formatters::s2v_f32_gain_to_db()),
+ }
+ }
+}
+
+impl Plugin for Mooxide {
+ const NAME: &'static str = "Mooxide";
+ const VENDOR: &'static str = "minerva-jupiter";
+ const URL: &'static str = env!("CARGO_PKG_HOMEPAGE");
+ const EMAIL: &'static str = "ryouturn@gmail.com";
+
+ const VERSION: &'static str = env!("CARGO_PKG_VERSION");
+
+ // The first audio IO layout is used as the default. The other layouts may be selected either
+ // explicitly or automatically by the host or the user depending on the plugin API/backend.
+ const AUDIO_IO_LAYOUTS: &'static [AudioIOLayout] = &[AudioIOLayout {
+ main_input_channels: NonZeroU32::new(2),
+ main_output_channels: NonZeroU32::new(2),
+
+ aux_input_ports: &[],
+ aux_output_ports: &[],
+
+ // Individual ports and the layout as a whole can be named here. By default these names
+ // are generated as needed. This layout will be called 'Stereo', while a layout with
+ // only one input and output channel would be called 'Mono'.
+ names: PortNames::const_default(),
+ }];
+
+
+ const MIDI_INPUT: MidiConfig = MidiConfig::None;
+ const MIDI_OUTPUT: MidiConfig = MidiConfig::None;
+
+ const SAMPLE_ACCURATE_AUTOMATION: bool = true;
+
+ // If the plugin can send or receive SysEx messages, it can define a type to wrap around those
+ // messages here. The type implements the `SysExMessage` trait, which allows conversion to and
+ // from plain byte buffers.
+ type SysExMessage = ();
+ // More advanced plugins can use this to run expensive background tasks. See the field's
+ // documentation for more information. `()` means that the plugin does not have any background
+ // tasks.
+ type BackgroundTask = ();
+
+ fn params(&self) -> Arc<dyn Params> {
+ self.params.clone()
+ }
+
+ fn initialize(
+ &mut self,
+ _audio_io_layout: &AudioIOLayout,
+ _buffer_config: &BufferConfig,
+ _context: &mut impl InitContext<Self>,
+ ) -> bool {
+ // Resize buffers and perform other potentially expensive initialization operations here.
+ // The `reset()` function is always called right after this function. You can remove this
+ // function if you do not need it.
+ true
+ }
+
+ fn reset(&mut self) {
+ // Reset buffers and envelopes here. This can be called from the audio thread and may not
+ // allocate. You can remove this function if you do not need it.
+ }
+
+ fn process(
+ &mut self,
+ buffer: &mut Buffer,
+ _aux: &mut AuxiliaryBuffers,
+ _context: &mut impl ProcessContext<Self>,
+ ) -> ProcessStatus {
+ for channel_samples in buffer.iter_samples() {
+ // Smoothing is optionally built into the parameters themselves
+ let gain = self.params.gain.smoothed.next();
+
+ for sample in channel_samples {
+ *sample *= gain;
+ }
+ }
+
+ ProcessStatus::Normal
+ }
+}
+
+impl ClapPlugin for Mooxide {
+ const CLAP_ID: &'static str = "net.minervajuppiter.mooxide";
+ const CLAP_DESCRIPTION: Option<&'static str> = Some("simple synth");
+ const CLAP_MANUAL_URL: Option<&'static str> = Some(Self::URL);
+ const CLAP_SUPPORT_URL: Option<&'static str> = None;
+
+ // Don't forget to change these features
+ const CLAP_FEATURES: &'static [ClapFeature] = &[ClapFeature::AudioEffect, ClapFeature::Stereo];
+}
+
+impl Vst3Plugin for Mooxide {
+ const VST3_CLASS_ID: [u8; 16] = *b"Exactly16Chars!!";
+
+ // And also don't forget to change these categories
+ const VST3_SUBCATEGORIES: &'static [Vst3SubCategory] =
+ &[Vst3SubCategory::Fx, Vst3SubCategory::Dynamics];
+}
+
+nih_export_clap!(Mooxide);
+nih_export_vst3!(Mooxide);
diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "xtask"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+nih_plug_xtask = { git = "https://github.com/robbert-vdh/nih-plug.git" }
diff --git a/xtask/src/main.rs b/xtask/src/main.rs
@@ -0,0 +1,3 @@
+fn main() -> nih_plug_xtask::Result<()> {
+ nih_plug_xtask::main()
+}