NTS-1 as Effects Processor

Good idea. Should be straightforward, very little code.

You’ve basically got two pointers to each frame in the buffer (actually 4 but…). Just average adjacent values, perhaps adding some follow-up gain with the depth parameter.

I haven’t done much with the SDK, so far just a very crude wavefolding mod effect.

I can have a look if you need a code example.

1 Like

That would be nice. Since I usually can adjust input volume on the monosynths themselves, I thought to use the NTS-1 knobs for pan L and pan R. This makes the averaging computation slightly more complicated but still quite simple.

This should work as your main.c

Sorry not sure how to format this correctly. :unamused:

//
#include “usermodfx.h”

static float gain;

void MODFX_INIT(uint32_t platform, uint32_t api)
{
gain = 1.0;
}

void MODFX_PROCESS(const float *main_xn, float *main_yn,
const float *sub_xn, float *sub_yn,
uint32_t frames)
{

for (uint32_t i = 0; i < frames; i++)
{
float inL = main_xn[i*2];
float inR = main_xn[i*2 + 1];

main_yn[i*2] = (inL+inR) * gain;
main_yn[i*2+1] = main_yn[i*2]

}
}

void MODFX_PARAM(uint8_t index, int32_t value)
{
const float valf = q31_to_f32(value);
switch (index)
{
case k_user_modfx_param_time:
break;
case k_user_modfx_param_depth:
gain = valf;
break;
default:
break;
}
}

2 Likes

Thanks! I think I can see how to use the knobs as I want. I’ll give it a try. (The code isn’t indentation-sensitive but I can format it properly anyway.)

1 Like

Yeah linear panning will be fairly easy and a good coding exercise.

Other pan laws for the advENTURous… :wink:

https://www.cs.cmu.edu/~music/icm-online/readings/panlaws/

Sorry, just realised you didn’t want to sum to mono… but you get the gist.

1 Like

My wavefolder below …

Watch out for the depth (B) parameter (out level). (A) is pre-fold gain.

wavefolder.ntkdigunit (994 Bytes)

Okay, that wasn’t so bad, considering I haven’t written C in about eight years. Way more time futzing with the toolchain than actually programming/debugging. Here’s the dual mono panner in case anyone wants it. (It implements constant power panning.)

dmpan.ntkdigunit (3.8 KB)

4 Likes

And, for illustrative purposes, the code.

//
#include "usermodfx.h"
#include <math.h>

static float lpan,rpan;

void MODFX_INIT(uint32_t platform, uint32_t api)
{
  lpan = 0.5;
  rpan = 0.5;
}

void MODFX_PROCESS(const float *main_xn, float *main_yn,
		   const float *sub_xn, float *sub_yn,
		   uint32_t frames)
{

  for (uint32_t i = 0; i < frames; i++)
    {
      float inL = main_xn[i*2];
      float inR = main_xn[i*2 + 1];

      main_yn[i*2] = (inL * sinf (lpan * PI / 2)) + (inR * sinf (rpan * PI / 2));
      main_yn[i*2+1] = (inL * cosf (lpan * PI / 2)) + (inR * cosf (rpan * PI / 2));
    }
}

void MODFX_PARAM(uint8_t index, int32_t value)
{
  const float valf = q31_to_f32(value);
  switch (index)
    {
    case k_user_modfx_param_time:
      lpan = valf;
      break;
    case k_user_modfx_param_depth:
      rpan = valf;
      break;
    default:
      break;
    }
}
5 Likes