HISE Logo Forum
    • Categories
    • Register
    • Login

    The Missing Piece of the HISE VI Puzzle: Continuous Per-Event Modulation

    Scheduled Pinned Locked Moved Solved Feature Requests
    24 Posts 3 Posters 1.9k 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.
    • A
      aaronventure @Christoph Hart
      last edited by

      @Christoph-Hart Here's one example how I use this right now.

      I have script voice start pitch modulators in multiple samplers, and each has its own little logic for setting the correct pitch. Now, I can't do this from the MIDI script itself because the pitch will differ for each event. So it reads from the MessageCustom data object to perform its logic.

      All events eventually pass through that pitch modulator. Some might not to have their pitch set by that specific modulator. So I use some of the slots to either flag them or do a simple ifDefined check for the slot inside the pitch modulator itself.

      Eventually, the data object will get filled because the event counter will overrun it and the modulo means it'll just overwrite the old array indexes.

      But the data in there will stay unless I clear it. So if a new ID is not not the one I want for a specific pitch modulator to play, it either needs to read undefined or it needs to read the value 0, which needs to be set.

      So for each event, I can either set all 16 slots, or clear all slots and set only the ones I'm using (so far 10 is max but usually a lot less).

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

        But the data in there will stay unless I clear it. So if a new ID is not not the one I want for a specific pitch modulator to play, it either needs to read undefined or it needs to read the value 0,

        Yes, but why don't you write the zero for the events that shouldn't apply any pitch? This would be your responsibility with the new system then too and taken off that burden feels like adding Garbage Collection.

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

          @Christoph-Hart Since the data object is an array, I found it easier to call MessageCustom.clearForId(eventid) than setting 0 for all the slots I don't use.

          Fewer lines of code, cleaner overall.

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

            @aaronventure actually I could add another data member to the array element that holds the actual event ID (and not the truncated modulo index), then you can check for equality and return undefined (or zero) without the collision at the wrap around. The performance overhead is neglible.

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

              @Christoph-Hart i'm failing to understand the technicality of what you're suggesting; are you saying that clearing wouldn't be necessary as a new ID couldn't read the data that was set for the old ID?

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

                @aaronventure yes exactly.

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

                  @Christoph-Hart perfect

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

                    @aaronventure Alright, I've written a few tools with this concept:

                    • a GlobalRoutingManager.setEventData(eventId, slotIndex, value) API method where you can set up to 16 double values per event ID and
                    • get them with GlobalRoutingManager.getEventData(eventId, slotIndex) (if the data hasn't been set yet it will return undefined.

                    This basically replicates our existing Javascript helper class but in C++ and globally accessible through the global routing manager. But then it gets interesting:

                    • a voice start modulator that will query the given data slot and resort to a default value if not set (so you don't need to use the script voice start modulator for just passing on that value to whatever target anymore).
                    • a routing.event_data_reader node that will polyphonically read the event data and send it as scriptnode modulation connection. There are two modes available, one only reads and sends the value when the node processes the incoming note on message (to replicate voice start modulation like behaviour) and the other one listens for changes from the last event ID and outputs a time-varying modulation signal.
                    • a routing.event_data_writer node that will write an incoming value into the data slot. This is polyphonic and timevarying, so you can basically send the envelope output from one scriptnode envelope to another (or create the data however you like). The update rate is tied to the buffer size though (because that's how the modules are processed one after another).

                    I'll clean it up a bit tomorrow and write some docs, but it looks promising.

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

                      @Christoph-Hart said in The Missing Piece of the HISE VI Puzzle: Continuous Per-Event Modulation:

                      The update rate is tied to the buffer size though (because that's how the modules are processed one after another).

                      What does this mean for wrapping stuff up in frame/block nodes? Will it just shout about rate mismatch like the midi node when you try to place it within a block node?

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

                        @aaronventure no, the update rate is simply the buffer size as this is the rate that the sound generators are able to talk with each other.

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

                          @Christoph-Hart so on higher buffer sizes, you get lower resolution streams?

                          Alright, it's then important to highlight it, as this warrants like 20ms smoothing at the lowest for consistency. Can the read nodes have smoothing built in? it'll be necessary anyway, this would just make it less of a mess.

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

                            You can use Engine.setMaximumBufferSize() to limit the buffer length to 64 or something then you get a guaranteed update rate of 1,5ms if that‘s what you need.

                            The nodes will not have any smoothing as you can simply add a smoothed parameter node, but the event data envelope (which is a polyphonic HISE envelope that automatically reads out the values from the given slot will have a smoothing parameter (like the LFO).

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

                              @Christoph-Hart Ah, good to know, I didn't know I can hard limit the buffer size for the plugin.

                              Yes, smoothing parameter/control is what I meant. Hiding smoothing inside the actual readout would be naughty.

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

                                @aaronventure Alright, the feature is pushed now (alongside with the documentation for each thing).

                                I've also added a bunch of snippets to the browser that demonstrate various use cases (Custom Data Event 101/102/103).

                                Let me know if you find some quirks.

                                1 Reply Last reply Reply Quote 2
                                • d.healeyD
                                  d.healey
                                  last edited by

                                  Does that solve this request? https://forum.hise.audio/topic/9501/message-event-flags-or-meta-data?_=1716378593963

                                  Libre Wave - Freedom respecting instruments and effects
                                  My Patreon - HISE tutorials
                                  YouTube Channel - Public HISE tutorials

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

                                    @d-healey yup. You can now write 16 number values to a slot using an event ID and pick it up later either using scripting, a new modulator or nodes in scriptnode.

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

                                      @Christoph-Hart Cool, have the docs been pushed?

                                      Libre Wave - Freedom respecting instruments and effects
                                      My Patreon - HISE tutorials
                                      YouTube Channel - Public HISE tutorials

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

                                        @d-healey It also solves Per-event routing: https://forum.hise.audio/topic/9625/per-event-routing?_=1716386003580

                                        Link Preview Image
                                        Compiling of a Polyphonic FX With a Selector Node Fails · Issue #521 · christophhart/HISE

                                        macOS 14.4.1 ebfbd32

                                        favicon

                                        GitHub (github.com)

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

                                          This is still broken because 0 cannot be sent:

                                          Link Preview Image
                                          [Engine] GlobalRoutingManager.setEventData(id, index, 0) doesn't execute · Issue #537 · christophhart/HISE

                                          The new method seems to be unable to set the value to 0. 0.001 works, but if you pass the method 0 or 0.0, it won't execute. macOS 14.5 6b070f5

                                          favicon

                                          GitHub (github.com)

                                          1 Reply Last reply Reply Quote 0
                                          • A aaronventure referenced this topic on
                                          • A aaronventure marked this topic as a question on
                                          • A aaronventure has marked this topic as solved on
                                          • A
                                            aaronventure @Christoph Hart
                                            last edited by

                                            @Christoph-Hart Hey boss, I might need more than 16 here (32; is it always power of 2?). Can I please trouble you for a preprocessor? What would be the implications of this, performance wise?

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

                                            20

                                            Online

                                            1.7k

                                            Users

                                            11.8k

                                            Topics

                                            103.1k

                                            Posts