// Pin for the buzzer
const int buzzerPin = 2;
// LED pins (10 LEDs for low-to-high notes, skipping pin 2)
const int ledPins[] = {12, 11, 10, 9, 8, 7, 6, 5, 4, 3};
const int numLeds = sizeof(ledPins)/sizeof(ledPins[0]);
// Define frequencies for notes
#define NOTE_E4 329.63
#define NOTE_F4 349.23
#define NOTE_G4 392.00
#define NOTE_A4 440.00
#define NOTE_AS4 466.16
#define NOTE_B4 493.88
#define NOTE_C5 523.25
#define NOTE_D5 587.33
#define NOTE_E5 659.25
#define NOTE_F5 698.46
// Melody using "NOTE DURATION" string format
const char* melodyStr[] = {
"F4","F4","F4","F4","F5","F5","F5","F5",
"E5","E5","C5","D5","E5","E5","F5","F5",
"AS4","AS4","AS4","AS4","D5","D5","D5","D5",
"C5","C5","C5","C5","C5","C5","C5","C5",
"D5","D5","D5","D5","AS4","AS4","AS4","AS4",
"A4","A4","F4","G4","A4","A4","B4","B4",
"G4","E4","F4","G4","A4","A4",
"F4","F4","F4","F4","F4","F4","C5","C5",
"A4","C5","A4","C5","A4","C5","A4","C5",
"AS4","C5","AS4","C5","AS4","C5","AS4","C5",
"D5","D5","D5","D5","D5","D5","D5","D5",
"D5","D5","D5","D5","D5","D5","C5","C5",
"A4","C5","A4","C5","A4","C5","A4","C5",
"B4","D5","B4","D5","B4","D5","B4","D5",
"E5","E5","E5","E5","E5","E5","E5","E5",
"G4","G4","G4","G4","AS4","AS4","AS4","AS4",
"F4","F4","F4","F4","F5","F5","F5","F5",
"E5","E5","C5","D5","E5","E5","F5","F5",
"AS4","AS4","AS4","AS4","D5","D5","D5","D5",
"C5","C5","C5","C5","C5","C5","C5","C5",
"D5","D5","D5","D5","AS4","AS4","AS4","AS4",
"A4","A4","F4","G4","A4","A4","B4","B4",
"G4","E4","F4","G4","A4","A4",
"F4","F4","F4","F4","F4","F4","C5","C5",
"A4","C5","A4","C5","A4","C5","A4","C5",
"AS4","C5","AS4","C5","AS4","C5",
"B4","C5","D5","E5","F5","F5","F5","F5"
};
// Map note name to frequency
float getFreq(const char* note) {
if(strcmp(note, "E4") == 0) return NOTE_E4;
if(strcmp(note, "F4") == 0) return NOTE_F4;
if(strcmp(note, "G4") == 0) return NOTE_G4;
if(strcmp(note, "A4") == 0) return NOTE_A4;
if(strcmp(note, "AS4")== 0) return NOTE_AS4;
if(strcmp(note, "B4") == 0) return NOTE_B4;
if(strcmp(note, "C5") == 0) return NOTE_C5;
if(strcmp(note, "D5") == 0) return NOTE_D5;
if(strcmp(note, "E5") == 0) return NOTE_E5;
if(strcmp(note, "F5") == 0) return NOTE_F5;
if(strcmp(note, "R") == 0) return 0;
return 0;
}
// Map frequency to LED index (approx)
int getLedForFreq(float freq) {
if(freq == 0) return -1;
float freqs[] = {NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_AS4,
NOTE_B4, NOTE_C5, NOTE_D5, NOTE_E5, NOTE_F5};
for(int i = 0; i < numLeds; i++) {
if(fabs(freq - freqs[i]) < 5) return i;
}
if(freq < NOTE_E4) return 0;
if(freq > NOTE_F5) return numLeds - 1;
return map(freq, NOTE_E4, NOTE_F5, 0, numLeds - 1);
}
// Duration helper
int getDuration(const char* dur) {
int base = 250;
int val = atoi(dur);
if(val == 0) val = 4;
return (base * 4 / val);
}
void setup() {
Serial.begin(9600);
delay(1000);
// Setup LEDs
for(int i = 0; i < numLeds; i++) {
pinMode(ledPins[i], OUTPUT);
digitalWrite(ledPins[i], LOW);
}
}
void loop() {
static int thisNote = 0;
char noteName[4];
char durStr[3];
sscanf(melodyStr[thisNote], "%s %s", noteName, durStr);
float freq = getFreq(noteName);
int duration = getDuration(durStr);
int ledIndex = getLedForFreq(freq);
if(ledIndex >= 0 && ledIndex < numLeds) digitalWrite(ledPins[ledIndex], HIGH);
if(freq > 0) tone(buzzerPin, freq, duration);
else noTone(buzzerPin);
Serial.println(freq);
delay(duration * 1.02);
if(ledIndex >= 0 && ledIndex < numLeds) digitalWrite(ledPins[ledIndex], LOW);
thisNote = (thisNote + 1) % (sizeof(melodyStr)/sizeof(melodyStr[0]));
}