HISE Logo Forum
    • Categories
    • Register
    • Login

    What is the process for writing my own module (not scriptnode)

    Scheduled Pinned Locked Moved C++ Development
    52 Posts 11 Posters 1.6k 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.
    • O
      Orvillain
      last edited by

      Heya. I'd like to write my own module for the module tree. Not a script node. Ultimately when it is all said and done, I want to write a derivative of the Audio Loop Player - I want to add functionality to it.

      I know a bit of c++ but I am not at all familiar with the HISE C++ api.

      How can I get started with this???

      Oli UllmannO ustkU 2 Replies Last reply Reply Quote 0
      • Oli UllmannO
        Oli Ullmann @Orvillain
        last edited by

        @Orvillain
        HISE is based on Juce. Maybe have a look at it as a starting point.

        O 1 Reply Last reply Reply Quote 0
        • ustkU
          ustk @Orvillain
          last edited by

          @Orvillain I’d ssy the very first step would be to analyse the code of the existing module and try to replicate it. Just a copy/paste that you can use as a starting point for your own module

          Can't help pressing F5 in the forum...

          1 Reply Last reply Reply Quote 2
          • O
            Orvillain @Oli Ullmann
            last edited by

            @Oli-Ullmann said in What is the process for writing my own module (not scriptnode):

            @Orvillain
            HISE is based on Juce. Maybe have a look at it as a starting point.

            @ustk said in What is the process for writing my own module (not scriptnode):

            @Orvillain I’d ssy the very first step would be to analyse the code of the existing module and try to replicate it. Just a copy/paste that you can use as a starting point for your own module

            Thanks guys. Certainly seems like I need to go off and learn some JUCE properly!!

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

              @Orvillain I don't want to demotivate anyone from learning JUCE, but I would not recommend trying to add HISE modules as the API there is rather old (read complicated) plus it will keep you off from being able to stay on the latest HISE develop branch because of your local changes which might affect your ability to pull in hot fixes etc.

              Can you elaborate again what's the limitation of the scriptnode API that makes you go into this direction? Was it the thing with the transient detection and trying to send back the beat slice positions back to the HISE UI?

              O 1 Reply Last reply Reply Quote 1
              • O
                Orvillain @Christoph Hart
                last edited by Orvillain

                @Christoph-Hart said in What is the process for writing my own module (not scriptnode):

                Was it the thing with the transient detection and trying to send back the beat slice positions back to the HISE UI?

                I think in large part, it is because I don't really understand ScriptNode very well. Oddly enough, I'm more comfortable writing code than I am using a UI "msp" style interface. I guess my brain just works that way. I assume that ScriptNode is not limited in any way that would prevent me from doing what I am doing.

                But yes, performing my transient detection in ScriptNode. I don't know exactly how to do it. I've got code I have written in HISEscript actually, and it isn't too bad. Quite performant with the Buffer object handling the brunt of the data processing.

                I totally understand you though. If writing my own module is just going to be a huge pain in the bum, and you wouldn't recommend going that route... then absolutely I'll take your advice!

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

                  I think what would help tremendously (not just for your particular example but in general) would be a better way of sending data between the C++ nodes and the scripting layer.

                  I'm currently extending the global cable system to be able to send any kind of data blob, with this feature you can create a C++ node where you calculate the transients in C++, then send back an array of transient positions back to the UI for display.

                  O griffinboyG 2 Replies Last reply Reply Quote 6
                  • O
                    Orvillain @Christoph Hart
                    last edited by

                    @Christoph-Hart That would be awesome!

                    I've got @griffinboy 's C++ node video queued up on Youtube for later, so maybe I'll go watch that and it'll show me how I should be doing this. Porting my code over to c++ shouldn't be too hard.

                    Is it possible to access Hise's FFT code from within a C++ node ???

                    griffinboyG 1 Reply Last reply Reply Quote 0
                    • griffinboyG
                      griffinboy @Orvillain
                      last edited by

                      @Orvillain

                      Yes it is. You can also access the Juce FFT and any libraries that Hise uses for FFT.
                      My own FFT c++ node did this

                      Link Preview Image
                      [Free dsp] C++ FFT

                      For @ustk Simple FFT implementation using Juce (C++ scriptnode) https://1drv.ms/u/c/6c19b197e5968b36/EcVjEd7aayFHhItxr2gISeMBUD15DXs-oPHNg9Os9pYXWA?e=EW0gfm ...

                      favicon

                      Forum (forum.hise.audio)

                      O 1 Reply Last reply Reply Quote 2
                      • griffinboyG
                        griffinboy @Christoph Hart
                        last edited by

                        @Christoph-Hart

                        Yay. This is a feature I've been wanting for a while : )
                        Good luck

                        1 Reply Last reply Reply Quote 2
                        • O
                          Orvillain @griffinboy
                          last edited by

                          @griffinboy That's awesome. I best get to learning!

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

                            Alright this is pushed now. You can send any type of data through a global cable and pick it up in your C++ node.

                            Here's a snippet that shows the usage. It contains a AudioWaveform connected to an external C++ node that will scan the audio file and send back some properties in a custom JSON object.

                            In order to use that example you'll also need to create a External C++ node and compile that before loading the snippet.

                            1. Create an empty project
                            2. Use Tools -> create C++ third party template. Use this exact string as class name: data_node, otherwise the compiler won't pick it up.
                            3. Replace the entire autogenerated code in the file DspNetworks/ThirdParty/data_node.h with the code below.
                            4. Compile the networks and load the snippet.
                            5. Load an audio file into the waveform on the interface, sit back in awe and see how the console spits out a JSON that was generated in C++.
                            #pragma once
                            #include <JuceHeader.h>
                            
                            namespace project
                            {
                            using namespace juce;
                            using namespace hise;
                            using namespace scriptnode;
                            
                            enum class GlobalCables
                            {
                            	dataCable = 0
                            };
                            
                            using cable_manager_t = routing::global_cable_cpp_manager<SN_GLOBAL_CABLE(-389806413)>;
                            
                            template <int NV> struct data_node: public data::base,
                            								    public cable_manager_t
                            {
                            	SNEX_NODE(data_node);
                            	
                            	struct MetadataClass
                            	{
                            		SN_NODE_ID("data_node");
                            	};
                            	
                            	static constexpr bool isModNode() { return false; };
                            	static constexpr bool isPolyphonic() { return NV > 1; };
                            	static constexpr bool hasTail() { return false; };
                            	static constexpr bool isSuspendedOnSilence() { return false; };
                            	static constexpr int getFixChannelAmount() { return 2; };
                            	
                            	static constexpr int NumTables = 0;
                            	static constexpr int NumSliderPacks = 0;
                            	static constexpr int NumAudioFiles = 1;
                            	static constexpr int NumFilters = 0;
                            	static constexpr int NumDisplayBuffers = 0;
                            
                            	data_node()
                            	{
                            		// this doesn't do anything, but if you want the communication the other way around
                            		// (from HISE to your C++ node, this is the way to register callbacks).
                            		this->registerDataCallback<GlobalCables::dataCable>([](const var& funky)
                            		{
                            			jassertfalse;
                            		});
                            	}
                            
                            	// We don't need any of the DSP callbacks for this example so we can use these macros to
                            	// define empty methods
                            	SN_EMPTY_PREPARE;
                            	SN_EMPTY_HANDLE_EVENT;
                            	SN_EMPTY_PROCESS;
                            	SN_EMPTY_PROCESS_FRAME;
                            	SN_EMPTY_MOD;
                            	SN_EMPTY_RESET;
                            
                            	void setExternalData(const ExternalData& data, int index)
                            	{
                            		if(data.isNotEmpty())
                            		{
                            			// convert the data to the juce::AudioSampleBuffer class
                            			auto buffer = data.toAudioSampleBuffer();
                            
                            			// fetch a few properties from the buffer
                            			// (this is the place where you could do your custom processing
                            			auto magnitude = buffer.getMagnitude(0, 0, buffer.getNumSamples());
                            			auto rms = buffer.getRMSLevel(0, 0, buffer.getNumSamples());
                            			auto length = buffer.getNumSamples();
                            			auto channels = buffer.getNumChannels();
                            
                            			hise::JSONObject obj;
                            
                            			// write the values into the JSON object
                            			obj["magnitude"] = magnitude;
                            			obj["RMS"] = rms;
                            			obj["length"] = length;
                            			obj["numChannels"] = channels;
                            
                            			// just attach the current knob position so you know it's working.
                            			obj["knobValue"] = value;
                            
                            			// send the JSON object back to HISE
                            			this->sendDataToGlobalCable<GlobalCables::dataCable>(obj);
                            		}
                            	}
                            	
                            	template <int P> void setParameter(double v)
                            	{
                            		// just save the parameter to be send in the JSON object later.
                            		value = v;
                            	}
                            
                            	double value = 0.0;
                            
                            	void createParameters(ParameterDataList& data)
                            	{
                            		{
                            			parameter::data p("MyParameter", { 0.0, 1.0 });
                            			registerCallback<0>(p);
                            			p.setDefaultValue(0.5);
                            			data.add(std::move(p));
                            		}
                            	}
                            };
                            }
                            
                            O griffinboyG 3 Replies Last reply Reply Quote 8
                            • O
                              Orvillain @Christoph Hart
                              last edited by

                              @Christoph-Hart Did you forget to put in the hise snippet Chris, or am I not getting it???

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

                                @Orvillain oops yeah haha will post it when I get back.

                                O 2 Replies Last reply Reply Quote 2
                                • O
                                  Orvillain @Christoph Hart
                                  last edited by

                                  @Christoph-Hart No problem! Thanks for the quick turnaround. This is going to be seriously cool, I can feel it!! 😊 😊

                                  1 Reply Last reply Reply Quote 0
                                  • O
                                    Orvillain @Christoph Hart
                                    last edited by

                                    @Christoph-Hart Hey dude, any ETA on that snippet?

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

                                      @Orvillain There you go:

                                      HiseSnippet 1230.3ocuWs0aiTCE1SZmtz.qDU.uOpOkBUQIj1rcYEhjlKKAHsQaJk8sJGONIl3wdjGOsMfVo9HOxOU9G.G6YlLSXydQQvlJUkyM6OeNemicFojDZTjTgbJe0xPJx4SbGuTnm2YNlIPC5B5c6h03qnQZz4KCwQQTejiyNO2X2Y+cQ1O+02cNliEDZtJD5ZIiP+IV.SmqcTqejw48w9zqXAE79jVCHRQGIWFCXYG2ZnPLYAdF8BrwsRtnuGGMG47kt0O6oD7IjSaVmdxjl9Owu4DxYjFSwM7e5o3F1u1rQiFHm854yzR0XMVSiPN6dtze434x6DIav0rH1DN0HTGMF14D08kbeyQznE0YNi6OJKIEgfUYTdJamjT1m6Nj4yVoOO08oVCd4QTLA5TZc3syZvqdQ3Uq.71.jbJ.ocSfzAtiIJVnN2hAOer6.glplhg5TQnj3KpzCNtcjfGBc0.7BZeEHrJhJMqU6XO3eG8rxkgZUj16VrxSE38sd8DyXBZ0YT8y4xIX9KjwZlX1Pr.pfpJqGgOPm5fgiFDnJvDjUpxgqLbnIfURUUzYrH.EcsZ37I.ynxzXAQyjhJF+Np7uWde.5QRv8PESnqbX21W09a7Nz6q7zJC7s9AK7qN5YYw5IEWH0zKEUrKP4WU16eaZ5zMZyjlTRN2b31fYC2V81BrhHNXBUcLjP3wzUNB0u0IEtuYRQQNKIopUvQoXffouLjJdSLYTZo1PfRQEzxnszmuHk9zN1mI+E7szoRU.h4anzqoqNxd.J10axy1FVEVLiBGDEz965XLY0zS3mIi94AlZZFB.v..LjpzLyY2oK8VX.RBgde2tznEZYn02fPov.8s.u2uBqOzp0xbgen0cLe87UJ9yGZElksF3amKZ2Bu9uDxludGGzqK8i4X85C.LiISM.Df055LcVhHldYwwn+mMU38EhG3NhoIy2LFKsALBUq+OvX5rzG61a5TJQmCvcc6+xO.CNcS1+xokYXOMa9ZU8hf3h3.KwpOia6ScLD5z4nN+gadKenhFhUzqji33kUhvAgb5K.fer2DtjrXL62nu9bhTl24FOpPliEBJOZaFmr26cpp9auRsZhtVwfVHW37OFtplP6jhNSNnjYpRhbsrd7wTguU3ugOoFquJgAFqmYLefD5Bp9NoZgsFk9cjyiLEj8cuSgCCghv0TUjgt57H2ZUg+Ps4b4clYCrThLTlr5FI4KCmKELhQUhGY3tcfLVny.O7FiqvLtg4ONNBFd5eoXL3r8gMFl2ERe3a60GSfr5xQXy.iCbMieA5JUUkrh1lCzbZiI2l7dlbqlUL6YOIYL.fA1gavLTfnA1SxCIacx83lgr2HLZVCJelKvb9Un8oZtCaZ6Kt.uK.LBqfXfqeS5Xxj.mGxDWmL820TBPCw2uRtNHaf5icGtLOlTy6At2rIpKcJNlqKrFmZ2bnC49r6EJzjUTBYFe5SuO4PkCDqzJXX4xEtRADJbXVyhcVfQBlzUJoyePz0FqDLOC2.G4bobQ.1RM2pau9fzHEfIJ4MjjYClC2GY0.IDQJ6anQ1aC2dG.OX8FBY8k50B7q21.arsAdx1F3oaafM21.ex1F3Yu6.M+dh1wZYPxDNDZ3ndVRniSOg4wx1KmP+Cf1ouMo
                                      
                                      O 2 Replies Last reply Reply Quote 1
                                      • O
                                        Orvillain @Christoph Hart
                                        last edited by

                                        @Christoph-Hart Right! That is really cool! I'll dig into this when I get some chance and see how I can leverage this kind of system for my thing.

                                        1 Reply Last reply Reply Quote 0
                                        • O
                                          Orvillain @Christoph Hart
                                          last edited by

                                          @Christoph-Hart I think this is going to be amazing. Been looking at the snippet, and it mostly makes sense. Being able to throw data from a custom node to the UI is exactly what I want to do.

                                          So ultimately, consider the title of this thread to be null and void - custom node is where it is at! I've just got to port my HISEscript over to c++ and start properly learning scriptnode.

                                          1 Reply Last reply Reply Quote 0
                                          • griffinboyG
                                            griffinboy @Christoph Hart
                                            last edited by griffinboy

                                            @Christoph-Hart

                                            Thanks, I'm already making use of the new Global Cable feature!
                                            It works great.

                                            Here we are sending the drawing straight from Hise into a c++ node for playback!

                                            ChazroxC ustkU LindonL Oli UllmannO ulrikU 5 Replies Last reply Reply Quote 9
                                            • First post
                                              Last post

                                            42

                                            Online

                                            1.7k

                                            Users

                                            11.7k

                                            Topics

                                            102.2k

                                            Posts