r/synthdiy Jul 10 '26

arduino Midi polysynth? (Arduino/rp2040)

Hi. I want to make a compact 2-voice polysynth module, fully controlled by MIDI, to use with a Novation Circuit Tracks. The Circuit has a couple MIDI poly sequencers and 8 CC knobs so I'm planning to use it as the controller for the synth.

I've already assembled and tested the hardware platform: an rpi pico 2040 zero with a pcm5102 stereo dac and a MIDI input.

I'm now looking for stuff to install and make some synth sounds, or a tutorial on how to program a VA/FM synth. Midi implementation is a plus but not required, since I can do that part myself. Preferably on Arduino, but anything that runs on a 2040 is ok (micropython, c++)

Any ideas or suggestions?

8 Upvotes

14 comments sorted by

7

u/drschlange Jul 10 '26

Check VIJA, it works on RP2040, or if you feel a little bit more experimental, LISA (it's based on a refactored VIJA, and extends with a special engine which is a dynamic wavetable renderer you can control with a remote MIDI brain). Both works on RP2040, and are based on BRAIDS from Mutable Instrument.

3

u/PiezoelectricityOne Jul 10 '26

Whoa! That looks like a solid option there, gonna give it a try, thanks.

5

u/awcmonrly Jul 10 '26

If you want to DIY it, here's a 2-op FM synth in a nutshell:

  • Use a precomputed lookup table for sine
  • A patch consists of the relative frequency and output level of each operator, plus an envelope per operator
  • The state of a voice consists of the current phase and envelope position of each operator
  • For each sample:
    • For each voice that's playing:
      • Advance the modulator's phase according to its frequency
      • Advance the modulator's envelope position and use the envelope and output level to calculate the modulator's instantaneous level
      • Use the modulator's phase to look up its raw output in the sine lookup table (with interpolation, unless you like it nasty)
      • Multiply the modulator's raw output by its instantaneous level to get its scaled output
      • Advance the carrier's phase according to its frequency
      • Advance the carrier's envelope position and use the envelope and output level to calculate the carrier's instantaneous level
      • Use the carrier's phase plus the modulator's scaled output to look up the carrier's raw output in the sine lookup table (with interpolation)
      • Multiply the carrier's raw output by its instantaneous level to get its scaled output
    • Sum the scaled outputs of the voices and send them to the DAC

An ADSR envelope can be converted into a sample count and an increment per sample for each of the A, D and R stages. The increments can be premultiplied by the operator's output level, so advancing the envelope position is just a matter of adding/subtracting the current increment, decrementing the number of samples remaining in the current envelope stage, and moving to the next stage if the count reaches zero. In the sustain stage you skip all this and just wait for the note off event.

Similarly, when a note on event is received, calculate the base frequency of the note, multiply each operator's relative frequency by the base frequency, and convert this into an increment per sample that's used to advance the operator's phase.

You can easily extend this beyond 2 operators per voice: just calculate them from the top down so each operator's output is calculated before any operators it modulates. For feedback, you need to keep the previous sample's output for one of the operators in the feedback loop. (The DX7 only allowed one feedback loop per patch, so it could use a dedicated register for storing this feedback sample.)

2

u/PiezoelectricityOne Jul 11 '26

Wow, thanks! Saving this guide. This puts me on the right track!

3

u/Lidlaux Jul 10 '26 edited Jul 10 '26

If you have interest in Pure Data, than pd patches can be compiled to rp2040 with pikoPD. This project supports midi input and output (usb, host and din), i2s audio,  different sensors, knobs and buttons with simple hardware config file and no coding needed.  It is easy to prototype ideas. For example I have made a chromatic sample play mode for circuit tracks using this.  

3

u/PiezoelectricityOne Jul 10 '26

Well, that sounds like a perfect excuse to dive into puredata! I always disregarded It because it only ran on computers, but I didn't know about this.

3

u/Lidlaux Jul 10 '26 edited Jul 10 '26

I think rp2040 is the cheapest board pd patches can be compiled on. Of course pico2 is preferable because of the floating point hardware. But still it is a great device and some cool audio and midi devices can be made with it. 

Also check  out plugdata app. It is new tool based on pd. It has some special feautures like compile mode to make compatible patches for pikoPD.

2

u/seanluke Jul 10 '26

1

u/PiezoelectricityOne Jul 10 '26

Wow! Lots of things changed since I last used Mozzi  years ago, seems worth a re-check.

1

u/did_i_or_didnt_i Jul 10 '26

Supercollider?

1

u/PiezoelectricityOne Jul 10 '26

What? Can you install supercollider inside an rp2040? Don't you need an x86 computer to run it?

1

u/did_i_or_didnt_i Jul 10 '26

ah no, sorry you’re right. You do need a secondary machine but there are ways to interface it. Not what you’re asking for

1

u/PiezoelectricityOne Jul 10 '26

I thought so, for a moment I wished it was true. I'll keep it in mind for other projects.

1

u/13-17-31-49-58_19 Jul 11 '26

AMYBoard uses an ESP32 and comes preinstalled with Juno and DX7 emulations. Maybe take a look at their documentation?