For beginners: Generate a simple sound

Zápisník experimentátora

In this article, we'll show you how Arduino can generate sound. It will be a simple sound, so don't expect any miracles from the example. But the sound will be loud enough to get on your nerves after a while. Depending on its durability, you can choose whether the sound is output from a piezoelectric transducer or a small speaker. In your place, I would choose the speaker.

Piezoelectric transducer or loudspeaker?

As I prepared the material for this article, I constantly found recommendations on the Internet that this example should be done with a piezo transducer. I have one piezo transducer from the EDU01 kit from Velleman. The piezoelectric transducer works by simply connecting it to 5 V and a sound is heard. The only problem is that there is a very unpleasant sound. And you can't sit for a few minutes at that sound. So my advice is, use a small speaker. Getting a small speaker is no problem. It can be bought or you can remove it from a toy. And the resulting sound will be much better. Use a small 8 OHM speaker (commonly used toy speakers). And with the 330-1000 R resistor, set the volume so that you can easily listen for a few minutes.

What will we listen to?

I chose two melodies.

  • The first melody comes from a example of the tone function. I couldn't figure out which song the melody came from. But I adapted the example itself to match a meaningful musical tempo. The original example set the tempo using a magic constant, and I modified the example so that the tempo was set using BPM.
  • The second melody is from the book Béla Bartók - Slovak Folk Songs. That song was recorded by Béla Bartók in 1914 in Poniky (a village near Banská Bystrica in Slovakia). It's called Hemp, hemp, and so that you can hear it in its normal arrangement, I prepared it for you along with the chords in the MuseScore program (music sample with notes). The program is the same as in the previous example.

BPM

BPM is an abbreviation for beats per minute. From this value we can derive the durations of individual notes. For example, 60 BPM means you hear 60 quarter notes in one minute. In the program, I use a simple formula to convert BPM to the duration of one quarter note in milliseconds. Other lengths of notes are derived from this value using simple constants. For example, a quarter note uses a constant of 4, an eighth note of 8. It's just a simple way to write common values of notes. Notes of a different length could not be written using this method.

// beats per minute
int bpm = 85;
// duration of a beat in ms
float beatDuration = 60.0 / bpm * 1000;

Note that the note does not play in milliseconds for the entire calculated time. The duration is set to 85% of the length. So after each note you hear a small pause. This length is not used in every song. Sometimes you also hear notes with a shortened duration (staccato) or notes with an extended duration (tenuto). And, for example, when playing the violin, it is common for the tones to sound continuously (legato). But I just turned to music theory for a moment. In our example, a normal length of notes will suffice.

Example 1

Both examples are the same, differing only in notes. These are written in the variable melody and their lengths are in the variable noteDurations. The number of notes is calculated by the compiler in the variable notesLength. Then there is no danger that if we add some more notes, we will have to calculate their number manually.

#include "pitches.h"

// notes in the melody
int melody[] = {
  NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
  4, 8, 8, 4, 4, 4, 4, 4
};

int notesLength = sizeof(melody)/sizeof(int);

// beats per minute
int bpm = 85;
// duration of a beat in ms
float beatDuration = 60.0 / bpm * 1000;

void setup() {
}

void loop() {
  for (int thisNote = 0; thisNote < notesLength; thisNote++) {

    float noteDuration = beatDuration * (4.0 / noteDurations[thisNote]);
    tone(8, melody[thisNote], noteDuration * 0.85);
    delay(noteDuration);
  }
  delay(500);
}

Example 2

Like I said, the program is the same, only the notes differ. To make it clear, I arranged them one bar by one. I chose the song by Béla Bartók because it is my daughter's favorite song. And because the melody is simple, my son is already singing it, and I recently heard my wife sing it. The children have already learned all the lyrics from the song.

Béla Bartók has an interesting history in Slovakia. He originally came for holidays to the village of Hrlica (near Hnúšte and Jelšava), but gradually his stay was extended and he returned here for several years. Here he became acquainted with Slovak folk music and began collecting songs. He collected about 3,000 of them. He then tried to release the songs, but it was a difficult process, accompanied by disagreements with the publishers and later complicated by moving to the United States. His collection of Slovak folk songs was not completely published until 2020 (he died in 1945). I have bought three volumes from his collection and I hope that I will live to see the release of the last volume.

#include "pitches.h"

// notes in the melody
int melody[] = {
  NOTE_G5, NOTE_F5, NOTE_E5, NOTE_G5,
  NOTE_C5, NOTE_G4,
  NOTE_G5, NOTE_F5, NOTE_E5, NOTE_G5,
  NOTE_C5, NOTE_G4,
  NOTE_G4, NOTE_C5,
  NOTE_D5, NOTE_E5, NOTE_F5, NOTE_B4,
  NOTE_F4, NOTE_A4,
  NOTE_C5, NOTE_D5,
  NOTE_G4,
  NOTE_G4, 0
};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
  8, 8, 8, 8,
  4, 4,
  8, 8, 8, 8,
  4, 4,
  4, 4,
  8, 8, 8, 8,
  4, 4,
  4, 4,
  2,
  4, 4
};

int notesLength = sizeof(melody)/sizeof(int);

// beats per minute
int bpm = 85;
// duration of a beat in ms
float beatDuration = 60.0 / bpm * 1000;

void setup() {
}

void loop() {
  for (int thisNote = 0; thisNote < notesLength; thisNote++) {

    float noteDuration = beatDuration * (4.0 / noteDurations[thisNote]);
    tone(8, melody[thisNote], noteDuration * 0.85);
    delay(noteDuration);
  }
  delay(500);
}

Source code

The source code is located on the GitHub server.


24.12.2020


Menu