MIDI Processor Inconsistent/Processing Speed Issue?
-
@aaronventure wow, that is a real problem within the engine, wouldn't have thought :)
The MIDI file contains a few MIDI messages with the same timestamp, and the internal MIDI processing is processing those right after another, however this means that the
setActiveGroup()
calls are being called immediately after another, so only the last group index is active when the voices are started a little bit later.There are a few options of solving this problem but I'm a bit surprised that this only pops up now after years of HISE usage :)
-
@Christoph-Hart said in MIDI Processor Inconsistent/Processing Speed Issue?:
but I'm a bit surprised that this only pops up now after years of HISE usage :)
Well yeah, me too :D
This fundamentally breaks the sampler RR group behavior in terms of selective group usage.
I didn't make the MIDI in the DAW, I cut this out out of a sequence of D5 chords, where 3 out of 15 or so behaved like this, so it's played behavior. There's all kinds of stuff that you can do with MIDI editors today that the user would never actually encounter, but this is one of the simplest things, just an imperfectly perfect chord.
-
@aaronventure 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'm currently working on a solution for this - I can query the note number of the current MIDI event during the onNoteOn callback and then store the active group into an array with 128 items so it will get picked up later by using the note number when the sample selection takes place, but this might cause some edge cases where you start transposing the MIDI message after calling
setActiveGroup()
.There's also the issue of being able to enable / disable multiple groups, which needs to be handled separately (and there it's not so easy because the data structure is already an array so I would have to make a 2D array which then grows to a non-trivial size.
-
@Christoph-Hart said in MIDI Processor Inconsistent/Processing Speed Issue?:
array so I would have to make a 2D array which then grows to a non-trivial size.
Rather than a 2D array could you not add a flag to the data stored in each element of the current array you're using?
-
@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?