This is a simple song with the Arduino. Look at this algo carefully. More to come : maybe a simple synthesis and musical library. It will work by simply pluging a PC speaker between pin 10 and Ground. You could generate a slightly less square wave by using a capacitor and a resistor. It also works with the Wiring interface.
/*
* Au Clair de la Lune with an Arduino and a PC speaker. * The calculation of the tones is made following the mathematical * operation: * * timeUpDown = 1/(2 * toneFrequency) = period / 2 * )c( Copyleft AlexandreQuessy 2006 http://alexandre.quessy.net * Inspired from D. Cuartielles's http://www.arduino.cc/en/Tutorial/PlayMelody */ int ledPin = 13; int speakerOut = 10; /* 2 octavas :: semitones. 0 = do, 2 = re, etc. */ /* MIDI notes from 48 to 71. Indices here are from 0 to 23. */ int timeUpDown[] = {3822, 3606, 3404, 3214, 3032, 2862, 2702, 2550, 2406, 2272, 2144, 2024, 1911, 1803, 1702, 1607, 1516, 1431, 1351, 1275, 1203, 1136, 1072, 1012}; /* our song. Each number is a (MIDI note - 48) on a beat. */ byte song[] = {12,12,12,14, 16,16,14,14, 12,16,14,14, 12,12,12,12, 14,14,14,14, 9,9,9,9, 14,12,11,9, 7,7,7,7}; // do do do re mi re do mi re re do... byte beat = 0; int MAXCOUNT = 32; float TEMPO_SECONDS = 0.2; byte statePin = LOW; byte period = 0; int i, timeUp; void setup() { pinMode(ledPin, OUTPUT); pinMode(speakerOut, OUTPUT); } void loop() { digitalWrite(speakerOut, LOW); for (beat = 0; beat < MAXCOUNT; beat++) { statePin = !statePin; digitalWrite(ledPin, statePin); timeUp = timeUpDown[song[beat]]; period = ((1000000 / timeUp) / 2) * TEMPO_SECONDS; for (i = 0; i < period; i++) { digitalWrite(speakerOut, HIGH); delayMicroseconds(timeUp); digitalWrite(speakerOut, LOW); delayMicroseconds(timeUp); } /* Uncomment this if you want notes to be discrete */ /* delay(50); */ } digitalWrite(speakerOut, LOW); delay(1000); }
Much improved version:
/*
* Square wave tune with an Arduino and a PC speaker. * The calculation of the tones is made following the mathematical * operation: * * timeUpDown = 1/(2 * toneFrequency) = period / 2 * )c( Copyleft 2009 Daniel Gimpelevich * Inspired from AlexandreQuessy's https://playground.arduino.cc/Code/MusicalAlgoFun */ const byte ledPin = 13; const byte speakerOut = 11; /* This makes a standard old PC speaker connector fit nicely over the pins. */ /* 10.5 octaves :: semitones. 60 = do, 62 = re, etc. */ /* MIDI notes from 0, or C(-1), to 127, or G9. */ /* Rests are note number -1. */ unsigned int timeUpDown[128]; /* our song. Each number pair is a MIDI note and a note symbol. */ /* Symbols are 1 for whole, -1 for dotted whole, 2 for half, */ /* -2 for dotted half, 4 for quarter, -4 for dotted quarter, etc. */ const byte BPM = 120; const char song[] = { 64,4,64,4,65,4,67,4, 67,4,65,4,64,4,62,4, 60,4,60,4,62,4,64,4, 64,-4,62,8,62,2, 64,4,64,4,65,4,67,4, 67,4,65,4,64,4,62,4, 60,4,60,4,62,4,64,4, 62,-4,60,8,60,2, 62,4,62,4,64,4,60,4, 62,4,64,8,65,8,64,4,60,4, 62,4,64,8,65,8,64,4,62,4, 60,4,62,4,55,2, 64,4,64,4,65,4,67,4, 67,4,65,4,64,4,62,4, 60,4,60,4,62,4,64,4, 62,-4,60,8,60,2}; int period, i; unsigned int timeUp, beat; byte statePin = LOW; const float TEMPO_SECONDS = 60.0 / BPM; const unsigned int MAXCOUNT = sizeof(song) / 2; void setup() { pinMode(ledPin, OUTPUT); pinMode(speakerOut, OUTPUT); for (i = 128; i--;) timeUpDown[i] = 1000000 / (pow(2, (i - 69) / 12.0) * 880); } void loop() { digitalWrite(speakerOut, LOW); for (beat = 0; beat < MAXCOUNT; beat++) { statePin = !statePin; digitalWrite(ledPin, statePin); i = song[beat * 2]; timeUp = (i < 0) ? 0 : timeUpDown[i]; period = (timeUp ? (1000000 / timeUp) / 2 : 250) * TEMPO_SECONDS * 4 / song[beat * 2 + 1]; if (period < 0) period = period * -3 / 2; for (i = 0; i < period; i++) { digitalWrite(speakerOut, timeUp ? HIGH : LOW); delayMicroseconds(timeUp ? timeUp : 2000); digitalWrite(speakerOut, LOW); delayMicroseconds(timeUp ? timeUp : 2000); } delay(50); } digitalWrite(speakerOut, LOW); delay(1000); }