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.
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.
Yes, I only used public domain classical and traditional music to avoid any such problem.
I’m surprised that the youtube copyright robot didn’t flag the video for 3rd party content!
Surprisingly the GEMA did not rear its ugly head on this one. Yet.
Not sure if it matters, the “artist” is the AVR playing so that would fall into “cover” song.
Like the recent Heino cover album… nobody cares about the rightful owners of the song there.
watch this, if you can tell me what the “third party content” is I’ll give you a dollar!!!!
https://www.youtube.com/watch?v=iUs2frHb6qk
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.
would that be why one of my cloud time lapse videos that has a Miles Davis sound track can not be viewed in Germany???
@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.
John Cage, “Four Thirty-Three”, 1952. http://en.wikipedia.org/wiki/4%E2%80%B233%E2%80%B3
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!
Any reasonable compiler should optimize those 8-bit shifts to byte operations.
You’re right!
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.
Awesome work.
Looks like I have a new weekend project.
Something that can put out similar results (though it can only do 4 voice poly from what I recall) but is very noob friendly is the The Mozzi Library (http://sensorium.github.io/Mozzi/).
A wave function based instruments version of this should be implementable.
Would have been amazing if it could take MIDI as input, instead of precompiled byte code.
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].
“If you’re not impressed by this bit of AVR C coding, then you’ve not tried to implement something similar yourself.”
Very true.
will this run on a chinese uno that has a 12mhz crystal?
I imagine it would but would not sound the same…
never mind, i found out they have a non visible 16mhz crystal also.
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 :-)
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.
Very cool. Reminds me of my Acorn Music 500 system!