Arduino OPL FM Synth

Someone recently asked me about a 2413 synth chip emulation library they’d found for the ESP32 and I’m very interested in taking a look.  But I’ve not done any ESP32 projects so far, so that will have to wait for a bit (come back in a few weeks maybe).  But that reminded me that I had some actual Yamaha YM2413 synthesizer chips to experiment with and had never really done anything with them.  They also seem to still be fairly widely available relatively cheaply so I thought it about time I had a proper look.

The YM2413 is a Yamaha OPL family FM synthesizer chip that was used in some of their entry level PSS keyboards from the 80s and 90s. It was a slightly cut-down version of the OPL2 chips made popular in PC sound cards from the time. It was also apparently used in some game consoles from the era too according to Wikipedia.

This post is the first try at getting to see what these can do.

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

These are the key Arduino tutorials for the main concepts used in this project:

Also refer to the YM2413 datasheet and the OPLL application manual (available from the above links and other places online).

If you are new to Arduino, see the Getting Started pages.

Parts list

  • Arduino Uno
  • YM2413
  • 2x2K2, 2x4K7 resistors
  • 2x27pF, 1x100nF ceramic capacitors
  • 1x10uF electrolytic or non-polar capacitor
  • 1×3.5795MHz oscillator
  • Audio amplification
  • One of the Ready-Made MIDI Modules or Arduino MIDI Interfaces
  • Protoboard or breadboard and jumper wires

The Circuit

This is the same circuit, but the second diagram has some of the wires removed for clarity.

I’m not going to go into much detail about the YM2413 as Marco from Majic Designs has done an excellent job already here: https://arduinoplusplus.wordpress.com/2020/02/22/making-music-with-a-yamaha-ym2413-synthesizer-part-2/

The above circuit is largely based on the YM2413 section of the shields that have been developed by Marco and by HTLabs and also following the example circuit design from the YM2413 application manual.  The key sections are:

  • YM2413 and its supporting 3.5795MHz oscillator.
  • The audio output circuit (low-pass filter, coupling capacitor).
  • The Arduino interface.
  • Not shown: the MIDI module connection to 5V, GND, RX, TX.

The audio output circuit is pretty minimal here and really needs a proper output stage, but it is ok to get started with some basic experiments.

The Arduino interface is as follows:

 YM2413  Arduino
 D0 (17)   D8
 D1 (18)   D9
 D2 (2)    D7
 D3 (3)    D6
 D4 (4)    D13
 D5 (5)    D12
 D6 (6)    D11
 D7 (7)    D10
 A0 (10)   D4
/WE (11)   D5
/CS (12)   GND

This is pretty much the Arduino interface use by Marco in his shield design, apart from swapping out his use of A0-A3 to the YM2413’s D4-7 for the Arduino D13-10 instead.

I build mine on an Adafruit proto shield.

IMG_6833

The Code

There are a number of different sets of code out there to interface to the YM2413:

Strictly speaking the ArudinoOPL2 isn’t supporting the YM2413 directly, but the “fuller” YM3812, and it is designed for use with the OPL2 Audio Board (as shown in the link).  Similarly, the HTLab code is geared up for their shield.

I went with Marco’s MD_YM2413 as it is more suited to driving this chip directly and is very nicely documented here: https://arduinoplusplus.wordpress.com/2020/03/07/making-music-with-a-yamaha-ym2413-synthesizer-part-3/

In particular, I first tried out the MD_YM2413_Custom example to get a feel for the basics of driving the chip, then used that code as the starting point for my own application. In particular, to add MIDI.

One of the “short cuts” with the OPLL compared to the fuller “OPL2” is only having a single customisable voice slot alongside several preset voices.  But Marco’s “custom” example provides a set of 128 GM voices based on the examples from the Arduino OPL2 Library which can be loaded into that custom slot to provide a “pseudo general MIDI” sound set.  I did notice that the definitions in the OPL2 library have moved on since Marco grabbed them for his example and was going to update them, but it turns out that the format used in the library has changed slightly, meaning it wouldn’t be a “drop-in” replacement. It would require some changes to Marco’s code too.

As the YM2413 can support 9 channels of sound (or 6 channels for melody and 5 channels for rhythm), it is possible to get 9-note polyphony from any one of those voices.  So this is what I’ve tried to do here.

The basic principles of my code are:

  • Respond to MIDI NoteOn, NoteOff, and ProgramChange messages via callbacks from the Arduino MIDI Library.
  • Play any received notes on the first available free YM2413 voice channel.
  • On receiving a ProgramChange message, load the corresponding voice from Marco’s set into the custom voice slot.
  • MIDI is connected to the hardware UART (D0/D1) and there is automatic software MIDI THRU enabled.
  • The YM2413 notes are played by specifying the frequency, so I use the same MIDI note to frequency table I’ve used with Arduino tones (from the ToneMelody built-in example).

In my first set of experiments I had MIDI IN/OUT connected to a PC running MIDIOx twice. One, to drive the YM2413 using the computer keyboard; and one to listen to the YM2413 MIDI OUT and drive the PC’s built-in synth. This meant I could get a feel for the accuracy of the pitch and instruments compared to a default GM sound set on the PC.

In the video I’ve used a MIDI controller keyboard through my Arduino MIDI Rotary Encoder Controller which allows me to both play notes and change the voice at the same time.

Find it on GitHub here.

Closing Thoughts

My initial experiment has largely proven successful.  The audio output is quite weak and noisy, as can be heard in the video, so this really is just a very basic “first go”, but it isn’t a bad start.  Some of those voices sound a little dodgy to me, so I’d like to find out more about how the synthesis engine actually works. Ideally I’d get hold of one of the keyboards that used the chip from the 80s and compare it with “the real thing”.

Usually at this point I’d be thinking about how to build the circuit onto protoboard, or perhaps more ideally in this case, one of my Arduino MIDI Proto Shields.  And that should be a relatively straight forward thing to do.  A simple amplifier/buffer output stage could even be added based on the schematics published in some of the references I’ve already mentioned.

But in this case I don’t have to. I was very fortunate to be able to get hold of one of Marco’s spare PCBs from his own experimenter shield.  I’ve just been “sitting on it” and not really doing anything with it for the past couple of years until now!  His shield works so much better than anything I’ve put together.

The only “hack” I’ve done is to re-route the pins for A0-A3 over to D13-D10 so that it leaves the analog pins available for some future experimentation.  The shield works really well with the “stacking” TRS MIDI version of my proto shield to provide the MIDI links.

I have a few more ideas for experiments with the chip itself (which may or may not make it to further blog posts) and then I’d quite like to take a look at that emulation library…

Kevin

Leave a comment