Forum
    • Categories
    • Register
    • Login

    Is there a way to pickup host transport messages directly within a custom node??

    Scheduled Pinned Locked Moved C++ Development
    6 Posts 2 Posters 286 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.
    • OrvillainO
      Orvillain
      last edited by

      I'd like to be able to poll transport start/stop and tempo changes from within a node. Is that possible, or do I have to use a data cable to feed messages from the top Hise layer?

      Musician - Instrument Designer - Sonic Architect - Creative Product Owner
      Crafting sound at every level. From strings to signal paths, samples to systems.

      HISEnbergH 1 Reply Last reply Reply Quote 0
      • HISEnbergH
        HISEnberg @Orvillain
        last edited by

        I'd like to be able to poll transport start/stop and tempo changes from within a node. Is that possible, or do I have to use a data cable to feed messages from the top Hise layer?

        +1 Would really like to know about how to do this.

        Definitley a good place to start experimenting is the tempo_sync node and the tempo_sync_base class it inherits from.

        Sonic Architect && Software Mercenary

        OrvillainO 1 Reply Last reply Reply Quote 0
        • OrvillainO
          Orvillain @HISEnberg
          last edited by

          @HISEnberg https://forum.hise.audio/topic/11486/c-transport-handler/4

          I just came across this too, which seems relevant.

          Musician - Instrument Designer - Sonic Architect - Creative Product Owner
          Crafting sound at every level. From strings to signal paths, samples to systems.

          HISEnbergH 1 Reply Last reply Reply Quote 1
          • HISEnbergH
            HISEnberg @Orvillain
            last edited by

            @Orvillain Nice find.

            Honestly up until now I have just been placing my C++ nodes inside of scriptnode and using that for interacting with transport/tempo information. Not always the most ideal solution but it does work in most scenarios.

            Sonic Architect && Software Mercenary

            OrvillainO 1 Reply Last reply Reply Quote 0
            • OrvillainO
              Orvillain @HISEnberg
              last edited by Orvillain

              @HISEnberg If in doubt, stalk @griffinboy 🤣

              So following Chris's comment in that thread, it sounds like the node needs to inherit from:

              public hise::TempoListener
              

              And then you write a custom callback. Something like:

              void tempoChanged(double newTempo) override
                  {
                      
                      // yo bro, do a thing here innit fam bruv dudemeister
                      for (auto& t : data)
              	{
              		t.bpm = newTempo;
              		t.refresh();
              	}
                   }
              

              But I haven't tried it yet.

              Musician - Instrument Designer - Sonic Architect - Creative Product Owner
              Crafting sound at every level. From strings to signal paths, samples to systems.

              1 Reply Last reply Reply Quote 0
              • OrvillainO
                Orvillain
                last edited by Orvillain

                #pragma once
                #include <JuceHeader.h>
                
                namespace project
                {
                using namespace juce;
                using namespace hise;
                using namespace scriptnode;
                using namespace snex;
                
                /**
                    Smallest possible BPM listener example.
                    Demonstrates:
                    - TempoListener registration
                    - tempoChanged() callback
                    - BPM flowing into the audio graph
                */
                struct MinimalBPMListener : public data::base,
                                            public hise::TempoListener
                {
                    SNEX_NODE(MinimalBPMListener);
                    struct MetadataClass { SN_NODE_ID("MinimalBPMListener"); };
                
                    static constexpr bool isModNode()            { return true;  }
                    static constexpr bool isPolyphonic()         { return false; }
                    static constexpr bool hasTail()              { return false; }
                    static constexpr bool isSuspendedOnSilence() { return false; }
                    static constexpr int  getFixChannelAmount()  { return 1; }
                
                    // --- Tempo sync ---
                    hise::DllBoundaryTempoSyncer* tempoSyncer = nullptr;
                    double bpm = 120.0;
                
                    // Exposed modulation value
                    double lastOut = 120.0;
                
                    // --- TempoListener ---
                    void tempoChanged(double newTempo) override
                    {
                        bpm = newTempo;
                        lastOut = bpm; // make it observable
                    }
                
                    // --- Lifecycle ---
                    void prepare(PrepareSpecs specs)
                    {
                        if (tempoSyncer == nullptr && specs.voiceIndex != nullptr)
                        {
                            tempoSyncer = specs.voiceIndex->getTempoSyncer();
                            if (tempoSyncer != nullptr)
                                tempoSyncer->registerItem(this);
                        }
                
                        // Initialize output
                        lastOut = bpm;
                    }
                
                    void reset() {}
                
                    ~MinimalBPMListener() override
                    {
                        if (tempoSyncer != nullptr)
                        {
                            tempoSyncer->deregisterItem(this);
                            tempoSyncer = nullptr;
                        }
                    }
                
                    // --- Processing ---
                    template <typename T>
                    void process(T& data)
                    {
                        static constexpr int NumChannels = getFixChannelAmount();
                        auto& fixData = data.template as<ProcessData<NumChannels>>();
                        auto fd = fixData.toFrameData();
                
                        while (fd.next())
                            fd.toSpan()[0] = (float)lastOut;
                    }
                
                    int handleModulation(double& value)
                    {
                        value = lastOut;
                        return 1;
                    }
                
                    void setExternalData(const ExternalData&, int) {}
                };
                
                }
                
                

                This is a minimal example of how to get your custom C++ node to listen to the host BPM. Code above doesn't actually DO anything with the BPM information. But it proves the concept.

                Musician - Instrument Designer - Sonic Architect - Creative Product Owner
                Crafting sound at every level. From strings to signal paths, samples to systems.

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

                22

                Online

                2.1k

                Users

                13.1k

                Topics

                113.3k

                Posts