MIDI Processor Inconsistent/Processing Speed Issue?
-
@d-healey Or maybe I'll add a (short) queue of events with the required action attached to it. During the MIDI processing inside the buffering this gets populated and then used later by the voice allocation. At the end of the buffer the queue can be cleared because the problem only arises with multiple messages within a buffer.
-
@Christoph-Hart said in MIDI Processor Inconsistent/Processing Speed Issue?:
yeah I guess there wasn't a project yet where the error of a RR group mismatch caused a "critical error" like this - usually all that happens is that it uses the same RR group for two different notes if they are played exactly at the same time (and only if you don't use the inbuilt RR counter as this calculated right before the voice start). Within a normal RR sample set this is hardly noticeable, but if you rely on it working with mathematical precision because the note ranges do not overlap, you're in trouble.
I can see how this could go unnoticed. If you have different articulations in different groups, you trigger the keyswitch which sets the active group and it just works, you're not setting activeGroup on each noteOn. If you're using it for RR, it just skips a group and 3/15 for a group skip is still plenty of variance unless you have like 2 RRs.
Is it fine if I just call setActiveGroup() at the very end of the noteOn callback?
I'd like to point out that in my actual project, I'm ignoring the event in the guitar's noteOn, and then have a Synth.playNoteWithOffset because I need it to play up to 5 notes (based on multitracking settings), which are all neighbouring zones. So when I press a C3, it plays B2, A#2, C#3 and D3, and the pitch modulator checks for the IDs and applies correct pitch modulation to make them all sound at the correct pitch.
Back when I had this in the playLogic script which was above the samplers, these Synth.play method calls produced 5 artificial noteOn events in the sampler.
I don't know what that looks like when the Synth.play happens in the sampler itself.
I am storing the IDs of the Synth.play calls, though. Is it a good idea to maybe have another method which sets the active group for a given event ID?
-
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?