Polyphonic, stack based synth & livecoding environment for STM32
Project overview (2016/02)
Adobe Portable Document Format - 463.30 kB - 02/15/2016 at 21:27
As an interim solution & since work got in the way over the recent months and has caused slow down (not halting!) development of this project, I've decided to push some of the earlier and more stable versions to this Github repo: http://thi.ng/synstack
For now this repo includes an iteration of the earlier node graph based, but more feature-rich synth engine (incl. 8 examples) and an earlier version of the Forth VM & REPL. Note though that this repo only contains the portable synth code and no STM32 specifics. Instead, to make experimentation easier for more people, all demos use Portaudio to allow running on OSX/Linux (Windows principally too, but untested).
Next weekend (20-21 Aug) I will run another iteration of the STM32 synth workshop, which might produce some more updates on this front...
Since all of the recent re-workings of this project have been centered around the idea of a Forth-style stack VM for defining audio operations and resulting synth voices, I decided to finally name the project: Synstack.
The stack VM is pretty functional by now too and heavily inspired by the classic JonesForth, a threaded code implementation of Forth, albeit so far still written in C. More highly useful guidance came from @phaendal's great documentation-forth (even though it's in Japanese) - both of which are probably the most readable Forth implementations I know of. So far no consideration has been given to aiming for ANS Forth compatibility.
The Synstack VM currently clocks in at 24-27KB. This includes some audio related stuff: oscillators, ADSR, IIR filter, foldback distortion, all of which are implemented as native words. The VM also features floating point support, basic string ops and user customizable inlining of Forth words (e.g. to speed up var lookups). Control structures, vars and a basic disassembler are implemented as Forth words.
The audio result of a few variations of the following monophonic synth code can be listened to here:
The final "update" word is repeatedly called by the audio manager to provide the next time slice of 32 samples. So far I found this to be the sweet spot between RAM usage for potentially dozens of operators (especially once polyphonic) and satisfying the Cortex M-7's cache line(s), however the buffer size is customizable. In this example the "update" word also acts as simple probabilistic sequencer, triggering new notes every 150ms w/ 60% chance. On the STM32 this all is triggered via the DMA ISR callbacks, on OSX I'm using Portaudio as audio backend for testing, which uses a v.similar approach...
It's nothing super exciting sounding just yet, but I'm very excited by the possibilities this opens... The first public release of this project is aimed for in mid-April...
Just ported and extended the MIDI step sequencer demo from previous STM32F401 iteration to STM32F746 and updated the repo.
The Korg Nanokontrol is configured as follows:
- the first row of buttons ("S") is used as 8 step sequencer for track 1
- the second row of buttons ("M") => track 2
- 2 leftmost sliders control filter cutoff freq for sequencer tracks 1 & 2
- 2 leftmost dials controls resonance for each filter
- 3rd dial => delay feedback
- 4th & 5th dial => attack time for track 1 & 2
- Marker left/right => change waveform for oscillator 1 (all tracks)
- Track left/right => transpose current sequence by -12, -5, 0, +7 or +12 semitones
- Rewind, Stop & Play do as expected (when the app starts, it is in Pause mode - you'll need to press Play and activate at least one "S" or "M" button)
The notes played in each sequencer track are randomly chosen from a musical scale defined in the source code. If you don't like a note, simply de-activate and then press the "S" or "M" button again to get another semi-random note...
Just a week after teaching a workshop at ACT Festival in Gwangju, we repeated and expanded on the experience and examples in London, built a 8-step / 2-track sequencer using the buttons on the Korg NanoKontrol MIDI controller and its faders to control various filter & oscillator params. Got some great feedback from participants and then focused on re-development using more generic DSP operators. Also ordered STM32F7 board with faster CPU & touch screen...
The first workshop using the latest iteration of the synth happened last weekend (23-24 Jan 2016). Outcomes are a new lightweight GUI module (soon to be released as separate library) and it was also the first time combining the synth with the touchscreen setup of the STM32F7 disco board. It turned out that polling for touchevents is a pretty costly (in terms of CPU cycles) operation and forced the use of high-priority timers (every 2ms) to keep the DMA half-buffers filled with fresh audio data. I recorded a little live session of the last workshop example and uploaded here: With the synth now pretty solid, the near future will be focused on getting ready an usable implementation of the synth DSL...
See workshop repos on Github for details how to build the current prototypes / examples