view history edit print login register

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);
 }