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

    Posts

    Recent Best Controversial
    • 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
    • RE: Frequency masking plugin advice/help

      @ustk

      It's pretty raw isn't it?

      I like my FFT analysers to be multiresolution. Lower detail for the lower frequencies and more resolution for the higher frequencies. I personally find it to be a cleaner and more practically useful representation. And then if you smooth the diagram a little in time, you can reduce noise. Small window, with smoothing afterwards, rather than using a longer window to slow things down, feels less flickery.
      I also like to tilt the entire graph towards pink noise rather than being truly flat.

      That being said it's been a while since I looked at the source I could be misremembering, and maybe it's doing some of these things under the hood? I felt like it wasn't.

      posted in Newbie League
      griffinboyG
      griffinboy
    • RE: Frequency masking plugin advice/help

      @JC

      Just to let you know, that's not necessarily very simple, but in theory you should be able to get a basic version working.
      Hise doesn't have a particularly amazing realtime FFT spectrum analyser so if you want it to be nice looking or accurate you'd have to create a custom one.

      That aside, yes, the sidechaining is the main thing here. I've not done that in Hise before. But someone here will know how to do it.

      What you'll need to do is feed the sidechained signal and the live signal into separate analysers.
      I'm not quite sure how that routing works in Hise.

      posted in Newbie League
      griffinboyG
      griffinboy
    • RE: Is it possible to get a wider Q shape?

      @Dan-Korneff
      @WillowWolf

      Indeed.
      Creating a custom filter is your best bet.

      Digital SVFs are a particular topology which have limits to the shapes you can make with them. There are a few different methods to choose from to create digital filters with more flexible frequency responses.

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

      @Orvillain

      I've never used sync / fir interpolators in a reverb.
      I'm not sure how high the benefit would be.
      For delays and synthesis it's great though when you need low aliasing and low ripple.

      posted in C++ Development
      griffinboyG
      griffinboy
    • RE: Ring Buffer design

      @Orvillain

      That's exactly it.
      And the cool thing about using a fir interpolator like this with multiple taps, is that you can SIMD it
      Process 4 taps in one SIMD instruction cut CPU significantly.

      Hise has XSIMD included.
      You don't need to include it you can just use it in a c++ node

      Oh but it has latency potentially to use this technique. So it's not good for certain uses where it's too fiddly to compensate latency in different places.
      But it's good for delay effects and for reading samples from a buffer at a new speed.

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

      @Orvillain

      https://gearspace.com/board/geekzone/380233-reverb-subculture.html

      I've also found this thread to be helpful!
      and for tuning reverbs there are some papers from a few years back about using neural networks to tune FDNs to be spectrally flat (no resonances)

      posted in C++ Development
      griffinboyG
      griffinboy
    • RE: Ring Buffer design

      @Christoph-Hart

      Thanks for all this, it's super interesting.

      I'm afraid I've turned this thread into an optimisation discussion, my fault whoops

      posted in C++ Development
      griffinboyG
      griffinboy