Skip to main content

Warps Symbiote

Warps Symbiote firmware is built on top of the Warps Parasites firmware and is my attempt to bring new life to the Mutable Instruments clones available from other manufacturers, let's try to preserve such an important legacy. It adds three new algorithms:

  • Ladder Filter: ported from an implementation of the improved Moog Ladder Filter
  • Dual State Variable Filter: implemented a dual filter based on Emillie's State Variable Filter
  • Reverbs: added 4 reverbs based on the implementations found in Rings, Clouds and Elements.

Here is a demo overview of the new effects:

 

Contents

Installation

Download the firmware .wav file version 0.2.0 and follow the usual update procedure stated in the Mutable Instruments Warps manual.

Interface

The interface of this firmware is the same as the one implemented in Warps Parasites. From left to right, the algorithms are:

  • Ladder Filter.
  • Dual State Variable Filter.
  • Reverbs.
  • Chebyschev Waveshaper.
  • Frequency Shifter.
  • Bitcrusher.
  • Doppler Panner.
  • Delay.
  • Meta

Ladder Filter

A ported implementation of the Moog Ladder Filter model:

This model is based on a reference implementation of an algorithm developed by Stefano D'Angelo and Vesa Valimaki, presented in a paper published at ICASSP in 2013. This improved model is based on a circuit analysis and compared against a reference Ngspice simulation. In the paper, it is noted that this particular model is more accurate in preserving the self-oscillating nature of the real filter.

References: "An Improved Virtual Analog Model of the Moog Ladder Filter" Original Implementation: D'Angelo, Valimaki

Dual State Variable Filter

Two independent SVFs, arranged in default configurations. This is implemented using the code from Mutable Instruments State Variable Filter. This filter drives the resonance up to distortion levels, sounding pretty close to an MS-20 filter model. The Low Pass is a two pole filter while the Band Pass and High Pass are one pole.

Reverbs

Compiled several Mutable Instruments reverbs implementation, based on their configurations in Rings, Clouds and Elements modules. Added control over parameters that were not available in the original implementations for an extra twist. Playing with the difussion knob is highly recommended. The four available reverbs are:

  • Caveman: found in Rings disastrous peace mode.
  • Rings: found in the additional resonator model KarplusVerb.
  • Clouds: close enough configuration based on the beloved reverb.
  • Elements: close enough configuration with reverb freeze (timbre knob completely CW) and added input gain control for dramatic and cinematic effects.

Parameters

Algorithm Algorithm Knob/CV Timbre Knob/CV Internal Oscillator Button Level 1 Knob Level 2 Knob Level 1&2 CV Output 1+2 Aux
Ladder Filter Cutoff frequency Resonance Warps internal oscillator Input 1 level/ oscillator frequency Input 2 level Inputs 1&2 VCA CV control Filter summed output Sum of 1+2 or internal oscillator out
Dual SVF Filter 1 cutoff frequency Filter 2 cutoff frequency Toggles between different combinations: LP/HP (unlit), LP/BP (green), BP/HP (yellow), BP/BP (red) Filter 1 resonance Filter 2 resonance Inputs 1&2 VCA CV control Filter 1 output Filter 2 output
Reverbs Diffussion Reverb time Selects reverbs: Caveman (unlit), Rings (green), Clouds (yellow), Elements (red) Reverb amount, reverb gain for Elements Filter LP filter, feedback for Clouds Inputs 1&2 VCA CV control Left output Right output
Chebyschev Waveshaper Order Gain Warps internal oscillator Input 1 level/ oscillator frequency Input 2 level Inputs 1&2 VCA CV control Out Sum of 1+2 or internal oscillator out
Frequency Shifter Frequency shift Crossfade between up/down outputs Warps internal oscillator Feedback Dry/Wet Feedback and Dry/Wet CV control Up Down
Bitcrusher Bit crushing amount Cross modulation: dry, AND, XOR Warps internal oscillator Input 1 level/ oscillator frequency Input 2 level Inputs 1&2 VCA CV control Out Sum of 1+2 or internal oscillator out
Doppler Panner X Coordinate Y Coordinate Space size: from smaller (unlit) to larger (red) LFO frequency LFO Amplitude LFO amplitude and frequency CV control Out Out symmetrical on axis
Delay Delay speed/direction Delay length Selects modes: open fb loop (unlit), dual (green), analog (yellow), ping-pong (red) Feedback Dry/Wet Feedback and Dry/Wet CV control Out 1 out 2

For Meta mode see Mutable Instruments stock firmware documentation

Graphical Quick Reference

A quick reference guide is provided. A ton of gratitude to epijdemic who volunteered to create such a great visual aid for the firmware. You can download the PDF here.

 

 

Change Log

Symbiote 0.2.0

New features:

  • Replaced Parasites Vocoder with Doppler Panner, find it in position 7 in the interface.
  • Replaced pulse train oscillator with square wave oscillator.
  • The internal oscillator options for the ladder filter are now: Triangle (green), Saw (yellow), Square (red).
  • Improved cutoff frequency calibration for the ladder filter.

Symbiote 0.1.0

New features:

  • Ladder Filter: ported from an implementation of the improved Moog Ladder Filter
  • Dual State Variable Filter: implemented a dual filter based on Emillie's State Variable Filter
  • Multi Reverb: added 4 reverbs based on the implementations found in Rings, Clouds and Elements.

NTS-1 Harmonik Oscillator

Since I already explored subharmonic sound generation related to the undertone series and in the process programmed the Subharmonikorg, a subharmonic oscillator for the nts-1, it was time to look into the overtone series. Also known as the harmonic series, the overtone series is generated by multiplying the fundamental frequency by a series of integer numbers in order to create harmonic relationships from the root note. Looking into the eurorack synth world, I came across the Verbos Electronics Harmonic Oscillator which has an architecture of one main oscillator and seven harmonic oscillators. Each harmonic oscillator multiplies the main frequency by its ordered number and has faders that allow the user to set the amplitude of the waves that are going to be added to the fundamental. The Verbos has more features but I decided to adopt the basic architecture limited to only four harmonics and include a wavefolder.

I made a post discussing the principles of creating complex wave forms from adding harmonic sine waves to the fundamental frequency wave. It is explained step by step in a python jupyter notebook. Based on those principles, we will be able to compose several harmonic related sine waves and combine them to get interesting timbres.

The Harmonik Oscillator

 

 

As mentioned before, the Harmonik oscillator will have one main and four harmonic sine wave oscillators. All of them with level controls for mixing the desired amplitudes in the final wave output. Lets start with the definition of the Oscillator:

typedef enum {
    harmonic = 0,
    odd = 1,
    even = 2,
    octaves = 3
} Spread;

typedef struct Oscillator {
    float phases[5] = { 0 };
    float gains[5]= { 1.f, 0.f, 0.f, 0.f, 0.f };
    float drive;
    float offset;
    Spread spread;
} Oscillator;

The Oscillator struct contains all the data related to the oscillator as a whole. Phase and gain information for the main and harmonic sine waves get processed with each cycle. The indexes of the arrays correspond to each harmonic order with zero being the fundamental, and the rest being the harmonic relationships.

The harmonic relationships with the main frequency can be set in four different Spread types:

  • Harmonic: each sine wave's frequency gets multiplied by its corresponding harmonic integer.
  • Odd: each sine wave gets spread apart in odd partials (main frequency multiplied by 3, 5, 7, 9).
  • Even: each sine wave gets spread apart in even partials (main frequency multiplied by 2, 4, 6, 8).
  • Octaves: each sine wave gets spread by the geometric progression, producing octaves.

The way we achieve this is with the simple function shown below:

int partial(int index) {
    int s;
    switch (spread) {
        case harmonic:
          s = index + 1;
          break;
        case odd:
          s = 2 * (index + 1) - 1;
          break;
        case even:
          s = (index == 0) ? 1 : 2 * index;
          break;
        case octaves:
          s = 1 << index;
          break;
    }
    return s;
}

In order to complete the additive synthesis combo, I decided to look into implementing a wavefolder. After many attempts without satisfying results, I searched for a solution and found an implementation done in C but for VCV rack, you can check it out in squinkylabs github repo. It doesn't fold the waves the exact way as you would see in VCV rack, but it folds them alright. Even though I am coding for the nts-1, I didn't change a thing from the original implementation:

float fold(float x) {
    float fold;
    const float bias = (x < 0) ? -1.f : 1.f;
    int phase = int((x + bias) / 2.f);
    bool isEven = !(phase & 1);
    if (isEven) {
        fold = x - 2.f * phase;
    } else {
        fold = -x + 2.f * phase;
    }
    return fold;
}

The Harmonik code can be found here and the nts-1 oscillator can be downloaded from here. A summary of features and parameters is described below:

Features

  • Six sine wave oscillators with amplitude control.
  • A wave folder that folds each sine wave before summing the result to the final signal.
  • Spread control for the partials so that we have harmonic, odd or even partial overtones.
  • Offset control for asymmetric wavefolding.
  • The wave folder can be modulated with the Shape LFO.

Parameters

Parameter Range Description
SHAPE 0 to 100 Wave folder control
ALT 0 to 100 Offset of signals for asymmetric wavefolding
P1 0 to 100 The first partial frequency amplitude
P2 0 to 100 The second partial frequency amplitude
P3 0 to 100 The third partial frequency amplitude
P4 0 to 100 The fourth partial frequency amplitude
P5 0 to 100 The fifth partial frequency amplitude
SPRD 0 to 3 The spread controller 0: harmonic, 1: odd, 2: even, 3: octaves

Music Synthesis Wave Creation With Python

In my previous post, Music Synthesis Wave Analysis With Python, I talked about harmonics in sound waves and how they can be synthezised from electrical signals. Knowing that there are harmonics present in the most used wave forms in music synthesis (triangle, sawtooth and square shapes), I showed the results of the fourier transform analysis to understand the harmonic components of each wave. We now understand that each wave is the result of summing different signals with different frequencies and amplitudes. This can be observed in the Fast Fourier Transform (FFT) graphs shown in the previous post.

It is awesome to know all of this, but you may wonder if it is possible to start from a simple sine wave and try to construct each wave by summing other sine waves to the fundamental. The short answer is: YES. Thanks to the FFT we can visualize each frequency component of a given wave, from there we can try and cook up each one according to the recipe. This is the basic principle of the Fourier Series. In this post, I will try to get as close as I can since the precise relationship of amplitudes and frequencies of each harmonic component for a given wave is hard to replicate. It will be an exercise of aproximations in order to illustrate how powerful the FFT is for understanding waveforms.

Importing Necessary Modules

 

As before, we will start by importing our needed modules and functions.

In [1]:
from typing import List
import pandas as pd
import numpy as np
from scipy.fftpack import fft, fftfreq
import IPython.display as ipd
import matplotlib.pyplot as plt
from scipy import signal

Audio and Plot

 

I did some modifications to the play_and_plot_wave function and added the sum_harmonics in order to do the Fourier sum of each wave related to the provided harmonics list. The amplitude of each harmonic component will be decreased exponentially as we advance the harmonic value. I decided to do this since the results of each previously analyzed waves ressembled an exponential decay in their amplitudes.

 

Note that only sine waves will be necessary in the following functions.

In [2]:
sr = 44100 # Sample Rate in Hz
duration = 2
frequency = 440 # Musical note A
plot_args = {"figsize": (6, 4), "legend": False} # Plot arguments

def sum_harmonics(harmonics: List[int], amplitude: float, bias: float, tau: float) -> np.array:
    waves = []
    # Fourier sum with exponential decay of harmonic amplitudes.
    for i in sorted(set([1] + harmonics)):
        harmonic = i * frequency
        phases = np.cumsum(2.0 * np.pi * harmonic / sr * np.ones(int(sr * float(duration))))
        waves.append(np.sin(phases) * (bias + amplitude * np.exp(-tau * (i - 1))))
    
    return sum(waves, start=np.empty(shape=(1,)))

def play_and_plot_wave(
    harmonics: List[int] = [1],   
    amplitude: float = 1,
    bias: float = 0.0,
    tau: float = 1
) -> None:
    wave = sum_harmonics(harmonics, amplitude, bias, tau)
    yf = fft(wave)
    xf = fftfreq(len(wave)) * sr
    
    fig, (axis1, axis2) = plt.subplots(2, 1, constrained_layout=True)
    axis1.set_title('Signal', fontsize=12)
    axis1.set_yticks([])
    axis2.set_title('FFT', fontsize=12)
    axis2.set_yticks([])
    axis2.set_xticks(np.arange(1, 11) * frequency)
    
    fft_df = pd.DataFrame({"Frequency": xf, "Magnitude": np.abs(yf)})
    wave_df = pd.DataFrame({"Time": np.arange(5, len(wave)+ 5) * (1000 / sr), "Amplitude": wave})
    wave_df.plot(x="Time", y="Amplitude", xlabel="Time (ms)", xlim=(0, 20), ax=axis1, **plot_args)
    xlim2 = (frequency / 2, frequency * 10)
    fft_df.plot(x="Frequency", y="Magnitude", xlabel="Frequency (Hz)", xlim=xlim2, ax=axis2, **plot_args)

    display(ipd.Audio(wave, rate=sr, normalize=True))

Creating The Waves

 

We will start with the fundamental wave, our sine at 440Hz frequency, just to have a comparison on how this will morph into our aproximated wave shapes. For every result in the following graphs, we will be observing up to the 10th harmonic.

 

WARNING

 

Be careful when listening to the audio. If you are wearing headphones, turned down the volume or take them off.

Sine Wave

 

No surprises here, we see a clean sine wave with the expected harmonic only at the fundamental 440Hz frequency. Let the wave shaping begin.

In [3]:
play_and_plot_wave()
No description has been provided for this image

Square(ish) Wave

 

As we observed in the square wave analysis of our previous post, this wave shape only had odd harmonic components and it seemed like an exponential decay between them. We will try to approximate the result by just adding sine waves up to the 9th odd harmonic and see what we get. We will have to tweak a bit the decay bias and damping variable tau.

In [4]:
play_and_plot_wave(
    harmonics=[1, 3, 5, 7, 9], 
    amplitude=2, 
    bias=0.05, 
    tau=0.8
)
No description has been provided for this image

Pretty close, right? We se can observe that we made the edges steep and the peaks a bit flattened. We also see some curly lines at the peaks, product of our harmonic amplitudes aproximations. Turns out Fourier was right, and he figured this out without computers. You can compare the FFT results with the graph in the previous post.

Lets not stop here and keep synthesizing waves!  

Sawtooth(ish) Wave

 

The sawtooth wave analysis showed us that this waveform has even and odd harmonic components present. Based on that, we proceed to sum all of the sine waves up to the 10th harmonic.

In [5]:
play_and_plot_wave(harmonics=list(range(1,11)), amplitude=2, bias=0.08, tau=0.8)
No description has been provided for this image

Again, close enough. The difference is that our frankenstein version is tilted to the left in comparison to the original which is tilted to the right. Again we see some curly peaks and slopes due to the way we calculated the amplitude relationship of each harmonic component. I followed the recipe and we see an exponential decay between each component up to the 10th harmonic. If you play the sound, you'll hear that it resembles pretty well the original sawtooth.  

Triangle(ish) Wave

 

This one was the hardest one to get and the aproximation is not that good in comparison to the previous ones. If you recall the triangle wave analysis, this wave had also only odd harmonic components but the amplitudes of each were smaller compared to the square wave. I had to sum only the odd harmonics up to the 5th and tweak a bit the tau parameter.

In [6]:
play_and_plot_wave(
    harmonics=[1, 3, 5], 
    amplitude=2, 
    bias=0.15, 
    tau=3
)
No description has been provided for this image

As you can see, I obtained some sharp peaks and straight slopes. It still resembles a sine wave but if you look the FFT graph you'll see that the harmonic components are present. Not as similar as the ones from the previous post but I am happy with the results.

Wrapping Up

 

Working with the knowledge acquired by understanding the FFT, we were able to see how we can build any waveform by just summing sine waves with different frequencies and amplitudes. We can easily obtain the usual syntheziser wave shapes by either using a function in any programming language or by designing a circuit that generates the electrical waves but... now you know how the fundamental principle works by visualizing the results of applying it.

As a sound synthesist, you work with whatever wave shape is given to you and mix, filter or distort them to make new sounds. Another approach is to use the basic building block, the sine wave, and add harmonics, subharmonics, fold or multiply the waves in order to create your sounds. These are the two perspectives that this series of posts are trying to give you and which opens up the discussion of Additive vs Subtractive Synthesis (or well known as West Coast and East Coast Synthesis). This could be a subject for a future post, since it is very broad.

I hope this is of use to someone, somewhere. I'm thinking about implementing a wavefolder, that could be the next post in this series.

Music Synthesis Wave Analysis With Python

Sound synthesis is all about combining basic electrical waveforms and processing them through different modules or components in order to obtain an output that either emulates sounds found in physical instruments or make new sound effects or musical tones. The main synthesizer component in charge of generating the output signal is the Voltage Controlled Oscillator (VCO). The most common generated signals in a synthesizer are sine, square, sawtooth and triangle. I wanted to make the excercise of analyzing these signals from the harmonics point of view, the visual aid is always useful if you want to understand exactly what a harmonic is.

Signals and Harmonics

 

What are harmonics? For starters, it is not a sole property of musical theory. It is a property of waves in general. Where there are waves involved, there is a harmonic analysis that can be done. That is why we talk about harmonics in music, where the sound waves are generated from the physical interaction with the musical instruments. Music synthesis is no different, we generate the harmonics from electrical waves which are eventualy transformed into sound waves.

So how can we define a harmonic? We can keep it simple by saying that if you have a wave that has a given frequency F, a harmonic is a wave that has a frequency which is a multiple of F. You can generate a new wave with a different shape by summing the two signals. This will make F the fundamental frequency of that signal.

There are two ways that you can help yourself wrap your head around this. You can read about the Overtone Series), which is the music theory approach for understanding harmonics, or you can read about the Fourier Series which is the full mathematical foundation of sound synthesis.

It is hard to understand this and that is why the visual aid always helps. We will see exactly how a sine wave looks like and the rest of the basic signals used in music synthesis. We will be able to listen to them also and notice how the sound changes when there are different harmonics present in a wave. For this, we will be using the Fourier Transform in order to visualize the different harmonic components of a given signal.

That is why this post is written as a jupyter notebook, so we can get hands on with python for visualizing everything.

Importing Necessary Modules

 

I will use pandas as a plotter helper, I have found it is an easier way to deal with matplotlib. Numpy and Scipy are used to generate the signals that we want to analyze. In addition, Scipy will provide the necesary functions to do the Fast Fourier transform, which is what we need in order to visualize the harmonic content of the waves.

In [1]:
import pandas as pd
import numpy as np
from scipy import signal
from scipy.fftpack import fft, fftfreq
import IPython.display as ipd
import matplotlib.pyplot as plt

Define The Signals

 

As I mentioned above, we will be generating four signals:

  • Sine
  • Sawtooth
  • Square
  • Triangle

They will be plotted and audible.

In [2]:
wave_types = {
    "sine": np.sin, 
    "saw": signal.sawtooth, 
    "square": signal.square, 
    "triangle": lambda w: signal.sawtooth(w, 0.5)
}

Audio and Plot

 

We define our python function that will help us plot and listen to the signals.

In [3]:
def play_and_plot_wave(
    wave_type: str, 
    frequency: float = 440, 
    duration: int = 2, 
    amplitude: float = 0.01
) -> None:
    sr = 44100 # Sample Rate in Hz
    phases = np.cumsum(2.0 * np.pi * frequency / sr * np.ones(int(sr * float(duration))))
    wave = wave_types.get(wave_type)(phases) * amplitude
    yf = fft(wave)
    xf = fftfreq(len(wave)) * sr
    
    plot_args = {"figsize": (6, 4), "legend": False} # Plot arguments
    fig, (axis1, axis2) = plt.subplots(2, 1, constrained_layout=True)
    axis1.set_title('Signal', fontsize=12)
    axis1.set_yticks([])
    axis2.set_title('FFT', fontsize=12)
    axis2.set_yticks([])
    axis2.set_xticks(np.arange(1, 11) * frequency)
    
    pd.Series(
        np.abs(yf), index=xf
    ).plot(xlabel="Frequency (Hz)", xlim=(frequency / 2, frequency * 10), ax=axis2, **plot_args)
    
    pd.Series(
        wave, index=np.arange(5, len(wave)+ 5) * (1000 / sr)
    ).plot(xlabel="Time (ms)", xlim=(0, 20), ax=axis1, **plot_args)

    display(ipd.Audio(wave, rate=sr, normalize=False))

Analyze The Waves

 

We now proceed to look into each wave and understanding the graphs being displayed. Each wave will be generated with a 440Hz frequency (musical note A) and we will be able to visualize up to the 10th harmonic in the plot.  

WARNING

 

Be careful when listening to the audio. If you are wearing headphones, turned down the volume or take them off.

Sine Wave

 

The sine wave is the fundamental wave shape. From this, every other wave shape is formed. When we talk about any type of complex wave, we can always decompose them to a sum of the fundamental sine wave with its harmonics.

As you can see below, the top part of the graph shows you how a sine wave looks like. The bottom portion shows you the frequency components the wave has. We only see one frequency component at 440Hz, which is its fundamental frequency. So far, everything checks. The sine wave is in fact a "pure" fundamental wave and it makes sense to think that other wave shapes can be derived from it.

In [4]:
play_and_plot_wave("sine")
No description has been provided for this image

Square Wave

 

Square waves are used in many electronics applications, the most common one is for clock signals in digital circuits. In music synthesis, it is one of the most common and it is worth taking a closer look at it.

Below we see again the wave shape along with its frequency components. Different to the sine wave, we see 5 different frequency components. The one with the greater magnitude lies in the fundamental frequency of 440Hz, the rest are its harmonic components. As we can see, and this is one of the interesting parts, there are only odd harmonics (frequencies of 3, 5, 7 and 9 harmonic component) which seem to decay in magnitude exponentially. This means that we could break down this signal into at least 5 different sine waves with different amplitudes and frequencies based on odd multiples of the fundamental frequency.

In [5]:
play_and_plot_wave("square")
No description has been provided for this image

Sawtooth Wave

 

Into the sawtooth wave. Also known in music synthesis as plain saw or ramp, it is also very common in synthesizer hardware architectures.

Going directly to the harmonic analysis, we see that this wave has frequency components in all 10 harmonics and they also have their magnitude decaying exponentially. I often heard that in music synthesis the sawtooth wave is considered "rich in harmonic content" and now I understand why. The same principle applies as in the previous example: we could break down this signal into at least 10 different sine waves with different weights and frequencies based on odd multiples of the fundamental frequency.

In [6]:
play_and_plot_wave("saw")
No description has been provided for this image

Triangle Wave

 

The triangle wave is not as popular in synthesizer architectures as the square and sawtooth when being used in a VCO. When it is present, it is mostly considered for bass sounds or "suboscillator" usage.

The harmonic content of this wave is low, sharing the common characteristic of the square wave which is only odd harmonics are present. The difference is in the order of magnitude, which is obviously lower. If you can listen to the wave, the sound is much closer to the sine wave than to the square wave.

In [7]:
play_and_plot_wave("triangle")
No description has been provided for this image

Summing Up

 

We got to take a closer look into 4 different wave shapes most commonly used in music synthesis. The most harmonically rich wave is the sawtooth, followed by the square and triangle. Harmonics are not a musical concept, it is a property that we defined to help us describe complex waves in general.

Hopefully when you listen or read about "harmonic content" of a wave when looking into synths, you will now have a better idea of what they are reffering to.

There is a lot to talk about on how to manipulate harmonics in sound design. How there are substractive, additive and FM synthesis and how all of those techniques manipulate harmonics to obtain different results in sound waves. But that might be a subject of future posts.

Subharmonikorg: Subharmonic Oscillators for the Korg NTS-1

I have been using the Korg NTS-1 for about 5 months, but it was just recently that I was able to spend some time trying to understand how to program it. Korg published its logue-sdk which is written in C/C++ and it provides useful templates and make files in order tu build custom oscillators, delays and modulation effects for your logue based synths. I have only tried programming the NTS-1 since I believe one of the main purposes of this little synth is to experiment and understand the logue-sdk and how to digitally process the signals, which is another way of saying that if you mess up and brick your synth it will only cost you $99 to replace it instead of bricking the Minilogue XD which retails at $549.

For a complete review of the NTS-1, I recommend my favorite synth reviewer Loopop. Watch the video below:

 

 

The Subharmonikorg

With the introductions out of the way, lets talk about the Subharmonikorg. I was inspired to program this oscillator after I saw what Moog did with its analog synth, The Subharmonicon which is sort of a mix of two previous instruments: the Tratonium and the Rythmicon. I wanted to emulate the subharmonic sound generation and found out that the subharmonics are derived from the Undertone Series which is basically a mathematics formula that is used to calculate the subharmonics of a given note based on its frequency. So if it is mathematically derived then it could be programmed.

The formula is easy: just divide the note frequency by an integer and you will get the undertone frequency related to the original note. This can be illustrated in the code hosted in the Logue-Hub Repository:

 

const float w1 = osc_w0f_for_note(
    ((params->pitch)>>8) + oscillator.semitone, 
    params->pitch & 0xFF
);

...

sw1 = w1 / oscillator.undertone1;
sw2 = w1 / oscillator.undertone2;

 

Where the function osc_w0f_for_note returns the frequency value that corresponds to the pitch (note value) passed to the OSC_CYCLE function exposed in the logue-sdk API. Then w1 is divided by the undertones values taken from the editing params of the NTS-1, which are integer numbers greater than zero. I limited the max possible value of subharmonics to the 7th undertone.

Features

The features for version 1.1-0 are as follows:

  • One main harmonic oscillator with semitone calibration up to one octave higher and one octave lower.
  • Two subharmonic oscillators that divide the main oscillator tone up to the 7th undertone.
  • Choose different undertones for each suboscillator.
  • Mix between the main oscillator and the suboscillators with the shape and alt knobs respectively.
  • Choose between square, saw and sine waveforms.
  • Modulate the main oscillator mix with the LFO.
  • Subharmonic oscillators arpeggiator with clock adjustment.

The arpeggiator is a separate implementation from the native NTS-1 arpeggiator. In the current version 1.1-0, there are only two patterns available which only affect the suboscillators: down and up-down. This means that if you hold a note, the main oscillator will stay on it while both suboscillators will cycle from the 2nd through the 7th subharmonic. Having separate arpeggiators allows you to play with interesting rhythm patterns.

Parameters

The parameters you can edit are listed below.

 

Parameter Range Description
SHAPE 0 to 100 level mix of main oscillator
ALT 0 to 100 level mix of suboscillators
semitone 1 to 13 semitone tuning of main oscillator (1 as root note, 13 higher octave)
undertone 1 1 to 7 undertone value of first suboscillator
undertone 2 1 to 7 undertone value of second suboscillator
oscT 1 to 3 The oscillator type 1: saw, 2: square, 3: sine
Arp Type 1 to 3 The arpeggiator type 1: off, 2: down, 3: up-down
Arp Clock 0 to 100 The arpeggiator clock percentage of max frequency.

 

The Showcase

I did some noise experiment where I played with the NTS-1 Subharmonikorg and Moog's Werkstatt-01. The Subharmonikorg is playing its arpeggio while I hit some lead notes with the Werkstatt. I tried to keep the mood creepy.

 

Here is the video of the weird experiment:

 

 

  • For the whole 7 minutes noise, listen to it in bandcamp here.

  • Get the latest version of the Subharmonikorg in github here.

There are some other oscillator ideas I have and some new features I want to test out for the NTS-1 for this oscillator. Hopefully I will also try this out with my newest adquisition, the Minilogue XD.