How to get event ids for artificial events?
-
How many events do you want to record per key? I'm still thinking that with acoustic instruments in general each repeated note will kill old notes, causing them to decay.
-
That's not completely true. For example if you press down the sustain pedal, play a loud note on the piano, then play a soft note on the same key shortly after it, you would hear that the new note is fading down the old note which sounds really bad.
That's why in the sampler options you have the "Kill second note" retrigger behaviour which allows you to have at least two notes of the same key ringing at once. This weakens that effect a little bit, but it's still noticeable.
-
@Christoph-Hart Very good point!
-
This should record as many event ids per key as needed --I didn't set a max number.
Here's what I got!
function onNoteOn() { Message.ignoreEvent(true); note = Message.getNoteNumber(); if (keyDown.getValue(note) == 1) keyVoiceCount[note]++; g_group_allows[G_START] = 1; eventIds[note][keyVoiceCount[note]] = Synth.playNote(note, 64); eventTimeStamp[note][keyVoiceCount[note]] = Engine.getUptime(); keyDown.setValue(note, 1); } function onNoteOff() { if (pedal == 0) { keyDown.setValue(Message.getNoteNumber(), 0); note = Message.getNoteNumber(); for (v = 0; v <= keyVoiceCount[note]; v++) { Synth.noteOffByEventId(eventIds[note][v]); if (delayedEventIds[note][v]) { Synth.noteOffByEventId(delayedEventIds[note][v]); delayedEventIds[note][v] = 0; }; eventTimeStamp[note][v] = 0; }; keyVoiceCount[note] = 0; }; } function onTimer() { for (n = 0; n < 128; n++) { for (v = 0; v <= keyVoiceCount[n]; v++) { if (eventTimeStamp[n][v]) { playPos = (Engine.getUptime() - eventTimeStamp[n][v]) * 1000; playPos = Engine.getQuarterBeatsForMilliSeconds(playPos); if (playPos > 4 && !delayedEventIds[n][v]) { g_group_allows[G_START] = 1; delayedEventIds[n][v] = Synth.playNote(n, 64); }; }; }; }; } function onController() { if (Message.getControllerNumber() == 64) { if (Message.getControllerValue() > 5) { pedal = 1; //Console.print("pedal down"); } else { pedal = 0; for (n = 0; n < 128; n++) { if (Synth.isKeyDown(n) == 0 && keyDown.getValue(n) == 1) { keyDown.setValue(n, 0); for (v = 0; v <= keyVoiceCount[n]; v++) { Synth.noteOffByEventId(eventIds[n][v]); eventIds[n][v] = 0; Synth.noteOffByEventId(delayedEventIds[n][v]); delayedEventIds[n][v] = 0; eventTimeStamp[n][v] = 0; }; keyVoiceCount[n] = 0; }; }; }; }; }
So basically now you can have multiple parallel sequences of artificial events on the same key, which are note off'd correctly by the pedal.
Before, I did this by using
Synth.addNote()
to schedule the sequence of artificial events, but I was running into some problems there.This is with Retrigger set to "Do nothing"
Man, this was a lot of work! Maybe I should have just done the "Kill Duplicate" option and just NOT allowed overlapping swells on the same key haha :face_with_tongue:
-
Maybe I should have just done the "Kill Duplicate" option and just NOT allowed overlapping swells on the same key haha
Looks like you're having fun though :)
-
Yep, I'm learning a lot :)
-
Yep, I'm learning a lot
Make sure you use the
reserve
function for all those arrays to avoid allocating items in the MIDI callbacks:https://docs.hise.audio/scripting/scripting-api/array/index.html#reserve
-
@Christoph-Hart Would an array of MIDI lists be more efficient?
-
For a multi-dimensional array, would
reserve
make sense used this way?delayedEventIds.reserve(128); // note slots delayedEventIds[n].reserve(16); // reserve 16 voices per note slot delayedEventIds[n][v] = Synth.playNote(n, 64);
-
Yes. You might need to initialise the element at
delayedEventIds[n]
as array before calling reserve, but then it should work.@d-healey the efficiency of the MIDI list gets interesting as soon as it helps you avoid writing for loops, so
- searching for an item
- clearing all items
It will speed up things a bit.
The nested for loop in this example will most likely be the bottleneck, so I would start optimizing there on a higher level though...
-
Cool, yep it gets initialized in the
onInit