32-Voice Synthesizer


Dual Waveset Synth with 5D Filter, and More
Dual Waveset Synth with 5D Filter, and More
Dual Waveset Synth with 5D Filter, and More
On this Page:
Downloads of 'Mocha Edition'
Quick Start
Main Features
Help Panel Screenshots
Design Source
(Click the images for a lightbox slideshow)

Husserl2 aims to be one of the best free synths you can get. Because it takes advantage of all the cores available on your machine, it cannot run inside plugin hosts, which only support one core thread per plugin. As a result, this is a standalone app with native, ASIO, and ReWire client drivers for connection to all current standard DAWs. Although the app includes anti-aliased oscillators and a 4x-oversampled filter, for professional applications a sample rate of at least 88kHz is recommended to provide crisp results in the C8 octave, but if you only play to C7 then standard sample rates are sufficient.

Downloads of 'Mocha Edition'

Windows 10 (64-bit):

Cycling74 Max8 Source:


Quick Start

Created: Winter 2019
Modified: Oct 6 2021
Mocha Release

Warning: Michael Jackson in my YouTube Demo! Most people don't like my own music, lol, and my YouTube vidoes take a while to get going, but everyone who's tried the synth out for themselves are very pleased with Husserl2.


To try it out, unzip to any location and open. If necessary, select a different Audio Driver from the toolbar or menu. The ad_directsound driver works for me. There's also ASIO and ReWire drivers if you want.

To demo the presets, double click the preset names to recall them (a single click on the preset names selects them for the add/insert/replace/delete buttons). The current playing notes are saved with a preset when you store it. If you dont want to recall notes when recalling a preset, turn RESTORE NOTES off.

The next most important thing to know is that the list boxes below each knob select a modulation source for that knob, with the modulation amount set by clicking and dragging on the number field below the list box.

The toolbar in the top left of the main panel has buttons to open the MIDI file player, bank manager, and detailed interactive help.

Main Features

Help Panel Screenshots

Husserl2 Oscillators
Husserl2 Oscillators
Husserl2 Filter
Husserl2 Filter
Husserl2 Envelopes
Husserl2 Envelopes
Husserl2 Modulators
Husserl2 Modulators

Husserl2 Toolbar and Keyboard
Husserl2 Toolbar and Keyboard
Husserl2 Microtunings
Husserl2 Microtunings
Husserl2 Preset Manager
Husserl2 Preset Manager
Husserl2 MIDI I/O
Husserl2 MIDI I/O

Husserl2 Audio Setup
Husserl2 Audio Setup

Design Source

Husserl2 Source Design
Husserl2 Source Design

The Max8 patch uses no phantom or vitual connections, and is fully wired, because SEND/RECEIVE pairs introduce an internal buffer delay. Likewise, the control portions of the patch are flat to reduce queue latencies from traversing the inlet/outlet ports. The main patch also contains a compiled JavaScript routine for maintaining display indicators, such as the filter and wave curves. The JavaScript runs in a low-priority thread at screen-refresh rate, so that processing and display of indicators do not interrupt the audio routines.


Husserl2 Setup Patch
Husserl2 Setup Patch

Much of the audio and display data is precalculated and loaded into buffers to reduce unnecessary transcendentals and divisions. The setup patch shown on the right loads all the buffer data, configures display elements, and defers starting the audio DAC by a message on the low-priority queue (so the buffers and other audio parameters have a chance to initialize first).

Design Notes: Audio Datapath

The audio data patch is derived from the SynthCore Library on this site. The SynthCore library will be extended with this designs enhanced filter and compander. The methods are mostly straightforward. Conditional statements and 'Selector' arguments contain all temporal-specific code, so that only the processing needed for the current clock cycle is performed. The main routine uses acronyms for the 115 input Params, which significantly reduces load time. At the end of the main routine, audio data values neeeded for display indicators for the most recently played note are poked to shared buffers, on a slow clock synchronized with the display rate, and picked up by JavaScript for additional processing on the low-priority thread.


The active voices are then mixed and passed to a single-channel output mastering routine. It would be simple to add individual outs for each voice, if desired.


Design Notes: Voice Allocator

Newest in this design is the gen-compiled voice allocator. The algorithm uses three buffers: two to maintain the current pitch and velocity of active notes, and one containing the voice age queue, which is preloaded with values from 1 to 32. When a new note-on message is received, it is placed at the begnning of of the queue taking the voice number of the oldest voice in the age queue. The age of all prior notes is incremented, and the audio path for that voice is switched on in the next audio clock cycle. When a note-off message is received, it is removed from the queue, and older voices which might still be in the release phase are moved up the queue to fill the hole it leaves, then the voice number of the turned-off note is inserted after the last of the previously released notes. This technique ensures that all turned-off notes remain in the queue for the longest possible duration so that their release phases may complete uninterrupted if possible. When the note reaches the end of its release phase (the amplitude envelope reaches zero), the note is turned off in the audio path to reduce CPU utilization. Lastly, the below code issues the voice number of the most recently played note on outlet 5, which sets the voice used for subsequent screen-display of waveform and filter curves. The code listing follows.


Design Notes: MIDI and Preset Management

Data from a MidiParse object is passed through initial filtering routines before being sent to the preset manager patch. All incoming MIDI data is scaled by a gen object, with a little external string parsing, in the MIDI parse subpatch. The resulting param name/value tuples are sent through the PattrStorage object, then distributed to controls by a pattrHub object at the patch's top level. Outgoing MIDI data is scaled by a gen object that performs the same transformations as for incoming data, but in reverse. The pattrstorage bank is loaded and stored in the Bank Manager patch, which does some tricky stuff to determine the current directory on both PC and Mac platforms.

Husserl2 MIDI Parsing
Husserl2 MIDI Parsing
Husserl2 Program Manager
Husserl2 Program Manager
Husserl2 MIDI Mapping
Husserl2 MIDI Mapping
Husserl2 Bank Manager
Husserl2 Bank Manager

Upon any panel change, the parameter value is immediately stored in an empty preset slot. Upon closing the device, the slot is saved, and restored upon reopening. Also, with prior experience on Reaktor I found the default method for inserting and deleting presets counterintuitive, so I added the small code section in the [patches] subpatch. This code for example APPENDs presets in the next available empty slot, rather than after the last preset in the bank. Special care is taken on boundary conditions to ensure that a user's hard work is never lost.


Please contact me if you need assistance with patch modifications, and I will do what I can to help.