HISE Logo Forum
    • Categories
    • Register
    • Login
    1. HISE
    2. HISEnberg
    • Profile
    • Following 0
    • Followers 6
    • Topics 64
    • Posts 718
    • Groups 1

    HISEnberg

    @HISEnberg

    340
    Reputation
    228
    Profile views
    718
    Posts
    6
    Followers
    0
    Following
    Joined
    Last Online
    Location Canada

    HISEnberg Unfollow Follow
    Beta Testers

    Best posts made by HISEnberg

    • Oscilloscope Script

      I am trying to optimize my oscilloscope script while still keeping it visually interesting. I recall having a discussion a few months ago about this but I can't find the original post.

      Anyways here is an oscilloscope script for drawing the analyzer to a path in a panel. There are a lot of adjustable variables for optimizing it (buffer size, frame rate, frame count, etc.) There is also optional opacity settings (glow effect) and ghost trails (though these consume a lot more CPU). Hope you guys like it and let me know if you can think of any optimizations or better visual performance for it!

      Here is an A/B comparison of it with the floating tile display

      osc.gif

      HiseSnippet 3084.3oc2as0baabEFTRH0Vw4Vmz59HFMsy.YISSRcupNQzTjRbh3kRRY0LdznYIvJx0BDfE.zxJdzL8WRm9SnO1eF8w9X+Ij+AsmcWbYW.PKZEeIN7AEuWNm8rmy24xtKRaWGCrmmiqRtE6c0XrRt6o18Ja+gUFhH1J02WI2mp53Y7PSb+ICTdxUiQddXSkb4l+.5Dxc2ETX+9wu8IHKjsANtKEkm5PLvGQFQ7i6s8deGwxpFxD2iLRX1quWcCG6JNVNS.gYd0BJiQFWfFfahnSaNUkCQdCUx8.09EMJfWquAB0GsCd6s2n+5au0NHbQyhaswl6rQgc5u4FasogRtOopIw2wsqOxG6ojagm3XdU2gNWZyWfmR7H8svzFEU5BqLu6ZNVlzsHsWkJCIVlsC0RdJ.SaGqylmqy9Z0FDSRT+w5tujMfVLEhJvbyIKdyKIdEEEuBBhWFhTNAQZAtH8UpcMbIi8iGgaKqa6icOGA1IQQgOWk4962WshCLCa+7iPWfq4BMhnPe8BEVUC9yx6tnMXT7.CDVqkmAXOAHhyX7huZQM3GXG870dAxUqrMx5JOraQsGqwfU4Gf8qd94XCe8khFbIfgxz8jiqUqZGQh1m3M1Bc0Sl.D61EvHf7bCb3rVcq.rfyqT7PuPJZFaacFrc.ZBUB.QUbFM1wFZnuTv3YrZ9.T1Enqp8.hMNugKFLoT7saq9OmtYSKeS78crKN00JX7vkRfZ5N6npMOn2g.wqWXmM2US6QORqC1bhA1TqOa2o4Q9Ar14NtZ8w9f8SqR6iiYjKd.iMs6zpc0N8pWsKvpWsDWwbD1df+vk9iBKzpZK0bxH.Vaais7fgJdMWrBzx48v9cH1C3L.fbiwt9Drmt7hrbJhJa3SdAV22cBN8FsW0FsOKBIv4cfpUOV1VdWIh1uS4SlIhRtZ05TtQ0ypz53l8.BWa2HE04t.VmyHOXjmcZ7PFSbcAqUM5LpaaheILdAg8AXVpfLFBVkwH+gZNLrfWD4ifvDsoCDCB3RJsyPHCch9tHh0MNS1enlbcBSNzHZ+IwsEzwJqrLaVb+T17E1c4GOwan9T0YAKy0x3nQnA1D+IlX5ZleCQbdixGzrdui2u5YcazpECuVH+NRyndyyhlEa3BaHq+1GaPFg7IN1hF4pUp2nbupmUqbkdsnF50JsaJTP0mVsy2eVyyXp.JBuXBiZEmIzXaILZAdYkq7cGzATa6CJuiZcLcQJ7xBA+D2CmT9oUq0pSCw4UtPsZkqNk408vx625D171Dl21Sie85Tt9QroslD6BUMG4bIH7u.YMA6I5pCNePqQzjwBr8fiZApDvunBEeS83jLDs5UuUS9R1MiwqzpSypchsiqkWRlaWt2gm06v5U9tlU6RouT9DBaiHXxjwl.vh0Ow1BBWpc9DaCpENXnnopmDrZ4XfrzrwWBSAVDAecZzSA51MhDQ3Y7+9AowlqDx2GnoWLeAsGlZJSgqM.WPHa4K0k.yqFOmz9Mf9fEyPyCR+Ck3.Klis0Ufxb7UZlbDOMngCwNHbQRMEkPbEgvOozUICDD6HSauxiS5DsbDkICK7rTg4N8YjSk0+PGwZmn+QVwG0S24JZEWV6OHEpJCM19tnKgbLQ5fL0KlvjDqHQevpPrWHqEydjTGMH+4vLKaYomxce4L1Nb32kDSVfXFao3tSncHh43yaHlLXnu3DOj0S5YNhX98v7BH3QZkl5Z6A+AadXHmCn3AAXPhME4x2oIWCphgtHr05gRL5QkRN49PfQSVxNfaLJWkusWUhvrL4AFJdJKNLxSibtF1FA0xZFMOnKcofNw3uWIiDo3XFepaxyupE0JQ5sv9CyxkMCCW8Xd93z.0kSQRPvNehcXjQweo5fqHo91YB4eX7lXEwMQl9Ao4qCT5Mw+JVFys.loSWnGIynG.is4LHoQEWj2vBibEgmI.enQisjh38PFbSF7IE4HbSd5yJb5xYv3301yG452DeY2I8Y0zPgwAPU1xt7LrShB4kHz1sI.X13lXkAKTFAz4BEHApblWxtYR2OI0GIS0mrJjFIrmi9KuYM20uInBWZvfJNt1fDoKUGvrXSFPKymepdc9+wK+kD+gksFODoKWqypQ3ZJ1cir1wCxSCGwPHQR3pAwqVENBSugDiKrgC7BGRIQQILddcBdFqItd5wxn0oypfWH+Oux8ztLbzgnCOXwugroSOb+LAYDYXB+rH4bFbuV7ssajr6yapaysXum1IIZ+ey9FYX+indlbADgMGX4boF+dNjx3ITD9zzSynCC+PDqlQl+j5.AWlvMzL6w.kwe8qWGIJtINIj.g2ZY3QktNc4yA2CCckaCbyuiyDHsLVOrJP8AKq8pXQLqZB8GR7jJQmO8qWV9TKrqvQqVX0kAmMlUmNTJ5xYVBpiMipJHKq9HiKRUXd30ePYRGLxL35nDtsir.U+zJmWtRcfKBqV1ktm5nXwyIiydjsWP2KHiCKAz2QiLZrqyKvoNeZz4MBNO9Jqr6hoJTK7r5eyiy5v8SyYJDo3hGSAJIqsI6aAHFscs.ZfcEeTHmr0Mg0VD+jFXDbodzqvw0wR2H759VkeJ9jHE5lmM.sD0hu1Bjuwa7Y50zvn+4b5edBj0ymo5jRcfQxoO64mxuNmoktMUwBA5WZdJlFUesBYF4Aa4gyjPmwb5BiWHXIBz67PULcuf8S1n.TesfEqoiOtkM3C+pEu6hfPjbnyOOywBXlEUbxX3.Ac5DpaOYTeraDtHXhJ4VP9ICTm9SFH9hFF76LTXhN10AG6Viw1S6cNTBtnQ5yKDHUvT8YOtvmG73BbUmBwTI2cUCziJLQV7ggTNt99HeTHi.dFeCwPe6ieAw.ye0h6ptO16BvTBKUzkgqj6S3K6mE9lFzCTyV0EUCuSdkWJ9vSWI1fUbQbGWsG+Xyw8P1SQXwtmeva5vWrZVNHH6xfdDPuRWyuPUrqouvj8lgENPgv28egZ4IlDmvW0Po+fvmC6dpqWZ6har9FaTZMEhOdjz.aUbss1oz1BCTJXjRat45EJrthO9k9hOsFydj6HUZzfkhr50Mg7uBOpxpzQYknRuxeVqZ.n14xSbbuf85OP+minNjWqHpB+Uy.LYVsW+s+bJ012rmI9bzDK+mxgZL.b5m.6KUa3XNwB4K+hbz2sLX.vmS5YvnO0ksGb.DQ36asmoaVEwuRsMw2XX1x3bYHifm06BYL3wM+LUdgrwB3Bp09KuidIy4DV+6D8fzDZs5GDt72SsAxCxXy5X5uHshx9XKjjZ5DYGxueuLdy551u.BM01wB4lTIO+LuKK952kKLyHA5VR6mBZcgYyT75ey6YE49qUYp7OlDXFj3iGA9KUgje+LPb4G4Z.b5SWBDIWs4jQ7GkO7Qhg9xMGsJBd6Bz1TApK11j03+A+BFrHsctfAKFNnnJQkqRVTMJ2H+qYHJWkjdH3iDf7CBN1+y8Z6BEZfuLnPiftuydu07peeqS9b9N4Sgvi1X12IASo7aYs0NAAmz5.rM1kBfJNs3j68u9r+yr9k6Ldl+xcZY3CKeOWjs2XGOIF2EOhzCJSvSryi8v0bw+0NTHsX+UbPtYNzO9s0fMYlzzE4Owk4aTdD8jcutH3KLa15a3CBZg2UePPumir7AqvHoueo6FJi7r9UgzwVvoEhxuvJ7KrWYbcCGamwCcrIFhF8NXvebv.rqnrm4FpruObjvnd9ww60AagQB.3l+i8NB.dHWPOguk5hhuweKWYZu9cpbwkcGUe7j.60Vb67yTwsu0k2O.E599NYw8CSVPyKDmr32vZSuMtojqXN4Zp+2uyyUTLyjER8lfhRYRQI4CB3OwVl07tjlEUUTCTEEEKOHryRhcB0fIwLnsDmZPDNc6+8aqxd66tXXmaxuHZpdVzkr8D3PzrRQKJRXb2kD69PjqIXCMdKjZSNluv7+n3Ce8Wz41J8tL2lxWmJ2lxu+Wf419vdYMy+K5KqY189f3g+71JdeUHtbIMloT6Cis78QAAuOViQHCWmyL3uX.0o+Nrdf8sM6+QNtqZCZasTOTfhxHHkwYFFxrJEgktsDt1skv0usDtwskvMusDt0skvsuYBoYzKOw2g+4XSKyocU9CIjiWgCyMQ4+iYkPuv
      
      Content.makeFrontInterface(400, 400);
      namespace Oscilloscope
      {
          const var Analyser1 = Synth.getEffect("Analyser1");
          const var BUFFER = Synth.getDisplayBufferSource("Analyser1");
          const var BUF_OSC = BUFFER.getDisplayBuffer(0);
          const var pnl_Osc = Content.getComponent("pnl_Osc1");
          const var timer = Engine.createTimerObject();
          const var Button1 = Content.getComponent("Button1");
          
          const BUF_LENGTH = 4096;  // Reduced buffer size for better CPU
          
          reg BUF_PROPERTIES = {"BufferLength": BUF_LENGTH, "NumChannels": 1};
          BUF_OSC.setRingBufferProperties(BUF_PROPERTIES);
          BUF_OSC.setActive(true);
          
          const TEMP_BUFFER = Buffer.create(BUF_LENGTH);  
          const DRAW_BUFFER = Buffer.create(BUF_LENGTH); 
          
          const FRAME_COUNT = 3;
          reg frameBuffers = [];
          reg currentFrameIndex = 0;
          
          // Cached path objects
          reg mainPath = Content.createPath();
          reg trailPath = Content.createPath();
          
          for (i = 0; i < FRAME_COUNT; i++)
          {
              frameBuffers.push(Buffer.create(BUF_LENGTH));
          }
          
          reg magnitude = 0.5;
          const MAGNITUDE_SMOOTH = 0.9;
          const MIN_MAGNITUDE = 0.05;
          
          // Decimation
          const DECIMATE_FACTOR = 32; 
          const DRAW_EVERY_N_FRAMES = 1;
          reg frameCounter = 0;
          
          const BACKGROUND_COLOUR = 0x00000000;
          const WAVEFORM_COLOUR = 0xA0FFAE00;
          const WAVEFORM_SHADOW = 0x60FF8000;
          const WAVEFORM_TRAIL = 0x30FFAE00;
          
          // Lower values for better performance
          const GLOW_EFFECT = true;
          const MOTION_TRAILS = true;
          const CORNER_SMOOTH = 3.0;
          const PATH_THICKNESS = 2.0;
          
          // Magnitude update
          inline function updateMagnitude()
          {
              local newMag = DRAW_BUFFER.getMagnitude();
              magnitude = magnitude * MAGNITUDE_SMOOTH + newMag * (1.0 - MAGNITUDE_SMOOTH);
              magnitude = Math.max(MIN_MAGNITUDE, magnitude);
          }
          
          // Frame storage - only copy decimated points
          inline function storeCurrentFrame()
          {
              for (i = 0; i < BUF_LENGTH; i += DECIMATE_FACTOR)
                  frameBuffers[currentFrameIndex][i] = DRAW_BUFFER[i];
              
              currentFrameIndex = (currentFrameIndex + 1) % FRAME_COUNT;
          }
          
          // Drawing function
          inline function drawOscilloscope(g, panel, mag)
          {
              g.fillAll(BACKGROUND_COLOUR);
              
              local width = panel.getWidth();
              local height = panel.getHeight();
              local midY = height / 2;
              
              local scaledHeight = height * Math.min(1.0, mag);
              local drawY = midY - scaledHeight/2;
              local bounds = [0, drawY, width, scaledHeight];
              
              // Draw trail frames if enabled
              if (MOTION_TRAILS)
              {
                  for (frameIdx = 0; frameIdx < FRAME_COUNT; frameIdx++)
                  {
                      if (frameIdx == currentFrameIndex)
                          continue;
                      
                      local age = (currentFrameIndex - frameIdx + FRAME_COUNT) % FRAME_COUNT;
                      local opacity = 0.7 - (age / FRAME_COUNT) * 0.6;
                      
                      trailPath.clear();
                      local sample = Math.max(-1.0, Math.min(1.0, frameBuffers[frameIdx][0]));
                      trailPath.startNewSubPath(0, midY - sample);
                      
                      for (i = DECIMATE_FACTOR; i < BUF_LENGTH; i += DECIMATE_FACTOR)
                      {
                          local x = (i / BUF_LENGTH) * width;
                          sample = Math.max(-1.0, Math.min(1.0, frameBuffers[frameIdx][i]));
                          trailPath.lineTo(x, midY - sample);
                      }
                      
                      trailPath.roundCorners(CORNER_SMOOTH);
                      
                      g.setColour(Colours.withAlpha(WAVEFORM_TRAIL, opacity * 0.5));
                      g.drawPath(trailPath, bounds, {"Thickness": PATH_THICKNESS * 0.5});
                  }
              }
              
              // Draw main path
              mainPath.clear();
              local currentFrame = frameBuffers[currentFrameIndex];
              
              local sample = Math.max(-1.0, Math.min(1.0, currentFrame[0]));
              mainPath.startNewSubPath(0, midY - sample);
      
              for (i = DECIMATE_FACTOR; i < BUF_LENGTH; i += DECIMATE_FACTOR)
              {
                  local x = (i / BUF_LENGTH) * width;
                  sample = Math.max(-1.0, Math.min(1.0, currentFrame[i]));
                  mainPath.lineTo(x, midY - sample);
              }
              
              mainPath.roundCorners(CORNER_SMOOTH);
              
              // Glow Effect
              if (GLOW_EFFECT)
              {
                  g.setColour(Colours.withAlpha(WAVEFORM_SHADOW, Math.min(1.0, mag)));
                  g.drawPath(mainPath, bounds, {"Thickness": PATH_THICKNESS * 2.0});
              }
              
              g.setColour(WAVEFORM_COLOUR);
              g.drawPath(mainPath, bounds, {"Thickness": PATH_THICKNESS/2});
          }
          
          pnl_Osc.setPaintRoutine(function(g) { 
              drawOscilloscope(g, this, magnitude); 
          });
          
          // Timer Function (Buffer copying)
          inline function onTimerCallback()
          {
              BUF_OSC.copyReadBuffer(TEMP_BUFFER);
              
              for (i = 0; i < BUF_LENGTH; i += DECIMATE_FACTOR)
                  DRAW_BUFFER[i] = TEMP_BUFFER[i];
              
              updateMagnitude();
              storeCurrentFrame();
              
              // Skip frames to improve performance
              frameCounter++;
              if (frameCounter >= DRAW_EVERY_N_FRAMES)
              {
                  pnl_Osc.repaint();
                  frameCounter = 0;
              }
          };
          
          timer.setTimerCallback(onTimerCallback);
          
          inline function onButton1Control(component, value)
          {
              if (value == 1)
              {
                  for (i = 0; i < FRAME_COUNT; i++)
                  {
                      for (j = 0; j < BUF_LENGTH; j += DECIMATE_FACTOR)
                          frameBuffers[i][j] = 0.0;
                  }
                  
                  timer.startTimer(30);
              }
              else
                  timer.stopTimer();
          };
          
          Button1.setControlCallback(onButton1Control);
      }
      
      posted in Scripting
      HISEnbergH
      HISEnberg
    • Free Reverse Delay built in RNBO

      I know some users were asking about a reverse delay so I wanted to share one I implemented in RNBO quite a while back.

      Link:
      RNBO Reverse Delay

      Unfortunatley I am away from my Mac at the moment, but I will update this link when I can. If you can't wait there is also build instructions for Mac.

      This project contains three folders:

      1. RnboExport: This is the .cpp .h files created by RNBO when exporting the patch. You will want to drag these into: YourProject/DspNetworks/ThirdPart/src
      2. ReverseDelay: This is a HISE project. If you are on Windows, after downloading you can go straight ahead and open this project. You will see the reverse delay embedded in a scriptnode network.
      3. RevDel3.maxpat: This is the Rnbo project itself which you can open inside of MSP/RNBO.

      Once you open the project and the Scriptnode there is a little write up about the reverse delay (just make sure to click on the comment box next to the xfader to see it).
      dc1d3ea7-7801-4355-8210-3761829f2582-image.png

      Most of the guts of the patch was taken from this generous homie, so shout out to Taylor Brooks for sharing this on Youtube:
      https://www.youtube.com/watch?v=hOX5eg7QCqM

      I recommend watching it and following along if you want to know how the patch works. My patch essentially operates the same but I added processing to make the left and right channels function independently, added a feedback path, and I also tweaked it to create different windowing functions (triangle, Blackmann, Hann, I can't remember the others). You can also tempo sync it in HISE using the tempo sync node, it's easier then trying to do it in RNBO and communicating that to HISE, then to the DAW.

      If you are on Mac, you can build it your own. I am not sure if you need a Max MSP license, but I know you DONT need a RNBO license. You will have to install Max MSP though. A RNBO license will allow you to make changes and save the patch, but I am pretty confident you can open and export patches without a license.

      All you will need to do is open the RevDel3.maxpat, then follow the steps to export it to a HISE project (I recommend this video):

      Hopefully everything is in working order, its been quite some time that I have looked at this project. Let me know if anyone has questions or recommendations, and happy holidays!

      Hisenberg

      @DabDab @udalilprofile @treynterrio

      posted in Blog Entries
      HISEnbergH
      HISEnberg
    • RE: Reverse Delay Faust

      @DabDab Cool I didn't know there would be so much interest. I will upload it on the forum in a couple of days!

      posted in ScriptNode
      HISEnbergH
      HISEnberg
    • RE: HISE Meet Up

      @ustk Only one shirt will do, hopefully @Lindon has some spares.....

      0d94aa62-654e-4c49-9983-0beb3117ff3e-image.png

      posted in General Questions
      HISEnbergH
      HISEnberg
    • RE: ChatGPT HISE Copilot?

      @hisefilo

      Ah I have been unmasked.

      So I have been working on this since the beginning of the year. I simply fed it a lot of information from the HISE docs and this forum, forgot I had it published. If anyone has a problem with it being there I can take it down fyi. Just send me a message.

      I meant to share it here once its performance is optimized, so the fact that I haven't tells you all you need to know. I also figured theres a bunch of users here who probably have their own versions (come on guys, fess up) so it didn't seem worthwhile publishing in the forum.

      My opinion is that it doesn't understand HISE scripting even until this day. It confuses HISE for Javascript constantly. Even after months of training it doesn't grasp simple concepts like the inline function and ControlCallback. (I don't know how many times I have tried to get the GPT to understand this but it constantly gaslights me on it).

      What I find it good for is mainly debugging or writing out redundant tasks. It seems to be okay with LAF as well but that is about the extent of its capabilities.

      As @d-healey said, beginners should definitely stay away from asking it to produce code. It will very easily provide wrong answers and tell you why it is right, so it can lead you in the wrong direction.

      However, if there is code from the forum or docs that you find, something about the ScriptingAPI you can't understand, the GPT is actually quite helpful at explaining it. This is where it performs most optimally, and it is also helpful for checking your code against (but always take its advice with a handful of salt).

      In short it is good for speeding up workflow and checking for errors, but anything more than that is asking too much generally. Its also advisable to know something of the topic you are talking about in order to prompt it with the right type of inquiries.

      In any case hope you all can make use of it and if there are any issues people see vis a vis intellectual property, reach out to me and we can talk about it

      posted in General Questions
      HISEnbergH
      HISEnberg
    • RE: Cost Of Operations?: License Fees?

      @HISEnberg said in Cost Of Operations?: License Fees?:

      You'll also need an Apple developer account which is about £99. And if you want to codesign on Windows you need to buy into the license cartel, although I think @aaronventure found a cheaper solution.

      Apologies that was lacking context, I was referring to the Windows codesigning!

      Just throwing this in the mix as it seems to be a relatively recent article with up-to-date info on codesigning for AU/VST3/AAX on Windows (Azure) and Mac, as well as the fees associated:

      Link Preview Image

      One of the last pain points before launching an audio plugin business is dealing with code signing. The ecosystem has changed over the years, especially on Windows, so here's a 2025 roundup.

      favicon

      (moonbase.sh)

      posted in General Questions
      HISEnbergH
      HISEnberg
    • HISE Flags Definitions

      Just making this post to reference later (I always have a hard time finding this)

      HISE Definitions: https://docs.google.com/spreadsheets/d/1crdLOkfyebQZefBQBJEXMisHs2qPkUafBtBjgVM-ir4/edit?gid=1018116899#gid=1018116899

      PROJUCER Definitions:
      https://docs.google.com/spreadsheets/d/1_1VHwHgDNo2ruV4zDOWTKKGUDnS2SOWEHOwHAZKcNHw/edit?gid=1220927349#gid=1220927349

      posted in Documentation
      HISEnbergH
      HISEnberg
    • The Audio Market Over the Next 10 Years

      I wouldn't usually post something like this but I looked into some recent (2023 & 2025) market research reports and thought I would share some encouraging news. According to these sources, the market for audio DSP is projected to double over the next decade. Obviously AI is a big reason behind this but interestingly immersive technologies and voice assistants take a big share of the market as well (as does DSP).

      For anyone who’s already invested years into this field, or for those considering getting into the game, I hope this can add a little enthusiasm and hope!

      Some highlights:

      Market growth:
      The global market for AI audio processing software is projected to grow from $3.8B in 2023 to over $18B by 2033 (CAGR ~16.8%).

      DSP software expansion:
      The broader audio DSP market is expected to nearly double, from around $6.2B in 2025 to $12.4B by 2034 (CAGR ~8.1%).

      Link Preview Image
      AI Audio Processing Software Market

      AI Audio Processing Software Market is estimated to reach USD 18 billion By 2033, Riding on a Strong 16.8% CAGR during forecast period.

      favicon

      Market.us (market.us)

      Link Preview Image
      Audio DSP Market Size, Share, Growth and Drivers 2034.

      Audio DSP Market is projected to grow from USD 6.17 Bn in 2025 to USD 12.36 Bn by 2034, exhibiting a CAGR of 8.12% during the forecast period 2025 - 2034.

      favicon

      (www.marketresearchfuture.com)

      posted in Blog Entries
      HISEnbergH
      HISEnberg
    • Free LED - Activity Indicator

      Just wanted to share an LED Indicator I put together today. It comes curtesy of a script that I believe @clevername27 has posted before on a VU Meter (can't find the link) as well as @d-healey 's video on LED styled buttons

      For this one I just mapped it to a gain node but it could easily be routed to something else.

      Led2.PNG Led1.PNG

      Enjoy and let me know if you have feedback.

      HiseSnippet 2181.3oc2Y01TajbDdEv5Xzcj5tTWpKebJW4CqHJXsB33HTjCYIAnJ.RkjNewkKJpgcGIMm22pcmErxU9eZ9P9Ij+AN8Ly9xrn0XLmOebYKaX2d5tmddlt6o6gAg9VjnH+PsJUGOOfnU4y0GM2iMq8LL0SqWGsJ55NDasmMO.GEAuToxxGwGpxpqnId9ue2yvNXOKRNIMsm6SsHmPcorbpCN3ePcbNDaSFScU3dqC5Y46012wOFLik0anEfsdEdJ4LLmskz0NFGMSqx556t81lX6I6LwbSycuzdhEYycZ7MasSS71e6jI6zvbqMs2YxVfQ9nt1Tle3HFlQhzprxy7smOZl+0dxI34zH5kND9GlZifYVR9PeGa9RjSUq8Lpi8fT7IRCPhA4n0xRz5qzOkZSynmiZegX.TtDp.XkkJZdKWv7LUMuFJlWIlTEESZEoI8k5irBoAr7Q31ymo2yiQBmfg8IUSQxq1R6uldaefCO1Ft3WQNLD9HSBCyFMpifeTaupUe5SQ6m8fNoaGTqy5cZqw85elx.b1FOiFgf+4hCBH1HlOhMifNEGApEwchPt91wNj5nKiYHJCY4G6Xi9w3HFBGgH3HpybthtjfBIAwgA9QR8.ZDg8li7AEFhlD6Ywn9dHCg9v72qiNsWmdHxUvJpNhvr1n1Zbam65EVE72f43JbHhg1G00aJ0irgUHA1NDLz+xejXwLfk6ZJ7NvyokG0UnePrT7ZJg012Mv2C9v3IpL8jZ6oJOeImr52GIhx3x1cxD9b8D4HbdDhkJXmtsa8hKF1ZbWPnFar6dH.P5PrvyQCAyMksQm1u+3i6c1QWbXq1i6ODX1D8WAA1YagDGReM.cQt9.jQ8lB1iSblvG+hQi6Nr6nditX7wvuOt+IcDyVCEYmMmaejHXCUHb5DOnaWNylaCbyMaPf1wgg.XfdNmun0pFRlhrhCOA1MbNIQwEoNr.UoYRrKQfBCkKkXZOAPPzQeeOo8Egl3GpX0qUkuG3.7bTLUXY4Z9libCE2gLAbPPrq8AWTGHxSnZJO7HvW5ukBkN9Wyyjw2gU8D3azFOgxHtx7bJdFynSmcWDoYhaA0ygaLYN84lAQnFCvDpKzZcDD7BoYpg9o0phfGGeKrSBQX1NECdfgXuoDCIs57EMDnuQC9TwkHjvhC8PRKHZCW5qKQ8.uuIam+RpUQjIyRWzzs3b2SkYiHFNjGv5Y+wy5E5D8WPFfVgXBwm0PqiRjCdK6EiMAFZlQol5Za.1i3fxy.Xz0wgFDQPWSYyP1y8vtvZW3fTDAfLOE1XiHrAPXNaneLCvCiT7vXZ1Zk6PhgEIDrFwcDNgu1elermcjQ1xiyjmenK1g9uH1hDpEfkhwJKBOb4sjgpoNfk4LIdodteZ8aLoR2RtB4wfPx.YFs+FpeLOU2zPrMkmMHZF11+ZQnCmqofpQDAqRomxAliR39PnTAiWl52wQ3VNAyvFYTlAQF7kz10pivur44nmhZxeaS4aRUVxy6VkW5.kcvUYSgJabN3xHz75.sM2YaNQSIwMUHxBiImmBoS2XBX3INFFu7lZoQIJQRKggcqmOvtmW.Y644QxQtO.HScKVt+WDwLO+CAsJpsFar0B3+cELLaVBZjPLgEInuY5GEAj1DtypvuzA9+OKuns9YgIKnNyaCTrCwW+wDTpiZJioeC+GUYb.PTESariykfOcdBFH+RVjOOz8DxDdAP4ElHJlQtCKxZXXVaODpfLC4X8sKjnNwTYBH3WkcPd5jppzLFFlvfXFRz.cBxPQC+875HRWK7G0hKx4dOw3uAQbfjzkw756qTdUB2het3TOTYpGV1TOTcpG9dl5gkO0od1sBBblKOc7FmklU.mf0EpSprCTKvS87Ue8EpYr1dKp0g2AsNLWqCKUqB0V3HPnbd9IfPE1HtaqnqhQDlnAAlnDcvMleNsvQ1PTjYs8xJbv26LeFoO3PW8mptZUXS6lCMYRoiwqYOz2wAzYYCKmsaQPCuX2KIPhOQIlYLBMeUriN82cGcpMbZIagPgQeuddTV+.h26pMTsj9Nf299dcvLLuMvDZ.eAjPFkaBU5PtBZBW1T3p5cHQuh4GH3MoYEsJ+NlXz0RaYjWgiFEZL72qqtco8Z0d6mq9wLBOXMmxKNPohUf7id6+V6s7AxIyo1XcIUsE6eE5bV1EWw1oEoaxZuqPOrbWSuHJat5kR7QqG66pI9k5CnLqYkaiKUhMB6a+RXiI2LwZ5xxvxMvUzO7e9I3ZHdb18HQcCbHGkN8etddGt2x0Ioo0g3fK.S+.0lMS0EqjKbpm2Ufi+.H+T3MA4kuyqRyaeUtxc1SPTK9CZu0+ft.lenajhs9G1F4WnCoM+UxDkcPNE54KjB4n0OK1cDjg0h.lGztfC+jnJKwOyP9cC92biXDzJr3i2BOICZx+tRxfloCpBCesDF9L8e.eEQbAVBD3OJ9F5qyEcDAZRgiOleLtw3f67MF22hAlvXnu2H9kDZpp4QDW5X3.unBTugDMKUhlEyKwh8JpZIoBbwghCAnPguGePJwlpDA2lBJC9tflNkpbr6+4655gAmhQDXka2OxB.FNNqhpChgpMEQLlpBlStoJ4iwg1vdn0skqbk6Vtx2y8l+nGb2a9uAJ6nvYpqlZixyT6BG14.U5kkIeBN1gkRsXn2o9d9Ay78nE1nGRfLFSmRJ3+T5BpEiAsPlS4qNXHwgfiTBG+yGbB0ifCAbhbOwByO3+LGkte8mzklKhmu.8a2xEW9+qKW7tG8Ao.eXuK905Pp3lHwVI5Wm8xOE0.7oXNbwVg9WXI6ylGz+XAEXc6I96.uJz+.7MxTSz6sJX5BGYbgkUQUsffMuuBt48UvstuBt88Uvu49J3N2WA+12uf7SzaEy7StLAnxlAcEWbQkJxhZDgIZ+OvkIPQf
      
      // ========== LED ANIMATION ==========
      // This is mapped to the Master Gain module, but it could just as easily
      // be repurposed to map any other function (modulation, MIDI event, etc.)
      
      //Timer
      const var t = Engine.createTimerObject();
      
      const var PnlAnimation = Content.getComponent("PnlAnimation");
      const var GainMaster = Synth.getEffect("MasterGain");
      
      const DECAY_RATE = 0.9; // Decay Rate
      const SMOOTHING_FACTOR = 1 - 0.75; // Fixed smoothing value
      const HYSTERESIS_THRESHOLD = 0.0; // Fixed hysteresis value
      const SPEED = 15.0;
      
      // Current Values
      reg curLevelL = 0.0;
      reg curLevelR = 0.0;
      reg smoothedLevelL = 0.0;
      reg smoothedLevelR = 0.0;
      
      // Last GUI values for hysteresis
      var lastGuiValueL = 0.0;
      var lastGuiValueR = 0.0;
      
      // Define two colors for interpolation
      const lowColor = PnlAnimation.get("itemColour");
      const highColor = PnlAnimation.get("itemColour2");
      
      inline function interpolateColor(low, high, factor) {
          local factor = Math.range(factor, 0.0, 1.0);
          return Colours.mix(low, high, factor);
      }
      
      // Cubic interpolation function
      inline function cubicInterpolation(start, end, factor) {
          local factor = Math.range(factor, 0.0, 1.0);
          return start + (end - start) * (factor * factor * (3 - 2 * factor));
      }
      
      // Panel Animation (Ellipse with dynamic color interpolation)
      PnlAnimation.setPaintRoutine(function(g) {
          var a = this.getLocalBounds(0);
          var normalizedGain = Math.range(smoothedLevelR, 0.0, 1.0);
          var currentColor = interpolateColor(lowColor, highColor, normalizedGain);
      
          // LED Effect: Outer gradient shadow for LED glow effect
          g.setGradientFill([Colours.withAlpha(Colours.white, 0.5), a[2] / 2, a[3] / 2,
                             Colours.withAlpha(Colours.black, 0.2), a[0] + a[2] * 0.375, a[1] + a[3] * 0.375, true]);
          g.fillEllipse([a[0] + a[2] * 0.05, a[1] + a[3] * 0.05, a[2] * 0.9, a[3] * 0.9]);
      
          // Inner LED glow
          g.setGradientFill([Colours.withAlpha(currentColor, 1.0), a[2] / 2, a[1],
                             Colours.withAlpha(currentColor, 0.4), a[2] / 2, a[3]]);
          g.fillEllipse([a[0] + a[2] * 0.125, a[1] + a[3] * 0.125, a[2] * 0.75, a[3] * 0.75]);
      
          // Center highlight
          g.setGradientFill([Colours.withAlpha(Colours.white, 0.4), a[2] / 2, a[1],
                             Colours.withAlpha(Colours.white, 0.1), a[2] / 2, a[3]]);
          g.drawEllipse([a[0] + a[2] * 0.125, a[1] + a[3] * 0.125, a[2] * 0.75, a[3] * 0.75], 2.0);
      });
      
      t.setTimerCallback(function() {
          var GainLeft = GainMaster.getCurrentLevel(1);  
          var GainRight = GainMaster.getCurrentLevel(0);
      
          var peakLevelL = GainLeft;  
          var peakLevelR = GainRight;
      
          if (peakLevelL > curLevelL) {
              curLevelL = peakLevelL;
          } else {
              curLevelL *= DECAY_RATE;
          }
          
          if (peakLevelR > curLevelR) {
              curLevelR = peakLevelR;
          } else {
              curLevelR *= DECAY_RATE;
          }
      
          // Apply cubic interpolation smoothing
          smoothedLevelL = cubicInterpolation(smoothedLevelL, curLevelL, SMOOTHING_FACTOR);
          smoothedLevelR = cubicInterpolation(smoothedLevelR, curLevelR, SMOOTHING_FACTOR);
      
          PnlAnimation.repaint(); 
      });
      
      // Set the timer
      t.startTimer(SPEED);
      
      posted in Presets / Scripts / Ideas panel led animation
      HISEnbergH
      HISEnberg
    • RE: LAF Collection for everyone

      Draggable AHDSR Component

      I've been a bit of a mooch lately so wanted to contribute something myself. I've been revisiting an old script posted here a while ago (can't find the original link) on creating a draggable AHDSR with a panel. I really like this script but always found it was a bit difficult to bring to new projects. I didn't do much other than organize it a bit and make it so you can attach the paint routine and mousecallback to several AHDSRs, and I hardcoded some of the values. Still a work in progress but here's the script:

      *Edit original script, courtesy of @ulrik :
      https://forum.hise.audio/topic/4541/paint-routines-adsr/65

      example.gif

      HiseSnippet 4331.3oc6b0DaabbEdos23P4TmDjl3dbhPa.YLkL2kj5mn3JIqerEhksfoyOFBBIK2cH4ZsbWlcWpehiQywdqmysbpG6kVTfdSnWJPQNjhjC8TQQu0dnHW5019lY1el8OpkTxNxokGj3Nyady68l26MeyOb2x1RE63XYKTXh6eXerPgWPr4gltcWoqhtovFqJT3hhJc0brEtwg8UbbvZBEJb9aRprPwKHP+7sKdCECESUbXQBBumktJ9158zcCKcqkdGcCi0Uzv2WuGG00WZCUKyUrLrF.Bx4EqJzWQcWkN36nPH6bhB2RwoqPg2Tb910letYppTSaNUrpZ81Mlcl5JR0q0PAOes1JRp3YaHqBB4yslltqkcSWEWriPgKbCKsCa10ZeSVG7d5N5sLvjGjDZB8Lq30sLzHpHoTgU5panskuExQ.X5Vg1qyyrW+PwM00zCJOzt8RzJPgsf2.V3bQEuyGQ7j3EupbhWJhTANQ5BLQ5kEapZq22MrFh7bIwMLcw1sUfwIdQgQqv4lsj3JV.EltS2SYW751vCAsnzLUqVAUqQ0xKLwDS.CVNtn8TrQ6Z1x4CWybOz0Q9MtC1cYCiUr502xDd1ozj.QDZlDZaXK6qXhMtos0f9NCsw8MMR1Xr4ddMEAMl5v50zMszFXn.VVnoKS7ai1vcMsZEzoauCnLlfKlC3tgQPufMr5im3QEmn30tFZpT+Pq51KuN58V9dar7Mt8ZMQuAh455LzlEJD2V2D+95ZtceOEiAXpJHOc0EPHdhfPJil5eB1mFfnZIHZcHbZMSEvSQCgXDIs.4+w6tikHR24vSUHQIjJvmUWkoxTBqdv5qOizLUWs1Bwo8VV6gsCHkQ6JqrN8SDhUTc02CynTxWLqdv7M7XLJIwb7VJFmiPstYBlSnVpZHqOtw62AbaPT+FcyNCkXcSCvbiZOvD5SKSDD84BNVDF3Tp7DEezDEIBfgkphAxbPu.mw9J1NXHdqjeH0zFXyNtcQWCMG3BSaUaKaTIchzu.RG81gsGd7pWsLiHudnHqK5Pp2yWuHx+CkQOjwnGBLZN3eAL.wwkvOTFMc+ANcCjvs0QuIZNzUQObmx7b+wbeOLfi0VJa7oFH7wDieTizBG+3wMMrZAJ2VjbHve0McQ2yZfKX4GoAGubKaY6MxPZ6pXHkWOBYLSmtoF9.nJNy4Fjh.i2TRfnVL9fBWhMugP+QGZWPsJ5sQkb6pCi6Wmm9s02orOIAzFZ886W8EhTWKarxtAEAFThQsHoK3aEQbCXtM1cfsIj8yWu1GXKQfHYQoolnCCdU1kqxag06z0sTYzTHoPJ1iiBZBK9la0tsC1EnHRJsv5M7SGBjDM0XHM8UzzfPOfhFgE1xx00p2VAUIWMrNGCKRWVZePPkA2TOFTFBm33vAgeUqEmD25g9gLdkPmkfT1jK65BXSlrBZxaAXEH+eUrpxgjuzbfiK3KR958vFXEG7jbrfD0bWaMrMgMvjoxv7oUP0qfZDgHHD.HHLrY6vAQN55yMmoJL96h2RwePq+zpPmaWxOJi8Whqssx9joNoyxgTGXuG1qx9SCRts6cv62bPKJm7rWUfA+oBr9SEyjOEp5zM76FhmI0p+ln81t5NPZAul4U+daKsC5mB+q9NnE4xPn0hLN0M53T7tpLTUIInTBWJGxazacB3TcdNsfuk3iGnnYSlg69VkN.bWj45sqQF0FIYM76yrSYttqB5fJf.6a7.ONV9wsoEGjO022bYPyndnLK8U4L0x6DH5jHIhTmGNGkI0HBprWUmF1QOAmxJ3OSQzgLLwSwKFf4kQN72fNXVvzkSCFmWX8TFbGeKTicNdwuwNCMdgpB4NdJhXMjVsSz3bZZXMEWkoAFfUcIYSfuEYXQAxXPfbPRWeCqAlZNkjhxkNS2B2Q271JGhsK4ZO.6WcmoaCXNAf1k7y2WZxVcXPqlrbHUPFeVgbzo6h6EmRxzTbnX4gfv5JV1nJTYNurWNJ+4..Gk+vn3977uR3bQom7zsqkCF0hfUNj87PmihACkFnsF7f0RGqkNY55vAxtDftnEin1w.WWF8VIplGmdD7YnPOgVGvbO.jGjb1S4MYcVTeXH0RCgZJW2DLrSaqX1AWpE3AGj2a+f1QR4D5WmTDocGOaNjiMcyfMIxSkfsrw80LLz66fKsMQ3HbNjY7eGhnkSCb6iSy8vPoEfGc+tXSDcLiHNzwNXwHt1VFg9LwGbecO3YwcG7.yLnca8CVHhuaZQ.t3CbiGfER95fPTZRFzYx2AbJRQ0MerV1J8H67BX8o3d1NlztSx1PpLXvhjQoDEIy1AfdRvic3vJFQHhaZfPgZfyOyF.8wjHsaLI3tyUPOmISJRrAiqyoNWEM4aATeUlzd0TMqDWikMz6Xh0tOXMKQ4REJfM5Dhv+2GbIpB9ESpBnurwZ2f5tMY7E0LBqfYSqAPZkUfX1V.1xSxRY1TktTFpmYlqlARf4.qxGZkaWJNPaPQXqCg4YV9Ys06f3mcK80xDVeZKmIBAouZFtvQroCc4FUiTbz0nvk0LskoDl7HLoPJKWKPo8WwVXIgsCuGYY.rnk23MPuN6YvStSlYTTMfIxbHqPRpZ0pSWMY3CjleCsCROvrGwe8CfFy5ogQ0CBn5vj8gqlE55IQrrvIa1SuLR5sa+A9ojTZ4TJXCVfdkMcWY5rFdk5oJkSNeAwDy31a6a2JGmlDBA8SnUl19ERkHlg1yMOZUONdAXCHOQn7.dIil.QZZfAwyNPmHOlY3PXoJuMJBkLwLSxKmZ+cbJXTkxmPXvNOrSZn1qGOroTxx61F2mrYRk3xkGQBectPsThsR1OSIk29Hd3rpgt5tPV5O8SQCMdNQKxQrw6X1hlWyIwFCh7fybS.8CYxA19QPBB4mpflnJcVerafQzFEO7l17XSijGG6.MxeGJIfOzCwXbGK6dJF5eBVqTJQ3IhyBGH2y2NEzCYsSmbe0YecW0tIP4MzQFUXNYT02JyvV1XrSW81tqZsuYnegMYFrUHi8oGz7nrCkRePZ6Y1g.WLtcKtMAHCvPE5a9AWiLuX4EFmtSsKAfuVoLZ8iyLuwojFWMeZb0SIMVJecGMUaX28fws6pdrF3iQXGqgGeXZo3lKktadFBfb9rVxivfS18zwnpCQojycr6oUb5r4yvL6ojW6re2GmVKeZbsSIMt1ouqesQx0ud9z25iPhhr6ow20u9HoTMxmR03jGO2XzUpGOFKhmd5vqv1hmfUwORqd2xb4asZy6AXLb73SIU+6.QED0f3cBkYrr73q1e+t5..D1Z9Ia9Df3zgBgyEfKzgsyTDi1zorfdtirMq0yG+7i4r+.nK+VwNR4zVdOIoXj1r8C2gtZFektbDxi13icCBRYWBB1pfneI1pte8HGRZT1j6yTsX.VvQ.QLizfyl65g2vkLIlseMQ2OkrnUwEF2aMvkg3WtRsJ0qznxLUlsxbUlOE1lwpCB1sykcbz63s8QL+UGNBndG6x7N1kc6B1M90SfMyfm9RxGrruHVJTX2d2cpf71HwL2uPNAlG7+tCG7uWbNswAoiJwwKeBYTvmFIGIF3rOQ1nO+jCPrnEZMEHDkV9PYW92usGwIwgQifxQugDd6pXI+jNkRa0jb2HBeCUDCQD1R21ReUJjuzb1g7tXQt8ljmoilcL0jrDy3xFrLvNHcSlM8lrkmNB1zLS48HNO5bluKtIMddN1N2S0i.aWx7+Q1M4GOwDSvMWwcrbw20rT4IftApCEup1sSsNONafsSsZxUxzdXMrj4fdsv1AyG4QnPgKD8tLJl8cYj+pVpxt9BbDZYtgot6c6iMy5BXJ3cmGDDJ7RdREPpK8VOdYua8XSCcMrsftF4tY5c0CYWZChFJIPkdu6d5W7U1FKIjCN8pQ4zsAebinrZoZ0t3Q4gUW1mUj6ORTdbzq7K+M4RbdEedPu6II0qiJ7aWLWL5k8Yj2cWIl44a9ZoiFI13cuWhwl+laywwJuB4FpDSw9xu7aVTXTF5oVnT3D5Wcy+znwoPmH4PN8u+Ovme1GM1NQbrp+F+8+H9ubkQ2IRNhhIH7y+5wzIJFi9ra+GFKmH4XwX+ywyIJtZc3udrchhIQ8u9+XbchhxoO62+u9yKJ7tarJrtExcw1K8DjxpO11UmjMrvp38zUwralcQwUwN65Z0Wnv4BtjyBElfIA+.+6sMYlVp.bEQxbmqv.vis8ugxBGveS6Oj+g8IG3UPAGYuTW5IbETxRCVx+5Z.8qnzLyN6rxRMDBO5XxOAf5xyWe9YlUd9FBb2pBVMyNmz7UqNWUtZXULmzbyVu9byA8Emt8BYoaSH5gKP5DnNBOXo9Jj8jlqGyxnkpdmP8BTbXtYq8C.rIT3EEIHMBKHGVLVOUu97MpMCYtq.Q7Ri1TVb1me7Rg1mk9nk5YoA744Do+dJ5ob.eN.GWbex0sj+GpQOcMMC7VVN5j41C4zuXI1ggCydKh5wTNxfFSJPtD1maCsPxg+bOkZnFbTqnpJSjtruHQoWfo+jvJU8Vjm4+co7fi3sHvmXVju3y+7e2hb5s1MDxv9HHezXo8WJun.xXD9yZ+DdD94DI8uvorxkF7jLzviLdBqgWTjJDm1duIANkgmKLDxDjhhdj9rqSaRXdY429wOgGUKJ5IBi23ZwQDBZFisfyarrRT58FfeMwvMdXKrM41BozAK3qNmW7mj4H2ecwSY0JU3vY4w9wmszpLQG8iRuwQTL6kdJCOZtpUkaTEPAk.dTcYo4qMu7nBOR9TFdTlVsmUwGIeVEeTlV5wGfj7yP.jxk5eo7tD2yZHjNgZWZK99LGDoSnCbx8E3YBLRmvQ1jaiwYPPR4RGKNh6wxY.TRmP8J0M74L.LorUqj+5+eIwfeC77uLBHuxF7pfza7uA.H+J+MAo3PdWsSs2PA4UDeYwsH2ZtzkwykhLJH7DQF8duN7CDWqcarpan.dAw0+fmLuDG369Ky59KI1DFoouYCnc9qQeF89J6gQ2DC9.DimzPdob7U48kxQ+b+R43tptP2eeaESm9VNQXbSbO86CNqN7E9tN30swe78Hil7kuhE45CmRUe6hqCJYpsooh6.apawx8rFX5FwM37C6c8gzX9t93Bm4dWe7LPvdjWGIuHSFunH8vMoh1yKReobD0wcSKSq9csL0U4ko6g8tqJ7ElpzyMID+wDElCm+HeXDye9ebvq82VexY4Qg8wctbLLRbmulOTEtyJye9Vty8ZMUqMYXYFGqszvs1h4ziHXgJzP7yd49isnkydB3KvfHeV098h93lOyZ.urOVzyplvgB+37e+F9A6pA0YSEHiKYMD2YPulvr9pXn2MMwFjK0QgyQl4l8bUxyro8M0nOPNEbuJkHOWvqRI+J4Uwq3CwgflIDhyqRetM.a9rBBGoTg3DozXsPN0VDozUwtCLixZVQQnhXJVGLEbz87K4WnLegaoXFgYvyQ3zl5Gvu1B1OT8lXPy0tqiJXXH1Y9PusFX3v9QvKw2vvhk4K9VJ1ZvXn5Sd.YO2+GP1SL.YxOgAjQuxEI.jQu9DQ.jAk8Qo.H6Hx8hgCPFcCR3AjQuqJw.jQt2IQAjQuCIee.P1Exm6vvCndZAN6opvdx.p8TUTOwf1dJ6Ebx.v8TUX+eYvb4dNI.X.5L8NBdEQ.fhLhNTh9tYr7oAx3mF8QOEUaqOz+2pAXgddZIfdaReE6VTbSxyHoX24R3SO.H0GppFkUIZn731vZiaCqOtMrw31vYF2FN631v4N9FRv4t7.WqdrXC.u+VqQuNpEJ38NohDlH7espGt3J
      
      Content.makeFrontInterface(600, 350);
      
      
      const var knbs_Env = Content.getAllComponents("knb_Env");
      const var panelGroups = Content.getAllComponents("pnl_Env");
      const var envGroups   = Synth.getAllModulators("Ahdsr");
      const var knobGroups = [];
      
      namespace Envelope
      {	
      	// ----------------------
      	// LAF VARIABLES & Colours
      	// ----------------------
      	const var LineWidthValue   = 2.0;  
      	const var BallSizeValue    = 3.0;  
      	const var FillEnabled      = 1;    
      	const var LineEnabled      = 1;    
      	const var BallsEnabled     = 1;    
      	
      	const var BallStaticColour   = 0xFF6160D3;
      	const var BallHoverColour    = 0xFCCFFFFFF;
      	const var activeColour1      = 0x956160D3; 
      	const var activeHoverColour1 = 0xFCCFFFFFF; 
      	const var inactiveColour1    = 0x106160D3; 
      	
      	// ----------------------
      	// Knob Grouping
      	// ----------------------
      	inline function sortEnvKnobs()
      	{
      	    local numGroups = parseInt(knbs_Env.length / 8);
      	    for (i = 0; i < numGroups; i++)
      	    {
      	    	local group = [];
      	         for (j = 0; j < 8; j++)
      	         {
      	              group.push(knbs_Env[i * 8 + j]);
      	         }
      	         knobGroups.push(group);
      	    }
      	}
      	
      	sortEnvKnobs();
      	
      	// ----------------------
      	// Global Panel Paint Routine
      	// ----------------------
      	inline function pnl_EnvPr()
      	{
      		// Determine group index
      		local groupIndex = -1;
      		for (i = 0; i < panelGroups.length; i++)
      		{
      		     if (this == panelGroups[i])
      		     {
      		          groupIndex = i;
      		          break;
      		     }
      		}
      		if (groupIndex == -1)
      		     return;
      
      		local w = this.getWidth();
      		local h = this.getHeight() - 1;
      		local v = this.getValue();
      		local offset = BallSizeValue;
      		local lineWidth = LineWidthValue;
      		local padding = 5;
      		local bottomPadding = 20;
      		local slot = (w - 2 * padding) / 5;
      		local x;
      		local db;
      		local obj = [];
      		local names = ["Attack", "Hold", "Decay", "Sustain", "Release"];
      		local knbsOrder = [0, 2, 3, 4, 5];
      		local knobs = knobGroups[groupIndex];
      		local p = Content.createPath();
      		p.clear();
      	    
      	    // Draw envelope curve 
      	    p.startNewSubPath(padding, h - padding - bottomPadding - 0.5);
      	    x = slot * v[0] + padding;
      	    v[1] > v[4] ?
      	         db = (h - 2 * padding - bottomPadding) * (1 - v[1]) + padding :
      	         db = (h - 2 * padding - bottomPadding) * (1 - v[4]) + padding;
      	    p.quadraticTo(x / 2 + padding / 2, (h - 2 * padding - bottomPadding) * (1 - v[1] * (1 - v[6])) + padding, x, db);
      	    obj.push([x, db]);
      	    local dbA = db;
      	    x += slot * v[2];
      	    p.lineTo(x, db);
      	    obj.push([x, db]);
      	    x += slot * v[3] * 2;
      	    db = (h - 2 * padding - bottomPadding) * (1 - v[4]) + padding;
      	    local ddb = db - dbA;
      	    p.quadraticTo(x - slot * v[3], (db - ddb * (1 - v[7])), x, db);
      	    obj.push([x, db]);
      	    x = slot * 4 + padding;
      	    p.lineTo(x, db);
      	    obj.push([x, db]);
      	    x += slot * v[5];
      	    p.quadraticTo(x - slot * v[5], h - padding - bottomPadding, x, h - padding - bottomPadding - 0.5);
      	    obj.push([x, h - padding - bottomPadding]);
      	    
      	    this.data.objects = obj;
      	    local area = p.getBounds(1);
      	    
      	    g.beginLayer(true);
      	    g.fillAll(this.get("bgColour"));
      	    g.setColour(this.get("itemColour"));
      	    if (FillEnabled)
      	         g.fillPath(p, area);
      	    g.setColour(this.get("itemColour2"));
      	    if (LineEnabled)
      	         g.drawPath(p, area, lineWidth);
      	    
      	    // Draw those balls
      	    if (BallsEnabled)
      	    {
      	         for (i = 0; i < 5; i++)
      	         {
      	              i == this.data.hover ? g.setColour(BallHoverColour) : g.setColour(BallStaticColour);
      	              local bx = obj[i][0] - offset;
      	              local by = obj[i][1] - offset;
      	              bx = Math.range(bx, padding, w - offset * 2 - padding);
      	              by = Math.range(by, padding, h - offset * 2 - padding - bottomPadding);
      	              g.drawEllipse([bx, by, offset * 2, offset * 2], 2);
      	         }
      	    }
      	    
      	    // Draw label when hovering over control
      	    if (this.data.hover != -1)
      	    {
      	         local suffix;
      	         g.setColour(this.get("textColour"));
      	         g.setFont("GlobalFont", 12);
      	         local paramName = names[this.data.hover];
      	         local data = Math.round(knobs[knbsOrder[this.data.hover]].getValue());
      	         this.data.hover == 3 ? suffix = " dB" : suffix = " ms";
      	         local label = paramName + ": " + data + suffix;
      	         g.drawAlignedText(label, [0, h - 20, w, 20], "centredBottom");
      	    }
      	}
      	
      	// ----------------------
      	// Global Panel Mouse Callback Routine
      	// ----------------------
      	inline function pnl_EnvMc()
      	{   
      		// Determine group index based on the current panel (this)
      		local groupIndex = -1;
      		for (i = 0; i < panelGroups.length; i++)
      		{
      		     if (this == panelGroups[i])
      		     {
      		          groupIndex = i;
      		          break;
      		     }
      		} 
      	    local w = this.getWidth();
      	    local h = this.getHeight();
      	    local v = this.getValue();
      	    local sens = 200;
      	    local padding = 5;
      	    local bottomPadding = 20;
      	    
      	    
      	    if (groupIndex == -1)
      	         return;
      	         
      	    if (event.hover && !event.drag)
      	    {
      	         local closest = 1000.0;
      	         local objIdx;
      	         this.data.mouseX = event.x;
      	         this.data.mouseY = event.y;
      	         local tdo = this.data.objects;
      	         for (i = 0; i < 5; i++)
      	         {
      	              local diffX = Math.abs(parseInt(tdo[i][0]) - parseInt(event.x));
      	              if (diffX < closest)
      	              {
      	                   closest = diffX;
      	                   objIdx = i;
      	              }
      	              else if (diffX == closest)
      	              {
      	                   if (Math.abs(tdo[i][1] - parseInt(event.y)) < Math.abs(tdo[objIdx][1] - parseInt(event.y)))
      	                        objIdx = i;
      	                   else if (objIdx == 0)
      	                        objIdx = 1;
      	              }
      	         }
      	         this.data.hover = objIdx;
      	         this.repaint();
      	    }
      	    else if (!event.hover)
      	    {
      	         this.data.hover = -1;
      	         this.repaint();
      	    }
      	    
      	    if (event.clicked || event.drag)
      	    {
      	         if (event.clicked)
      	         {
      	              local KnbValues = [];
      	              // Get the knobs for the current group
      	              local knobs = knobGroups[groupIndex];
      	              for (i = 0; i < knobs.length; i++)
      	              {
      	                   KnbValues.push(knobs[i].getValueNormalized());
      	              }
      	              this.data.values = KnbValues;
      	         }
      	         
      	         switch (this.data.hover)
      	         {
      	              case 0:
      	                   if (event.shiftDown || event.rightClick)
      	                   {
      	                        knobGroups[groupIndex][6].setValueNormalized(this.data.values[6] + event.dragX/sens);
      	                        knobGroups[groupIndex][6].changed();
      	                   }
      	                   else
      	                   {
      	                        knobGroups[groupIndex][0].setValueNormalized(this.data.values[0] + event.dragX/sens);
      	                        knobGroups[groupIndex][1].setValueNormalized(this.data.values[1] - event.dragY/sens);
      	                        knobGroups[groupIndex][0].changed();
      	                        knobGroups[groupIndex][1].changed();
      	                   }
      	                   break;
      	              case 1:
      	                   knobGroups[groupIndex][2].setValueNormalized(this.data.values[2] + event.dragX/sens);
      	                   knobGroups[groupIndex][2].changed();
      	                   break;
      	              case 2:
      	                   if (event.shiftDown)
      	                   {
      	                        knobGroups[groupIndex][7].setValueNormalized(this.data.values[7] + event.dragX/sens);
      	                        knobGroups[groupIndex][7].changed();
      	                   }
      	                   else
      	                   {
      	                        knobGroups[groupIndex][3].setValueNormalized(this.data.values[3] + event.dragX/sens);
      	                        knobGroups[groupIndex][3].changed();
      	                   }
      	                   break;
      	              case 3:
      	                   knobGroups[groupIndex][4].setValueNormalized(this.data.values[4] - event.dragY/sens);
      	                   knobGroups[groupIndex][4].changed();
      	                   break;
      	              case 4:
      	                   knobGroups[groupIndex][5].setValueNormalized(this.data.values[5] + event.dragX/sens);
      	                   knobGroups[groupIndex][5].changed();
      	                   break;
      	         }
      	    }
      	}
      	
      	// ----------------------
      	// Global Knob Control Callback
      	// ----------------------
      	inline function onAHDSRKnbsControl(component, value)
      	{
      		local groupIndex = -1;
      
      		// Determine which group contains the triggering knob.
      		for (i = 0; i < knobGroups.length; i++)
      		{
      		     for (j = 0; j < knobGroups[i].length; j++)
      		     {
      		          if (knobGroups[i][j] == component)
      		          {
      		               groupIndex = i;
      		               break;
      		          }
      		     }
      		     if (groupIndex != -1)
      		          break;
      		}
      		if (groupIndex == -1)
      		     return;
      	   
      	    local knobs = knobGroups[groupIndex];
      	    local envelope = envGroups[groupIndex];
      	    local panel = panelGroups[groupIndex];
      	    local attributes = [2,3,4,5,6,7,8,9];
      	    local panelValues = [];
      	         
      	    // Assign the controls     
      	    for (k = 0; k < 8; k++)
      	    {
      	         envelope.setAttribute(attributes[k], knobs[k].getValue());
      	         panelValues.push(knobs[k].getValueNormalized());
      	    }
      	    panel.setValue(panelValues);
      	    panel.changed();
      	}
      	
      	// ----------------------
      	// Assign the Global Panel Callbacks to Each Panel
      	// ----------------------
      	for (i = 0; i < panelGroups.length; i++)
      	{
      	    panelGroups[i].setPaintRoutine(function(g)
      	    {
      	         pnl_EnvPr();
      	    });
      	    panelGroups[i].setMouseCallback(function(event)
      	    {
      			pnl_EnvMc();
      	    });
      	}
      	
      	// ----------------------
      	// Assign the Knob Control Callback to All Knobs in Each Group
      	// ----------------------
      	for (i = 0; i < knobGroups.length; i++)
      	{
      	    for (j = 0; j < knobGroups[i].length; j++)
      	    {
      	         knobGroups[i][j].setControlCallback(onAHDSRKnbsControl);
      	    }
      	}
      }
      
      posted in Presets / Scripts / Ideas
      HISEnbergH
      HISEnberg

    Latest posts made by HISEnberg

    • RE: Audio FX - Play an audio file?

      Cool just to confirm for anyone else who ends up here, it does indeed work with the file_player in scriptnode

      HiseSnippet 1448.3ocuX8zSabDEeVCiSvoIsopsms5IRUDxFLjf5gXL1t0sAvB6PiTOfF1cLdj2cls6NKXmnHkC8P+Vzy8qP+1zC8d9Fz9dyt16t0FJXQqQB44OuY9898dueuA5Fnr4ggp.hUo9S74DqOh1ahTOb+gLgjzoIw5SnsGuWjiPcTjtOOTSZLwmEFxcHVVq7M3trVaUh4yGdQClKSZySmhPNQIr4uT3Izoy1s92Kbcayb38EdY1cs5crUx8UtpH.QqPqP7Y1iXmyOjgaq.k7srvgDquht8laYWy4YNat416tiMaG9tCXCFTcKmZ01446VcqcY0d9N7JaSrJ1xQnUA8zLMODNzFJmI8FptTFeAmHBEm4xwAUI8faNdZx9CEtNcmROgDh0pcSIqUhIqOidfvQLa9rjFtP4TKxRZVEtNHU8V.IqLPZ0XH8XZO6.guNcEDOOf1Qp4ACXPrIKTh2Kw5Oo6qfMH0a3wFwaG.ClYv5aVoxSKC+5IecoRsjmKj7MbULGSRQagKOD1ppqR4tNtiRChj1ZgRVVIOTo4GIW+Ikdao0J8tRk+mKMXvBWCwRfx0kGrvkwblfqyv0kQdmwCdZ4KXtQ7YaD3n7DewaFwaGSMY1nR1QJzG4ySF2V45fDJ984CSjDtEBXERPHb2ZS35ySBWFx7GXWvGnB7HBGLEJ2bUIFmIakkCSyHVeI8scO9nuq098Os8QurYqie2IBkKWW9PkHjuwkrKHAL44bvoCfHM0BM0LSKoCN9298hwPzfqUhw0iRvUiHsVIM.ZMZ7fEfDxq5zDACjRk3qf+6yCzBjlsZxu.z.hyOWi1jGNRq7MjgmuRhLiE8VSGiyBfIYG3Ok663XzyLmX41uFiMo2XwafidE2w6+w5W8c3yB.wJn1AW4QzFZog46gtLY95UPoP4D4xz4kOPg0jEfT6b0rXgoLTnmjU38VnoT4Z0TtoP7wztBs8vEiwBK.iX1++AXLQI9gzVCFvs0o.bUZ6WurxtUt4xtz36uTRJ.bm3kmKiHKHNLxKU2Dq9vxwopv+BMULyOfCYR79pttrIqGx77c4GC.+okOyUYOpm3M74U.SxJaf6Xc6gLoj6FtLBkEui5PQNVEoExyOfoCDP0DE7+dPyca99InC4fBnFY73JSUn5wkNlA+E7IYwpyHLXwpSWLUdkbHWeoJXjIFk7ch08w.xWDKefjIO3zjX0XxdttpKQQAQRRLDhLy0U4NwenRJrwoh2wTLummJxnYY.dZEPioAlo9.7Xk9LgKVPzKJD5V3bjrGbNlWHYsxI7fPycdOZkMfefBjCUNvR2qMyFX+IcY5gXkF1.BRq4AaXOK89Jbnb4ZlGMcEaDuooOzJFsfS5YTFgmYgw5tSExPI7BVqjQROtD.GAE3EhS36DdBtpMykbRb+AfdvaINZXbrh3VeHc.vAm5a.DImq9ofqFv2H65y6P4s+58i7n1H+6xGOsWUlJwri.siNRG93oGXKnFwA5uaLKIo6.gLwKi2yArwyFaZnlg8vmNNcDjNlZZpzXp4ylqdOM2ONaJUlu2H9kwLV1YQV8QTLBeF7b4CPptOertuxblP4wE.Cf28CnuBbrAPpjCYNLzjOfE4pmadRFvu1MC7.PuUfuHzuSeGB5O7h8hzJO3LMciHWO8Wq9bdP8ecAzOn6bkdvGSOVozsC3+TDTdO4V6Ju+s0Wnq.yStCRdp+Gu4muF9+ATD4GipX29fvGdwUEDxWDXk0OhSYy83n69TqVigKSxby7HEnQcSQHCZd4jO2Y9TKyaYkbSKyv7CSTpwW3kWMpa1G+kjUSZnTi7Xl1RK0Ck+eoIpGyNPcpc76BP289lY.EToQ0cM5A33xK30+dvep6o114Op4Lbyk0vsVVCqsrFt8xZ3NKqgOaYM74+6Fh+mHRjCwTWnnpaq3VYVsjwUBPuUxeCPIPoOE
      
      posted in General Questions
      HISEnbergH
      HISEnberg
    • RE: Audio FX - Play an audio file?

      @griffinboy Yes I am going to run a quick test now, but @ustk made a good assessment. It would be nice if there was a separate flag which would allow audio output from any of the sound generators in an FX plugin, though perhaps there is a good reason this doesn't exist (i.e. the relationship of input to output channels).

      posted in General Questions
      HISEnbergH
      HISEnberg
    • RE: Audio FX - Play an audio file?

      @ustk Ah this is exactly the issue I have been using the Audio Loop Player! This explains why I could see it operating in the background but not output any audio.

      @griffinboy thanks for confirming it's possible. I didn't imagine there would be anything unique about the FX export that would disable audio generation, so I'll test with the scriptnode version!

      posted in General Questions
      HISEnbergH
      HISEnberg
    • Audio FX - Play an audio file?

      Is it possible to export an audio FX plugin and play an audio file from it?

      I see there is the Enable Sound Generators in the project settings but it explicitly states that the sound output will not be used.

      Has anyone had success in creating an FX plugin that can produce sound. I have an example snippet of using an Audio Loop Player here which doesn't work.

      HiseSnippet 1320.3ocyWssSibCF1CvrpjtUsa6VopdQ0nU8B1JDJIDBj1KJPNrKc4PTRV11KpPlwNIV3wdjGGfHDOS80nW1WhdeeCn+1yDxLPVHjtrp4hn3+C9+y+mSSkzmFEIUHmbcFFRQNO0s8Pgte09Xl.sSMjyW3137sFPXxCFn6PiznsGFhihnDjiy7uxHkyhKfre9medaLGK7oiIgPGJY9zcYAL8XpM27MLNuAlP6vBRIcoM2wWJpJ4xA.hl2MOJD6eBtGcerQr4bQuFG0G47CtqUbU+Rj0IEKtVkx93xzJcwc6VXURoRk2nRgUqfKsQYZ90PNOoNgokp1ZrlFAW51Rxv18kmIhMvgrH1wbp4PATavxwjQU6y3jlibOQHjiaywNq4icVO2cOFgcM8zNMCCuwZj1o4L2cAoBO.H4jBRKDCom411WwB0i4Xvym5tiPSUcwPrIMThkE472tUkf.B8JA3SnMTvgqUXoh4yurG70K+ob4pK5wDzU3RLwlTzfwoQfnxlRIeIiD45NP3qYRgmTruTSOPrzKycQtEycYNuaxpa2IxyfEkjyopIx1jyntKEWRLH3XpZYuSw7AzqED7QYc7OY5b79wtlTBJE6HX5CBoImaH4DiC076aGlPI9VS.KAgfs01v0WmDtrNy2gOk1UpBPLhIEJCsBH6iIckEAqwHmuy8hlsN3WpWsyQMNX2Z0acYaHBcFn1JvWHEVziBOXEDkccLpYoTWPLmC9Cfva2ol4lRPG.T.7gTklY7QN0nmBEvwIWK5ViFchVFB0hUkAgRg4Y439feKmm9cLL8gvQNtcHl5Kqdd6JkgdM43gTkwAO1xOUmTGFa4FPdolI50AxJsF9ycSS58a2eayyXDceiK4Ogi8ord8sNrFiCewtfbtugN7XIVQPG2aTmpEeBgPtxbQLMMXL0qt5puMK0hIjsBqomqGK7HXYCFy86NtWjyy6Ef0dmAZu3G8JTZk7KanUiEEBNiC70fCceatNvtKlGQs72UdFnFPph83qYwmJTbc64pChzxfWovg8Y9QYzrFsKd.WuUXHEqLcxAtZ0fXlayglwvU0BbnRfQ9UJWw9YiMxudk7qWvJUGYudb5dRBMyMa5GB8GEBJ2.EKs2FQOj5CEjovx0VCX1fi0s0C423lZVeTH3lzs44isRwQzgr8T1tbtKgQP2pyIzyVRF.lLaibyHtDFPSlLcOMsHEQL8vzi.e.c2yemc2mVH9L2lLse+Iiw4l.FgJ8GCLlLS7ybq2sKDUGCvEba7qy5.vo27e0HyaaYX5XPim8MwlHu+kX9qocIlvodIFXiJeSAQ5zDaLqiBpnflSoMkAl0EX38SRStkTpMyLSuDUabPHOt4Nb8YjldJUEk8FLipi2i5dFYDXbGwyJBvmOZLAGvUl4HbKPudLhy7YCpKLcCWyVdkR9IrtyBOVafsvzk.dOi4++eKkLKLt3HL1lYRipKNkxghFKF+R2jIAinlshYOoPF1WJX9YS5zJVudTUZrOwGzVZMj3Olxy2rEkSwQoxt+9M2ExIwpaV27nt77DiWeiaLb8Lk4d+WhaeTSytywByOUiE9fi2YeDwGFnzRNvrK3dXHQ0zXC1cpMzk1mlrcPjoY1blU9hOmeTut1TAwdvr5VByBlyNILKLh4GEaDf8Uxi7i+uDlb4OwRAd2BaC9Ec2yb1aB+og.nq3Q99YupaoXwYUwUmUEKMqJt1rpX4YUw0mUE239UzLzZqAv54wkrHDr8p8OD33b8RANyi9WPT0jLt
      
      posted in General Questions
      HISEnbergH
      HISEnberg
    • RE: ScriptEditor: better CSS styling

      @Christoph-Hart said in ScriptEditor: better CSS styling:

      HISE | Scripting |

      Thanks for clarifying!!

      posted in Feature Requests
      HISEnbergH
      HISEnberg
    • RE: ScriptEditor: better CSS styling

      @Christoph-Hart Can you explain a bit further? How do you you "use" a CSS file within the HISE scripting framework?

      posted in Feature Requests
      HISEnbergH
      HISEnberg
    • RE: Get FFT values

      @ustk @griffinboy are right the scripting portion doesn’t work for realtime. I’ve recently worked on something similar to this, you can perform the FFT analysis in a C++ node then broadcast the values to HISE using global cables.

      posted in General Questions
      HISEnbergH
      HISEnberg
    • RE: HISE would crash when compiling ScriptFX network and now when trying to load project after reinstalling to the latest version on Windows.

      @Bicrome the issue is your air windows nodes. Whenever you update HISE you need to recompile any nodes you are using as well. If you have air windows inside of scriptnode networks it will fail initially. You need to compile the air windows nodes first, then do another round of compiling the scriptnode networks that contain them.

      posted in General Questions
      HISEnbergH
      HISEnberg
    • RE: a simple compressor meter to show how much compression...

      @gryphonsegg ah apologies I didn’t piece together you were using the dynamics module. If you check out this HISE tutorial I believe it has an example of displaying gain reduction:

      Link Preview Image
      hise_tutorial/DynamicsFX at master · christophhart/hise_tutorial

      The Tutorial project for HISE. Contribute to christophhart/hise_tutorial development by creating an account on GitHub.

      favicon

      GitHub (github.com)

      posted in General Questions
      HISEnbergH
      HISEnberg
    • RE: a simple compressor meter to show how much compression...

      @gryphonsegg have a look at this it may be useful

      Link Preview Image
      Anyone know why this isn't working?

      Hi guys, anyone know why this isn't working? I've been going round in circles for the past 3 days straight. All I aim to do is send the core.peak for the inp...

      favicon

      Forum (forum.hise.audio)

      posted in General Questions
      HISEnbergH
      HISEnberg