This is my engineering log for the development of an analog/digital hybrid modular synthesizer system. The synth will be built from a collection of separate modules which can be connected (patched) like a traditional modular synth. The modules contain a fast CPU and an audio codec and perform all work in the digital domain. The same PCB design is used in all modules, and the firmware will make each module behave as a different function like oscillators, filters, wave shapers, delay, reverb, etc.
Some specs for the module so far:
Source and design files are available on Github
The synth basically works: I've put 5 modules in a wooden contraption, and I now have a fully working modular synth. The front panels were laser-cut by a local company and spray-painted by hand, I haven't found a cheap method for printing the panel designs yet.
The biggest problem with the current design is that the input circuits for voltage conversion have a flaw, causing a non-zero input value to be read if the input is not connected. To fix this the input stage needs to be redesigned. This is basically done in the schematics, but I have not updated the PCB for this yet.
I've put quite some time and effort in this, and it would be a shame to let it all to waste. In case anyone else might be interested to pick this up, all design files and source code is available on Github
At this time the board requires external +5 and -5 analog voltages. Not a big problem, but for a next revision I will try to get a DC/DC converter on board to generate the negative power supply voltages to simplify external interfacing.
Bringing up the SSM2604 codec chip was a bit of a hassle: there was an excessive amount of noise in the ADC, which had me baffled for some time. After a long day of debugging I found out that there was jitter on the I2S master clock generated by the LPC4330, which the codec really does not like. This was resolved by using a different clock divider, and audio is just fine now. I haven't done proper measurements for SNR yet, but at this time noise is below audible level for me.
Also some more proof of concept modules were implemented: multitap delay and pitch shifter are both functional
The DSP modules are now also stored in flash, so the board is now able to run self contained without having to load the software in the PCB from the PC every time.
Basic MIDI over USB is also starting to work. This will be used as the main machine interface for control, debugging and firmware updates. I've been fighting to integrate nxpusblib, but that's a big pain to integrate. The headers clash with LPCOpen, and there's a lot of overhead that is not needed for my project.
Instead I just implemented the USB MIDI spec on top of the minimal ROM USB driver, which seems to work just fine. Next would be isochronous audio over USB, but I'll save that for later.
And last but not least: the PCB's and most of the components are in. The first PCB will be assembled by hand, whish me luck!
The current panels are generated from the code; a simple SDL defines the inputs, outputs and controls and generates some C code which makes sure the right signals are delivered to the right modules. The same DSL is used to generate front panel layouts, which I hope to send to a printer one of these days.
At this time a DSP program can be loaded into the lower memory bank from flash or USB, after which the M4 reboots into the new image - all the while the M0 just continues running the OS functions like handling the USB stack, flash I/O, I²S, A/D converters, etc.
The DSP code in the M4 does almost nothing at bootup, since all the peripherals are already initialized. It just goes in a tight loop, waits for samples to arrive, performs the DSP functions for the specific module, and goes to sleep again.
The main advantage is that the M4 is now 100% available for audio, so there will never be issues with jitter or interrupt latencies. Another pro is that by using polling a lot of cycles are saved, because the interrupt handler does not need to do any extra work to save and restore the floating point CPU context.
Routing was quite an adventure, taking in account proper separation of analogue and digital power domains, decoupling, et cetera.
The analogue input and output stages are built around TL972 rail-to-rail very-low-noise op amps. I've been told these are an excellent choice for audio applications, although they're not the cheapest.
The audio inputs take -5..+5 volts at 10KΩ and are passed to the codecs completely flat, 0Hz to 24Khz.
The control inputs also take -5..+5 volts at 10KΩ, but have a 6dB/oct filter with a cutoff at approx 12Khz to allow higher quality sampling at 48Kz.
The module will be fit with 12 footprints for banana connectors, potmeters or switches,
and will have two 96Khz 24 bit
SSM2604
codec chips giving 4 high quality audio inputs outputs. The other 8 slots are
connected to the ADC channels of the LPC43XX chip and can be used for reading
out potmeters, switches or low quality audio channels.
I decided to convert the analog channels from 0..+3.3 to -5..+5 volts. Although
this will cost a handful of opamps and resistors, this will probably be worth
the advantages like better signal/noise ration and compatibiity with other synths.
Of course there is still a lot to do: adding more modules, optimizing
performance, making use of the M0 core, add support for the CAN bus, add
USB audio support, et cetera.
The setup consists of a wooden panel with each LPC xplorer board routed to two
audio inputs, two audio outputs, and some potentiometers and switches connected
to the ADC channels.
Not everything is wired up yet, but the first sounds can be patched.
I have also spent some time measuring the audio performance using the UDA1380
codec chip (which is the default on the LPC Xplorer board). I'm looking to use
a 24 bit codec in the real design, but these tests might give me a preview on
what to expect.
The first minisynth will be built from two LPC4330 CPUs with one UDA1330 codec
each. Instead of using the banana plugs I'll just put up some header pins on
the PCB so I can patch with tiny test leads.
I hope this first board will answer some questsions:
I now got myself a basic simple app: initialize the I²S bus and UDA1380 audio
codec, and handle audio with only one sample latency directly from the I²S IRQ.
I added basic performance monitoring to see how much time is spent in interrupt
context. Using the (32-bit float only) FPU of the Cortex M4 I'm able to run a
serious number (50+) of biquad filters in real time. CPU performance seems to
be just fine for this purpose.
The problem with building a real analog synth myself is this: I'm just not a
analog kind of guy. The old fashioned way with tons of dedicated PCB's with
descrete components is just not going to work for me. Instead, I'm going
digital.
My first idea was just to fake it: build a kind of stub panel with a lot of
modules and interconnects, but with no audio passing through. The whole thing
is just one big HID interface, connecting to a PC which does the actual work of
generating sound. That would probably work and could be pretty cheap, but it
feels too much like cheating to me.
I came up with a pretty simple alternative plan instead: design a single PCB
with a fast CPU, a few channels of high quality audio and some A/D converters
and GPIO for connecting potentiometers, LEDs and switches. The same type of PCB
can then be used in a large number of different synth modules: VCO's, filters,
wave shapers, delays, et cetera, just by putting in different software and
mounting them on different front panels.
I've orderded a
development kit
today and hope to do some first tests this week to see if I can get low latency
audio to work.
// vi: ft=html
2017-10-02: Software architecure
The software architecture is kind of done. I can now conveniently put
DPS functions into modules, and bind one or more modules to the various
in- and outputs of the board, and I've made some basic modules for VCO,
VCF and reverb.
2017-09-30: Audio measurements and prototype build
Today I spent some time building the first basic prototype. I found myself
another two LPC43xx development kits, so I just put them all in.
The bad:
2017-09-29: First prototype parts
Yay, parts for prototype A are in.
2017-09-28: ADCs
With some trickery the LPC43xx ADCs can now be used as additional 10 bit
analogue inputs at 48Khz, with 2.13 times oversampling. Far from optimal for
audio (too low resolution, lots of jitter), but very usable for reading
potentiometers and control signals. Unfortunately the IRQ load of the ADCs at
full speed take up quite a bit of the CPU, but I guess 8 additional channels at
this speed is overkill anyway.
2017-09-27: Board bringup
Yesterday I received the
LPC4330-Xplorer
board from farnell. Bringup was not too hard because of the sample apps provided with the
LPCopen
libraries, although I had to fix up makefiles and linker scripts myself, as those
are not included. (these are probably generated by some kind of IDE, which I do
not have)
2017-09-25: Intro
I've been toying the idea of building myself a modular synth for ages, but for
various reasons this just never got off. Building musical instruments requires
a lot of planning and is lots of work, and seems to take more persistence then
I can bring myself to.
However, visiting
Thomas Ankersmit
at the
TodaysArt
music festival last week gave me new inpsiration. Over the years I have had
lots of fun with
various
other
real
,
not so real,
and
virtual
modular synths in the past, but I particulary liked the design and philosiphy of the
Serge modular
synthesizer. It has slick looks, and I love that it allows patching multiple
cables in one connecter by using banana plugs instead of the more traditional
jacks.
The time is here for a design like this: fast CPUs and audio codecs cost next
to nothing because these are now mainstream parts for consumer electronics. I
have put up some basic specifications I'd like to meet on the module:
I've found a good candidate CPU from NXP (LPC4330), which can be paired with
any basic codec over
I²S
for doing high quality audio. There's a dual core (!) Cortex M4/M0 in there,
a lot of A/D channels and timers, and all for the price of a coffee at a
restaurant.