Arduino Audio Output

Picture of Arduino Audio Output
Generate sound or output analog voltages with an Arduino.  This Instructable will show you how to set up a really basic digital to analog converter so you can start generating analog waves of all shapes and sizes from a few digital pins on an Arduino.  (This article is a companion to another Instructable I've written about sending audio into an Arduino, find that here)

Some ideas that come to mind:

sample based instrument- store samples on the Arduino or on an SD card and trigger playback with buttons or other types of controls.  Check out my Arduino drum sampler for an idea of how to get started.
digital synthesizer- make saw, sine, triangle, pulse, or arbitrary waveshapes- check out my waveform generator to get started
MIDI to control voltage module/ MIDI synthesizer- receive MIDI messages and translate them into a voltage so you can control an analog synthesizer with MIDI, or use the MIDI data to output audio of a certain frequency
analog output- you may find yourself needing to generate analog voltages from your Arduino at some point, maybe to communicate with an analog device
effects box/digital signal processing- in combination with a microphone/audio input you can perform all kinds of digital signal manipulations and send the processed audio out to speakers.  Check out my vocal effects box for an example. 
audio playback device- make your own ipod.  With the addition of an SD shield you could create your own Arduino mp3 player (check out the wave shield documentation for an idea of how to get started with the code).  The circuits and code provided here are compatible with SD shields that communicate via SPI.

Feel free to use any of the info here to put together an amazing project for the DIY Audio Contest!  We're giving away an HDTV, some DSLR cameras, and tons of other great stuff!  The contest closes Nov 26.

Parts List:

(x9) 1/4 Watt 20kOhm Resistors Digikey 0KQBK-ND
(x7) 1/4 Watt 10kOhm Resistors Digiikey CF14JT10K0CT-ND
(x2) TS922IN Digikey 497-3049-5-ND I like these because they can be powered off the Arduino's 5V supply (one 924 works too, but they don't seem to be available on digikey at the moment)
(x1) 10kOhm potentiometer linear Digikey 987-1308-ND
(x1) 0.01uF capacitor Digikey 445-5252-ND
(x1) 220uF capacitor Digikey P5183-ND
(x1) 0.1uF capacitor Digikey 445-5303-ND
(x1) 1/4 Watt 3kOhm Resistor Digikey CF14JT3K00CT-ND
(x1) 1/4 Watt 10Ohm Resistor Digikey CF14JT10R0CT-ND
(x1) Arduino Uno Sparkfun DEV-09950

Additional Materials:
22 Gauge Wire
Remove these adsRemove these ads by Signing Up
Reddyco1 month ago

Hey Amanda! Great job on this instructable, I'm using it to embase my work on a eletronic drum sound generator with Arduino (hopefully, one day I'll post here how to do it).

I'm writing to ask abuot that 0.01 uF and 10ohm resistor in parallel with the speaker and the DC offset capacitor. What are they used for?

Thanks in advance!

amandaghassaei (author)  Reddyco28 days ago

thanks! they're just threre to reduce noise, not a big deal if you don't have them

flowirin1 month ago

what's the upper limit on the sampling frequency for the arudino? can i get it up to 80kHz?

amandaghassaei (author)  flowirin28 days ago

definitely, you could get up to a few hundred kHz with no problem.

One concern is that the resistor ladder dac that I show in this ible might not respond fast enough as you increase the sampling rate - this might end up applying a low pass filter on your output. I updated step 1 with a little more info about alternative DACs, you might check out the R2R DAC IC I demonstrated in this Instructable (you can wire it up to only use one channel if you need), it has much better quality control then just throwing a bunch of resistors together on a breadboard and I think it will give you better results. It says the settling time for that DAC is 100ns, which should work fine for 80kHz sampling rate.

you will also have to change the frequency of the interrupt. For 40kZ I used this line:

OCR0A = 49;// = (16*10^6) / (40000*8) - 1

try this instead:

OCR0A = 24;// = (16*10^6) / (40000*8) - 1

ibirnam6 months ago
Just wanted to confirm this: since the TS922IN is now obsolete, would this be a sufficient replacement? Thank you!
amandaghassaei (author)  ibirnam6 months ago
that's going to be really hard to work w bc it's surface mount. Just get the lm386 chip and a couple of resistors and capacitors and wire it up like this:
it may need a 9v supply instead of 5v, I can't remember.

I'm working my way through this trying to substitute the lm386 at Step 3. The gif you linked looks like the replacement for the amplifier. I can see the part that replaces the low pass filter (thanks to your excellent explanation of what that is) but I don't see anything that I recognize as being the DAC buffer. Is the buffer unnecessary with the lm386, or is it there and I don't recognize it?
PS I'm a software engineer, so use small words. :-)

amandaghassaei (author)  heymarky1 month ago

actually, a resistor and capacitor only act as a low pass filter when the output signal is connected to the junction between them, here is a pic. You can see that switching the order of the components will turn it into a high pass filter. The lm386 circuit is not wired up the same way, so it won't act as a low pass filter. So here's what I would do:

arduino - dac - lm386 - low pass filter - output

you could also use a tl1072 or tl082 to replace both ts922's, but these require a +/- 9v supply, which is annoying.

Awesome, thanks for the help!

Ibirnam Is LM386 working instead of using TS922IN ?

joshuaphua12 months ago

near the end of the circuit, what's the 0.1uF capacitor and 10Ohm resistor for? another kind of filter?

amandaghassaei (author)  joshuaphua12 months ago

not a filter, just helps make the DC offset more stable.

joshuaphua13 months ago
Can you explain the DC offset more? I understand how a +2.5VDC offset works but am confused about this one. Thanks!
amandaghassaei (author)  joshuaphua13 months ago

I always think of it like this: the signal going into one side of the capacitor causes an alternating excess of positive or negative charge on one side of the cap. The other side of the cap reacts by accumulating opposite charge - this causes an alternating voltage on the opposite side of the cap. Since no current (or a negligible amount) actually gets passed across the cap, the DC voltage on one side does not transfer over to the other side, so the alternating voltage is centered around 0.


punk12904 months ago
I had to replace the TS922 with an LM386. I am trying to get step 3 working. Unfortunately I don't have an oscillator to verify I did things right in step 2. My issue is that when I connect my Adruino to my breadboard with this circuit the power LED dims and my computer no longer sees the Arduino. I tried unhooking the breadboard and then loading the program to my Arduino. That worked fine. When I connected everything back up, the LED came on immediately without ramping up. Any thoughts or ideas for me?
amandaghassaei (author)  punk12903 months ago

sounds like you're shorting out one of the arduino's power pins (the strip of pins near the analog inputs). Double check those.

Ploopy4 months ago
How did you write your code in those squares that you scroll?
amandaghassaei (author)  Ploopy3 months ago

it's a feature that's actually no longer supported, sorry! we're looking at new ways to make code easier to embed in the editor, it will happen.

avionics28 months ago
Thank you so much for making it clear now I understand everything very clearly and thank you for making such a concise tutorial. My hat off to you.

take care and please give us more tutorials.
amandaghassaei (author)  avionics26 months ago
These chips come in handy if you do this alot. And they can be dasychained to increase the resolution.
I made a 32 bit one for my propeller, but frankly couldn't tell much of a difference.
elbiot7 months ago
Doesn't the Arduino UNO have PWM out? Is there a reason you use an external DAC instead of the PWM?
amandaghassaei (author)  elbiot7 months ago
yes it does, but the PWM only does 0 and 5V output, I wanted to output analog voltages so I could make any waveform shape.
um, you mean you want waveforms at ultrasonic frequencies? The PWM is for putting out any analog waveform, but it seems its a bit slower than the PCM that you use. The digital outs in your Pulse Code Modulation r2r setup only put out 0 or 5 volts, but this leads to an analog voltage of 0-5v. Pulse Width Modulation out just needs a capacitor and resistor (low pass filter) to do the same.
elbiot elbiot7 months ago
Ah, I see its not that simple for good audio. Lots of examples used 8kHz sample rates and things like that. This clever person used dual PWM to get 16 bit depth at a good sample rate. Hardware is still super simple.
AntonDan8 months ago
Hi! That is a really nice guide :). I've got a question though.. The output is 8 bit right? I want to make a vocal effect (mostly distortion) pedal.. Will the 8 bit output reduce the quality of the sound (or something like that)? Thanks :)
amandaghassaei (author)  AntonDan8 months ago
yes, 8-bit (especially out an r2r dac like this) is going to sound noticeably distorted/noisy, but it is still a pretty good approximation of the original signal. here is an example:
avionics29 months ago
Great Amanda ! that made it clear now here it comes the second question hope you don't mind. in OCRA1 you put 49 , can you explain how you reached to number 49?

thanks for the good article.
amandaghassaei (author)  avionics28 months ago
my comment on that line has an error, it should say
(16*10^6) / (40000*8) - 1
which means the arduino has a clock speed of 16Mhz (16*10^6), and I set the prescaler to 8 (divide by 8) and the frequency I want is 40000 (divide by 40000) and all numbers are zero indexed (-1)
(16*10^6) / (40000*8) - 1 = 49
avionics29 months ago
Amanda can you explain where you get the numbers in your sine[] ?
amandaghassaei (author)  avionics29 months ago
I wrote a little python script to generate them, nothing fancy, just a bunch of values of 127+127*sin(x)
qwertyfinger9 months ago
Amazing tutorial! Thank you so much, I'm using an arduino uno to make a musical sequencer and hopefully this will help me a lot!
also, i'm assuming that if I want to use 16 bit sound i just increase the length of the ladder? i'm using a shift register for serial output because i don't have rapidly changing sound and if i weren't i'd need something like 42 digital I/O pins in total!
amandaghassaei (author)  qwertyfinger9 months ago
theoretically yes, but after 8 bit the noise caused by adding more resistors in your ladder makes the increased resolution kind of pointless. I'd recommend getting an r2r dac ic for this they might even make 16 bit versions. The resistors in those dacs are calibrated to reduce noise.
hpan10 months ago
thank you so much! you're pretty awesome
hpan10 months ago
hola. Amanda.
when you create a sine wave, why do you use
"PORTD = 127+127*sin(2*3.14*t/100)" and let t runs from 0 to 100? I'm a little confused about that. please help. thank you
amandaghassaei (author)  hpan10 months ago
it's not 0 to 100, it's 0 to 255, where 255 is a 5V output and 0 is a 0V output (127 is 2.5V and so on). the sin function always returns something between -1 and 1, so the equation will only fall between 127+127 =~256 and 127 - 127 = 0
faziefazie1 year ago
can I using this mono jack instead of yours?
amandaghassaei (author)  faziefazie1 year ago

Get More Out of Instructables

Already have an Account?


PDF Downloads
As a Pro member, you will gain access to download any Instructable in the PDF format. You also have the ability to customize your PDF download.

Upgrade to Pro today!