MIDI Processor Inconsistent/Processing Speed Issue?
-
hmm, that makes it even more complicated and I would have to change the API for the
setActiveGroup()
call to take in an event ID.On the other hand this would leave the "default" path as it is right now without overhead but the slight inconsistency that the active group will get overriden for each event in the current audio buffer (and chances are great that if you go into this kind of advanced event modification & RR group control you want it to be tied to the event ID properly anyways).
So in this case I would add a new API method
Sampler.setActiveGroupForEventId(int eventId, int groupIndex).
which will take the event ID and then check in the note on callback of the sampler which group to use for the current group index.
-
@Christoph-Hart exactly, yeah!
Great.
Don't forget warning for any clowning around with usage of both this and the current setActiveGroup method in the same callback (or will one simply override the other?)
-
@Christoph-Hart said in MIDI Processor Inconsistent/Processing Speed Issue?:
Sampler.setActiveGroupForEventId(int eventId, int groupIndex).
Also, any chance this bad boy could also be taking an array of indices in its second parameter? That'd be two flies with one strike.
-
@aaronventure I think you can just use a for loop for that, I would avoid branching inside the API call for your special use case :)
-
@Christoph-Hart Really? Wouldn't another call override the previous one?
I meant what if one wanted two different groups active for a note? I mean, sure, that can be another
Synth.playNote
and its ID passed into anotherSampler.setActiveGroupForEventId(int eventId, int groupIndex)
call. -
@aaronventure Ah you mean the second parameter, I thought you were just too lazy to make a for loop for your 5 events that you want to spawn.
For this, I would rather add another API call that's similar to
setMultiGroupIndex()
as this would be the non-event-ID-agnostic counterpart in the Sampler API. -
This post is deleted! -
@Christoph-Hart haha isn't looping the lazy way?
Just so we're on the same page, I play a note, I ignore the event, then I execute 5 notes via
Synth.playNote
in a loop, storing their ID, and right in the next line (still within the loop) I just pass that ID into theSampler.setActiveGroupForEventId
?So it would be possible to have multiple Sampler.setActiveGroupForEventId calls within a single noteOn callback, each directing its own eventId to the appropriate group?
-
@aaronventure yes, that should be possible.
-
@Christoph-Hart fuckin' A
-
@aaronventure Alright, it's pushed to the current working branch
new_dispatcher
(which should be considered stable unless you're on Linux, then it won't compile :)https://github.com/christophhart/HISE/commit/05b9f1f474bbf7c0cf0a2850da2b44cbcaadd46e
and:
https://docs.hise.audio/scripting/scripting-api/sampler/index.html#setactivegroupforeventid
-
@Christoph-Hart oh shit look at that doc entry!
-
@Christoph-Hart I'm ready to test this, but the plugin version of HISE fails to build. Standalone builds fine.
Windows 11. All commits since this one. Reverted back to develop just to check, develop builds fine.
1>F:\HISE\HISE Source\tools\SDK\perfetto\perfetto.h(338,1): fatal error C1189: #error: Perfetto is exploring a switch to C++17 in v34 (Feb 2023). During this transitionary period, we are throwing an error when compiling Perfetto with a standard less than C++17. Please reach out to perfetto-dev@googlegroups.com if you have objections or thoughts on this move. To continue compiling this release of Perfetto with C++11/14, specify the define PERFETTO_ALLOW_SUB_CPP17. *Note*: this define *will* stop working in v34 (Feb 2023). (compiling source file ..\..\JuceLibraryCode\include_hi_core.cpp) 1>F:\HISE\HISE Source\tools\SDK\perfetto\perfetto.h(338,1): fatal error C1189: #error: Perfetto is exploring a switch to C++17 in v34 (Feb 2023). During this transitionary period, we are throwing an error when compiling Perfetto with a standard less than C++17. Please reach out to perfetto-dev@googlegroups.com if you have objections or thoughts on this move. To continue compiling this release of Perfetto with C++11/14, specify the define PERFETTO_ALLOW_SUB_CPP17. *Note*: this define *will* stop working in v34 (Feb 2023). (compiling source file ..\..\Source\PluginProcessor.cpp) 1>F:\HISE\HISE Source\tools\SDK\perfetto\perfetto.h(338,1): fatal error C1189: #error: Perfetto is exploring a switch to C++17 in v34 (Feb 2023). During this transitionary period, we are throwing an error when compiling Perfetto with a standard less than C++17. Please reach out to perfetto-dev@googlegroups.com if you have objections or thoughts on this move. To continue compiling this release of Perfetto with C++11/14, specify the define PERFETTO_ALLOW_SUB_CPP17. *Note*: this define *will* stop working in v34 (Feb 2023). (compiling source file ..\..\JuceLibraryCode\include_hi_snex.cpp) 1>F:\HISE\HISE Source\tools\SDK\perfetto\perfetto.h(338,1): fatal error C1189: #error: Perfetto is exploring a switch to C++17 in v34 (Feb 2023). During this transitionary period, we are throwing an error when compiling Perfetto with a standard less than C++17. Please reach out to perfetto-dev@googlegroups.com if you have objections or thoughts on this move. To continue compiling this release of Perfetto with C++11/14, specify the define PERFETTO_ALLOW_SUB_CPP17. *Note*: this define *will* stop working in v34 (Feb 2023). (compiling source file ..\..\JuceLibraryCode\include_hi_snex_62.cpp) 1>F:\HISE\HISE Source\tools\SDK\perfetto\perfetto.h(338,1): fatal error C1189: #error: Perfetto is exploring a switch to C++17 in v34 (Feb 2023). During this transitionary period, we are throwing an error when compiling Perfetto with a standard less than C++17. Please reach out to perfetto-dev@googlegroups.com if you have objections or thoughts on this move. To continue compiling this release of Perfetto with C++11/14, specify the define PERFETTO_ALLOW_SUB_CPP17. *Note*: this define *will* stop working in v34 (Feb 2023). (compiling source file ..\..\JuceLibraryCode\include_hi_streaming.cpp) 1>F:\HISE\HISE Source\tools\SDK\perfetto\perfetto.h(338,1): fatal error C1189: #error: Perfetto is exploring a switch to C++17 in v34 (Feb 2023). During this transitionary period, we are throwing an error when compiling Perfetto with a standard less than C++17. Please reach out to perfetto-dev@googlegroups.com if you have objections or thoughts on this move. To continue compiling this release of Perfetto with C++11/14, specify the define PERFETTO_ALLOW_SUB_CPP17. *Note*: this define *will* stop working in v34 (Feb 2023). (compiling source file ..\..\JuceLibraryCode\include_hi_scripting_01.cpp) 1>F:\HISE\HISE Source\tools\SDK\perfetto\perfetto.h(338,1): fatal error C1189: #error: Perfetto is exploring a switch to C++17 in v34 (Feb 2023). During this transitionary period, we are throwing an error when compiling Perfetto with a standard less than C++17. Please reach out to perfetto-dev@googlegroups.com if you have objections or thoughts on this move. To continue compiling this release of Perfetto with C++11/14, specify the define PERFETTO_ALLOW_SUB_CPP17. *Note*: this define *will* stop working in v34 (Feb 2023). (compiling source file ..\..\JuceLibraryCode\include_hi_scripting_03.cpp) 1>F:\HISE\HISE Source\tools\SDK\perfetto\perfetto.h(338,1): fatal error C1189: #error: Perfetto is exploring a switch to C++17 in v34 (Feb 2023). During this transitionary period, we are throwing an error when compiling Perfetto with a standard less than C++17. Please reach out to perfetto-dev@googlegroups.com if you have objections or thoughts on this move. To continue compiling this release of Perfetto with C++11/14, specify the define PERFETTO_ALLOW_SUB_CPP17. *Note*: this define *will* stop working in v34 (Feb 2023). (compiling source file ..\..\JuceLibraryCode\include_hi_tools.cpp) 1>Done building project "HISE_SharedCode.vcxproj" -- FAILED. 2>------ Rebuild All started: Project: HISE_VST, Configuration: Release x64 ------ 2>include_juce_audio_plugin_client_VST2.cpp 2>C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Microsoft\VC\v170\Microsoft.CppCommon.targets(1096,5): error MSB6006: "link.exe" exited with code 1181. 2>LINK : fatal error LNK1181: cannot open input file 'HISE x64.lib' 2>Done building project "HISE_VST.vcxproj" -- FAILED.
Testing in the standalone, it seems to work. I can't get it it "drop" a note. Going back and forth between the new and the old method, I get wrong active group 3/20 times with the old one, and so far none with the new one.
Great!
-
@aaronventure Did you try cleaning the build folder between building the standalone and the plugin?
-
@d-healey I always do.
Tried it again just in case I was maybe tripping earlier but no, clearing and building fails.
-
Everything working great in the latest commit.
-
@Christoph-Hart Posting here because I think it's related.
I wanna introduce humanization to my instrument. In theory, this is dead simple: call the delay method for a random number of samples within a limited range.
The issue: storing event IDs and properly noting them off, as well as preventing execution of the play() method in the first place in case the note was shorter than the set humanized delay.
The noteOn callback will always execute in its entirety before the noteOff callback (for the same key). if there's a Message.delay() in there, the noteOn still executes and it seems like it stores any Synth.play() calls into a queue.
So I thought about reverting my dismemberment of the original Play Logic script and stuffing it all back there (since the new setActiveGroupForEventId() solves the issue there), and did a quick test.
I call Console.print() in noteOn and noteOff of the Play Logic, which resides in the master container, and then in the Guitar Event Handler which is a Script Processor for the Sampler. The Guitar Event Handler features a Message.delay() call in the loop that executes its <5 voices (multitracking).
The actual MIDI note is incredibly short. It's released way before the delayed events begin playing. Even so, the noteOns get executed first, and then noteOffs.
This makes any isKeyDown checks (whether using the built in Synth class method or filling my own array in noteOn/noteOff) impossible, because even though the note was released at the time the delayed note is scheduled to launch, the scheduling of it was executed on the physical noteOn.
The noteOff happens before the scheduled play() execution, there's no event ID to noteOff and the scheduled voice will then play forever (or until the sample/envelope runs out, but you get it).
I'm not sure if timers are a solution because this would require a crazy resolution of 1ms or shorter (and I've already been yelled at by HISE for timer timing before).
-
@aaronventure why don't you delay the note-off too?
-
@Christoph-Hart because even if I delay the entire noteOff by
humanize.get("max") * 2
, so around 100ms (which introduces noticeable floatiness to performance), I can still reproduce the hanging notes by playing a very short note on a keyboard (I don't have to try and make artificially small nanosecond long MIDI events in the piano roll).I use the humanize control for all multitracks beyond the first, so that even as you play, the sound starts coming out (the first voice plays) on your time with the others having a small random delay, so it "feels" tight.
In Kontakt, the solution is to simply call wait() and it delays the execution of the callback at that line. I My understanding is that HISE works differently so that's not exactly an option here.
-
@Christoph-Hart I made some progress by childing the sampler 2 levels. The event handler is now at the top, the humanization happens second, and at sampler level I check if the key is down.
But there's another problem here:
The multitracking I do is based on neighbouring zones. So the actual NoteNumber of these events differs from the key that is pressed.
I already have the tuning numbers for each event so I can use these correct the check to make sure I'm checking for the correct key.
The issue comes with playing multiple notes at the same time (on the same string). Due to execution order (same timestamp event, container will execute twice before the child gets to play), the second note's IDs will overwrite the first in the ID array. This is not normally an issue because for the notes on the same string I execute on note-off before playing them (and overwriting their IDs).
However, due to humanization the note are not yet playing and by the time the check for ignoring the event in AntiHang comes, the tuning numbers are already different (overwritten) so it runs the same 5 tuning numbers for both notes (10 events in total).
The execution order of script processors prevents any solid event-related information hand-down down the hierarchy. I can create a massive array and store information into indexes based on event IDs, but I'm not sure how ideal that is memory wise. The solution then gets highly specific with each individual project and refactoring, as well as keeping track of the whole setup between projects, becomes a mess.
Is there a chance the message object could get an empty property (or 16) where we could store data? Something like Message.getCustom(index) and Message.setCustom(index, value). This would be highly beneficial to any complex project. Kontakt has EVENT_PAR_CUSTOM with 16 value slots and it works really well for passing down event-related data.
HISEScript isn't typed so maybe just a single property, and we can then put an array there or whatever (would that be accesed by Message.getCustom()[6], after being set as Message.setCustom(array)?)Actually this is dynamic and realtime+dynamic=nono, so maybe the last idea of 16 slots is better.