Add more basic fields for PolyModSynth
This commit is contained in:
parent
e77eca88a5
commit
4ad4f8f76d
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -2939,6 +2939,8 @@ name = "poly_mod_synth"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nih_plug",
|
"nih_plug",
|
||||||
|
"rand 0.8.5",
|
||||||
|
"rand_pcg 0.3.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3057,7 +3059,7 @@ dependencies = [
|
||||||
"rand_chacha 0.2.2",
|
"rand_chacha 0.2.2",
|
||||||
"rand_core 0.5.1",
|
"rand_core 0.5.1",
|
||||||
"rand_hc",
|
"rand_hc",
|
||||||
"rand_pcg",
|
"rand_pcg 0.2.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3127,6 +3129,15 @@ dependencies = [
|
||||||
"rand_core 0.5.1",
|
"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]]
|
[[package]]
|
||||||
name = "range-alloc"
|
name = "range-alloc"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
|
|
@ -10,3 +10,6 @@ crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nih_plug = { path = "../../../", features = ["assert_process_allocs"] }
|
nih_plug = { path = "../../../", features = ["assert_process_allocs"] }
|
||||||
|
|
||||||
|
rand = "0.8.5"
|
||||||
|
rand_pcg = "0.3.1"
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use nih_plug::prelude::*;
|
use nih_plug::prelude::*;
|
||||||
|
use rand::Rng;
|
||||||
|
use rand_pcg::Pcg32;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// The number of simultaneous voices for this synth.
|
/// The number of simultaneous voices for this synth.
|
||||||
|
@ -13,6 +15,9 @@ const MAX_BLOCK_SIZE: usize = 64;
|
||||||
struct PolyModSynth {
|
struct PolyModSynth {
|
||||||
params: Arc<PolyModSynthParams>,
|
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.
|
/// The synth's voices. Inactive voices will be set to `None` values.
|
||||||
voices: [Option<Voice>; NUM_VOICES as usize],
|
voices: [Option<Voice>; NUM_VOICES as usize],
|
||||||
/// The next internal voice ID, used only to figure out the oldest voice for voice stealing.
|
/// 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
|
/// 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.
|
/// voice. This is used to steal the last voice in case all 16 voices are in use.
|
||||||
internal_voice_id: u64,
|
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 {
|
impl Default for PolyModSynth {
|
||||||
|
@ -46,6 +60,7 @@ impl Default for PolyModSynth {
|
||||||
Self {
|
Self {
|
||||||
params: Arc::new(PolyModSynthParams::default()),
|
params: Arc::new(PolyModSynthParams::default()),
|
||||||
|
|
||||||
|
prng: Pcg32::new(420, 1337),
|
||||||
// `[None; N]` requires the `Some(T)` to be `Copy`able
|
// `[None; N]` requires the `Some(T)` to be `Copy`able
|
||||||
voices: [0; NUM_VOICES as usize].map(|_| None),
|
voices: [0; NUM_VOICES as usize].map(|_| None),
|
||||||
next_internal_voice_id: 0,
|
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
|
// `context.set_current_voice_capacity()` in `initialize()` and in `process()` (when the
|
||||||
// capacity changes) to inform the host about this.
|
// capacity changes) to inform the host about this.
|
||||||
fn reset(&mut self) {
|
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.voices.fill(None);
|
||||||
self.next_internal_voice_id = 0;
|
self.next_internal_voice_id = 0;
|
||||||
}
|
}
|
||||||
|
@ -125,6 +143,10 @@ impl Plugin for PolyModSynth {
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: Add and set the other fields
|
// 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 {
|
NoteEvent::NoteOff {
|
||||||
timing,
|
timing,
|
||||||
|
@ -211,6 +233,10 @@ impl PolyModSynth {
|
||||||
internal_voice_id: self.next_internal_voice_id,
|
internal_voice_id: self.next_internal_voice_id,
|
||||||
channel,
|
channel,
|
||||||
note,
|
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);
|
self.next_internal_voice_id = self.next_internal_voice_id.wrapping_add(1);
|
||||||
|
|
||||||
|
|
|
@ -131,6 +131,7 @@ impl<P: ClapPlugin> ProcessContext for WrapperProcessContext<'_, P> {
|
||||||
PluginApi::Clap
|
PluginApi::Clap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn transport(&self) -> &Transport {
|
fn transport(&self) -> &Transport {
|
||||||
&self.transport
|
&self.transport
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,6 +101,7 @@ impl<P: Plugin, B: Backend> ProcessContext for WrapperProcessContext<'_, P, B> {
|
||||||
PluginApi::Standalone
|
PluginApi::Standalone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn transport(&self) -> &Transport {
|
fn transport(&self) -> &Transport {
|
||||||
&self.transport
|
&self.transport
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,6 +135,7 @@ impl<P: Vst3Plugin> ProcessContext for WrapperProcessContext<'_, P> {
|
||||||
PluginApi::Vst3
|
PluginApi::Vst3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn transport(&self) -> &Transport {
|
fn transport(&self) -> &Transport {
|
||||||
&self.transport
|
&self.transport
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue