Pro začátečníky: Generování jednoduchého zvuku

Zápisník experimentátora

V tomto článku si ukážeme, jak umí Arduino generovat zvuk. Bude to jednoduchý zvuk, takže od příkladu nečekejte žádný zázrak. Ale ten zvuk bude dostatečně hlasitý na to, aby vám po chvíli lezl na nervy. V závislosti na své odolnosti si můžete vybrat, zda bude zvuk vydávat piezoměnič nebo malý reproduktor. Na vašem místě bych zvolil ten reproduktor.

Piezoměnič nebo reproduktor?

Když jsem si připravoval podklady pro tento článek, na Internetu jsem neustále nacházel doporučení, že tento příklad je třeba dělat s piezoměničem. Mám jeden piezoměnič ze stavebnice EDU01 od firmy Velleman. Piezoměnič funguje tak, že ho stačí připojit na 5 V a ozve se zvuk. Jediný problém je v tom, že se ozve velmi nepříjemný zvuk. A při takovém zvuku nevydržíte sedět ani pár minut. Takže moje rada zní, použijte malý reproduktor. Sehnat malý reproduktor není žádný problém. Dá se koupit, nebo si ho vymontujete z nějaké hračky. A výsledný zvuk bude mnohem lepší. Použijte malý reproduktor 8 OHM (běžně používané reproduktory v hračkách). A pomocí rezistoru 330-1000 R si nastavte takovou hlasitost zvuku, kterou bez problémů vydržíte poslouchat několik minut.

Co budeme poslouchat?

Vybral jsem dvě melodie.

  • První melodie pochází ze vzorového příkladu k funkci tone. Nepodařilo se mi zjistit, z které písně melodie pochází. Ale samotný příklad jsem upravil tak, aby odpovídal smysluplnému hudebnímu tempu. Originální příklad tempo nastavoval pomocí magické konstanty a já příklad upravil tak, aby bylo tempo nastaveno pomocí BPM.
  • Druhá melodie je z knihy Béla Bartók - Slovenské lidové písně. Tu píseň zaznamenal Béla Bartók v roce 1914 na Ponikách (vesnice nedaleko Banské Bystrice na Slovensku). Jmenuje se Konopí, konopí a abyste si ji mohli poslechnout i v normální úpravě, připravil jsem ji pro vás i spolu s akordy v programu MuseScore (hudební ukázka s notami). Program je stejný jako v předchozím příkladu.

BPM

BPM je zkratka pro beats per minute (počet čtvrťových not za minutu). Od této hodnoty můžeme odvodit délky trvání jednotlivých not. Například 60 BPM znamená, že za jednu minutu slyšíte 60 čtvrťových not. V programu používám jednoduchý vzorec pro převod BPM na trvání jedné čtvrťové noty v milisekundách. Ostatní délky not jsou odvozeny od této hodnoty pomocí jednoduchých konstant. Například čtvrťová nota používá konstantu 4, osminové 8. Je to jen jednoduchý způsob pro zápis běžných hodnot not. Noty s jinou délkou by touto metodou nedaly zapsat.

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

Všimněte si, že nota nehraje po celou dobu vypočtené doby v milisekundách. Je trvání je nastaveno na 85% délky. Takže po každé note slyšíte i malou pauzu. Tato délka není používána v každé skladbě. Občas slyšíte i noty se zkráceným trváním (staccato) nebo noty s prodlouženým trváním (tenuto). A například při hře na housle je běžné, pokud tóny znějí nepřerušovaně za sebou (legato). Ale to jsem jen na chvilku odbočil k hudební teorii. V našem příkladu vystačíme s běžnou délkou not.

Příklad 1

Oba příklady jsou stejné, liší se pouze notami. Ty jsou zapsány v poli melody a jejich délky jsou v poli noteDurations. Počet not nám vypočítá kompilátor v proměnné notesLength. Potom nám nehrozí nebezpečí, že pokud přidáme nějaké další noty, že budeme muset ručně počítat jejich počet.

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

Příklad 2

Jak jsem řekl, program je stejný, liší se jen noty. Aby to bylo přehledné, uspořádal jsem je po jednotlivých taktech. Píseň od Bély Bartóka jsem vybral proto, že je to oblíbená píseň mé dcery. A protože je melodie jednoduchá, už si ji prozpěvuje i syn a nedávno jsem slyšel i svou manželku, jak si ji prozpěvovala. Děti se už naučili i všechna slova z písně.

Béla Bartók má na Slovensku zajímavou historii. Původně přišel na prázdniny do obce Hrlica (nedaleko Hnúště a Jelšavy), ale postupně se jeho pobyt prodlužoval a vracel se sem několik let. Zde se seznámil se slovenskou lidovou hudbou a začal písně sbírat. Nasbíral jich přibližně 3000. Pak se písně snažil vydat, ale byl to náročný proces, který byl doprovázen neshodami s vydavateli a později se zkomplikoval i tím, že se přestěhoval do Spojených států. Jeho sbírku Slovenská lidových písní se podařila kompletně vydat až v roce 2020 (zemřel v roce 1945). Tři svazky z jeho sbírky mám koupené a doufám, že se dožiju i vydání posledního dílu.

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

Zdrojový kód

Zdrojový kód se nachází na serveru GitHub.


24.12.2020


Menu