Week 10 – Assignment

Concept: Music Box

Our inspiration for this project was from a music box, which is a pretty nostalgic instrument that plays melodies when you wind it up. Music boxes are usually these small, mechanical devices that play a set of tunes with a simple winding mechanism, and have a sweet, tinkling sound.

Our version of this is more interactive and customizable. Instead of just one melody, our “music box” allows the users to choose between two pre-programmed songs , which are Twinkle Twinkle Little Star and Frère Jacques. In addition to that, they can also increase or decrease the tempo of the song with a button, adjust the pitch of the melody with the potentiometer, and as the music plays, the LEDs flash and change, synchronized to the rhythm and notes.

Code Snippet/Difficulties

One aspect we had difficulties with was getting the LED’s to align with music and the notes played, however after a few tries we were able to get this code. In summary, to get this “visualizer” effect, we used the flashVisualizer() function , and called it inside the playSong() function, right after each note was played. The i variable, which is the index of the current note in the song, is passed to flashVisualizer(), and so, as the song progresses, the i value increments, causing the 3 LEDs we used to cycle through in sequence. In general, every time a note is played, the flashVisualizer() function is called, which results in a flash of an LED that matches the timing of the note. So, the flashing LED visualizes the rhythm of the music, and since the song is made up of an array of notes, the LEDs change with each note.

// Function to play the melody
void playSong(int *melody, int *durations, int length) {
  for (int i = 0; i < length; i++) {
    int baseNote = melody[i];
    int noteDuration = tempo * (4.0 / durations[i]);  // Calculate note duration

    // Read potentiometer and calculate pitch adjustment
    int potVal = analogRead(potPin); // range: 0–1023
    float pitchFactor = 0.9 + ((float)potVal / 1023.0) * 0.4;  // pitch range: 0.9–1.3
    int adjustedNote = baseNote * pitchFactor;

    if (baseNote == 0) {
      noTone(buzzer); // Pause
    } else {
      tone(buzzer, adjustedNote, noteDuration); // Play adjusted tone
      flashVisualizer(i); // Flash LEDs
    }

    delay(noteDuration * 1.3); 
  }

  // Turn off all LEDs after song ends
  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);
  digitalWrite(led3, LOW);
}

// LED Visualizer Function
void flashVisualizer(int index) {
  // Turn off all LEDs first
  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);
  digitalWrite(led3, LOW);

  // Turn on one LED based on index
  if (index % 3 == 0) digitalWrite(led1, HIGH);
  else if (index % 3 == 1) digitalWrite(led2, HIGH);
  else digitalWrite(led3, HIGH);
}

Reflections/Improvements

Overall, this project was very fun and engaging, and we are very happy with how it turned out as we were able to implement most of the ideas we brainstormed. That said, there are a few things we’d improve. For one, we could expand the number of songs it can play. Also, the current LED visualizer is pretty simple and linear, so adding more LEDs or creating more complex patterns based on pitch, tempo, or things like that, could make it feel more like a true light show.

 

Leave a Reply