CrispyZebra is a lightweight, high-performance C++ synthesizer core engine designed to replicate the Phase Distortion (PD) synthesis of the 1980s CZ-series synthesizers.
https://hugelton.github.io/CrispyZebra/wasm
The interactive WebAssembly (WASM) implementation with a full GUI is available.
- Authentic PD Synthesis: Reproduces the Phase Distortion waveforms including Saw, Square, Pulse, Double Sine, Saw-Pulse, and Resonance windows (Saw, Triangle, Trapezoid).
- 8-Stage Envelopes: Three independent 8-stage EGs (DCO, DCW, DCA) per voice, fully compatible with vintage hardware SysEx point systems (Sustain/End points). DCA output can remain linear or use a selectable pseudo-exponential response for CZ-style loudness experiments.
- Fixed-Point Math: Designed with platform-independent integer arithmetic (int32_t / Q16) for minimal CPU overhead.
- WASM & Embedded Ready: Zero external dependencies (header-only wrapper ready). Suitable for both browser-based execution and microcontrollers.
- Modulation & Master Section: Built-in Vibrato LFO, Detuning, Key Follow (DCA/DCW), Ring Modulation, Noise Modulation, Portamento, and Master Drive/Pan controls.
The engine is structured within the CrispyZebra namespace:
-
Oscillator: The core Phase Distortion engine utilizing a custom Sine Look-Up Table (LUT) to warp phases dynamically.
-
Envelope: High-precision Q16 internal state envelope generator supporting up to 8 stages with rate/level configurations. -
LFO: Low-frequency oscillator providing Triangle, Square, Saw Up, and Saw Down shapes for pitch modulation.
-
Voice: A polyphonic container that couples two parallel lines (Oscillators) with routing, detuning, and modulation options. -
Engine<MaxVoices>: The template-driven master class that handles MIDI inputs (midiNoteOn/midiNoteOff) and renders block buffers. The default WebAssembly build intentionally usesEngine<8>in all line-select modes; two-line patches are not reduced to four voices.
CrispyZebra is a single-header engine. Include CrispyZebra.h into your project.
#include "CrispyZebra.h"
// Prepare your Sine Look-Up Table
const int16_t my_sine_lut[2048] = { /* pre-calculated sine values */ };
// Instantiate the engine with 8-voice polyphony
CrispyZebra::Engine<8> synthEngine;
void initAudio() {
uint32_t sampleRate = 44100;
synthEngine.setup(my_sine_lut, 2048, sampleRate);
}
void processAudio(float* buffer, uint32_t numSamples) {
// Render stereo float samples directly into your audio callback
synthEngine.processBlock<float, true>(buffer, numSamples);
}
void onMidiEvent(uint8_t status, uint8_t note, uint8_t velocity) {
if (status == 0x90 && velocity > 0) {
synthEngine.midiNoteOn(note);
} else if (status == 0x80 || (status == 0x90 && velocity == 0)) {
synthEngine.midiNoteOff(note);
}
}
The WebAssembly build defaults to 44.1 kHz, but the default engine rate and the browser AudioContext request can be selected at build time:
cd wasm
make SAMPLE_RATE=48000Browsers may still choose the hardware output rate, so the engine is initialized with the actual AudioContext.sampleRate after startup.
- PicoCZ: A hardware port of the CrispyZebra engine optimized for the RP2040 (Raspberry Pi Pico) microcontroller.
This project is licensed under the GNU General Public License v3.0 (GPL-3.0) - see the LICENSE file for details. Copyright (C) 2026 Leo Kuroshita (@kurogedelic)
CrispyZebra is an independent open-source project developed by Leo Kuroshita. It is not affiliated with, endorsed by, or associated with CASIO Computer Co., Ltd. in any way. "CZ-101", "CZ-series", and "Phase Distortion" are referenced solely for historical and educational compatibility purposes.
