HISE Logo Forum
    • Categories
    • Register
    • Login
    1. HISE
    2. griffinboy
    3. Posts
    • Profile
    • Following 8
    • Followers 9
    • Topics 115
    • Posts 969
    • Groups 1

    Posts

    Recent Best Controversial
    • RE: I think I've figured out a better way to create parameters for a node

      @Orvillain

      That's very interesting.

      In case you didn't already know, there are quite a few other 'hidden' features in parameter data. Such as defining skews, labelled discrete type parameters etc.

      posted in C++ Development
      griffinboyG
      griffinboy
    • RE: Reference External C++ Node as Audio Sample script - is it possible?

      @Christoph-Hart

      yeah that was my thinking.
      But I'm not certain whether that's the case @HISEnberg was asking about or not!

      posted in Feature Requests
      griffinboyG
      griffinboy
    • RE: Recreating Roland Alpha Juno PWM Saw oscillator - ideas?

      @dannytaurus said in Recreating Roland Alpha Juno PWM Saw oscillator - ideas?:

      I'll be doing a lot of processing after the oscillator section,

      That emphasises differences rather than obscures them. Everything downstream is affected by the source.

      But if accuracy to the original is not the goal, this isn't a problem whatsoever.

      As for creating wavetables, use python. You can code custom tools to take your cycles and stitch them into a wavetable. You can even generate PWM in python.

      (it takes a bit of setup to get python up and running though, with all the right libraries and versions, it can be a pain) After it's setup though it's great, and ChatGPT is good at writing python code, so you basically have an unlimited supply of little audio dev tools that you can generate.

      Or... if you own Serum2, use that. The wavetable editor is good and it can extract cycles and stitch them using different morphs.

      posted in General Questions
      griffinboyG
      griffinboy
    • RE: Reference External C++ Node as Audio Sample script - is it possible?

      @Christoph-Hart

      Can you push to that buffer from inside the c++ node though?

      I think @HISEnberg is wanting to generate an audio file in c++, then push it out to the Hise script?

      I might be wrong.

      posted in Feature Requests
      griffinboyG
      griffinboy
    • RE: Recreating Roland Alpha Juno PWM Saw oscillator - ideas?

      @modularsamples
      @dannytaurus

      Just a note on this, the file player has no antialiasing! Pitching up any file will create harsh additional harmonics. Just something to be aware of

      posted in General Questions
      griffinboyG
      griffinboy
    • RE: Recreating Roland Alpha Juno PWM Saw oscillator - ideas?

      @dannytaurus

      So, the easiest way to achieve it in a 'pretend' hacky manner, would be to record the original waveform output from the synth while sweeping the PWM, and extract frames to create a wavetable. You could then use the built in Hise wavetable synthesiser module to play it back.

      It'll sound the same as the original thing, perceptually
      That is, until you go and do other synthesis stuff with it.
      The signal won't interact with the other parts of the synth in the exact same way unless you simulate it properly / with more detail. That's only an issue if you are wanting a really analog sound, or to actually get very close to the original.

      And that's where things get really tricky immediately.
      You'd probably need to code the oscillator in c++ from scratch. You'd need to code an antialiasing system since you can no longer rely on the Hise one from the wavetable synthesiser module. But it would open up freedom to properly implement PWM in high detail and create simulations to recreate any other quirks of the oscillator.

      If you want more info I'll give it, but the method you should choose really depends on what aspects you want to simulate.

      posted in General Questions
      griffinboyG
      griffinboy
    • RE: What is the correct approach for making a custom polyphonic c++ node?

      @Orvillain

      Voices in Hise are managed 'automatically'.
      Take a read of Polydata.

      I don't remember where it can be found. But the Hise source has all the .h and .cpp files which have the implementations for voice handling. You can see what's currently going on, and perhaps there will be some useful api that you're not yet making use of.

      Christoph is the person to ask though!

      posted in C++ Development
      griffinboyG
      griffinboy
    • RE: I wrote a bbd delay

      @Orvillain

      Oh yeah I tried a moog. It was arguably not very good haha.
      It becomes very dark in a very musty way.

      Unless you're willing to stack a few to get a high order it's going to sound quite blurry. Whether or not that's a bad thing is up to you.

      For refrence the real antialising filters from pedals like the memory man are steep. They are almost like low order elliptic lowpasses. That's the closest 'standard' filter response I found to the real thing. This allows them to have a high and crisp feeling cut-off (3.5k) while still killing aliasing.
      It's different to a synth filter.

      But that's what the hardware BBD effects do anyway.

      posted in C++ Development
      griffinboyG
      griffinboy
    • RE: I wrote a bbd delay

      @Orvillain

      Really fun ideas!

      I took a couple of weeks to learn how to derive filters from analog because I wanted some BBD delay antialiasing filters that match hardware exactly. If you need any tips on that I'm happy to share.

      But in all honesty, making up new filters is probably more fun. It's not like the analog filters are the best ever - there are probably unexplored shapes that will sound more interesting or be useful in different ways.

      0e35eaaf-67d7-4185-86d8-7a2cfb2438a0-image.png

      posted in C++ Development
      griffinboyG
      griffinboy
    • RE: I wrote a bbd delay

      @Orvillain

      That's really comprehensive, more so than mine.
      The only thing I noticed missing is possibly the fact that filters change shape in BBD delays depending on the delay time. They kind of warp into a lower order lower filter as time increases.

      If you take IR measurements from a real device you can recreate matching filters using vector fitting!

      I'd love to hear more of your delay though. BBD delay is wonderful.

      posted in C++ Development
      griffinboyG
      griffinboy
    • RE: I wrote a bbd delay

      @Orvillain

      Nice work!
      May as well share mine : D

      https://youtu.be/yhpfCLf968Q

      An incredibly distorted take on BBD haha!

      posted in C++ Development
      griffinboyG
      griffinboy
    • RE: Wanted to share a release and HISE VSTs we created

      @Straticah

      Congrats

      posted in Blog Entries
      griffinboyG
      griffinboy
    • RE: Best Practice for Getting RMS/Peak on an audio buffer

      @Yarost

      I think you'll have to use the global cable system.
      you can take the modulation signal out of the c++ node, into one of the global cable nodes, and then you can access the value in hise script.

      posted in General Questions
      griffinboyG
      griffinboy
    • RE: Ring Buffer design

      @Christoph-Hart
      @Orvillain

      Yep, if your buffer is a power of two you can use bitmasking.

      The only case where I've used other strategies, is when my interpolator is very wide. My Fir convolution interpolator has 64 reads every sample, and so even bitmask wraps add up.
      But in such situations I actually just use strategies to hoist the wraps. I don't do any checking at all inside the loop. I note down where the edges are and if we are nowhere near the edges we run a separate vectorized loop that avoids any checks.

      posted in C++ Development
      griffinboyG
      griffinboy
    • RE: Few questions from a newbie

      @ScreamingWaves

      Adding to David's answer,
      no time at all to import samples, if your samples are named properly (already organised) or have metadata etc.

      If you need to organise all the samples etc, then it will take quite a while longer.

      You should be able to find youtube videos (David Healy likely has multiple) about using the stock hise sampler and how sample import works.

      posted in Newbie League
      griffinboyG
      griffinboy
    • RE: Few questions from a newbie

      @ScreamingWaves

      If you want to get it done on a tight deadline, simplify the scope.
      Probably don't do the multi output routing at first.
      Prototype each part of the project separately so that you can learn how each bit works, then create your actual project.

      posted in Newbie League
      griffinboyG
      griffinboy
    • RE: Oversamping in C++

      @Christoph-Hart 😆 ah, right. Yes looking at the profile it's very obvious.

      posted in C++ Development
      griffinboyG
      griffinboy
    • RE: Oversamping in C++

      @Christoph-Hart

      Shoot you're right.
      I didn't even think of that.
      I wonder what the point of Ai botting a forum like this would be

      posted in C++ Development
      griffinboyG
      griffinboy
    • RE: Oversamping in C++

      @weston-donald

      Yes agreed.
      Make sure to match your upsampling / downsampling filters.
      Your upsample stage and downsample stage need to be designed together so that they don't cause bad ripple or other artefacts. Mismatched filters will cause aliasing even (going from 2x as many samples, down to half as many may create discontinuities if not smoothed / interpolated proper).

      posted in C++ Development
      griffinboyG
      griffinboy
    • RE: Oversamping in C++

      @Allen

      I made this custom one at one point when I needed stronger alias rejection.
      It's old though and I only used it once. just posting an alternative in case it's useful.

      Something you'll need to be careful of when oversampling is that the antialising filters usually introduce latency.
      So if you have things that are oversampled mixed with things that aren't, make sure to phase align them by compensating latency.

      // FILE: src/Oversampler2xKaiser.h
      /*
          2x Kaiser-windowed FIR oversampler/downsamlper 
          Linear-phase, unity DC gain. Default taps=63, beta=8.0.
      
          USAGE:
            - Oversampler2xKaiser os; os.prepare(63, 8.0); os.reset();
            - double u0,u1; os.upsample(x, u0, u1);                   // generate 2x stream
            - double y = os.downsample(v0, v1);                        // consume pair from 2x domain
      */
      
      #pragma once
      #include <vector>
      #include <cmath>
      #include <cstring>
      #include "Utils_General.h"
      
      
      #define OS2X_HAVE_XSIMD 1
      
      
      class Oversampler2xKaiser
      {
      public:
          Oversampler2xKaiser() noexcept = default;
      
          void prepare(int taps = 63, double beta = 8.0)
          {
              if ((taps & 1) == 0) ++taps;
              N = taps;
              B = beta;
              buildCoeffs();
      
              upHist.assign((size_t)H, 0.0);
              dEven.assign((size_t)L0, 0.0);
              dOdd.assign((size_t)L1, 0.0);
          }
      
          void reset() noexcept
          {
              std::fill(upHist.begin(), upHist.end(), 0.0);
              std::fill(dEven.begin(), dEven.end(), 0.0);
              std::fill(dOdd.begin(), dOdd.end(), 0.0);
          }
      
          inline void upsample(double x, double& y0, double& y1) noexcept
          {
              shift_in(upHist.data(), H, x);
              y0 = dotSIMD(p0.data(), upHist.data(), L0);
              y1 = dotSIMD(p1.data(), upHist.data(), L1);
          }
      
          inline double downsample(double v0, double v1) noexcept
          {
              shift_in(dEven.data(), L0, v0);
              shift_in(dOdd.data(), L1, v1);
              const double a = dotSIMD(p0.data(), dEven.data(), L0);
              const double b = dotSIMD(p1.data(), dOdd.data(), L1);
              return a + b;
          }
      
      private:
          // PURPOSE: Kaiser window, halfband ideal (wc=pi/2) + normalization. Build polyphase strides p0/p1.
          void buildCoeffs()
          {
              const int M = (N - 1) / 2;
              std::vector<double> h((size_t)N);
              const double kPi = gdsp::PI;
              const double i0B = i0(B);
      
              for (int n = 0; n < N; ++n)
              {
                  const int m = n - M;
                  const double r = (double)m / (double)M;
                  const double w = i0(B * std::sqrt(std::max(0.0, 1.0 - r * r))) / i0B;
      
                  double sinc;
                  if (m == 0) sinc = 0.5;
                  else         sinc = std::sin(0.5 * kPi * m) / (kPi * m);
      
                  h[(size_t)n] = w * sinc;
              }
              double s = 0.0; for (double v : h) s += v;
              const double invS = (s != 0.0) ? (1.0 / s) : 1.0;
              for (double& v : h) v *= invS;
      
              L0 = (N + 1) / 2;
              L1 = N / 2;
              H = std::max(L0, L1);
      
              p0.resize((size_t)L0);
              p1.resize((size_t)L1);
      
              for (int k = 0; k < L0; ++k) p0[(size_t)k] = h[(size_t)(2 * k)];
              for (int k = 0; k < L1; ++k) p1[(size_t)k] = h[(size_t)(2 * k + 1)];
          }
      
          static inline void shift_in(double* hist, int len, double x) noexcept
          {
              std::memmove(hist + 1, hist, sizeof(double) * (size_t)(len - 1));
              hist[0] = x;
          }
      
          // PURPOSE: SIMD dot with scalar fallback.
          static inline double dotSIMD(const double* a, const double* b, int n) noexcept
          {
      #if OS2X_HAVE_XSIMD
              using vd = xsimd::batch<double>;
              constexpr int W = (int)vd::size;
              int i = 0;
              vd acc = vd::broadcast(0.0);
              for (; i + W <= n; i += W)
                  acc = xsimd::fma(xsimd::load_aligned(a + i), xsimd::load_aligned(b + i), acc);
              double s = xsimd::reduce_add(acc);
              for (; i < n; ++i) s += a[i] * b[i];
              return s;
      #else
              double s = 0.0;
              for (int i = 0; i < n; ++i) s += a[i] * b[i];
              return s;
      #endif
          }
      
          // PURPOSE: Modified Bessel I0 via series. Accurate for |x| up to ~12 within ~1e-12.
          static inline double i0(double x) noexcept
          {
              double t = 1.0;
              double y = (x * x) * 0.25;
              double s = 1.0;
              for (int k = 1; k < 50; ++k)
              {
                  t *= y / (double)(k * k);
                  s += t;
                  if (t < 1e-12 * s) break;
              }
              return s;
          }
      
          int N{ 63 }, L0{ 0 }, L1{ 0 }, H{ 0 };
          double B{ 8.0 };
      
      #if OS2X_HAVE_XSIMD
          template<typename T> using AAlloc = xsimd::aligned_allocator<T, 64>;
      #else
          template<typename T> using AAlloc = std::allocator<T>;
      #endif
      
          std::vector<double, AAlloc<double>> p0, p1;
          std::vector<double, AAlloc<double>> upHist, dEven, dOdd;
      };
      
      
      
      /*
          Utils_General.h
      
      	General useful math for dsp programming
      */
      
      
      #pragma once
      
      #include <climits>
      #include <cmath>
      
      #if defined(_MSC_VER)
      #pragma once
      #pragma warning(4 : 4250)          // "Inherits via dominance" 
      #endif
      
      namespace gdsp
      {
      
      	//===================| Constants |===================
      
      	// PI
      	static const double  PI = 3.1415926535897932384626433832795;
      
          static const double TWOPI = 2 * PI;
      
      	// FORCEINLINE
          #if defined(_MSC_VER)
          #define FORCEINLINE __forceinline
          #else
          #define FORCEINLINE inline
          #endif
      
      
      
          //===================| Fixed Point Math |===================
      
           /*----- 16-bit signed -----*/
      #if defined(_MSC_VER)
          typedef __int16                 Int16;
      #elif (defined(__MWERKS__) || defined(__GNUC__) || defined(__BEOS__)) && SHRT_MAX == 0x7FFF
          typedef short int               Int16;
      #else
      #error No signed 16-bit integer type defined for this compiler!
      #endif
      
          /*----- 32-bit signed -----*/
      #if defined(_MSC_VER)
          typedef __int32                 Int32;
      #elif (defined(__MWERKS__) || defined(__GNUC__) || defined(__BEOS__)) && INT_MAX == 0x7FFFFFFFL
          typedef int                     Int32;
      #else
      #error No signed 32-bit integer type defined for this compiler!
      #endif
      
          /*----- 64-bit signed -----*/
      #if defined(_MSC_VER)
          typedef __int64                 Int64;
      #elif defined(__MWERKS__) || defined(__GNUC__)
          typedef long long               Int64;
      #elif defined(__BEOS__)
          typedef int64                   Int64;
      #else
      #error No 64-bit integer type defined for this compiler!
      #endif
      
          /*----- 32-bit unsigned ----*/
      #if defined(_MSC_VER)
          typedef unsigned __int32        UInt32;
      #elif (defined(__MWERKS__) || defined(__GNUC__) || defined(__BEOS__)) && UINT_MAX == 0xFFFFFFFFUL
          typedef unsigned int            UInt32;
      #else
      #error No unsigned 32-bit integer type defined for this compiler!
      #endif
      
      	// Helpers for fixed-point math
          union Fixed3232
          {
              Int64  _all;
              class
              {
              public:
      #if defined(__POWERPC__)            /* big-endian */
                  Int32   _msw;
                  UInt32  _lsw;
      #else                               /* little-endian */
                  UInt32  _lsw;
                  Int32   _msw;
      #endif
              } _part;
          }; 
      
           // simple branch-free min/max 
          template <typename T> FORCEINLINE T min(T a, T b) { return (a < b) ? a : b; }
          template <typename T> FORCEINLINE T max(T a, T b) { return (a > b) ? a : b; }
      
          // IEEE-safe rounding 
          FORCEINLINE int  round_int(double x) { return (x >= 0.0) ? int(x + 0.5) : int(x - 0.5); }
          FORCEINLINE long round_long(double x) { return (x >= 0.0) ? long(x + 0.5) : long(x - 0.5); }
      
          // bidirectional (signed) bit-shift helper
          template <typename T>
          FORCEINLINE T shift_bidi(T x, int s)
          {
              return (s >= 0) ? (x << s) : (x >> (-s));
          }
      
      
      
      } // namespace gdsp
      
      posted in C++ Development
      griffinboyG
      griffinboy