Avoid clicks in the MIDI sine example
This commit is contained in:
parent
073fe743c2
commit
2c0b797c40
|
@ -33,8 +33,14 @@ struct Sine {
|
||||||
|
|
||||||
/// The current phase of the sine wave, always kept between in `[0, 1]`.
|
/// The current phase of the sine wave, always kept between in `[0, 1]`.
|
||||||
phase: f32,
|
phase: f32,
|
||||||
/// The active frequency, if triggered by MIDI.
|
|
||||||
active_note_freq: Option<f32>,
|
/// The frequency if the active note, if triggered by MIDI.
|
||||||
|
midi_note_freq: f32,
|
||||||
|
/// A simple attack and release envelope to avoid clicks.
|
||||||
|
///
|
||||||
|
/// Smoothing is built into the parameters, but you can also use them manually if you need to
|
||||||
|
/// smooth soemthing that isn't a parameter.
|
||||||
|
midi_note_gain: Smoother<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Params)]
|
#[derive(Params)]
|
||||||
|
@ -56,7 +62,8 @@ impl Default for Sine {
|
||||||
sample_rate: 1.0,
|
sample_rate: 1.0,
|
||||||
|
|
||||||
phase: 0.0,
|
phase: 0.0,
|
||||||
active_note_freq: None,
|
midi_note_freq: 1.0,
|
||||||
|
midi_note_gain: Smoother::new(SmoothingStyle::Linear(5.0)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,16 +165,12 @@ impl Plugin for Sine {
|
||||||
match next_event {
|
match next_event {
|
||||||
Some(event) if event.timing() == sample_id as u32 => match event {
|
Some(event) if event.timing() == sample_id as u32 => match event {
|
||||||
nih_plug::NoteEvent::NoteOn { note, .. } => {
|
nih_plug::NoteEvent::NoteOn { note, .. } => {
|
||||||
// Reset the phase if this is a new note
|
self.midi_note_freq = util::midi_note_to_freq(note);
|
||||||
if self.active_note_freq.is_none() {
|
self.midi_note_gain.set_target(self.sample_rate, 1.0);
|
||||||
self.phase = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.active_note_freq = Some(util::midi_note_to_freq(note));
|
|
||||||
}
|
}
|
||||||
nih_plug::NoteEvent::NoteOff { note, .. } => {
|
nih_plug::NoteEvent::NoteOff { note, .. } => {
|
||||||
if self.active_note_freq == Some(util::midi_note_to_freq(note)) {
|
if self.midi_note_freq == util::midi_note_to_freq(note) {
|
||||||
self.active_note_freq = None;
|
self.midi_note_gain.set_target(self.sample_rate, 0.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -177,10 +180,8 @@ impl Plugin for Sine {
|
||||||
next_event = context.next_midi_event();
|
next_event = context.next_midi_event();
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.active_note_freq {
|
// This gain envelope prevents clicks with new notes and with released notes
|
||||||
Some(frequency) => self.calculate_sine(frequency),
|
self.calculate_sine(self.midi_note_freq) * self.midi_note_gain.next()
|
||||||
None => 0.0,
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let frequency = self.params.frequency.smoothed.next();
|
let frequency = self.params.frequency.smoothed.next();
|
||||||
self.calculate_sine(frequency)
|
self.calculate_sine(frequency)
|
||||||
|
|
Loading…
Reference in a new issue