You are on page 1of 21

http://www.instructables.

com/id/Arduino-Audio-Input/
Food Living Outside Play Technology Workshop
Arduino Audio Input
by amandaghassaei on July 25, 2012
Table of Contents
Arduino Audio Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Intro: Arduino Audio Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Step 1: Preparing audio signals for Arduino . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Step 2: Prepare audio jack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Step 3: Non-Inverting Amplifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Step 4: DC Offset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Step 5: Simple Analog In . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Step 6: Sampling rate of ~40kHz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Step 7: Interrupt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Step 8: Clipping Indicator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Related Instructables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Advertisements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
http://www.instructables.com/id/Arduino-Audio-Input/
Author:amandaghassaei uh-man-duh-guss-eye-dot-com
I'm a developer here at Instructables, I work on the website and iOS app.
Intro: Arduino Audio Input
Send sound into your Arduino. This Instructable will show you how to prepare audio so that it can be sampled and processed by an Arduino to make sound responsive
projects and audio effects. (This article is a companion to another Instructable I've written about building an audio output circuit for an Arduino, find that here )
Some ideas that come to mind include:
beat detection - trigger lighting effects, build a set of turntables that beat match themselves, or make a robot that dances along with the music you play for it
amplitude detection - make a simple vu meter with LEDS
frequency analysis - you could make a project that reacts to different frequencies in different ways, recognizes certain melodies, turns audio into MIDI data , or
translates incoming frequencies into square waves with the tone() library
digital effects boxes/digital signal processing - check out what I did with my vocal effects box (all processing done with Arduino), lots of possibilities here: pitch
bending, distortion, sampling, delay , reverb , granular synthesis , mixing , and much more... I've provided code in this Instructable that lets you sample at up to 38.5kHz.
Here is another instructable describing how to set up a simple audio out circuit with Arduino.
digital recorder - with the addition of an SD card of course (the Arduino has very limited memory by itself), this opens up the possibility of looping large samples and
doing lots of other digital manipulations to pieces of stored audio The circuits and code provided here are compatible with SD card shields that communicate via SPI.
graphical representations of sound - Arduino oscilloscope/visualizer
Feel free to use any of the info in this Instructable 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:
(x1) Microphone Radioshack 33-3038
(x1) TL072 Digikey 296-14997-5-ND or TL082 Digikey 296-1780-5-ND (TL081/TL071 are fine too) I used a tl082 in my examples
(x2) 9V battery
(x2) 9V battery snap connector Radioshack 270-324
(x1) mono audio jack 1/4" Radioshack 274-340 or Radioshack 274-252 or 1/8" Radioshack 274-333 or Radioshack 274-251
(x1) LED Digikey C513A-WSN-CV0Y0151-ND
(x1) 10kOhm potentiometer linear Digikey 987-1301-ND
(x3) 100kOhm 1/4watt resistors Digikey CF14JT100KCT-ND
(x1) 10uF electrolytic capacitor Digikey P5134-ND
(x1) 47nF ceramic capacitor Digikey P4307-ND
(x1) Arduino Uno (Duemilanove is fine too) Sparkfun DEV-09950
Additional Materials:
22 gauge wire
solder
Step 1:Preparing audio signals for Arduino
If you've ever recorded audio on your computer, you may have seen it represented as a waveform like the one in fig 1. If you zoom in on this wave (as in fig 2) you will
see that the shape is made of thousands of tiny oscillations back and forth. This is called an audio signal and when we are dealing with audio signals in electronics, these
oscillations represent oscillating voltages over time.
When we look at an audio signal with an oscilloscope , we see a similar picture (fig 3). Notice how the audio signal in fig 3 oscillates around a center voltage of 0V; this is
typical of audio signals. The amplitude of an audio signal is the distance between its center voltage and its high or low peak. The amplitude of the wave in fig 3 is 2V: it
reaches a maximum voltage of +2V and a minimum voltage of -2V. This is a problem if we want to measure the audio signal with one of the Arduino's analog inputs
because the Arduino can only measure voltages between 0 and 5V. If we tried to measure the negative voltages in the signal from fig 3, the Arduino would read only 0V
and we would end up clipping the bottom of the signal. In this Instructable I'll show you how you can amplify and offset audio signals so that they fall within this 0-5V
range. Ideally you want a signal with an amplitude of 2.5V that oscillates around 2.5V (like in fig 7) so that its min voltage is 0V and its max voltage is 5V (see the
calculations below).
Min voltage = Center Voltage - Amplitude
Min voltage = 2.5V - 2.5V = 0V
Max Voltage = Center Voltage + Amplitude
Max Voltage = 2.5V + 2.5V = 5V
Fig 4 shows the signal coming straight out of the microphone on an oscilloscope. The signal is relatively weak, with an amplitude of only 200mV, you may find that signals
http://www.instructables.com/id/Arduino-Audio-Input/
from other sources (ipods, guitars, record players...) also produce audio signals with small amplitudes. These signals need to be amplified to get them up to the amplitude
we want (2.5V). Amplification means increasing the amplitude (distance between the center point and max or min) of a signal. Amplification also buffers the audio source
(in my case this was a microphone) from any loads that you may put on it later in the circuit, which is a good thing because it prevents distortion.
Fig 5 shows the same microphone signal after amplification, you can see how the height of the peaks has increased so that the wave has an amplitude of 2.5V. But since
the center voltage of the wave is still 0, the wave is oscillating between -2.5 and +2.5V. It will need to be DC offset to correct this. DC offset means changing the center
voltage that the wave oscillates around (the average voltage of the wave). Fig 6 shows the signal after it has been DC offset; it still has an amplitude of 2.5V, but the
center voltage is 2.5V instead of 0V, so the wave never drops down below 0V. (Note- the slight change in shape between the signals in figures 5 and 6 is dues to
changes in my voice between the two pics, it has nothing to do with the circuit). The signal in fig 6 is ready to go to an Arduino analog input pin.
Image Notes
1. zoomed in from fig 1 shows individual oscillations of signal
Image Notes
1. 0V
2. volts/div = 2V
Image Notes
1. signal directly from microphone has a relatively small amplitude
2. volts/div = 2V
http://www.instructables.com/id/Arduino-Audio-Input/
Image Notes
1. microphone mono input
2. amplifier
3. DC offset
Step 2:Prepare audio jack
In this Instructable, I'm only going to talk about how to route one channel of audio into an Arduino. It is possible to copy the same circuit I've proposed here many times to
add multiple channels, but it can complicate/slow things down in the code and at some point you will probably have to lower your sampling rate. I'll leave it up to you to
figure out the details, but please post what you learn in the comments! Almost all microphones and electronic instruments are mono , meaning they only have one
microphone element or pickup which is generating a signal (as opposed to stereo ). You can tell for sure by looking at the plug and comparing it to the image above. My
microphone has a 1/4" plug on it so I used a 1/4" jack for this instructable, you may find that you need a 1/8" jack, but the main ideas here still apply.
Solder a black wire to the ground pin of the mono jack. The ground pin is usually the larger pin on the jack, test for continuity with the threaded portion of the jack to make
sure that you have located the ground pin correctly (see fig 3). Solder a green wire to the signal pin of the mono jack. Test for continuity with the clip that extends out from
the jack (fig 3).
If you have an oscilloscope handy, connect the reference to the black wire, connect the probe tip to the green wire, plug the microphone in the jack and look for a signal
(fig 5). The signal from my microphone has an amplitude of about 200mV.
Image Notes
1. stereo plug
2. mono plug
Image Notes
1. the ground pin will be electrically connected to this portion of the jack
2. The signal pin will be electrically connected to this portion of the jack
3. ground pin
4. signal pin
http://www.instructables.com/id/Arduino-Audio-Input/
Image Notes
1. volts/div = 200mV
Step 3:Non-Inverting Amplifier
The amplifier is the first step in the circuit, it increases the amplitude of the signal from around + or - 200mV to + or - 2.5V (ideally). The other function of the amplifier is to
protect the audio source (the thing generating the audio signal in the first place) from the rest of the circuit. The outgoing amplified signal will source all its current from the
amplifier, so any load put on it later in the circuit will not be "felt" by the audio source (the microphone element in my case). Do this by setting up one of the op amps in
the TL072 or TL082 package in a non-inverting amplifier configuration .
The datasheet of the TL072 or TL082 says that it should be powered with +15 and -15V, but since the signal will never be amplified above + or - 2.5V it's fine to run the
op amp with something lower. I used two nine volt batteries wired in series to create a + or - 9V power supply.
Wire up your +V(pin 8) and -V(pin 4) to the op amp. Wire the signal from the mono jack to the non-inverting input (pin 3) and connect the ground pin of the jack to the 0V
reference on your voltage supply (for me this was the junction between the two 9V batteries in series). Wire a 100kOhm resistor between the output (pin 1) and inverting
input (pin 2) of the op amp. In this circuit I used a 10kOhm potentiometer wired as a variable resistor to adjust the gain (the amount that the amplifier amplifies) of my non-
inverting amplifier. Later in this Instructable, I'll show how you can add an LED indicator to Arduino pin 13 to let you know when you have this pot turned up too high
(resulting in clipping of the incoming signal by the Arduino); this way you know when you should turn the pot down and get the signal back in the range you want
(amplitude of ~2.5V). Wire this 10K linear taper pot between the inverting input and the 0V reference.
The following equation describes the relative amplitudes of the signal before and after the non-inverting amplifier:
Vout =~ Vin * (1 + R2/R1)
or
Vout/Vin =~ 1 + R2/R1
where R2 is the feedback resistor (between the output and non inverting input), R1 is the resistor to ground, Vout is the amplitude of the outgoing signal (the output from
the amplifier), and Vin is the amplitude of the incoming signal (the input to the amplifier)
In this circuit R2 is a 100kOhm resistor and R1 is a 10kOhm potentiometer (variable resistor). By turning the pot you can change the resistance of R1 from 0Ohms to
10KOhms. Here are some example calculations:
When the pot is turned all the way to the left the resistance of R1 is 10kOhms and the ratio of Vout to Vin is about:
1+ 100/10 = 11
A signal coming out of the microphone with an amplitude of 200mV (which is fairly loud on my microphone) will be amplified to:
200mv * 11 = 2200mV = 2.2V
this is right in the range we want (amplitude close to 2.5V without going over)
Turning the pot to its halfway position will give it a resistance of 5kOhms, we can calculate the ratio of Vout to Vin again:
1+ 100/5 = 21
now the amplitude gets multiplied by 21
this is too much amplification for the 200mV signal:
200mV * 21 = 4200mv = 4.2V >> 2.5V
but this amplification would be perfect for a 100mV signal:
100mV *21 = 2100mV = 2.1V =~ 2.5V
Turning the pot farther to the right will keep decreasing the resistance of R1 and increase the amplification (also called gain ) of this amplifier theoretically to infinity.
Obviously at some point the amplifier will not be able to power a signal with a huge amplitude, but you get the idea. By adjusting the potentiometer you can adjust the
gain of the amplifier and tune the sensitivity of the microphone while still keeping it in a range that the Arduino likes.
Note: As you can see in the circuit above, this project only uses one of the two available op amps in the TL072/TL082 package. I used this chip because they are easily
sourced (you can even buy the TL082 at Radioshack these days), they are basically the same price as the single op amp packages (TL071 and TL081), and you may
want to use the extra op amp somewhere else on your circuit (another channel of input, an audio out circuit...). But if you have a TL071 or TL081, it will do fine for this
project.
http://www.instructables.com/id/Arduino-Audio-Input/
Image Notes
1. non-inverting amplifier
2. unused op amp in dual package
3. microphone input
Image Notes
1. signal directly from microphone has a relatively small amplitude
2. volts/div = 2V
Image Notes
1. amplified signal oscillates between -2.5 and 2.5 V
2. volts/div = 2V
Image Notes
1. 9V
2. 0V reference, both audio in ground 10k pot ground connect here. Arduino
ground will reference here as well, more info in the next step
3. -9V
Image Notes
1. -9V to 082 pin 4
2. 9V to 082 pin 8
3. signal pin from mono jack to pin 3 of 082
4. ground pin from mono jack
5. battery snaps
http://www.instructables.com/id/Arduino-Audio-Input/
6. battery snaps
7. battery snaps
8. 100k bridges pins 1 and 2 of 082
9. 10k pot bridges pin 2 of 082 and 0V reference between two 9V batteries in
series
Step 4:DC Offset
The next portion of the circuit DC offsets the output from the amplifier. As I explained in step 1, this +2.5V DC offset causes audio signal to oscillate around 2.5V so that it
stays within the acceptable range for the Arduino's analog inputs (0-5V). Compare the non dc offset signal is fig 2 with the dc offset in fig 3. Specifically, notice how the
signal in fig 3 always stays within the 0-5V range.
The DC offset circuit has two main components: a voltage divider and a capacitor. The voltage divider is made from two 100k resistors wired in series from the Arduino's
5V supply to ground. Since the resistors have the same resistance, the voltage at the junction between them equals 2.5V. This 2.5V junction is tied to the output of the
amplifier via a 10uF capacitor. As the voltage on the amplifier side of the capacitor rises and falls, it causes charge to momentarily accumulate and repel from the side of
the capacitor attached to the 2.5V junction. This causes the voltage at the 2.5V junction to oscillate up and down, centered around 2.5V.
As shown in figs 3-8 and the schematic, connect the negative lead of a 10uF capacitor to the output from the amplifier. Connect the other side of the cap to the junction
between two 100k resistors wired in series between 5V and ground. Also add a 47nF capacitor from 2.5V to ground.
http://www.instructables.com/id/Arduino-Audio-Input/
Image Notes
1. DC offset
Image Notes
1. amplified signal- oscillates between -2.5V and 2.5V
2. volts/div = 2V
Image Notes
1. amplified and dc offset signal- oscillates between 0 and 5V
2. volts/div = 2V
Image Notes
1. to Arduino Vin
2. to Arduino 5V
3. to Arduino A0
4. to Arduino ground
5. 47nF
6. 100k resistors
7. 0V reference- junction between two 9V in series
8. 9V
http://www.instructables.com/id/Arduino-Audio-Input/
Step 5:Simple Analog In
Load the following code onto the Arduino. This code reads the voltage of the incoming audio signal using analogRead(A0) as a number between 0 and 1023 and stores it
as the variable "incomingAudio." From here you could store this value for later use, perform mathematical operations to it, or do any other manipulations you can think of.
//Simple Audio In
//by Amanda Ghassaei
//http://www.instructables.com/id/Arduino-Audio-Input/
//Sept 2012
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
*/
int incomingAudio;
void setup(){
}
void loop(){
incomingAudio = analogRead(A0);//read input from A0
//do stuff with the variable "incomingAudio"
}
In the images above I set up a really simple 8 bit digital to analog converter (read more about it here , or check out fig 4) so that I could visualize the data points that the
Arduino was storing as the variable "incomingAudio" and see how close it was to the original signal. You can see from fig 2 (zoomed in view of fig 1) that the Arduino is
taking one sample every 125us from A0. We can calculate the sampling rate as follows:
sampling rate = 1/125us = 1/0.000125s = 8000hz
To give you a point of comparison, normal audio sampling rates are at least 40kHz. If a sampling rate of 8kHz or less is good enough for your purposes then you should
probably go ahead and use analogRead() to measure your signal, as it keeps things very simple. You can see in fig 1 that it actually does a pretty good job of tracing out
the path of the incoming 360hz signal. In order to get above 8kHz, we'll have to bypass the analog read function. It may sound daunting, but it's actually not too bad, just
a matter of copying some setup() code that I've written in the next step.
I also want to point out the behavior of the Arduino in response to a signal that rises over 5V and dips under 0V. In fig 3 you can see how the Arduino clips the incoming
signal so that it is always bounded by 0 and 5V. This causes the tops of the peaks and the bottom of the valleys to get flattened. In step 8 I'll talk some more about this
and how to set up a clipping indicator light to let you know to turn the amplifier down.
Some notes about the 8 bit digital to analog converter (DAC): I used the command "PORTD = " to send a value between 0 and 255 out of the Arduino and into the DAC
where it is converted back into a voltage between 0 and 5V. The code I used can be found below. I've written a whole instructable about the 8 bit DAC here .
//Simple Audio In w output to 8 bit DAC
//by Amanda Ghassaei
//http://www.instructables.com/id/Arduino-Audio-Input/
//Sept 2012
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
*/
int incomingAudio;
void setup(){
for (byte i=0;i<8;i++){
pinMode(i,OUTPUT);//set digital pins 0-7 as outputs (DAC)
}
}
void loop(){
incomingAudio = analogRead(A0);//read voltage at A0
incomingAudio = (incomingAudio+1)/4 - 1;//scale from 10 bit (0-1023) to 8 bit (0-255)
http://www.instructables.com/id/Arduino-Audio-Input/
if (incomingAudio<0){//deal with negative numbers
incomingAudio = 0;
}
PORTD = incomingAudio;
}
Image Notes
1. input to A0 shown in yellow, data stored in Arduino (subsequently output from 8
bit DAC) shown in blue
2. volts/div = 2V
3. time/div = 500us
Image Notes
1. one sample each ~125us
2. tims/div = 100us
3. volts/div = 2V
Image Notes
1. when input signal (yellow) drops below 0V the Arduino clips it as it measures it.
This clipping is reflected in the outgoing signal from the Arduino (blue)
2. when input signal (yellow) rises above 5V the Arduino clips it as it measures it.
This clipping is reflected in the outgoing signal from the Arduino (blue)
3. volts/div = 2V
4. time/div = 500us
Image Notes
1. signal out from 8 bit R2R DAC
2. resistor ladder digital to analog converter (DAC)
Step 6:Sampling rate of ~40kHz
In the code below I bypassed the function analogRead() in order to increase my sampling rate. The code required to do this is fairly advanced, maybe it can be the
subject of another instructable if there's interest (leave a comment if you are interested), but for now it's only important to understand how to use this code in the loop()
function, not how I set it up.
Here's simple explanation (all you need to know for now):
Basically in the setup() function I've told the Arduino that I want it to continuously measure pin A0 and forget about the other analog inputs all together. So while other
things are going on in the loop() function, the Arduino is constantly updating a variable called "ADCH" with new values from A0 at a rate of 38.5kHz (that's one sample
every 26us, you can see it in fig 2). When I want to get one of these values I can just set a variable equal to ADCH, or as I wrote in my code:
incomingAudio = ADCH;
I did have to lower the resolution of these analog measurements a little bit to get a higher sampling rate. In the last step we were using analogRead() to measure the
voltage of the signal as a value between 0 and 1023, now these values will always be between 0 and 255. Also, continuous monitoring of A0 means that the other analog
pins are now useless, but if you really need to measure a potentiometer or sensor, check out how you can do it with a digital pin using RCTime It's possible that the
analog pins can still be used as digital I/O pins, but I haven't actually tested this yet, leave a comment if you try it!
The complicated explanation (not necessary, but for those who are interested):
I manually set the Arduino's internal analog to digital converter (ADC) counter to 500kHz and read an 8 bit value from analog input 0 from the ADCH directly (I just read
http://www.instructables.com/id/Arduino-Audio-Input/
the most significant 8 bits of the 10 bit ADC to save time in the code). I set the ADC counter to 500kHz because the ADC takes 13 clock cycles to read a new analog
value. 500/13 =~ 38.5kHz which gets me pretty close to 40kHz (standard audio sampling rate) without introducing extra noise. As you can see in fig 2, this gives me one
sample every 13/500000 = 26us. A lot of the ideas here (prescalers and counters) are similar to the setup for Arduino timer interrupts, and you can read more about how
that works here .
//Audio out with 38.5kHz sampling rate
//by Amanda Ghassaei
//http://www.instructables.com/id/Arduino-Audio-Input/
//Sept 2012
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
*/
int incomingAudio;//storage for A0 data
void setup(){
//set up continuous sampling of analog pin 0 (you don't need to understand this part, just know how to use it in the loop())
//clear ADCSRA and ADCSRB registers
ADCSRA = 0;
ADCSRB = 0;
ADMUX |= (1 << REFS0); //set reference voltage
ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz
ADCSRA |= (1 << ADATE); //enabble auto trigger
ADCSRA |= (1 << ADEN); //enable ADC
ADCSRA |= (1 << ADSC); //start ADC measurements
//if you want to add other things to setup(), do it here
}
void loop(){
incomingAudio = ADCH;//get new value from A0
//do other stuff here
}
As in the previous step, I sent the values of the variable "incomingAudio" out an 8 bit DAC so that I could visualize the data as it was being stored in the Arduino. You can
see the incoming signal (yellow) and output from the DAC (blue) in the images above. Notice how much better the Arduino follows the signal compared to the last step. In
fig 2 you can see that the step size is down to 26us (compared to 125us when using analogRead). Again you can see the effects of clipping at 0V and 5v in fig 3.
The code for sampling rate of 38.5kHz with DAC output is given below.
//Audio out with 38.5kHz sampling rate and DAC output
//by Amanda Ghassaei
//http://www.instructables.com/id/Arduino-Audio-Input/
//Sept 2012
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
*/
void setup(){
for (byte i=0;i<8;i++){
pinMode(i,OUTPUT);
}
//set up continuous sampling of analog pin 0
//clear ADCSRA and ADCSRB registers
ADCSRA = 0;
ADCSRB = 0;
ADMUX |= (1 << REFS0); //set reference voltage
ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz
ADCSRA |= (1 << ADATE); //enabble auto trigger
ADCSRA |= (1 << ADEN); //enable ADC
ADCSRA |= (1 << ADSC); //start ADC measurements
//if you want to add other things to setup(), do it here
}
void loop(){
PORTD = ADCH;//send 8 bit value from analog pin 0 to DAC
}
http://www.instructables.com/id/Arduino-Audio-Input/
Image Notes
1. volts/div = 2V
2. time/div - 500us
3. input to A0 shown in yellow, output from Arduino D0-D7 in blue
Image Notes
1. one sample every 26us
2. time/div = 25uS
3. volts/div = 2V
Image Notes
1. when input signal (yellow) drops above 5V the Arduino clips it as it measures it.
This clipping is reflected in the outgoing signal from the Arduino (blue)
2. when input signal (yellow) drops below 0V the Arduino clips it as it measures it.
This clipping is reflected in the outgoing signal from the Arduino (blue)
3. volts/div = 2V
4. time/div = 500us
Step 7:Interrupt
In this piece of code, I set up the Arduino to continuously monitor pin A0 at 38.5kHz, but now I've added a piece of code that automatically updates the variable
"incomingAudio" each time a new value from A0 has been calculated. Instead of putting the line:
incomingAudio = ADCH;
in the loop() function of the Arduino sketch, I've put it in a special function called an "interrupt routine." The interrupt routing looks like this:
ISR(ADC_vect) {
incomingAudio = ADCH;
}
Think of it as a normal sketch, the Arduino first goes through the setup() function then it starts the loop(), but every 26us (when a new value is ready from A0) the Arduino
stops what it is doing in the loop and does whatever is encapsulated in the interrupt routine (in this case just the line "incomingAudio = ADCH;"). Once the interrupt
routine has finished, the Arduino picks up again where it was in the loop() for another 26us. Then the interrupt routine executes again.... this goes on repeating forever. If
you want, you can read more about Arduino interrupts here .
This interrupt code generally a better way of reading the incoming signal than the way I wrote it in the last step because you are only updating the variable incomingAudio
once each time a new value comes in. Updating the variable multiple times, before the value has even had time to change is redundant. Also, if you want to record these
values you can put the storage code in the interrupt routine so you know that your storage sampling rate is exactly 38.5kHz.
//Audio out with 38.5kHz sampling rate and interrupts
//by Amanda Ghassaei
//http://www.instructables.com/id/Arduino-Audio-Input/
//Sept 2012
/*
* This program is free software; you can redistribute it and/or modify
http://www.instructables.com/id/Arduino-Audio-Input/
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
*/
int incomingAudio;
void setup(){
cli();//disable interrupts
//set up continuous sampling of analog pin 0
//clear ADCSRA and ADCSRB registers
ADCSRA = 0;
ADCSRB = 0;
ADMUX |= (1 << REFS0); //set reference voltage
ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz
ADCSRA |= (1 << ADATE); //enabble auto trigger
ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
ADCSRA |= (1 << ADEN); //enable ADC
ADCSRA |= (1 << ADSC); //start ADC measurements
sei();//enable interrupts
//if you want to add other things to setup(), do it here
}
ISR(ADC_vect) {//when new ADC value ready
incomingAudio = ADCH;//update the variable incomingAudio with new value from A0 (between 0 and 255)
}
void loop(){
//do other stuff here
}
Step 8:Clipping Indicator
A clipping indicator LED is useful so that you know if you need to turn the gain down on your amplifier. If your signal is clipping as it comes into the Arduino, you are
losing information about the signal. Figs 2 and 3 show the incoming signal (yellow) and the data stored in the Arduino (blue) for both 8kHz and 38.5kHz sampling rates.
Notice how the Arduino completely misses the behavior of the peaks and valleys due to clipping.
To set up the clipping counter I created a few new variables. "clipping" has a state of 1 when the Arduino detects clipping (the incoming signal is measured to be 0 or 5V)
and a state of 0 when the Arduino does not detect clipping. In the code below (for 8kHz sampling rate) I also set up a variable called clippingCounter. The purpose of this
variable is to keep the indicator LED on for a moment after the clipping was detected so that it is visible to the human eye. In the 38.5kHz code (at the bottom of this step)
I used a delay(100) to achieve the same effect.
//Simple Audio In with clipping indicator
//by Amanda Ghassaei
//http://www.instructables.com/id/Arduino-Audio-Input/
//Sept 2012
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
*/
int incomingAudio;
boolean clipping = 0;//zero = not clipping, one = currently clipping
int clippingCounter = 5000;
void setup(){
}
void loop(){
http://www.instructables.com/id/Arduino-Audio-Input/
incomingAudio = analogRead(A0);//read input from A0
//do stuff with the variable "incomingAudio"
if (incomingAudio == 0 || incomingAudio == 1023){//if clipping
digitalWrite(13,HIGH);//set pin 13 high
clipping = 1;//currently clipping
clippingCounter = 5000;//reset clippingCounter
}
if (clipping){
if (clippingCounter>0){
clippingCounter--;//decrement clipping counter
}
else{//if clippingCounter has counted all the way down
clipping = 0;//no longer clipping
digitalWrite(13,LOW);//turn of clipping indicator
}
}
}
and below is the code for 38.5kHz with interrupts:
//Audio in with 38.5kHz sampling rate, interrupts, and clipping indicator
//by Amanda Ghassaei
//http://www.instructables.com/id/Arduino-Audio-Input/
//Sept 2012
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
*/
//variable to store incoming audio sample
byte incomingAudio;
//clipping indicator variables
boolean clipping = 0;
void setup(){
pinMode(13,OUTPUT);//led indicator pin
cli();//disable interrupts
//set up continuous sampling of analog pin 0
//clear ADCSRA and ADCSRB registers
ADCSRA = 0;
ADCSRB = 0;
ADMUX |= (1 << REFS0); //set reference voltage
ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz
ADCSRA |= (1 << ADATE); //enabble auto trigger
ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
ADCSRA |= (1 << ADEN); //enable ADC
ADCSRA |= (1 << ADSC); //start ADC measurements
sei();//enable interrupts
//if you want to add other things to setup(), do it here
}
ISR(ADC_vect) {//when new ADC value ready
incomingAudio = ADCH;//store 8 bit value from analog pin 0
if (incomingAudio == 0 || incomingAudio == 255){//if clipping
digitalWrite(13,HIGH);//set pin 13 high
clipping = 1;//currently clipping
}
}
void loop(){
if (clipping){//if currently clipping
clipping = 0;//
digitalWrite(13,LOW);//turn off clipping led indicator (pin 13)
}
delay(100);
}
http://www.instructables.com/id/Arduino-Audio-Input/
Image Notes
1. when input signal (yellow) drops below 0V the Arduino clips it as it measures
it. This clipping is reflected in the outgoing signal from the Arduino (blue)
2. when input signal (yellow) rises above 5V the Arduino clips it as it measures
it. This clipping is reflected in the outgoing signal from the Arduino (blue)
3. volts/div = 2V
4. time/div = 500us
Image Notes
1. when input signal (yellow) drops above 5V the Arduino clips it as it measures
it. This clipping is reflected in the outgoing signal from the Arduino (blue)
2. when input signal (yellow) drops below 0V the Arduino clips it as it measures
it. This clipping is reflected in the outgoing signal from the Arduino (blue)
3. volts/div = 2V
4. time/div = 500us
Related Instructables
Arduino Vocal
Effects Box by
amandaghassaei
Lo-fi Arduino
Guitar Pedal by
kylemcdonald
Girino - Fast
Arduino
Oscilloscope by
Caffeinomane
Audio Delay
Module by
LargeMouthBass
USB Headphone
Hack! by
babblin5
Arduino
Frequency
Detection by
amandaghassaei
http://www.instructables.com/id/Arduino-Audio-Input/
Advertisements
Comments
50 comments Add Comment view all 186 comments
jiffymanager says: Apr 25, 2014. 10:10 PM REPLY
super
calmlunch says: Apr 20, 2014. 8:55 PM REPLY
good
sheepbars says: Apr 19, 2014. 2:28 AM REPLY
that's a good point about the op amp, I hadn't thought of that.
creditrepairaid says: Apr 3, 2014. 11:20 PM REPLY
Scaling from 10 bits to 8 bits may be quicker with bit shifting instead of that extra math:
amandaghassaei says: Apr 4, 2014. 11:27 AM REPLY
yes it is! I just wanted it to be clear what was going on :)
cmars4 says: Mar 26, 2014. 7:07 PM REPLY
is +5 - 0 ok too (the arduino power) for vcc+ and vcc- ? (if we want to amplify bigger input signals ?)
amandaghassaei says: Apr 2, 2014. 10:20 AM REPLY
I don;t think that will work with the tl082, but you can try
azalesov says: Mar 27, 2014. 1:57 PM REPLY
Should such scheme work with regular input from a mp3 player instead of mic? I constantly getting just 3 values 0 1023 and something around 512. I dont have
an osciloscope but it obviously It does not look like a waveform. tripple checked the scheme.
amandaghassaei says: Apr 2, 2014. 10:19 AM REPLY
yes it should work with any analog signal. is there a hackerspace near you where you can get on an oscilloscope?
stupsi99 says: Mar 8, 2014. 12:28 PM REPLY
Awesome tutorial!!! Thank you very much, this helped me a lot! Now I already have an amplified signal, might have to apply DC Offset to it though (not a big
problem with your tutorial!) . I would like to record it to an sd card!
I've searched the web and so far couldn't find the right information. The file needs to be able to be played on a computer later. Any idea how to get this
done?
amandaghassaei says: Mar 9, 2014. 12:13 PM REPLY
use the sd library, here's an example of logging analog data to it.
clickyummy says: Mar 8, 2014. 1:52 AM REPLY
super
raghavlite says: Feb 28, 2014. 11:05 AM REPLY
i tried the fast sampling code and it seems like the serial monitor gets struct up with these setup commands .for now i am testing with giving zero input at the
A0 pin .
I copied the whole of your code and executed it.is there anything else i am missing
the code is .........
int a;
void setup()
{
http://www.instructables.com/id/Arduino-Audio-Input/
Serial.begin(9600);
Serial.println("started");
delay(1000);
cli();//disable interrupts
//set up continuous sampling of analog pin 0
//clear ADCSRA and ADCSRB registers
ADCSRA = 0;
ADCSRB = 0;
ADMUX |= (1 << REFS0); //set reference voltage
ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz
ADCSRA |= (1 << ADATE); //enabble auto trigger
ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
ADCSRA |= (1 << ADEN); //enable ADC
ADCSRA |= (1 << ADSC); //start ADC measurements
sei();//enable interrupts
//if you want to add other things to setup(), do it here
pinMode(2,INPUT);digitalWrite(2,HIGH);
attachInterrupt(0,up,FALLING);
// Serial.begin(9600);
a=1;
}
ISR(ADC_vect) {//when new ADC value ready
Serial.println("yes");
// incomingAudio = ADCH;//update the variable incomingAudio with new value from A0 (between 0 and 255)
}
void up()
{
a=0;
}
void loop()
{
Serial.println("aaaa");
if(a==0)
{
Serial.println("0000");
delay(5000);
}
a=1;
}
amandaghassaei says: Mar 4, 2014. 9:59 AM REPLY
remove the line:
Serial.println("yes");
you can't put any commands that take a long time in the interrupt - Serial.print takes a long time to execute.
http://www.instructables.com/id/Arduino-Audio-Input/
foobar8675 says: Feb 17, 2014. 1:42 PM REPLY
This is really excellent Amanda. thank you. I have a few questions
Instead of the mic, I have an old USB mic. Can I use that instead? 1.
I'm having a hard time finding the 47nF cap. Can I use a larger one instead? Or is it not necessary as akellyirl says? If it is, is there a rule of thumb 2.
that can be applied to the size of the capacitor to remove the signal noise?
amandaghassaei says: Mar 4, 2014. 9:57 AM REPLY
you should be fine w/o the 47nf cap. Does your mic output digital usb data? that will not work, you need to use an analog signal.
mavriksc says: Feb 28, 2014. 11:51 AM REPLY
How is the 0V reference not a short?
bearblue says: Feb 25, 2014. 7:41 PM REPLY
wonderful
raghavlite says: Feb 5, 2014. 12:34 PM REPLY
hello amanda,
that was a great tutorial,can you please tell me how to extend this sampling at 40khz to some other(say 3) analog pin of arduino.
anyway thanks in advance
amandaghassaei says: Feb 13, 2014. 9:16 PM REPLY
try putting the line:
ADMUX |= 3;
in the setup
ss1306 says: Feb 11, 2014. 7:21 AM REPLY
Hi, this maybe a stupid question but how do we prepare the audio signal to be used in this project? can we use any audio signal? Thanks!
amandaghassaei says: Feb 13, 2014. 8:37 PM REPLY
anything will work, you might have to adjust the gain of the amplifier depending on your audio source.
chimplost says: Jan 21, 2014. 9:36 PM REPLY
that's a good point about the op amp, I hadn't thought of that.
bowerymarc says: Dec 21, 2013. 9:28 PM REPLY
- you should never leave an op-amp unconnected, it'll oscillate or pick up the signal from the other side and clip and heat the package, draw lots of current,
and cause the other one to misbehave. Hook it up as a unity gain buffer and ground the input.
- the circuit could damage the arduino since it can drive the input past the arduino's rails. Better to run the op-amp off 0-5V (maybe something with RRIO).
Create the VCC/2 bias with a bias network on the + input of the opamp, and AC couple the input and configure as an inverting stage. There's an example of
that here: http://www.ecircuitcenter.com/Circuits/opinv_ss/opinv_ss.htm just don't need the output cap (or load R), just go to the Arduino from the opamp
output. Also putting a cap in parallel with R2 (from the linked schematic) will give you a bit of a low pass filter, to help with aliasing. with a 200K R, 100pF
would give you a corner of 8KHz, first order filter which would be a good start.
amandaghassaei says: Jan 13, 2014. 9:06 PM REPLY
that's a good point about the op amp, I hadn't thought of that.
hilukasz says: Dec 2, 2013. 10:09 AM REPLY
hey sorry for the stupid question, but you mention you are wiring in series to get 9v, but wouldn't that actually give you 18v if you did series and not the 9v
you suggest?
amandaghassaei says: Jan 13, 2014. 9:04 PM REPLY
it gives me +9 and -9, yes technically an 18v spread, but usually when you talk about the power supply for an op amp you talk about the +/-V, in this case
+/-9V
http://www.instructables.com/id/Arduino-Audio-Input/
steveazhocar says: Dec 20, 2013. 7:16 PM REPLY
yes it is automatically triggered every time a new analog measurement is complete.
matteoM1983 says: Nov 17, 2013. 5:24 AM REPLY
Hi Amanda, thank you for this excellent tutorial! I'd have a couple of questions about the circuit and will be very grateful if you could answer! :-)
As in many other tutorials, the choice of resistors and capacitors seems to me (I'm very uneducated in hardware) a bit mysterious.
Question 1) From what I understand, the choice of 100k/10k resistors for the opamp is arbitrary, all that matters is the 10:1 ratio. Is this correct? Similarly, the
choice of 100k/100k for the voltage divider is arbitrary: you could have used 10k/10k or 100ohm/100ohm
Question 2) Somebody else already asked bout the 49nF capacitor. Interpreting your answer (reducing noise) I guess what this capacitor does is, basically,
trying to compensate (i.e., average) changes in the signal. Since this is a very small cap, it helps compensating changes in (what we could consider as) the
least important bits of the signal, which are what rumor is about (hopefully).
Question 3) What about the 10uF capacitor? What does it do? Why 10uF? Could we eliminate it entirely from the circuit? What would change? And if not,
why?
It seems to me that, without the 10uF cap, the opamp (at the moment when it is emitting -2.5V) would receive some current from the +2.5 side (I guess
(5/100k)A = 0.05mA having the 100k resistor). Is this correct?
THANKS!!!!
akellyirl says: Dec 10, 2013. 2:44 AM REPLY
Hi Matteo,
1) The resistor values can't be too small (100Ohms) because the op-amp has to drive that current e.g. 1V/100 = 10mA. It also can't be too big because
op-amp leakage current will cause an offset voltage that gets gained up by the amplifier too.
2) The 49nF cap is usually used to reduce high frequency noise. But it's ineffective in this circuit because it being driven by a 10uF capacitor.
3) The 10uF cap is used to block DC. It forms a high-pass filter with the 100k resistors. It will pass frequencies above 1/(2*pi*R*C) i.e. 1/(2*pi*50k*10u) =
0.32Hz. The reason you need to block DC here is because you want to bias the Arduino Analogue input to Vdd/2 but you don't want that the DC current
to flow into the op-amp.
matteoM1983 says: Dec 12, 2013. 1:34 AM REPLY
Thank you very much for the nice and instructive answer!
A) Answer 1) is very clear! thanks!
B) Could you please elaborate on answer 2) ?
Which Cap value should be chosen in place of 49nF to effectively reduce high-frequency noise? And how this work precisely? I guess It should work
as a Low-Pass filter, but where is the associated resistance? (I have this picture in mind:
http://upload.wikimedia.org/wikipedia/commons/3/3b/RC_Divider.svg )
C) shouldn't the expression be 1/(2*pi*100k*10u) = 0.16Hz ?
It seems from your explanation that the value 10uF for the cap (which is anyway necessary to block DC as you explained) is chosen as a function of
100kOhm, basically to allow all frequencies to pass.
Is it correct to say that a 1F cap would work in this context even better? (but of course it would be much bigger and expensive and give just a very
small better result in terms of filtering)
Or perhaps a 1F cap would create problems, as it will allow the DC to pass (just after the circuit starts running) for a way too long time? Thank you
very much again!
akellyirl says: Dec 13, 2013. 7:55 AM REPLY
B) The associated resistance is actually the reactance of the 10uF cap. Because there is no resistance involved there is no value of capacitance
that will make this arrangement work.
C) It's actually 50k because the 100k resistors appear to be in parallel for AC analysis (because both GND and +Ve are GND from an AC
perspective).
As a rule you choose the smallest practical value of capacitance, even if a larger one might work.
matteoM1983 says: Nov 19, 2013. 2:27 PM REPLY
Searching the web for ideas about question 3) above, I discovered this is probably a so-called "coupling capacitor".
I only found very generic and not clear informations about how this work. Basically "stops DC and allow AC to pass". This is compatible with the idea that
the +2.5 stay fixed on the left, and the -2.5,..,+2.5 can pass making up 0..+5v.
However I'd like to understand how this can happen, in a (relatively) precise way.
Could you spend a few words on this please? It seems to me that this is a very interesting and possibly crucial part of the circuit :)
THANKS!
http://www.instructables.com/id/Arduino-Audio-Input/
arodriguez cueto says: Nov 4, 2013. 3:35 AM REPLY
hi amandaghassaei.
Thanks a lot for this HQ tutorial!
Could yo please expand on how hacking the A/D conversion rate works on a fundamental level?
I thought its conversion rate was a fundamental aspect of A/D and could not be changed.
What negative aspects does this bypassing carry?
Thank you!
amandaghassaei says: Nov 4, 2013. 9:58 PM REPLY
the conversion from A to D takes a certain number of clock cycles (13), but the length of each clock cycle can be changed. That's essentially what I did
here. By speeding up the clock to 500kHz, 13 clock cycles takes less time and the analog to digital conversion happens faster. There are some trade-offs
though, it's best to keep the clock slow to give time for the analog pins to settle and minimize noise in your analog measurements. Hope that helps!
kilianciuffolo says: Nov 3, 2013. 2:24 PM REPLY
Thanks so much Amanda!
I have I question for you though, what is the purpose of the 10uF Cap? My understanding is that the output from the amp is -/+ 2.5V. Connecting it directly to the
+2.5V wouldn't have the same result? (I know that the answer is no, but it would be nice to explain deeply the flow of electron for the DC offset and why we
need the cap).
Also the cap will "store" 5V right? Delta V from +2.5V divider and -2.5V from the amp. Not sure how it works when it is discharging. Vout from the cap will be 5V,
and DeltaV from cap to voltage divider will be 2.5V, will this create a 5V signal?
If am correct, a cap with just 2.5V "stored" will not discharge at all since delta V would be 0 between Vcap and Vdivider, am I right?
mjconver says: Oct 11, 2013. 5:04 PM REPLY
Doesn't two 9 volts in series = 18 V? That's higher than 15, not lower.
kilianciuffolo says: Nov 3, 2013. 1:55 PM REPLY
It's 18V but from -9V to +9V! The total input voltage allowed is 30V (+-15V).
amandaghassaei says: Oct 12, 2013. 4:31 PM REPLY
it's +9 and -9 vs +15 and -15
timmyadu says: Oct 26, 2013. 3:48 PM REPLY
Hi Amada, thanks for the awesome instructable.
Quick question: you have set the ADC to be auto triggered. So what's the auto-trigger source?
amandaghassaei says: Oct 27, 2013. 2:05 PM REPLY
yes it is automatically triggered every time a new analog measurement is complete.
Alderin says: Oct 1, 2013. 11:31 AM REPLY
Scaling from 10 bits to 8 bits may be quicker with bit shifting instead of that extra math:
incomingAudio = (incomingAudio+1)/4 - 1;
to
incomingAudio = incomingAudio >> 2;
True division is computationally expensive, so depending on how smart the optimizer is in the compiler, bit shifting for dividing by powers of two could save a
significant amount of processing time. This also avoids divide-by-zero protection requirements (+1/-1 in your original code). I would also do the negative number
protection before bit shifting, as results of bit shifting negative numbers can be confusing.
amandaghassaei says: Oct 2, 2013. 2:19 PM REPLY
good call
6400 says: Sep 2, 2013. 8:57 AM REPLY
This method can be used to run a servo motor?
please its support
thank you
http://www.instructables.com/id/Arduino-Audio-Input/
amandaghassaei says: Sep 8, 2013. 9:09 PM REPLY
yes, use the value returned by ADCH to control the servo.
6400 says: Sep 9, 2013. 3:43 AM REPLY
Mr. amandaghassaei Can you help how schema and scripts of the design?
thx
amandaghassaei says: Sep 8, 2013. 9:09 PM REPLY
helps remove noise in the input signal
asuba?? says: Sep 1, 2013. 8:31 AM REPLY
What does the 47nF capacitor do?
amandaghassaei says: Sep 8, 2013. 9:08 PM REPLY
helps remove noise in the input signal
amandaghassaei says: Sep 8, 2013. 9:08 PM REPLY
yeah, you'll have to lower the sampling rate to free up more time to sample from two inputs.
view all 174 comments

You might also like