int speakerPin = 2; // speaker or MIDI out pin
// define LED pins (10 LEDs, reversed so lowest note is D12)
int ledPins[10] = {12, 11, 10, 9, 8, 7, 6, 5, 4, 3};
// TEMPO CONTROL — change this to make it faster/slower
int tempo = 100; // beats per minute
// TRANSPOSE CONTROL — shift all notes up/down in semitones
// e.g. 0 = normal pitch, -12 = down 1 octave, +12 = up 1 octave
#define TRANSPOSE 0
// note range that maps to the LEDs (these will be shifted by TRANSPOSE)
int minNote = 65; // F4
int maxNote = 77; // F5
// melody: MIDI note number and duration (base duration in ms)
int melody[][2] = {
{65,500},{65,500},{65,500},{65,500},
{77,500},{77,500},{77,500},{77,500},
{76,500},{76,500},{72,500},{74,500},
{76,500},{76,500},{77,500},{77,500},
{70,500},{70,500},{70,500},{70,500},
{74,500},{74,500},{74,500},{74,500},
{72,500},{72,500},{72,500},{72,500},
{72,500},{72,500},{72,500},{72,500},
{74,500},{74,500},{74,500},{74,500},
{70,500},{70,500},{70,500},{70,500},
{69,500},{69,500},{65,500},{67,500},
{69,500},{69,500},{71,500},{71,500},
{67,500},{64,500},{65,500},{67,500},
{69,500},{69,500},
{65,500},{65,500},{65,500},{65,500},
{65,500},{65,500},{72,500},{72,500},
{69,500},{72,500},{69,500},{72,500},
{69,500},{72,500},{69,500},{72,500},
{70,500},{72,500},{70,500},{72,500},
{70,500},{72,500},{70,500},{72,500},
{74,500},{74,500},{74,500},{74,500},
{74,500},{74,500},{74,500},{74,500},
{74,500},{74,500},{74,500},{74,500},
{74,500},{74,500},{72,500},{72,500},
{69,500},{72,500},{69,500},{72,500},
{69,500},{72,500},{69,500},{72,500},
{71,500},{74,500},{71,500},{74,500},
{71,500},{74,500},{71,500},{74,500},
{76,500},{76,500},{76,500},{76,500},
{76,500},{76,500},{76,500},{76,500},
{67,500},{67,500},{67,500},{67,500},
{70,500},{70,500},{70,500},{70,500},
{65,500},{65,500},{65,500},{65,500},
{77,500},{77,500},{77,500},{77,500},
{76,500},{76,500},{72,500},{74,500},
{76,500},{76,500},{77,500},{77,500},
{70,500},{70,500},{70,500},{70,500},
{74,500},{74,500},{74,500},{74,500},
{72,500},{72,500},{72,500},{72,500},
{72,500},{72,500},{72,500},{72,500},
{74,500},{74,500},{74,500},{74,500},
{70,500},{70,500},{70,500},{70,500},
{69,500},{69,500},{65,500},{67,500},
{69,500},{69,500},{71,500},{71,500},
{67,500},{64,500},{65,500},{67,500},
{69,500},{69,500},
{65,500},{65,500},{65,500},{65,500},
{65,500},{65,500},{72,500},{72,500},
{69,500},{72,500},{69,500},{72,500},
{69,500},{72,500},
{71,500},{72,500},{74,500},{76,500},
{77,500},{77,500},{77,500},{77,500}
};
int melodyLength = sizeof(melody) / sizeof(melody[0]);
void setup() {
Serial.begin(9600);
// set LED pins as output
for (int i = 0; i < 10; i++) {
pinMode(ledPins[i], OUTPUT);
digitalWrite(ledPins[i], LOW);
}
pinMode(speakerPin, OUTPUT);
}
void loop() {
float tempoFactor = 120.0 / tempo; // tempo scaling
for (int i = 0; i < melodyLength; i++) {
int note = melody[i][0] + TRANSPOSE; // apply transpose
int baseDuration = melody[i][1];
int duration = baseDuration * tempoFactor / 2; // shorten for rhythm
// Map note to LED index, clamp to valid range (with transpose)
int ledIndex = map(note, minNote + TRANSPOSE, maxNote + TRANSPOSE, 0, 9);
ledIndex = constrain(ledIndex, 0, 9);
// Light LED
digitalWrite(ledPins[ledIndex], HIGH);
// Calculate frequency and play note
float freq = 440.0 * pow(2.0, (note - 69) / 12.0);
tone(speakerPin, freq);
Serial.println(freq);
delay(duration);
// Turn off LED
digitalWrite(ledPins[ledIndex], LOW);
}
noTone(speakerPin);
delay(1000); // brief pause before repeating
}