32-Voice Synthesizer
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
- 2 Oscillators with dual contour, phase, ring modulation, frequency modulation, oscillator mix, plus gate/osc sync controls. EPTR-antialiased square/pulse and saw/triangle waveforms are followed by 44 wavesets, including filter sweeps, morphs, formants, and harmonic bundles. The wavesets contain 5,842 individual wavecycles, with 256 sample points each, and 127 wavecycles per waveset. To calculate intermediate points between each wavecycle, the current wavepoint is spline-interpolated for the prevous and next wavecycle, then the fractional offset is linearly interpolated between them to create the output value.
- SVF Filter with cutoff, resonance, 0/2/4 pole mix, LP/BP/HP mix, and saturation continuously variable in 5 dimensions, providing a million unique settings from the synth panel. There are some dead zones, but the filter is always effective with cutoff set to note pitch, and provides about half a million unique usable sounds (by setting the filter cutoff above the note pitch if mixing more low-pass filtering, or below the note pitch with more high-pass filtering). When set lower, transient peaks are louder, until there is no saturation at the minumum setting. When set higher, the input is boosted, and transient peaks are increasingly distorted by mirroring the signal to within the unity-gain range.
- Internally, the filter is a dual two-pole Butterworth cascade, with the the lowpass, bandpass, and hipass outputs mixed after each stage. The input is delayed to remove phase offset from the filter and mxed appropriately with the two-pole and four-pole outputs, which is then passed to a 4x-oversampled saturator (a tanh-based waveshaper, with level continually adjusted between maximum levels sampled at 40Hz, and mirror-based distortion at higher saturation settings). Finally the saturator output is downsampled and returned. The filter curve display for the 100,000 possible filter settings is calculated at screen refresh rate from a 1,000-entry table of predrawn 100-point filter curves.
- Compressor and limiter with polyphonic and monophonic modes. The limiter and compressor are integrated into one function for optimal performance, with min/max samples at the filter saturator rate. Standard attack, release, threshold, and ratio controls are available.
- Internal Modulation Matrix with 151 modulation destinations and 143 sources including:
- 3 ADSR Envelopes with graph control of velocity shaping. The ADSR curve is linearly interpolated from a precaulculated, 64K-entry tablle of POW(2.5) values. ADSR values are updated at audio rate.
- 3 LFOs with sine/double-sine, square/pulse, saw/triangle, stepped, and random waveforms; contour shaping, freq mod, amp mod, and sync; two polyphonic, one monophonic linked to mod wheel. The LFOs calculate output values in the same manner as for the oscillators, except anti-aliasing is disabled, at audio clock rate.
- Sample and Hold with adjustable trigger level on the modulator. The S&H output is available for mixdown in the XY pad.
- XY Pad to mix up to four modulation sources to any modulation destination. The individual X and Y axes, as well as the combined XY value, are available as modulation sources in additive and multiplicative forms. The additive form mixes the X/Y values, and the multiplicative form allows an envelope to control the LFO level, for example.
- 120 Mapped MIDI Controllers, plus bend, modwheel + lfo, note pitch, velocity, voice number, and #notes. the voice number allows for example slight detunings on each voice.
- 50 Microtuning Tables with classical, oriental, and experimental tunings across the entire MIDI range.
- Preset Manager with simple button controls, preset naming, and bank load/save.
- Lots of Demo Presets. Notes may be stored and recalled with presets too.
- MIDI file player built in, with channel selection.
- MIDI I/O: note on/off, MIDI clock, program change, pitch bend, all 90 panel controls, and standard MIDI controllers such as pedals, etc.
- Graph Display of oscillator waveforms, filter settings, audio waveform, and modulation values for most recent voice.
- Resizable Panel. Zoom in or out as much as you like. Synth reopens the way you closed it.
- Interactive Help built in for wavesets, filter characteristics, microtuning tables, and with complete description of all panel controls.
- Fully Compiled 64-bit Multithreaded Audio Path, carefully optimized for performance without sacrificing quality. Base CPU usage is ~9% for first voice, +0.75% per playing voice, on a 4GHz i7 @44.1kHz with Windows10 DirectX drivers.
- Open Source distribution in Cycling74 Max8, if you wish to change it in any way.

Help Panel Screenshots









Design Source

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.

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.




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.