1
0
Fork 0

Add an octave shift to Buffr Glitch

This commit is contained in:
Robbert van der Helm 2022-11-09 18:38:44 +01:00
parent 179ff6a035
commit 333ff2c05e
2 changed files with 28 additions and 6 deletions

View file

@ -16,7 +16,7 @@
use nih_plug::prelude::*; use nih_plug::prelude::*;
use crate::NormalizationMode; use crate::{NormalizationMode, MAX_OCTAVE_SHIFT};
/// A super simple ring buffer abstraction that records audio into a recording ring buffer, and then /// A super simple ring buffer abstraction that records audio into a recording ring buffer, and then
/// copies audio to a playback buffer when a note is pressed so audio can be repeated while still /// copies audio to a playback buffer when a note is pressed so audio can be repeated while still
@ -47,9 +47,12 @@ impl RingBuffer {
/// MIDI note 0 at the specified sample rate, rounded up to a power of two. Make sure to call /// MIDI note 0 at the specified sample rate, rounded up to a power of two. Make sure to call
/// [`reset()`][Self::reset()] after this. /// [`reset()`][Self::reset()] after this.
pub fn resize(&mut self, num_channels: usize, sample_rate: f32) { pub fn resize(&mut self, num_channels: usize, sample_rate: f32) {
let note_frequency = util::midi_note_to_freq(0); // NOTE: We need to take the octave shift into account
let note_period_samples = (note_frequency.recip() * sample_rate).ceil() as usize; let lowest_note_frequency =
let buffer_len = note_period_samples.next_power_of_two(); util::midi_note_to_freq(0) / 2.0f32.powi(MAX_OCTAVE_SHIFT as i32);
let loest_note_period_samples =
(lowest_note_frequency.recip() * sample_rate).ceil() as usize;
let buffer_len = loest_note_period_samples.next_power_of_two();
// Used later to compute period sizes in samples based on frequencies // Used later to compute period sizes in samples based on frequencies
self.sample_rate = sample_rate; self.sample_rate = sample_rate;

View file

@ -19,6 +19,10 @@ use std::sync::Arc;
mod buffer; mod buffer;
/// The maximum number of octaves the sample can be pitched down. This is used in calculating the
/// recording buffer's size.
pub const MAX_OCTAVE_SHIFT: u32 = 2;
struct BuffrGlitch { struct BuffrGlitch {
params: Arc<BuffrGlitchParams>, params: Arc<BuffrGlitchParams>,
@ -38,6 +42,10 @@ struct BuffrGlitchParams {
/// Controls if and how grains are normalization. /// Controls if and how grains are normalization.
#[id = "normalization_mode"] #[id = "normalization_mode"]
normalization_mode: EnumParam<NormalizationMode>, normalization_mode: EnumParam<NormalizationMode>,
/// The number of octaves the input signal should be increased or decreased by. Useful to allow
/// larger grain sizes.
#[id = "octave_shift"]
octave_shift: IntParam,
} }
/// Controls how grains are normalized. /// Controls how grains are normalized.
@ -69,6 +77,14 @@ impl Default for BuffrGlitchParams {
fn default() -> Self { fn default() -> Self {
Self { Self {
normalization_mode: EnumParam::new("Normalization", NormalizationMode::Auto), normalization_mode: EnumParam::new("Normalization", NormalizationMode::Auto),
octave_shift: IntParam::new(
"Octave Shift",
0,
IntRange::Linear {
min: -(MAX_OCTAVE_SHIFT as i32),
max: MAX_OCTAVE_SHIFT as i32,
},
),
} }
} }
} }
@ -140,9 +156,12 @@ impl Plugin for BuffrGlitch {
self.midi_note_id = Some(note); self.midi_note_id = Some(note);
// We'll copy audio to the playback buffer to match the pitch of the note // We'll copy audio to the playback buffer to match the pitch of the note
// that was just played // that was just played. The octave shift parameter makes it possible to get
// larger window sizes.
let note_frequency = util::midi_note_to_freq(note)
* 2.0f32.powi(self.params.octave_shift.value());
self.buffer.prepare_playback( self.buffer.prepare_playback(
util::midi_note_to_freq(note), note_frequency,
self.params.normalization_mode.value(), self.params.normalization_mode.value(),
); );
} }