HISE Logo Forum
    • Categories
    • Register
    • Login

    MIDI Processor Inconsistent/Processing Speed Issue?

    Scheduled Pinned Locked Moved Scripting
    51 Posts 5 Posters 12.4k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Christoph HartC
      Christoph Hart @aaronventure
      last edited by

      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.

      A 2 Replies Last reply Reply Quote 1
      • A
        aaronventure @Christoph Hart
        last edited by

        @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?)

        1 Reply Last reply Reply Quote 0
        • A
          aaronventure @Christoph Hart
          last edited by aaronventure

          @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.

          Christoph HartC 1 Reply Last reply Reply Quote 1
          • Christoph HartC
            Christoph Hart @aaronventure
            last edited by

            @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 :)

            A 1 Reply Last reply Reply Quote 0
            • A
              aaronventure @Christoph Hart
              last edited by

              @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 another Sampler.setActiveGroupForEventId(int eventId, int groupIndex) call.

              Christoph HartC 1 Reply Last reply Reply Quote 0
              • Christoph HartC
                Christoph Hart @aaronventure
                last edited by

                @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.

                d.healeyD A 2 Replies Last reply Reply Quote 1
                • d.healeyD
                  d.healey @Christoph Hart
                  last edited by d.healey

                  This post is deleted!
                  1 Reply Last reply Reply Quote 0
                  • A
                    aaronventure @Christoph Hart
                    last edited by

                    @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 the Sampler.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?

                    Christoph HartC 1 Reply Last reply Reply Quote 1
                    • Christoph HartC
                      Christoph Hart @aaronventure
                      last edited by

                      @aaronventure yes, that should be possible.

                      A 1 Reply Last reply Reply Quote 2
                      • A
                        aaronventure @Christoph Hart
                        last edited by

                        @Christoph-Hart fuckin' A

                        Christoph HartC 1 Reply Last reply Reply Quote 0
                        • Christoph HartC
                          Christoph Hart @aaronventure
                          last edited by

                          @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 :)

                          Link Preview Image
                          - added Sampler.setActiveGroupForEventId() et al · christophhart/HISE@05b9f1f

                          The open source framework for sample based instruments - - added Sampler.setActiveGroupForEventId() et al · christophhart/HISE@05b9f1f

                          favicon

                          GitHub (github.com)

                          and:

                          Link Preview Image
                          HISE | Docs

                          favicon

                          (docs.hise.audio)

                          A 2 Replies Last reply Reply Quote 3
                          • A
                            aaronventure @Christoph Hart
                            last edited by

                            @Christoph-Hart oh shit look at that doc entry!

                            1 Reply Last reply Reply Quote 0
                            • A
                              aaronventure @Christoph Hart
                              last edited by aaronventure

                              @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!

                              d.healeyD 1 Reply Last reply Reply Quote 0
                              • d.healeyD
                                d.healey @aaronventure
                                last edited by

                                @aaronventure Did you try cleaning the build folder between building the standalone and the plugin?

                                A 1 Reply Last reply Reply Quote 0
                                • A
                                  aaronventure @d.healey
                                  last edited by aaronventure

                                  @d-healey I always do.

                                  Tried it again just in case I was maybe tripping earlier but no, clearing and building fails.

                                  1 Reply Last reply Reply Quote 1
                                  • A
                                    aaronventure
                                    last edited by

                                    Everything working great in the latest commit. 🍻

                                    1 Reply Last reply Reply Quote 1
                                    • A
                                      aaronventure
                                      last edited by

                                      @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.

                                      68c5ecda-c5d9-4cca-bee7-b96791732307-image.png

                                      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).

                                      Christoph HartC 1 Reply Last reply Reply Quote 0
                                      • Christoph HartC
                                        Christoph Hart @aaronventure
                                        last edited by

                                        @aaronventure why don't you delay the note-off too?

                                        A 2 Replies Last reply Reply Quote 0
                                        • A
                                          aaronventure @Christoph Hart
                                          last edited by aaronventure

                                          @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.

                                          1 Reply Last reply Reply Quote 0
                                          • A
                                            aaronventure @Christoph Hart
                                            last edited by aaronventure

                                            @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.

                                            4d8a50ed-c7ce-4c83-bd73-ced8ff7076a1-image.png

                                            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.

                                            D 1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post

                                            16

                                            Online

                                            1.7k

                                            Users

                                            11.9k

                                            Topics

                                            103.6k

                                            Posts