Forum

    • Register
    • Login
    • Search
    • Categories

    What's all this JIT stuff

    General Questions
    2
    8
    1422
    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.
    • d.healey
      d.healey last edited by

      I'm seeing this in the commits recently, is this related to C++ API or JS?

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

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

        It's a big new feature that I am working on right now. Basically its a embedded C compiler that generates terribly fast machine code that can be used to write new DSP algorithms with almost native C++ speed. You can then call it from Javascript. This is the last missing piece to make the scripting environment really awesome 🙂

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

          Oh 🙂 I see what you're doing. You're turning it up to 11!

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

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

            Its about 95% faster than a Javascript loop so It's rather 11.5 🙂

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

              Alright, I started to migrate this into HISE and it is real fun. I made some tests using a additive synthesizer with 6 harmonics and 6 low pass filters that smooth out the amplitudes.

              Check out the CPU usage of the three different engines (native C++, NativeJIT and Javascript):

              Performance

              As you can see it's 17% JS vs 2,2% NativeJIT vs 0.9% C++. While it's not 100% there, it definitely allows writing DSP algorithms without compiling!

              The Javascript Code

              /** NativeJIT Example Script
              *
              *    Drop this into a ScriptFX Processor and compare the performance between the different engines.
              *
              *    The example algorithm is a additive sine wave generator with 6 sinewaves and simple LP smoothing
              *    of the amplitudes to reduce clicking.
              *
              *    You can use the SliderPack to draw the harmonic structure and switch between the different engines
              *    (they should sound the same)
              */
              
              // Loads the "Example.cpp" file in the script folder and creates a NativeJIT compiler called "Example"
              loadJITModule("Example.cpp");
              
              // Compile and create an object from the given source code 
              // The globals in the C code become local to this instance and you can access them via "c.global"
              const var c = Example.createModule();
              
              // Loads a compiled DSP module with the same functionality
              const var cppMod = Libraries.load("core").createModule("additive_synth");
              
              // The variables for the Javascript version
              reg b = Buffer.create(6);
              reg lastValues = Buffer.create(6);
              reg uptime = 0.0;
              reg uptimeDelta = 0.03;
              reg a = 0.999;
              reg invA = 1.0 - a;
              
              // GUI Stuff...
              
              const var SliderPack = Content.addSliderPack("SliderPack", 10, 10);
              // [JSON SliderPack]
              Content.setPropertiesFromJSON("SliderPack", {
                "width": 240,
                "sliderAmount": 6
              });
              // [/JSON SliderPack]
              const var Engine = Content.addComboBox("Engine", 271, 9);
              // [JSON Engine]
              Content.setPropertiesFromJSON("Engine", {
                "items": "Off\nJavascript\nNativeJIT\nCompiled C++"
              });
              // [/JSON Engine]
              Content.setHeight(120);
              
              function prepareToPlay(sampleRate, blockSize)
              {
                  // Needed for DSP Modules...
                  cppMod.prepareToPlay(sampleRate, blockSize);
                  
              }
              
              function processBlock(channels)
              {
                  local e = Engine.getValue();
                  
                  if(e == 3)
                  {
                      // Calling the c.processBlock method iterates the buffer
                      // and calls the defined process(float input) function for
                      // each sample
                      c.processBlock(channels[0]);
                      
                      channels[0] >> channels[1];
                  }
                  else if (e == 2)
                  {
                      // The same code in slow Javascript
                      local a0, a1, a2, a3, a4, a5;
                      local v0, v1, v2, v3, v4, v5;
              
                      for(s in channels[0])
                      {
                          a0 = (lastValues[0]*a + b[0]*invA);
                          a1 = (lastValues[1]*a + b[1]*invA);
                          a2 = (lastValues[2]*a + b[2]*invA);
                          a3 = (lastValues[3]*a + b[3]*invA);
                          a4 = (lastValues[4]*a + b[4]*invA);
                          a5 = (lastValues[5]*a + b[5]*i);
                  
                          v0 = a0 * Math.sin(uptime);
                          v1 = a1 * Math.sin(2.0*uptime);
                          v2 = a2 * Math.sin(3.0*uptime);
                          v3 = a3 * Math.sin(4.0*uptime);
                          v4 = a4 * Math.sin(5.0*uptime);
                          v5 = a5 * Math.sin(6.0*uptime);
                  
                          lastValues[0] = a0;
                          lastValues[1] = a1;
                          lastValues[2] = a2;
                          lastValues[3] = a3;
                          lastValues[4] = a4;
                          lastValues[5] = a5;
              
                          uptime += uptimeDelta;
              
                          s = v0+v1+v2+v3+v4+v5;
                      }
                      
                      channels[0] >> channels[1];
                      
                  }
                  else if (e == 4)
                  {
                      // give the native C++ module the buffer to calculate
                      cppMod.processBlock(channels);
                  }
              }
              
              function onControl(number, value)
              {
                  if(number == SliderPack)
                  {
                      // Set global values of NativeJIT modules directly
                      // as if they were a Javascript Object!
                      c.b[value] = SliderPack.getSliderValueAt(value);
                      
                      // Use the parameter API to set the overtones
                      cppMod.setParameter(value, SliderPack.getSliderValueAt(value));
                      
                      // set the buffer value for the given overtone for JS
                      b[value] = SliderPack.getSliderValueAt(value);
                  }
              }
              
              

              The NativeJIT code

              This is how the NativeJIT code looks like. It's plain old C with the addition of the Buffer type.

              /** The NativeJIT code for the additive synthesiser. */
              
              double uptime = 0.0;
              double uptimeDelta = 0.03;
              
              // Buffer is a custom type which correlates to the Buffer type in Javascript
              // Treat them like a float array (there is a buffer overrun protection)
              Buffer b(6);
              Buffer lastValues(6);
              
              float a = 0.999f;
              float invA = 0.001f;
              
              float process(float input)
              {
                  const float uptimeFloat = (float)uptime;
              
                  const float a0 = (lastValues[0]*a + b[0]*invA);
                  const float a1 = (lastValues[1]*a + b[1]*invA);
                  const float a2 = (lastValues[2]*a + b[2]*invA);
                  const float a3 = (lastValues[3]*a + b[3]*invA);
                  const float a4 = (lastValues[4]*a + b[4]*invA);
                  const float a5 = (lastValues[5]*a + b[5]*invA);
              
                  const float v0 = a0 * sinf(uptimeFloat);
                  const float v1 = a1 * sinf(2.0f*uptimeFloat);
                  const float v2 = a2 * sinf(3.0f*uptimeFloat);
                  const float v3 = a3 * sinf(4.0f*uptimeFloat);
                  const float v4 = a4 * sinf(5.0f*uptimeFloat);
                  const float v5 = a5 * sinf(6.0f*uptimeFloat);
                  
                  lastValues[0] = a0;
                  lastValues[1] = a1;
                  lastValues[2] = a2;
                  lastValues[3] = a3;
                  lastValues[4] = a4;
                  lastValues[5] = a5;
              
                  uptime += uptimeDelta;
              
                  return v0+v1+v2+v3+v4+v5;
              };
              
              

              Note: This feature is not yet committed so you won't be able to check this out (I remove this hint when it's in the codebase).

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

                Looks exciting, I'm going to have to relearn C 😛 so what sort of things will this be useful for?

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

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

                  You can use this to script custom modulators, effects or synths. It's a bit like Reapers JSFX but embedded into HISE (I have to make performance tests between those two).

                  Especially the effect section in HISE is a bit underpopulated so this might come in handy there.

                  I will be using it to prototype DSP modules which will then be hardcoded into HISE. There are yet some drawbacks (only x64 support, no "real" branching, no iOS support)

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

                    Aha now I get it!

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

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

                    11
                    Online

                    1.1k
                    Users

                    6.8k
                    Topics

                    62.3k
                    Posts