Pre začiatočníkov: Generovanie jednoduchého zvuku

Zápisník experimentátora

V tomto článku si ukážeme, ako vie Arduino generovať zvuk. Bude to jednoduchý zvuk, takže od príkladu nečakajte žiaden zázrak. Ale ten zvuk bude dostatočne hlasný na to, aby vám po chvíli liezol na nervy. V závislosti na svojej odolnosti si môžete vybrať, či bude zvuk vydávať piezomenič alebo malý reproduktor. Na vašom mieste by som zvolil ten reproduktor.

Piezomenič alebo reproduktor?

Keď som si pripravoval podklady pre tento článok, na Internete som neustále nachádzal doporučenia, že tento príklad treba robiť s piezomeničom. Mám jeden piezomenič zo stavebnice EDU01 od firmy Velleman. Piezomenič funguje tak, že ho stačí pripojiť na 5 V a ozve sa zvuk. Jediný problém je v tom, že sa ozve veľmi nepríjemný zvuk. A pri takom zvuku nevydržíte sedieť ani pár minút. Takže moja rada znie, použite malý reproduktor. Zohnať malý reproduktor nie je žiaden problém. Dá sa kúpiť, alebo si ho vymontujete z nejakej hračky. A výsledný zvuk bude omnoho lepší. Použite malý reproduktor 8 OHM (bežne používané reproduktory v hračkách). A pomocou rezistora 330-1000 R si nastavte takú hlasitosť zvuku, ktorú bez problémov vydržíte počúvať niekoľko minút.

Čo budeme počúvať?

Vybral som dve melódie.

  • Prvá melódia pochádza zo vzorového príkladu k funkcii tone. Nepodarilo sa mi zistiť, z ktorej piesne melódia pochádza. Ale samotný príklad som upravil tak, aby zodpovedal zmysluplnému hudobnému tempu. Originálny príklad tempo nastavoval pomocou magickej konštanty a ja som príklad upravil tak, aby bolo tempo nastavené pomocou BPM.
  • Druhá melódia je z knihy Béla Bartók - Slovenské ľudové piesne. Tú pieseň zaznamenal Béla Bartók v roku 1914 na Ponikách (dedina neďaleko Banskej Bystrice na Slovensku). Volá sa Konope, konope a aby ste si ju mohli vypočuť aj v normálnej úprave, pripravil som ju pre vás aj spolu s akordami v programe MuseScore (hudobná ukážka s notami). Program je rovnaký ako v predchádzajúcom príklade.

BPM

BPM je skratka pre beats per minute (počet štvrťových nôt za minútu). Od tejto hodnoty môžeme odvodiť dĺžky trvania jednotlivých nôt. Napríklad 60 BPM znamená, že za jednu minútu počujete 60 štvrťových nôt. V programe používam jednoduchý vzorec na prevod BPM na trvanie jednej štvrťovej noty v milisekundách. Ostatné dĺžky nôt sú odvodené od tejto hodnoty pomocou jednoduchých konštánt. Napríklad štvrťová nota používa konštantu 4, osminová 8. Je to len jednoduchý spôsob na zápis bežných hodnôt nôt. Noty s inou dĺžkou by sa touto metódou nedali zapísať.

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

Všimnite si, že nota nehrá počas celej vypočítanej doby v milisekundách. Je trvanie je nastavené na 85 % dĺžky. Takže po každej note počujete aj malú pauzu. Táto dĺžka nie je používaná v každej skladbe. Občas počujete aj noty so skráteným trvaním (staccato), alebo noty s predĺženým trvaním (tenuto). A napríklad pri hre na husle je bežné, ak tóny znejú neprerušovane za sebou (legato). Ale to som len na chvíľku odbočil k hudobnej teórii. V našom príklade vystačíme s bežnou dĺžkou nôt.

Príklad 1

Oba príklady sú rovnaké, líšia sa iba notami. Tie sú zapísané v poli melody a ich dĺžky sú v poli noteDurations. Počet nôt nám vypočíta kompilátor v premennej notesLength. Potom nám nehrozí nebezpečenstvo, že ak pridáme nejaké ďalšie noty, že budeme musieť ručne rátať ich 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);
}

Príklad 2

Ako som povedal, program je rovnaký, líšia sa len noty. Aby to bolo prehľadné, usporiadal som ich po jednotlivých taktoch. Pieseň od Bélu Bartóka som vybral preto, lebo je to obľúbená pieseň mojej dcéry. A pretože je melódia jednoduchá, už si ju pospevuje aj syn a nedávno som počul aj svoju manželku, ako si ju pospevovala. Deti sa už naučili aj všetky slová z piesne.

Béla Bartók má na Slovensku zaujímavú históriu. Pôvodne prišiel na prázdniny do obce Hrlica (neďaleko Hnúšte a Jelšavy), ale postupne sa jeho pobyt predlžoval a vracal sa sem niekoľko rokov. Tu sa zoznámil so slovenskou ľudovou hudbou a začal piesne zbierať. Nazbieral ich približne 3000. Potom sa piesne snažil vydať, ale bol to náročný proces, ktorý bol sprevádzaný nezhodami s vydavateľmi a neskôr sa skomplikoval aj tým, že sa presťahoval do Spojených štátov. Jeho zbierku slovenských ľudových piesní sa podarila kompletne vydať až v roku 2020 (umrel v roku 1945). Tri zväzky z jeho zbierky mám kúpené a dúfam, že sa dožijem aj vydania posledného dielu.

#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 sa nachádza na serveri GitHub.


23.12.2020


Menu