1
0
Fork 0

Move event timing clamping to functions

So this doesn't need to be repeated everywhere.
This commit is contained in:
Robbert van der Helm 2023-02-01 17:33:14 +01:00
parent d5a8eb42ec
commit 55c3701d2e
4 changed files with 51 additions and 43 deletions

View file

@ -94,7 +94,9 @@ use crate::plugin::{
use crate::util::permit_alloc;
use crate::wrapper::clap::util::{read_stream, write_stream};
use crate::wrapper::state::{self, PluginState};
use crate::wrapper::util::{hash_param_id, process_wrapper, strlcpy};
use crate::wrapper::util::{
clamp_input_event_timing, clamp_output_event_timing, hash_param_id, process_wrapper, strlcpy,
};
/// How many output parameter changes we can store in our output parameter change queue. Storing
/// more than this many parameters at a time will cause changes to get lost.
@ -1079,12 +1081,10 @@ impl<P: ClapPlugin> Wrapper<P> {
let mut output_events = self.output_events.borrow_mut();
while let Some(event) = output_events.pop_front() {
// Out of bounds events are clamped to the buffer's size
let time = event.timing() + current_sample_idx as u32;
nih_debug_assert!(
time < total_buffer_len as u32,
"Output event is out of bounds, will be clamped to the buffer's size"
let time = clamp_output_event_timing(
event.timing() + current_sample_idx as u32,
total_buffer_len as u32,
);
let time = time.min(total_buffer_len as u32 - 1);
let push_successful = match event {
NoteEvent::NoteOn {
@ -1423,12 +1423,10 @@ impl<P: ClapPlugin> Wrapper<P> {
let raw_event = &*event;
// Out of bounds events are clamped to the buffer's size
let timing = raw_event.time - current_sample_idx as u32;
nih_debug_assert!(
timing < total_buffer_len as u32,
"Input event is out of bounds, will be clamped to the buffer's size"
let timing = clamp_input_event_timing(
raw_event.time - current_sample_idx as u32,
total_buffer_len as u32,
);
let timing = timing.min(total_buffer_len as u32 - 1);
match (raw_event.space_id, raw_event.type_) {
(CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_PARAM_VALUE) => {

View file

@ -15,6 +15,7 @@ use crate::buffer::Buffer;
use crate::context::process::Transport;
use crate::midi::{MidiConfig, MidiResult, NoteEvent, PluginNoteEvent};
use crate::plugin::Plugin;
use crate::wrapper::util::{clamp_input_event_timing, clamp_output_event_timing};
/// Uses JACK audio and MIDI.
pub struct Jack {
@ -122,11 +123,7 @@ impl<P: Plugin> Backend<P> for Jack {
input_events.clear();
if let Some(midi_input) = &midi_input {
input_events.extend(midi_input.iter(ps).filter_map(|midi| {
nih_debug_assert!(
midi.time < num_frames,
"Input event is out of bounds, will be clamped to the buffer's size"
);
let timing = midi.time.min(num_frames - 1);
let timing = clamp_input_event_timing(midi.time, num_frames);
NoteEvent::from_midi(timing, midi.bytes).ok()
}));
@ -139,11 +136,7 @@ impl<P: Plugin> Backend<P> for Jack {
let mut midi_writer = midi_output.writer(ps);
for event in output_events.drain(..) {
// Out of bounds events are clamped to the buffer's size
nih_debug_assert!(
event.timing() < num_frames,
"Output event is out of bounds, will be clamped to the buffer's size"
);
let timing = event.timing().min(num_frames - 1);
let timing = clamp_output_event_timing(event.timing(), num_frames as u32);
match event.as_midi() {
Some(MidiResult::Basic(midi_data)) => {

View file

@ -61,6 +61,34 @@ pub fn strlcpy(dest: &mut [c_char], src: &str) {
dest[copy_len] = 0;
}
/// Clamp an input event's timing to the buffer length. Emits a debug assertion failure if it was
/// out of bounds.
#[inline]
pub fn clamp_input_event_timing(timing: u32, total_buffer_len: u32) -> u32 {
let last_valid_index = total_buffer_len.saturating_sub(1);
nih_debug_assert!(
timing < last_valid_index,
"Input event is out of bounds, will be clamped to the buffer's size"
);
timing.min(last_valid_index)
}
/// Clamp an output event's timing to the buffer length. Emits a debug assertion failure if it was
/// out of bounds.
#[inline]
pub fn clamp_output_event_timing(timing: u32, total_buffer_len: u32) -> u32 {
let last_valid_index = total_buffer_len.saturating_sub(1);
nih_debug_assert!(
timing < last_valid_index,
"Output event is out of bounds, will be clamped to the buffer's size"
);
timing.min(last_valid_index)
}
/// Set up the logger so that the `nih_*!()` logging and assertion macros log output to a
/// centralized location and panics also get written there. By default this logs to STDERR unless
/// the user is running Windows and a debugger has been attached, in which case

View file

@ -37,7 +37,7 @@ use crate::plugin::{
};
use crate::util::permit_alloc;
use crate::wrapper::state;
use crate::wrapper::util::process_wrapper;
use crate::wrapper::util::{clamp_input_event_timing, clamp_output_event_timing, process_wrapper};
// Alias needed for the VST3 attribute macro
use vst3_sys as vst3_com;
@ -1101,14 +1101,10 @@ impl<P: Vst3Plugin> IAudioProcessor for Wrapper<P> {
// Later this timing will be compensated for block splits by calling
// `event.subtract_timing(block_start)` before it is passed to the
// plugin. Out of bounds events are clamped to the buffer>
let timing = sample_offset as u32;
nih_debug_assert!(
timing < total_buffer_len as u32,
"Input event is out of bounds, will be clamped to the \
buffer's size"
let timing = clamp_input_event_timing(
sample_offset as u32,
total_buffer_len as u32,
);
let timing = timing.min(total_buffer_len as u32 - 1);
let value = value as f32;
// MIDI CC messages, channel pressure, and pitch bend are also sent
@ -1175,12 +1171,10 @@ impl<P: Vst3Plugin> IAudioProcessor for Wrapper<P> {
nih_debug_assert_eq!(result, kResultOk);
let event = event.assume_init();
let timing = event.sample_offset as u32;
nih_debug_assert!(
timing < total_buffer_len as u32,
"Input event is out of bounds, will be clamped to the buffer's size"
let timing = clamp_input_event_timing(
event.sample_offset as u32,
total_buffer_len as u32,
);
let timing = timing.min(total_buffer_len as u32 - 1);
if event.type_ == EventTypes::kNoteOnEvent as u16 {
let event = event.event.note_on;
@ -1573,15 +1567,10 @@ impl<P: Vst3Plugin> IAudioProcessor for Wrapper<P> {
let mut vst3_event: Event = mem::zeroed();
vst3_event.bus_index = 0;
// There's also a ppqPos field, but uh how about no
vst3_event.sample_offset = event.timing() as i32 + block_start as i32;
// Out of bounds events are clamped to the buffer
nih_debug_assert!(
vst3_event.sample_offset < total_buffer_len as i32,
"Output event is out of bounds, will be clamped to the buffer's size"
);
vst3_event.sample_offset =
vst3_event.sample_offset.min(total_buffer_len as i32 - 1);
vst3_event.sample_offset = clamp_output_event_timing(
event.timing() + block_start as u32,
total_buffer_len as u32,
) as i32;
// `voice_id.unwrap_or(|| ...)` triggers
// https://github.com/rust-lang/rust-clippy/issues/8522