diff --git a/Cargo.lock b/Cargo.lock index f3d33ae1..8553f386 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1822,6 +1822,13 @@ dependencies = [ "log", ] +[[package]] +name = "loudness_war_winner" +version = "0.1.0" +dependencies = [ + "nih_plug", +] + [[package]] name = "lru" version = "0.7.5" diff --git a/Cargo.toml b/Cargo.toml index 2e3f2bbd..6242a1fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ members = [ "plugins/crisp", "plugins/diopser", + "plugins/loudness_war_winner", "plugins/puberty_simulator", ] diff --git a/README.md b/README.md index bf47b58e..7f5fb842 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,9 @@ for download links. Useful for oomphing up kickdrums and basses, transforming synths into their evil phase-y cousin, and making everything sound like a cheap Sci-Fi laser beam. +- [**Loudness War Winner**](plugins/loudness_war_winner) does what it says on + the tin. Have you ever wanted to show off your dominance by winning the + loudness war? Neither have I. Dissatisfaction guaranteed. - [**Puberty Simulator**](plugins/puberty_simulator) is that patent pending One Weird Plugin that simulates the male voice change during puberty! If it was not already obvious from that sentence, this plugin is a joke, but it might diff --git a/plugins/loudness_war_winner/Cargo.toml b/plugins/loudness_war_winner/Cargo.toml new file mode 100644 index 00000000..6b6b299e --- /dev/null +++ b/plugins/loudness_war_winner/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "loudness_war_winner" +version = "0.1.0" +edition = "2021" +authors = ["Robbert van der Helm "] +license = "GPL-3.0-or-later" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +nih_plug = { path = "../../", features = ["assert_process_allocs"] } diff --git a/plugins/loudness_war_winner/README.md b/plugins/loudness_war_winner/README.md new file mode 100644 index 00000000..dc3e9a52 --- /dev/null +++ b/plugins/loudness_war_winner/README.md @@ -0,0 +1,38 @@ +# Loudness War Winner + +This plugin does what it says on the tin. Have you ever wanted to show off your +dominance by winning the loudness war? Neither have I. Dissatisfaction +guaranteed. + +_Loudness War Winner may cause side effects such as headache, nausea, diarrhea, +loss of balance, loss of sight, loss of hearing, loss of other senses, loss of +common sense, heart palpitations, heart arrhythmia, heart attack, other Demi +Lovato songs, rashes, acne, boils, simmers, chronic earwax, acute belly button +lint, athlete's foot, tennis elbow, couch potato butt, depression, anxiety, +Scientology, multiple sclerosis, single sclerosis, divorced sclerosis, it's +complicated sclerosis, paralysis, hyperactivity, TikTokism, time travel, +Matrixism, Marxism, sudden clarity and awareness of your surroundings and +situation, existential dread, suicide, and enlarged earlobes. Ask your doctor if +Loudness War Winner is right for you._ + +## Download + +You can download the development binaries for Linux, Windows and macOS from the +[automated +builds](https://github.com/robbert-vdh/nih-plug/actions/workflows/test.yml?query=branch%3Amaster) +page. If you're not signed in on GitHub, then you can also find the last nightly +build [here](https://nightly.link/robbert-vdh/nih-plug/workflows/build/master). + +The macOS version has not been tested and may not work correctly. You may also +have to [disable Gatekeeper](https://disable-gatekeeper.github.io/) to use the +VST3 version as Apple has recently made it more difficult to run unsigned code +on macOS. + +### Building + +After installing [Rust](https://rustup.rs/), you can compile Puberty Simulator +as follows: + +```shell +cargo xtask bundle loudness_war_winner --release +``` diff --git a/plugins/loudness_war_winner/src/lib.rs b/plugins/loudness_war_winner/src/lib.rs new file mode 100644 index 00000000..c01407aa --- /dev/null +++ b/plugins/loudness_war_winner/src/lib.rs @@ -0,0 +1,126 @@ +// Loudness War Winner: Because negative LUFS are boring +// Copyright (C) 2022 Robbert van der Helm +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use nih_plug::prelude::*; +use std::sync::Arc; + +struct LoudnessWarWinner { + params: Arc, +} + +#[derive(Params)] +struct LoudnessWarWinnerParams { + /// The output gain, set to -24 dB by default because oof ouchie. + #[id = "output"] + output_gain: FloatParam, +} + +impl Default for LoudnessWarWinner { + fn default() -> Self { + Self { + params: Arc::new(LoudnessWarWinnerParams::default()), + } + } +} + +impl Default for LoudnessWarWinnerParams { + fn default() -> Self { + Self { + output_gain: FloatParam::new( + "Output Gain", + util::db_to_gain(-24.0), + // Because we're representing gain as decibels the range is already logarithmic + FloatRange::Linear { + min: util::db_to_gain(-24.0), + max: util::db_to_gain(0.0), + }, + ) + .with_smoother(SmoothingStyle::Logarithmic(10.0)) + .with_unit(" dB") + .with_value_to_string(formatters::v2s_f32_gain_to_db(2)) + .with_string_to_value(formatters::s2v_f32_gain_to_db()), + } + } +} + +impl Plugin for LoudnessWarWinner { + const NAME: &'static str = "Loudness War Winner"; + const VENDOR: &'static str = "Robbert van der Helm"; + const URL: &'static str = "https://github.com/robbert-vdh/nih-plug"; + const EMAIL: &'static str = "mail@robbertvanderhelm.nl"; + + const VERSION: &'static str = "0.1.0"; + + const DEFAULT_NUM_INPUTS: u32 = 2; + const DEFAULT_NUM_OUTPUTS: u32 = 2; + + fn params(&self) -> Arc { + // The explicit cast is not needed, but Rust Analyzer gets very upset when you don't do it + self.params.clone() as Arc + } + + fn accepts_bus_config(&self, config: &BusConfig) -> bool { + config.num_input_channels == config.num_output_channels && config.num_input_channels > 0 + } + + fn reset(&mut self) { + // TODO: Keep track of silence samples and reset it here to avoid a DC offset + } + + fn process( + &mut self, + buffer: &mut Buffer, + _context: &mut impl ProcessContext, + ) -> ProcessStatus { + for channel_samples in buffer.iter_samples() { + let output_gain = self.params.output_gain.smoothed.next(); + + // TODO: Slowly fade back to zero after a period of uninterrupted silence so this + // doesn't output a constant DC signal even when the input is silent + // TODO: Add a second parameter called "WIN HARDER" that bandpasses the signal around 5 + // kHz + for sample in channel_samples { + *sample = if *sample >= 0.0 { 1.0 } else { -1.0 } * output_gain; + } + } + + ProcessStatus::Normal + } +} + +impl ClapPlugin for LoudnessWarWinner { + const CLAP_ID: &'static str = "nl.robbertvanderhelm.loudness-war-winner"; + const CLAP_DESCRIPTION: &'static str = "Win the loudness war with ease"; + const CLAP_FEATURES: &'static [&'static str] = &[ + "audio_effect", + "stereo", + "mono", + "limiter", + "distortion", + "utility", + "pain", + ]; + const CLAP_MANUAL_URL: &'static str = Self::URL; + const CLAP_SUPPORT_URL: &'static str = Self::URL; +} + +impl Vst3Plugin for LoudnessWarWinner { + const VST3_CLASS_ID: [u8; 16] = *b"LoudnessWar.RvdH"; + const VST3_CATEGORIES: &'static str = "Fx|Dynamics|Distortion"; +} + +nih_export_clap!(LoudnessWarWinner); +nih_export_vst3!(LoudnessWarWinner);