KSynth

CPP, ASM

64kb realtime modular software synthetizer

Introduction

One of the main features that determine the quality of a 4kb/64kb intro is the music. Traditionally coders used the minifmod lib to play tiny XM music modules, tipically made using FastTracker2. This library is a very small module player implementation that doesn't tax too much the CPU, leaving room for the effects.

KSynth

The problem of using XM is that you can’t use high quality samples as they must be stored inside the module file, limiting the quality of the sound. Therefore, the most common music style was chiptune. A later attempt to improve the quality of the music was to store the XM without the samples (just music notes, patterns and sequences) and generate the samples procedurally on the code while loading the intro. This approach gave much better quality but the loading times could increase considerably. Also, even if the quality of the generated samples were good enough, the player couldn't help much with the effects and postprocessing of the final music.

On december 2000 the demogroup farbrausch released a 64kb intro fr-08: .the .product which was a significant milestone in sound quality and the reference for years in this category.

The music on the intro wasn't a module with precalculated samples but a full realtime software synthetizer (softsynth).

KB did and excelent work while coding his famous Virus softsynth and everyone wanted to know how to create their own synthetizers. Even if you were familiar on the theory you would need to deal with two big problems: not to be expensive in CPU usage ,as everything should be calculated in realtime, and enough tiny to fit in a 64kb intro. He explained the details of his implementation on a series of articles.

Origins

At that time I started to read them and visit IRC and websites like musicdsp. I started a proof of concept synth as I never developed anything related to real-time audio, and the following is the very first audio test I created using it:

After that I worked hard to have nice sounding drums and add massive reverb to hide my shortcomings as a composer:

Being a newbie I was quite happy with the result but I knew it didn't have the quality expected for a state of the art 64kb, so I started to dig on DSP, filters, and size and CPU optimization. At that time I met the most talented audio programming guy I've ever known: arguru, so sad he passed away so young :(

He was the creator, among other cool projects, of Psycle and I learnt a lot from the base code of this modular music creation software. After that I was also interested on his plugins for Jeskola Buzz, a very famous modular music software full of plugins by its huge community.

Once I got the synth code and player I decided it could be fun to try to make a module system similar to buzz and psycle. I had experience with Borland C++ Builder as I already developed the first version of the KTexGen on it so I decided to keep using it for the UI and Visual Studio C++ for the player engine and plugins. Each box was a DLL plugin, they could be generators of sound (drums, sinewaves, ...) or effects (phaser, flanger, reverb, ...). Those boxes could be connected together to chain the transformations applied to the original signal.

The UI ended up being a mix between psycle and buzz, adding the features I liked the most and others they didn't have yet.

KSynth

For example I made it easier to test the presets for each machine as you could just click the preset and press any key to get it note with the current preset:

KSynth

The pattern editor lets the musician to edit every parameter from the current plugin and allows virtual unlimited polyphonic voices. I implemented some extra features like copy & paste, parameter range checking, interpolation between values. You could even let the editor generate random parameters values for you.

KSynth

In the sequence editor I tried to replicate the same features as the original buzz as I found it quite easy and intuitive to use.

KSynth

The following video shows a basic usage of the ASKSynth:


Once I released the alpha version of the KSynth I got the help from many musician friends: Herotyc, Wonder, r08028, Josss, Khrome, among others, and they started to play with the synth and keep sending me much better quality tests that the ones I did:

Buzz

Even if the ASKSynth was used in several compositions as I kept learning about synthethizers I started to create a new generator machine: KSynth2. I must admit I got quite tired of the development of the UI even if it got a stable release, so I decided to move on with the UI and create a plugin for Buzz and give a try. Once I got the plugins running on buzz, it was a quite easy task as I based my plugin interface on theirs, I started a file format parser. The specs weren't official anywhere so I did a reverse engineering to parse the whole file. I soon got a BMX to KSYNTH (Really a binary and a C++ header file) converter.

These screenshots show the complexity of the ThisWay64k theme from Wonder.

Conclusions

This project was probably one of the hardest I did as it involved plenty of challenges:

  • Realtime digital signal processing: I didn't know much about DSP and it's a very interesting field but also quite hard to get working propertly.
  • Performance and size optimization: Although it was a bit challenge to optimize the whole synth and plugins to prevent taxing the CPU too much, the hardest problem was to optimize the binary format of the final song. I followed the advices from kb about using deltas, I remap and normalize parameters, used bitwise store, grouped the same kind of actions and plenty of more tricks.
  • Plugin systems: Each machine (Generator or effect) was an independent DLL. You could just implement a simple plugin definition included in a header file, compile your plugin to DLL, place on the plugins folder and the editor will load it automatically.
  • Integration between different systems: The UI was developed in C++ Builder, the 64kb intro library was done in C++ and ASM with Visual Studio. The link between the UI and the LIB was the plugin system described below.
  • Multithread: It was a must to run the synth code in a different thread from the main intro code, but they needed to be synchronized so the animation should follow the music.
  • Reversing-engineering binary format: Deciphering a binary format from a third-party software is is always a complex task so I needed to do my best to understand the BMX file format from Buzz.
  • A lot of custom UI development. C++ Builder didn't include a good enough grid control so I needed to create a new one from scratch. It was used for the pattern and sequence editor. I implemented double buffering to avoid flickering and a lot of cool features as copy paste or multirow and multicolumn selection.

The synth was used on three 64kb and on several 32kb exe music competitions. Although I got plenty of cool songs that never got released.

Songs and attempts

Here you could listen some of the coolest: