Tuesday, January 27, 2015

Arduino Due Audio Tests


I have had this Arduino due for a while and have wanted to make a music project out of it. It has been hard to find any really good examples of using this thing for audio. I finally found these few sites that have helped me speed up the ADC conversions so they are good for audio.

http://forum.arduino.cc/index.php?topic=156849.0

http://www.djerickson.com/arduino/


So from those two posts I was able to build these two projects and I'm overall impressed with the results:


Simple Audio Delay with Feedback

Note that the ADC's only track ~0-3V and most audio signals go negative  (example: -1V to 1V). You will mostly likely need to add a DC offset to your input to avoid clipping the signal. (cutting off the lower half of the waveform). You can do this in many of different ways. I happen to have some modular synth gear and one module in particular is the MATHS by Make Noise. I use this to amplify and offset the input signal. In a later post I might build a circuit to perform the DC offset. They are very simple but right now I want to just do some simple tests without spending too much time if it sounds terrible. For now here is an image of a DC offset amplifier:






Here is the code to create a very simple audio delay with feedback using the Arduino Due. Not all of this code will run on other Arduino's as they might be to slow or not have enough memory and setting of the ADC registers is specific to this version.





#define MAX_ADC_RESOLUTION 12 #define L 20000 int array[L]; // audio buffer to store previous input levels. This makes the delay line. int p=0; int d=0; void setup() { Serial.begin(9600); REG_ADC_MR = (REG_ADC_MR & 0xFFF0FFFF) | 0x00020000; analogReadResolution(MAX_ADC_RESOLUTION); analogWriteResolution(MAX_ADC_RESOLUTION); adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX*2, 3); pinMode(ADC0,INPUT); pinMode(DAC0,OUTPUT); } void loop() { int value = analogRead(ADC0) + array[p]; analogWrite(DAC0, value); array[p++]=value>>1; // bit shift to fade out over time if(p > L) p=0; }
Here is an example of what it sounds like. Not bad but there is a lot of room for improvement. The noise is the first issue that needs to be addressed. I found that this comes from the delay line and I will most likely need to add some type of filter to overcome this.



If you take the loop function above and change it to just the following code then this will simply pass the signal through without modification. Notice that the signal output is much cleaner.






void loop() { int value = analogRead(ADC0); analogWrite(DAC0, value); }
In my next post I will try to clean this up. But for right now this at least gets me started.

LFO for CV Control 

The below application uses a potentiometer on A0 to control the speed of the LFO. One end of the pot is tied to the 3.3 V header, center is tied to A0, and the other end is tied to GND. This is just a test as this is a terrible CV controller since the output only goes to about 3 volts while most CV signals can get up to 10 volts. I may try to put an amplifier on the end to get the voltage to real CV levels.

 








#define MAX_ADC_RESOLUTION 12 void setup() { REG_ADC_MR = (REG_ADC_MR & 0xFFF0FFFF) | 0x00020000; analogReadResolution(MAX_ADC_RESOLUTION); adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX*2, 3); pinMode(DAC0,OUTPUT); pinMode(ADC0,INPUT); } int i=0; void loop() { int val = analogRead(ADC0); analogWrite(DAC0, sinx(val)); } float sinx(int skip){ float x = (125.0*sin(2*PI*i/90000.0))+125.0; // 125.0 is my DC offset. You need to get the sine wave so it does not ever go negative or it will clip i=i+skip/125+1; // The 125 in this skip is arbitrary and not at all related to the dc offset. if(i >= 90000) i=0; return x; } Below is the board i use for these projects:
Arduino Due

No comments:

Post a Comment