Wavetable sound synthesis engine.
It's a proof of concept helping understaing the topic and eventually implementing similar synthesizer on STM32 ARM chip.
What's included:
- BPM Clock with trigger and gate
- Sequencer x3
- ADSR envelope for amplitude and filter
- State Variable Filter
- Phase modulation
- Waveform generators + collection imported from Plaits
- Waveform oscillator
- Waveshaper based on waveforms, bipolar and unipolar
To play a sound load and run sound.core
(use toggle-playing
to start/stop sound generation).
sound.patch
defines complete configuration of the synthesizer you can change it live(!).
Listen to the Lost Woods from Zelda - Koji Kondo generated by syntesizer. This is what is defined in sound.patch
Implementation is highly based on Mutable Instruments source code and enables easy translation to C++ (custom types and class-like modularity).
Singal is created by following path:
- Clock / Sequencer generates MIDI note + information about the gate (open/close + trigger)
- Both ADSRs (amplitude and filter) are triggered
- Oscillator generates sample from wavetable (actually two wavetables mixed together) and phase which is calculated from note frequency and phase modulator (the other oscillator)
- Signal can be shaped by another oscillator
- Signal is filtered by filter controlled by ADSR
- Amplitude ADSR is applied
- Above procedure is applied for two other sequencers and mixed (added) together
- Finally, hard clipping is applied + quantized to 8-bit depth
Every step generates new sample which are gathered in small buffer and send to audio engine.
Waveforms are bandlimited (generated as sum of sines or as FFT/IFFT interpolation) wavetables of 256 samples. Waveform is stored as integrated signal (according to Higher-Order Integrated Wavetable Synthesis) as 16 bit signed integer (short
type). This representation + following procedure generates sample with minimized aliasing.
Sample generation follows the procedure:
- For given frequency scaling factor, gain and one-pole low pass filter coefficien are calculated
- Current phase is taken from previous phase and step (taken from given frequency)
- Integrated sample is read from wavetable using 4-point hermite interpolation for given phase
- Difference with previous value + one-pole low pass filter + scaling + gain gives the sample
State Variable Filter is used here because it's simple and doesn't require trigonometry (actually it's partly true, tan
is required but some interpolations can be used instead) functions to calculate the parametrization and the result. The second: 3 filtered samples are generated at once: low pass, high pass and band pass.
There is an option to modulate the phase (which is cheap replacement for frequency modulation (FM) - but works well enough) by other oscillator. Also there is an option to shape wave by any defined waveform.
It works by adding value of one oscillator (multiplied by amount) to the phase of second oscillator.
Amplitude of the signal is used as a phase of the shaping oscillator. Both values are mixed together (you can control amount)
Attack-Delay-Sustain-Release shaper is used to control amplitude of the signal and frequency of the filter. Slopes are exponential.
Patch, as a configuration of every module in the path, are kept as global variables to allow live coding. Playing is done in separated thread as future
. Thread is stopped via playing?
atom.
- Sample rate: 44100.0Hz
- Bit depth: 8 (-128 to 127)
- mono
- 3 independent tracks (sequencers) mixed together.
- echo / delay
- resonator (implemented, not tested)
- build full collection of waveforms
- write blog post about this implementation
- translate to C++
Copyright © 2020 GenerateMe
This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0.
This Source Code may also be made available under the following Secondary Licenses when the conditions for such availability set forth in the Eclipse Public License, v. 2.0 are satisfied: GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version, with the GNU Classpath Exception which is available at https://www.gnu.org/software/classpath/license.html.