Creating Custom Oscillators & Effects for the Korg Prologue

Posted on Tue 29 May 2018 in entries

UPDATE December 2018 – Korg have released a new firmware update version 1.3 that improves tuning stability and speeds up tuning settling time.

Watch the video to find out how to update your Prologue.

The Prologue is Korg’s latest polyphonic synth, available in 8- and 16-voice models. It has analogue oscillators and filters, and also a digital ‘multi-engine’ oscillator and digital effects.  It’s these last two aspects that Korg has made open-source, so programmers can get amongst the code and write their own. Sounds easy! It is… if you know C/C++ pretty well and are OK with having no technical support from Korg!

January 2019 UPDATE: see below for an update on available 3rd party custom oscillators and effects.

Korg’s decision to allow third party coding is a great move, and one that opens up some interesting possibilities to create some unique sounds. Admittedly, the likelihood of having the skills to code for this kind of embedded system and also owning a Prologue is quite slim, but the thinking behind it must be that a handful of developers will make their oscillators available to the public, either free or as paid for add-ons. With this in mind, Korg have also announced a limited run Prologue SDK Development board that is a PCB with one voice chip of the kind used in the Prologue itself and the necessary inputs/outputs.

The SDK (Software Development Kit) is free to download (https://github.com/korginc/logue-sdk) and is a collection of files that enable the coder to access the multi-engine and effects via an API (Application Programming Interface). Some additional files are required to get the system building correctly (depending on what OS platform is being used), the details of which are found in the various ReadMe’s in the SDK package. Once the build environment is up and running, creating the file that can be uploaded to the Prologue (or dev board) is pretty straight forward using the ‘make’ command in a terminal window. This command looks for a ‘makefile’ file in the current folder and uses that to produce the final zipped file (a .prlgunit file) that can be uploaded to the Prologue or dev board via the librarian software. The main limitation here is that the code must fit into 32kb – yes a whole 32kb!!

For the multi-engine oscillator, Korg have given access to 8 control parameters in total. Six of these are found in the edit menu, and the ‘Shape’ knob is the one control that is immediately available on the main synth panel. This control can also have a secondary function when holding the ‘shift’ key. There are 16 slots that can be filled with custom oscillators, and these can be mixed with the standard oscillators.

The digital effects section can be coded for other modulation and reverb/delay-based effects, and here you also have access to 2mb of sample memory. The Speed and Depth controls can be used to control the effects, and there are 16 user slots that can be filled with custom code.

So, we let our marketing man Rich loose with the SDK to see what he could make of it…

Getting the build environment up and running on a PC was relatively straight forward once I found the ReadMe’s that gave instructions for what additional software was required. This included a ZIP utility (that creates the final prlgunit file) that at first caused the build to fail – this was fixed by finding another version of the ZIP software.

The chip used in the Prologue is an ARM Cortex M-4 chip (with an FPU unit) and some extra files are needed to compile the code for it including CMSIS (Cortex Microcontroller Software Interface Standard) and the GNU Arm Embedded Toolchain.

Once the environment is set up correctly, editing the files can be done in any text editor (with C/C++ highlighting ideally!). I used Notepad++ to view and edit the files, and put them under source control using git/sourcetree/bitbucket – this is great as you can go back and forward in time and merge code branches back to the master branch until the project is done and dusted.

Now the fun bit – how does the API work?

The only way to find out what functions were available was to look through the source files. Some had notes to say what the function did, others didn’t so would have to be worked out. Of course, different C/C++ libraries could be used in addition to the API (assuming the end product compiles to 32kb or less).

I soon realised how the oscillator was structured, with the main sections to edit being the OSC_CYCLE function (where the waveform is generated) and the OSC_PARAM function that determines what the controls will do. OSC_INIT initialises the oscillator (sets the starting point of the waveform and resets any other values that you may want to reset).

C++ ‘classes’ are not used, instead the data structure is contained within a ‘struct’ which makes things a little simpler. The struct contains all the variables that are to be used for the oscillator.

So we're all dressed up, but right now there's no way to load up any custom oscillator directly to the Prologue - not until some time in June when the firmware is updated. The dev board works, but I don't have my hands on one! When the firmware is updated, we'll be uploading some custom oscillators and effects, so stay tuned!

Now, we did say you needed to know C/C++, here is the code for a basic sinewave oscillator..

/*
 * File: sine.cpp
 * Naive sine oscillator test
 */
#include "userosc.h"

typedef struct State {
  float w0;
  float phase;
  float drive;
  float dist;
  float lfo, lfoz;
  uint8_t flags;
} State;

static State s_state;
enum {
  k_flags_none = 0,
  k_flag_reset = 1<<0,
};

void OSC_INIT(uint32_t platform, uint32_t api)
{
  s_state.w0    = 0.f;
  s_state.phase = 0.f;
  s_state.drive = 1.f;
  s_state.dist  = 0.f;
  s_state.lfo = s_state.lfoz = 0.f;
  s_state.flags = k_flags_none;
}

void OSC_CYCLE(const user_osc_param_t * const params,
               int32_t *yn,
               const uint32_t frames)
{ 
  const uint8_t flags = s_state.flags;        
  s_state.flags = k_flags_none;                                   
  const float w0 = s_state.w0 = osc_w0f_for_note((params->pitch)>>8, params->pitch & 0xFF);
  float phase = (flags & k_flag_reset) ? 0.f : s_state.phase;
  const float drive = s_state.drive;
  const float dist  = s_state.dist;
  const float lfo = s_state.lfo = q31_to_f32(params->shape_lfo);
  float lfoz = (flags & k_flag_reset) ? lfo : s_state.lfoz;
  const float lfo_inc = (lfo - lfoz) / frames;
  q31_t * __restrict y = (q31_t *)yn;                        
  const q31_t * y_e = y + frames;

  for (; y != y_e; ) {
    const float dist_mod = dist + lfoz * dist;                             
    float p = phase + linintf(dist_mod, 0.f, dist_mod * osc_sinf(phase));
    p = (p <= 0) ? 1.f - p : p - (uint32_t)p;                  
    const float sig  = osc_softclipf(0.05f, drive * osc_sinf(p));                          
    *(y++) = f32_to_q31(sig);
    phase += w0;                                                
    phase -= (uint32_t)phase;       
    lfoz += lfo_inc;             
  }

  s_state.phase = phase;
  s_state.lfoz = lfoz;
}

void OSC_NOTEON(const user_osc_param_t * const params)
{
  s_state.flags |= k_flag_reset;                                  
}

void OSC_NOTEOFF(const user_osc_param_t * const params)
{
  (void)params;
}
void OSC_PARAM(uint16_t index, uint16_t value)
{
  const float valf = param_val_to_f32(value);

  switch (index) {
  case k_osc_param_id1:
  case k_osc_param_id2:
  case k_osc_param_id3:
  case k_osc_param_id4:
  case k_osc_param_id5:
  case k_osc_param_id6:
    break;

  case k_osc_param_shape:
    s_state.dist = 0.3f * valf;
    break;

  case k_osc_param_shiftshape:
    s_state.drive = 1.f + valf;
    break;

  default:
    break;
  }

}

January 2019 UPDATE - 3rd Party Custom Oscillators

A number of custom oscillators and effects have now been released, and are compatible with the Minilogue XD multi-engine...

PWG - Parametric Waveform Generator

PWG is an interesting oscillator that allows unique PWM-type waveform manipulation on all waves including a sine wave. This creates filter-type changes on basic waves (without using a filter) that can be modulated with an extra envelope or the Prologue LFO. Further harmonic modulation can be applied with waveshaping/folding that can also be modulated.

MORPH - Wavetable Oscillator

Morph is a set of three oscillators, each with different wavetables. The SHAPE control blends between adjacent wavetables, and the same waveform selection can be modulated with the Prologue LFO or extra envelope.

FMonsta

DirtBoxSynth were first to release a custom oscillator - FMonsta - which is a set of oscillators based around a wavetable/FM hybrid engine that can create very complex and harmonically rich sounds. For details head over to the DirtBoxSynth website.

ORIGAMI - Wavefolding Oscillator

A very organic sounding oscillator, based on a simple waveform fed through a wavefolding algorithm. Great for pads and evolving textures,  Origami is available for free from DirtBoxSynth if you sign up for support via their newsletter.

SUPAwave

DirtBoxSynth SUPAwave is a seven-voice per note oscillator that 'spreads' the pitch of each voice slightly to create super-fat leads and basses. As well as the classic 'super-variety' saw wave, there are other waves to choose from that also allow PWM-type modulation. SUPAwave also adds another LFO and distortion for more colour and modulation possibilities.

ORGANism

Also by DirtBoxSynth, ORGANism is an additive engine that creates both authentic and non-conventional organ sounds. Over 40 base waves are available and the six parameters control the 'drawbars' for each organ stop. The 'Shape' control re-pitches each of the six 'pipes' to create a new inversion of the organ partials in a unique way where some pitches go up and others down. Very interesting!

BLINDS

Blinds is by Edouard Digital and takes two waveformss that morph from one to another in a PWM-type way. The first waveform is called the Front Wave and the second one is called the Back Wave. You can then progressively transform the first one into the second one by opening a “blind” in the centre of the waveform, using manually the Shape knob or leaving it to the Prologue’s LFO shape modulation.

Sinevibes TURBO

Turbo is a variable waveshaping oscillator plugin for Korg’s multi engine. An original DSP technology developed at Sinevibes, Turbo uses a pair of sine oscillators coupled with special sine-based waveshapers to create truly unique, spectrally rich sounds with very distinct character.

Plaits

Ported over from Mutable Instruments open source Eurorack hardware, Plaits offers a selection of oscillator algorithm, including VA, waveshaping, granular and FM. Available from Github.

Custom Effects for the Prologue and Minilogue XD

Exotic Delay pack

A collection of seven special delay effects, including pitch-modulation, cross-modulation, and signal-triggered rising and falling pitched delays.

Filter Pack

A set of filters for the MOD FX section of the Prologue, including resonant HPF, LPF, BPF and BRF filters. This pack adds filter flavours not available as standard.

DirtBoxSynth AMPit

AMPit is a distortion effect for the MOD FX slot. The Prologue has a built-in distortion that can be switched in at one of two levels, but this plug-in adds a high-gain variable distortion with a tone control.

Pan and Tremolo Pack

Does what is says on the tin - but with one little extra..  The DirtBox Pan and Tremolo Pack includes sine and square LFOs that can be selected for 'smooth' and 'gated' autopan and tremolo effects.

Resonance

A mod effect that creates sweepable comb filter peaks for adding harmonics and inharmonics. Great for interesting pads, leads, and for creating 'plucked' transients and eerie effects.

Basic Autopanner

This Autopanner is a simple yet effective MOD Effect. Used in conjunction with DirtBoxSynth's ORGANism, for instance, adds a leslie to an already great-sounding organ.