1
0
Fork 0

Add more basic fields for PolyModSynth

This commit is contained in:
Robbert van der Helm 2022-07-06 16:35:07 +02:00
parent e77eca88a5
commit 4ad4f8f76d
6 changed files with 44 additions and 1 deletions

13
Cargo.lock generated
View file

@ -2939,6 +2939,8 @@ name = "poly_mod_synth"
version = "0.1.0"
dependencies = [
"nih_plug",
"rand 0.8.5",
"rand_pcg 0.3.1",
]
[[package]]
@ -3057,7 +3059,7 @@ dependencies = [
"rand_chacha 0.2.2",
"rand_core 0.5.1",
"rand_hc",
"rand_pcg",
"rand_pcg 0.2.1",
]
[[package]]
@ -3127,6 +3129,15 @@ dependencies = [
"rand_core 0.5.1",
]
[[package]]
name = "rand_pcg"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e"
dependencies = [
"rand_core 0.6.3",
]
[[package]]
name = "range-alloc"
version = "0.1.2"

View file

@ -10,3 +10,6 @@ crate-type = ["cdylib"]
[dependencies]
nih_plug = { path = "../../../", features = ["assert_process_allocs"] }
rand = "0.8.5"
rand_pcg = "0.3.1"

View file

@ -1,4 +1,6 @@
use nih_plug::prelude::*;
use rand::Rng;
use rand_pcg::Pcg32;
use std::sync::Arc;
/// The number of simultaneous voices for this synth.
@ -13,6 +15,9 @@ const MAX_BLOCK_SIZE: usize = 64;
struct PolyModSynth {
params: Arc<PolyModSynthParams>,
/// A pseudo-random number generator. This will always be reseeded with the same seed when the
/// synth is reset. That way the output is deterministic when rendering multiple times.
prng: Pcg32,
/// The synth's voices. Inactive voices will be set to `None` values.
voices: [Option<Voice>; NUM_VOICES as usize],
/// The next internal voice ID, used only to figure out the oldest voice for voice stealing.
@ -39,6 +44,15 @@ struct Voice {
/// The voices internal ID. Each voice has an internal voice ID one higher than the previous
/// voice. This is used to steal the last voice in case all 16 voices are in use.
internal_voice_id: u64,
/// The voice's current phase. This is randomized at the start of the voice
phase: f32,
/// The phase increment. This is based on the voice's frequency, derived from the note index.
/// Since we don't support pitch expressions or pitch bend, this value stays constant for the
/// duration of the voice.
phase_delta: f32,
/// The square root of the note's velocity. This is used as a gain multiplier.
velocity_sqrt: f32,
}
impl Default for PolyModSynth {
@ -46,6 +60,7 @@ impl Default for PolyModSynth {
Self {
params: Arc::new(PolyModSynthParams::default()),
prng: Pcg32::new(420, 1337),
// `[None; N]` requires the `Some(T)` to be `Copy`able
voices: [0; NUM_VOICES as usize].map(|_| None),
next_internal_voice_id: 0,
@ -77,6 +92,9 @@ impl Plugin for PolyModSynth {
// `context.set_current_voice_capacity()` in `initialize()` and in `process()` (when the
// capacity changes) to inform the host about this.
fn reset(&mut self) {
// This ensures the output is at least somewhat deterministic when rendering to audio
self.prng = Pcg32::new(420, 1337);
self.voices.fill(None);
self.next_internal_voice_id = 0;
}
@ -125,6 +143,10 @@ impl Plugin for PolyModSynth {
);
// TODO: Add and set the other fields
voice.phase = self.prng.gen();
voice.phase_delta =
util::midi_note_to_freq(note) / context.transport().sample_rate;
voice.velocity_sqrt = velocity.sqrt();
}
NoteEvent::NoteOff {
timing,
@ -211,6 +233,10 @@ impl PolyModSynth {
internal_voice_id: self.next_internal_voice_id,
channel,
note,
velocity_sqrt: 1.0,
phase: 0.0,
phase_delta: 0.0,
};
self.next_internal_voice_id = self.next_internal_voice_id.wrapping_add(1);

View file

@ -131,6 +131,7 @@ impl<P: ClapPlugin> ProcessContext for WrapperProcessContext<'_, P> {
PluginApi::Clap
}
#[inline]
fn transport(&self) -> &Transport {
&self.transport
}

View file

@ -101,6 +101,7 @@ impl<P: Plugin, B: Backend> ProcessContext for WrapperProcessContext<'_, P, B> {
PluginApi::Standalone
}
#[inline]
fn transport(&self) -> &Transport {
&self.transport
}

View file

@ -135,6 +135,7 @@ impl<P: Vst3Plugin> ProcessContext for WrapperProcessContext<'_, P> {
PluginApi::Vst3
}
#[inline]
fn transport(&self) -> &Transport {
&self.transport
}