Slick Six-Voice Synth For AVRs

He started off making an AVR synthesized guitar, but [Erix] ended up with much more: a complete six-voice AVR wavetable synthesis song machine that’ll run on an ATMega328 — for instance, on an Arduino Uno.

If you’re an AVR coder, or interested in direct-digital synthesis or PWM audio output, you should have a look at his code (zip file). If you’d just like to use the chip to make some tunes, have a gander at the video below the break.

It’s pretty sweet to get six channels of 31.25 kHz sampled 8-bit audio running on a 16MHz chip. The code underlying it works through some tricky optimization in the sample update routine (UpdateVoiceSample() in play.c if you’re reading along) and by carefully prioritizing the time critical elements.

For instance, the pitch is updated once every two PWM samples, I/O and other auxiliary player tasks every eights samples, and the sound’s dynamic volume envelope is only recalculated every 48 samples. Doing the slow math as infrequently as possible lets [Erix] make his timing.

And to round out the tools, [Erix] also provides wavetable editors and song generators in Lua to compile the tables of music data that the AVR routines need to run.

If you’re not impressed by this bit of AVR C coding, then you’ve not tried to implement something similar yourself.

26 thoughts on “Slick Six-Voice Synth For AVRs

  1. I bet the germans can’t watch the video because of their maniacal copyright org.
    Before you say it: Nope doesn’t matter the music isn’t copyrighted from what I hear.

        1. I guess I don’t get away with “that’s the new skrillex song at 8:31” – and people who like skrillex may feel offended. Bad jokes aside, I don’t want to tell you that. Because it was not my decision nor do I want to defend people who do that, I can clearly see the video now – which points me at “it was a mistake” by someone? I just pointed out some oddities in german music rights.

          1. @cyberteque, yes indeed. In general it’s best to only use free music or self made music. Here comes the funny thing though: If you’re a GEMA “protected” artist, you may run in a problem when you want to publish your own stuff on youtube, because youtube won’t pay GEMA anything so they have to take it down and all this infringement stuff ruins videos.

  2. Just after a very quick look at the code Erix is not using interrupts but instead active waiting until the timer 0 overflows. I guess in that way he avoids all the overhead of the interrupt and the interrupt handler (specially when written in C) and he get’s very accurate timing.

    Well done!

    One thing I’m not sure though. He’s using an ATmega that has multiplication support; but there’s no barrel shift support, so I wonder if those 8 bit left shifts would be better using a multiplication (may be the C compiler is doing that optimization behind the scene? I don’t know).

    There’s a lot to learn from this project!

    1. Yes, interrupts would have cost too much and would have disrupted the good register preloading job performed by the avr-gcc optimizer.
      Of course, optimizer miracles work better if one spends a few hours looking at the assembly language produced by the compiler and gently nudges it in the right direction :-)
      The 8-bit shifts on an 8-bit MCU are just syntactic conveniences; the optimizer routinely takes care of that. But thanks for the hint about the lack of a barrel shift (I am not an AVR expert; actually this is my first AVR program); after reading your post I had a look at the less critical code in the music interpreter: a 6-bit right shift gets compiled to one ‘swap’ and two ‘lsr’ instructions, for a total of 3 CPU cycles.

    1. I considered adding MIDI input for some of the voices, but it would have defeated the “let’s see wat I can do with no external active components” idea (connecting a MIDI bus directly to the MCU would be asking for trouble), so I left it in my endless wish list.
      In any case, I think it could be done; the serial line can be read fast enough and the available time slots should be able to handle the MIDI decoding. It should be possible to set a voice threshold using 3 logic inputs, so that the voices over that number are MIDI-controlled while the lower-numbered voices are interpreter-controlled; this would allow MIDI-controlled play over a musical base. The serial connection to the PC would have to be switchable because, as far as I know, MIDI uses a non-PC-standard baud rate [caveat: I have not done any real feasibility study].

    1. Don’t take this for a definitive answer, but I think it should. Keep in mind that:
      – It will play at a lower pitch (about a musical ‘fifth’ below normal, from a quick & dirty & possibly dead wrong estimate) unless you change line 17 of tool/tables.lua and run it to generate new note and tempo tables.
      – You should also change line 28 of pwm.h to the new clock frequency. That should also take care of the serial baud rate.
      – The sampling rate will decrease from 31.25 kHz to 23.625 kHz. Still out of hearing range but it could produce more high-frequency aliasing (possibly audible as high notes distortion), that could be reduced by lowering the filter cutoff frequency. Maybe it would not be too bad even with the current filter; the PWM frequency should be decently attenuated anyway.
      – The lowest and/or highest frequency notes could play incorrectly (I haven’t checked).
      – Relative tuning errors will be larger.
      Maybe I didn’t think of something important, but it’s an interesting experiment. Try it :-)

      1. it compiles and uploads fine, i think it will work. i may build the rc network for this as i have an old out of key synth with a fractured circuit board that has seen many previous repairs that would be a suitable candidate with some more engineering.

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.