Week 5 - Audio + Arduino = FREQOUT

ARDUINO + AUDIO = FREQOUT
Demo Notes by Steve Belovarich

Audio is something most of us take for granted, but how does sound work? Sound is basically pressure waves flowing through a medium (air), that our brain interprets as a noise. The structure of sound is a wave. Waves have this basic structure:

 

The amplitude of a sound wave determines volume. A combination of amplitude and period determines the frequency of the wave, how many periods happen in 1 second. Frequency in music is called pitch.

Electronics operate under these same characteristics, current flows in a wave-like pattern, as indicated by when someone looks at an electrical signal through an oscilloscope.

 

 

Electronic musicians have used oscillators for some time now, not to monitor the structure of a wave, but to produce a structured and modifiable sound. The instruments that use this technique are called synthesizers.

Computers and electronics can sense sound as well, through the input of a microphone.  Devices output sound through a powered speaker. Both microphones and speakers normally operate at a very low amplitude, that is to say a microphone by itself will only sense very minimal noise. Mics and speakers must be amplified in order to really sense or hear any audio. In the case of a microphone, you must build a pre-amp before you input the sound into the Arduino. In the case of the speaker, you must build an amplifier to make any loud noise.

An amplifier takes the input signal and increases it, then outputs an amplified signal. The amount of amplification is called the gain. The current state of amplification in audio  terms is called the level (or volume). 

There are various low voltage ways to amplify a signal, think about all the handheld devices you have used over the years from a Walkman to an iPod. These devices must conserve power in order to have a long battery life. Since these techniques are so ubiquitous, it is relatively cheap to make a low voltage amplifier.

Here is a schematic for building a Low Voltage Amplifier using a LM386 Chip:

 

 

Go here for more information: http://web.mit.edu/6.s28/www/schematics/lm386.htm

 

Here is a picture of the completed circuit on a breadboard. This circuit could be miniaturized on a soldered circuit board.

As for a pre-amp for a Microphone, follow this link for a schematic:
http://www.zen22142.zen.co.uk/Circuits/Audio/lvpreamp.htm

So now if you have built an amplifier, you can produce sounds with an Arduino. Here are some samples of code that will help you. There are links at the end of this document for various Audio and Arduino resources.

/*

This is a basic audio output program for the Arduino. The program uses PWM to output a frequency (pitch).

*/

//Arduino Sound Hello World
//Created by David Fowler of uCHobby.com

#define SOUNDOUT_PIN 9 // Define the I/O pin we will use for our sound output

void setup(void){

pinMode(SOUNDOUT_PIN,OUTPUT); // Set the sound out pin to output mode
}

void loop(void){
// Generate sound by toggling the I/O pin High and Low
// Generate a 1KHz tone. set the pin high for 500uS then
// low for 500uS to make the period 1ms or 1KHz.

digitalWrite(SOUNDOUT_PIN,HIGH); // Set the pin high and delay for 1/2 a cycle of 1KHz, 500uS.
delayMicroseconds(500);

digitalWrite(SOUNDOUT_PIN,LOW); // Set the pin low and delay for 1/2 a cycle of 1KHz, 500uS.
delayMicroseconds(500);
}

/*

FREQOUT -

This program demonstrates a more sophisticated understanding of Pitch / Frequency. Major differences between this program and others the class has previously seen is another method to initialize a variable (#define), the inclusion of the math library (math.h) so we can perform advanced math operations, the use of arrays, and another function loop called void freqout, that is used in addition to void loop. Close attention to this program reveals the loop function is linked to the freqout function through this line of code:

freqout ((int)noteval, dur);

Notice how the start of next function reads

void freqout(int freq, int t)  // freq in hz, t in ms

noteval = frequency in void loop
freq = frequency in void freqout

dur = the beat
t = the beat

One function calls the other, in this case Void Loop is used to structure the song, Void FreqOut actually sends that information to the Arduino, but only because freqout is called inside of Void Loop.

Arrays are used to structure a melody.

float majScale[] = {
A,  B,  CS,  D,  E,  FS,  GS,  A2,   B2,  C2S,  D2,  E2,  F2S,  G2S,  A3};

This is the Major Scale. Notice how the array is formatted and where it gets the values for each slot in the array.

To get information out of an array, we use the following notation, where ‘x’ is the number of the item in the array. A = 1, B = 2, CS = 3, D = 4, E = 5, etc.

majScale[x]

To call up F Sharp, write majScale[6]

To write a song, call a custom arrays inside a For Loop, like in the example. You can do this too for the beat inside the same for loop.

*/

/*  freqout(freq, t)  // freq in hz, t in ms
*   Paul Badger 2007
*   a simple tone generation function
*   generates square waves of arbitrary frequency and duration
*   program also includes a top-octave lookup table & transposition function
*/

#include <math.h>  // requires an Atmega168 chip

#define outpin 9   // audio out to speaker or amp
int ptime;
int   k,  x, dur, freq, t;
int i, j;

float ps;         // variable for pow pitchShift routine

float noteval;

// note values for two octave scale
// divide them by powers of two to generate other octaves

float REF = 0;
float A     = 14080;
float AS    = 14917.2;
float B     = 15804.3;
float C     = 16744;
float CS    = 17739.7;
float D     = 18794.5;
float DS    = 19912.1;
float E     = 21096.2;
float F     = 22350.6;
float FS    = 23679.6;
float G     = 25087.7;
float GS    = 26579.5;
float A2    = 28160;
float A2S   = 29834.5;
float B2    = 31608.5;
float C2    = 33488.1;
float C2S   = 35479.4;
float D2    = 37589.1;
float D2S   = 39824.3;
float E2    = 42192.3;
float F2    = 44701.2;
float F2S   = 47359.3;
float G2    = 50175.4;
float G2S   = 53159;
float A3    = 56320;

//rhythm values
int wh = 1024;
int h  = 512;
int dq = 448;
int q = 256;
int qt = 170;
int de = 192;
int e = 128;
int et = 85;
int dsx = 96;
int sx = 64;
int thx = 32;

// major scale just for demo, hack this

float majScale[] = {
A,  B,  CS,  D,  E,  FS,  GS,  A2,   B2,  C2S,  D2,  E2,  F2S,  G2S,  A3};

float minScale[] = {
A,  B,  C,  D,  E,  F,  GS,  A2,   B2,  C2,  D2,  E2,  F2,  G2S,  A3};

float banginbeat[] = {
qt, qt, sx, sx, qt, qt, sx, sx, sx, sx, qt, qt};

float banginmelody[] = {
E, REF, F, F, REF, E, F, F, F, F, REF, REF};

void setup() {
Serial.begin(9600);
}

void loop(){

// Default Scaling App, comment to try other things

for(i= 0; i<=11; i++){
ps = (float)i / 12;         // choose new transpose interval every loop
for(x= 0; x<=15; x++){                     
noteval = (minScale[x] / 64) * pow(2,ps);    // transpose scale up 12 tones
// pow function generates transposition
// eliminate " * pow(2,ps) " to cut out transpose routine

dur = sx;

freqout((int)noteval, dur);

delay(qt);

}
}

/*
noteval = majScale [3] /64 ;

dur = 10000;
freqout((int)noteval, dur);

delay(1000);

*/

/* 

noteval = minScale [5] / 512 * pow(2,ps);

dur = 5000;
freqout ((int)noteval, dur);

delay (3000);

*/

 

 

/*

for(x= 0; x<=12; x++){                      
noteval = (banginmelody[x] / 64);

dur = banginbeat[x];

freqout((int)noteval, dur);

delay(qt);

}

*/

}

void freqout(int freq, int t)  // freq in hz, t in ms
{

int hperiod;                               //calculate 1/2 period in us
long cycles, i;
pinMode(outpin, OUTPUT);                   // turn on output pin

hperiod = (500000 / freq) - 7;             // subtract 7 us to make up for digitalWrite overhead

cycles = ((long)freq * (long)t) / 1000;    // calculate cycles
// Serial.print(freq);
// Serial.print((char)9);                   // ascii 9 is tab - you have to coerce it to a char to work
// Serial.print(hperiod);
// Serial.print((char)9);
// Serial.println(cycles);

for (i=0; i<= cycles; i++){              // play note for t ms
digitalWrite(outpin, HIGH);
delayMicroseconds(hperiod);
digitalWrite(outpin, LOW);
delayMicroseconds(hperiod - 1);     // - 1 to make up for digitaWrite overhead
}
pinMode(outpin, INPUT);                // shut off pin to avoid noise from other operations

}

RESOURCES:

Arduino Synth Page: http://www.arduino.cc/playground/Main/ArduinoSynth
LM386 Amplifier Circuit: http://web.mit.edu/6.s28/www/schematics/lm386.htm
Preamp w/ LM386 (Scroll Down):
http://sun-livingart.blogspot.com/
Audio Circuits: http://www.zen22142.zen.co.uk/Circuits/Audio/audio.html
Arduino Sound Part 1-3:
http://www.uchobby.com/index.php/2007/11/11/arduino-sound-part-1/
Arduino + Keyboard: http://narbotic.net/?p=95
Attempts at making Arudino Synths:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1186530609/25
How to Build a 1 Bit Groovebox:
http://web.media.mit.edu/~nvawter/projects/1bit/buildit/html/instruction...
Commodore 64 Audio Emulator using Arduino:

http://www.roboterclub-freiburg.de/atmega_sound/atmegaSID.html

Control an iPod w/ an Arduino: http://www.jonasolson.se/content/arduino_tutorial/