Midi input quantize to next beat or next bar?

Hello

Is there some example code how can quantize a midi note on and note off for trigger a sequencer pattern to next beat or next bar or next half bar ?.

I don’t suppose this is a viable endeavor, as quantizing might need to move an event backwards in time, which obviously is only possble if you additionally impose a huge delay (which a DAW only could handle by PDC, i.e. delaying the other tracks by the same amount. This seems not very desirable.
-Michael

you need press the trigger key earlier then the note on and note off should delay to the next bar or beat.

kontakt have a builtin script for this. it is in performance input quantize. so questions is how this can do in juce.

if ($Note_on = 1)
ignore_event($EVENT_ID)

  select ($synctype)
  	case 0
  		$time_length := $DURATION_SIXTEENTH/2
  	case 1
  		$time_length := $DURATION_QUARTER/6
  	case 2
  		$time_length := $DURATION_SIXTEENTH
  	case 3
  		$time_length := $DURATION_QUARTER/3
  	case 4
  		$time_length := $DURATION_EIGHTH
  	case 5
  		$time_length := ($DURATION_QUARTER*2)/3
  	case 6
  		$time_length := $DURATION_QUARTER
  	case 7
  		$time_length := $DURATION_QUARTER*2
  	case 8
  		$time_length := $DURATION_BAR
  end select

  $rest_bar_time := $DURATION_BAR - $DISTANCE_BAR_START
  $rest_click_time := ($rest_bar_time+(10*$DURATION_BAR)) mod $time_length

  if ($rest_bar_time mod ($time_length*2) < $time_length)
  	$helper := ($rest_click_time*$Amount)/100
  	if ($helper > 0)
  		wait($helper)
  	end if
  else
  	$helper := ((($rest_bar_time mod ($time_length*2)) - $time_length)*$Amount)/100
  	if ($helper > 0)
  		wait($helper)
  	end if
  end if
  
  if ($Note_off = 1 and $Sustain_NoteOff = 0 and $NOTE_HELD = 1)
  	$art_id := play_note($EVENT_NOTE,$EVENT_VELOCITY,0,0)
  end if
  if ($Note_off = 1 and $Sustain_NoteOff = 1 and $NOTE_HELD = 0)
  	$helper := play_note($EVENT_NOTE,$EVENT_VELOCITY,0,$time_length)
  	set_event_par($helper,0,1)
  end if
  if ($Note_off = 1 and $Sustain_NoteOff = 1 and $NOTE_HELD = 1)
  	$art_id := play_note($EVENT_NOTE,$EVENT_VELOCITY,0,0)
  end if
  if ($Note_off = 0 and $NOTE_HELD = 1)
  	$art_id := play_note($EVENT_NOTE,$EVENT_VELOCITY,0,-1)
  end if

else
if ($Note_off = 1)
ignore_event ($EVENT_ID)
$art_id := play_note($EVENT_NOTE,$EVENT_VELOCITY,0,-1)
end if
end if
end on

you could let a phasor run at the frequency of your bpm and the phase at ppq * rate (or something like that) and everytime the signal jumps from 1 to 0 your measure is reached. you have collected midi events in the meantime and put them back into the midi buffer at these moments

1 Like

is there no access to variables as this
$DURATION_BAR - $DISTANCE_BAR_START

in Juce ?. i think thats all need and then can calc the delay time

sure. check out juce::AudioPlayHead. i was just saying that for different measures to work you have to find values that you can multiply or devide with bpm and ppq in order to let a phasor run at the correct frequency and phase, because the project position is only given to you once per block. you’ll see what that means when experimenting with it

1 Like

You need to handle the (in and out) events (points in time) within a single Audio block all at the same call, while you need to handle the events in different Audio blocks in different calls.
Seemingly Kontakt can handle this internally. I rather sure that Juce will not do this. I.e. the Midi event “offset” is tied to a single block and not allowed to be negative or greater that block size,
-Michael

maybe in future there can add functions that juce can do midi offsets of any length. or maybe somebody can do methods of a midi quantize feature. i think many like this. i have suggest such a feature to juce plugins developers too, but they tell it is not easy to add. so i ask. Same is with the highdpi desktop scale. when such examples are here, help alot many people

i have to disagree with the juce developers that claimed it’s not easy to add. it might not be such a one-liner as in native instruments’ kontakt framework, but it’s still super easy. you just gotta grasp the concept a bit.
image
i like to visualize it like this. imagine a timeline (yellow) and processBlock happens in some interval (pink). might be regular or not, doesn’t matter. only thing that matters is only at the start of each block you get the info about ppq and bpm. so if you used this directly as your modulation source (or whatever) you’d get a steppy curve, rather than a continuous one like this (green). in order to get the continuous one you have to take the ppq, the bpm and whatever rate value you wanna play this thing with and calculate the intermediate values, so that it all together creates this signal. whenever the signal jumps back to 0 you know your measure restarts at the correct point in the project again. that’s when something is supposed to happen in step-sequencer-sorta implementations like this.
image
in your case it would be something like this. you keep saving midi events in a buffer (orange dots). probably a fixed size array large enough for a reasonable amount of events so you don’t have to allocate in processBlock. whenever a new measure appears you put all of them into the midi buffer given by processBlock at that place in time (green dots) and clear the buffer for the next measure to come.

the question was about unify. Unify is a plugin host. it can layer sounds. so it is possible that some layers are quantize to beats some quantize to bars (drums or bar sequences) some not

this need more work. maybe in juce can add easy that a incoming midi event just can delay by change the time stamp and put it back on the event to process cue ?. or maybe remove the event and add a new event at the time that is need ?

I am not a unify developer i only are a user and i and i think many other wish this feature since longer time