Fyzikální kabinet FyzKAB

Zvukový výstup na ESP32

Aktualizováno: 3. července 2024
UPOZORNĚNÍ
Na začátku roku 2024 bylo aktualizováno jádro ESP32 IDF, které je používáno jako doplněk pro programování modulu ESP32 v prostředí Arduino IDE. Od verze 3.x tohoto doplňku jsou některé funkce a příkazy zcela přepracovány! (například časovač a od něj odvislé volání přerušení…)
V následujícím textu je použito několik knihoven od různých autorů, kteří se ke vzniklé situaci staví různými způsoby. Situace se tedy postupně odvíjí podle jejich přístupu. Čtěte poznámky u jednotlivých kódů!

Pokud jde o jednoduché pípání a pískání, jistě nám dokáže posloužit připojený akustický bzučák (piezobudič), u kterého můžeme zvolit aktivní typ s předem definovanou a neměnitelnou frekvencí nebo pasivní, který budeme budit výstupním PWM signálem. My však dnes chceme daleko víc! Jsou aplikace, kdy se nám může hodit, aby naše zapojení přehrálo nějaký reálný zvuk, hudební skladbu, nebo dokonce promluvilo.

ESP32 + audio zesilovac

V tomto textu se podíváme na možnost přehrávání WAV souboru a pak i MP3 souboru, který bude uložen v paměti modulu ESP32. Zvukovým výstupem modulu ESP32 nám bude jeden z dvojice digitálně analogových převodníků (piny GPIO 25 a GPIO 26).

UPOZORNĚNÍ
Pokud si procházíte specifikační list modulu ESP32, můžete v souvislost se zvukovým výstupem narazit na termín "I2S". (POZOR nepleťte si I²C!) I2S je protokol pro výstup digitálního zvuku. Pro reprodukci hudby přes I2S kanál je třeba zvláštních modulů. V tomto článku se však dále zabýváme standardním analogovým zvukovým výstupem, tedy použitím I2S se zabývat nyní nebudeme!

Rychlé odkazy:

Než se pustíme do přehrávání zvukových souborů, je třeba zdůraznit, že na analogové výstupy (pin GPIO 25 a GPIO 26) modulu ESP32 není dobré připojovat reproduktor přímo, ale je třeba je doplnit o audio zesilovač (viz obr. 1). My použijeme levný modul půlwattového zesilovače s obvodem LM386 (k zakoupení za 32 Kč např. u firmy Hadex). V naší ukázce se zaměříme jen na výstup MONO, tedy na jeden audio kanál. Nechceme z modulu ESP32 vyrábět bůhvíjaký Hi-Fi přehrávač, jde nám o ukázku schopnosti modulu ESP32 vydávat zvuky dle zadaného zvukového souboru.

pripojeni-audio-vystupu
Obrázek č. 1 – navržené připojení audio zesilovače a reproduktoru k modulu ESP32

ESP32 – Přehrávání souborů WAV

WAV je zkratka a přípona pro zvukový formát Waveform Audio File format, což je jednoduchý souborový formát pro ukládání digitálního zvuku. Oproti klasickému souboru číselných data představujících zvukovou vlnu je na začátku souboru několik dat záhlaví, aby pomohl programu přehrávající data poznat informace typu: je to STEREO nebo MONO, jaký je počet bitů na vzorek a počet vzorků za sekundu. Jednou z hlavních výhod je to, že protože je tento soubor bez jakékoliv komprese, většina zvládne ho snadno dekódovat a přehrát i řada procesorů s nízkým výkonem. Bohužel určitou nevýhodu absence komprese naopak přináší, neboť soubory pak bývají velké – zvláště pokud budeme chtít pracovat s relativně dlouhým zvukem. Použití WAV souboru spíše využijeme pro kratší zvukové soubory.

Vše, co tedy musíme udělat, je poslat jednotlivá čísla představující zvukovou vlnu v pravém okamžiku do DAC (digitálně analogový převodník modulu ESP32), který je připojen k audio zesilovači a poté k reproduktoru. Jediná věc, kterou se musíme zabývat, je, jak často posíláme hodnoty do DAC, tím se bude řídit rychlost přehrávání. A to je vše!

 

Knihovna XT_DAC_Audio

Abychom se o tento proces nemuseli příliš zajímat, využijeme připravenou knihovnu XT_DAC_Audio pro ESP32, která se postará o všechny pro nás „špinavé a drsné“ aspekty přehrávání WAV souboru.

DŮLEŽITÉ UPOZORNĚNÍ!
Knihovna XT_DAC_Audio (verze 4.2.1 a nižší) již měla problém s kompilací v prostředí Ardino IDE už v případě nainstalovaného doplňku pro desky ESP32 verze 2.
Kompilace končila chybovou hláškou: error: 'rtc_gpio_desc' was not declared in this scope
Jak problém odtsranit, popisujeme níže v poznámce k této verzi.
K situaci s kompilací v doplňku pro desky ESP32 verze 3 se autor zatím také moc pozitivně nestaví!
Do doby, než autor vydá novou oficiální verzi (pokud k tomu vůbec dojde), jsme si dovolili jeho knihovnu opravit tak, aby byla kompilovatelná v Arduino IDE s verzí 3 doplňku pro desky ESP32.
Tuto naši verzi dále uvádíme níže jako knihovnu XT_DAC_Audio (ver. 4.9.9), neboť předpokládáme, že svou novou a zcela přepracovanou knihovnu autor vydá již pod číslem verze 5.0.0.

Odkazy pro stažení knihovny XT_DAC_Audio

  • Odkaz na naši (snad jen dočasnou) úpravu knihovny verze 4.9.9: knihovna XT_DAC_Audio (ver. 4.9.9).
    Knihovna je použitelná pouze, máte-li ve svém prostředí Arduino IDE nainstalovaný balík pro desky ESP32 verze 3!
  • Odkaz na stránky autora knihovny a původní verzi knihovny XT_DAC_Audio: https://www.xtronical.com/the-dacaudio-library-download-and-installation/.
    Knihovna (ver. 4.2.1) je použitelná pro nainstalovaný doplněk desek ESP32 verze 1, nebo s níže uvedenou úpravou i ve verzi 2.
    Sledujte, zda se zde objeví nová verze – tedy vyšší než současná verze 4.2.1!
POZNÁMKA:
Pokud použijete původní verzi knihovny XT_DAC_Audio (verze 4.2.1 a nižší) a máte ve svém prostředí Arduino IDE v manažéru desek nainstalovaný balík pro desky ESP32 verze 2.x.x, je nutné po stažení knihovny XT_DAC_Audio provést určitý zásah. Jinak bude pokus o překlad ukázkového kódu končit chybovou hláškou:
error: 'rtc_gpio_desc' was not declared in this scope.
Nutný zásah do knihovny XT_DAC_Audio (3. ledna 2023)

Tato informace se týká knihovny XT_DAC_Audio (verze 4.2.1 a nižší), POUZE pokud máte v prostředí Arduino IDE nainstalovaný balík pro desky ESP32 ve verzi 2.0.0 až 2.0.17.

Po nainstalování knihovny do prostředí Arduino IDE, musíme v jednom ze souborů knihovny učinit drobnou změnu.

  1. Přejdeme do složky, ve které jsou uloženy knihovny prostředí Arduino IDE – zpravidla něco jako:
    C:\user\vase_jmeno\Documents\Arduino\libraries\

  2. Vyhledáme složku XT_DAC_Audio, která se zde po nainstalování knihovny vytvořila. Vstoupíme do složky XT_DAC_Audio, kde najdeme soubor XT_DAC_Audio.cpp.
  3. Soubor XT_DAC_Audio.cpp otevřeme pomocí Poznámkového bloku. V první části objevíme sekci několika příkazů #include.
  4. Do této sekce přidáme následující řádek: #include "soc/rtc_io_reg.h"
  5. Soubor XT_DAC_Audio.cpp uložíme (Ctrl+S) a máme hotovo!

Upravený soubor XT_DAC_Audio.cpp by v úvodní části měl vypadat takto (viz obr. 2):

uprava knihovny XT_DAC_Audio
Obrázek č. 2 – přidání řádku s definicemi IO registrů modulu ESP32 do souboru XT_DAC_Audio.cpp

Máme-li knihovnu XT_DAC_Audio opravenou, můžeme si zazpívat! 😎

Nejdříve si ukážeme, jak pomocí této knihovny přehrajeme jednoduchý WAV soubor, ale pak i ještě ukážeme, že tato knihovna se dá užít i k dalším audio kouzlům.

Ukázkový kód WAV přehrávače

Knihovna je dodávána s příklady, jakmile ji nainstalujeme, přejdeme do SouborPříkladyXT_Dac_AudioPlayWav a měli bychom vidět následující kód:

#include "SoundData.h"
#include "XT_DAC_Audio.h"

XT_Wav_Class ForceWithYou(Force);     // vytvoreni objektu typu XT_Wav_Class, ktery je pouzivan
                                      // tridou DacAudio (níže), WAV predava jako parametr

XT_DAC_Audio_Class DacAudio(25,0);    // Vytvoreni objektu hlavni tridy prehravace
                                      // Pouzije GPIO 25 a časovač 0

uint32_t DemoCounter=0;               // Jen citac, ktery se pouzije v seriovem monitoru
                                      // neni nezbytny pro prehravani zvuku

void setup() {
    Serial.begin(115200);             // Neni potreba pro zvuk, jen pro tisk na ser. monitor
}

void loop() {
     DacAudio.FillBuffer();                  // Naplneni vyrovnavaci pameti zvuku daty
     if(ForceWithYou.Playing==false)         // pokud nehraje,
         DacAudio.Play(&ForceWithYou);       // prehrajte to, dojde k opakovani a opakovani...
     Serial.println(DemoCounter++);          // Ukazka toho, ze zvuk se bude prehravat nezavisla
                                             // na behu hlavního kodu, ktery zde bezi.
}

Kromě tohoto kódu bychom se měli podívat i na druhou záložku s názvem SoundData.h, která obsahuje aktuální zvuková data WAV a kterou též budeme potřebovat. Nejdříve se podíváme na kód přehrávače, k SoundData se ale ještě vrátíme!

Když se podíváte na kód výše, vidíme, že se tam vytvoří dva objekty. Jeden s názvem DacAudio, který vytvoří objekt, který přehraje jakoukoli zvukovou produkci prostřednictvím DAC. Předáváme mu číslo jednoho ze dvou DAC pinů a číslo systémového časovače (na ESP32 jsou čtyři). Druhý objekt (ten s názvem ForceWithYou) slouží pro uložení zvukových dat WAV a je typu XT_Wav_Class. K vytvoření tohoto objektu mu předáme název proměnné zvukových dat WAV. Ta je uložena na kartě SoundData.h.

V hlavní nekonečné smyčce loop() nejdříve zkontrolujeme, zda hraje zvuk ForceWithYou, pokud ne, pustíme ho. Jakmile zvuk dohraje, je puštěn znova, takže se zvuk opakuje neustále dokola. Třeba dokud se z toho nezblázníme! Druhým úkole této ukázky je demonstrace toho, že se zvuk přehrává nezávisle na kódu hlavní smyčky. Kód v hlavní smyčce stále běží dál, zvyšuje číslo v proměnné DemoCounter a vypisuje jej na sériový monitor. Můžete to vidět po otevření okna sériového monitoru.

Přidání vlastního zvukového souboru

Jako ukázka hezké, ale asi bychom rádi přidali nějaký ten svůj zvuk. Asi nejpoužívanější cesta k získání potřebných dat pro nějaký ten zvuk ve WAV souboru vede přes programy Audacity a editor HxD.

  • Aplikace Audacity je freewarový editor zvukových souborů, je možné jej stáhnout na následujících stránkách: https://www.Audacityteam.org (lze stáhnout i portablovou verzi, kterou není třeba instalovat)
  • Editor HxD je freewarový hexadecimální editor, lze jej stáhnout na stránkách: https://mh-nexus.de/en/HxD/

Postupně si ukážeme jednotlivé kroky, které musíme pro získání potřebných zvukových dat, vykonat.

  1. Nejdříve si opatříme potřebný zvukový soubor. Může to být WAV, ale třeba i MP3 (ale program Audacity zvládne i mnohem exotičtější formáty). Zvukový soubor si uložíme do počítače.
  2. Otevřeme software pro úpravu zvuku Audacity Přejděte na Soubor→Otevřít… a otevřete svůj zvukový soubor (viz obr. 3). Tento konkrétní zvukový soubor je MONO, takže se zobrazí pouze jedna stopa.
Audacity
Obrázek č. 3 – Prostředí programu Audacity a jeho použití pro úpravu WAV souboru
  1. Asi jsme opomněli zdůraznit, že současná verze knihovny XT_DAC_Audio funguje pouze se soubory MONO, takže pokud máte ve svém zvukovém souboru dvě stopy stereo zvuku, bude nutné vytvořit MONO stopu. Přejít na StopySmíchatSmíchat stereo a monofonní stopy.
  2. Dále musíme (obvykle) snížit kvalitu na vzorkovací frekvenci 10 000 vzorků za sekundu, protože knihovna XT_DAC_Audio může pracovat pouze se vzorkovací frekvencí 10 kHz. Běžné nastavení zvukových souborů zpravidla bývá 44100 Hz. Vyberte celý soubor (buď CTRL+A, nebo VybratVšechno) a přejděte na StopyPřevzorkovat. Poté můžete vybrat možnost z rozbalovací nabídky (viz obr. 4), ale hodnota 10 000 tam není, proto zadáme vlastní hodnotu z klávesnice. Nakonec vše potvrdíme kliknutím na tlačítko OK. Bude to chvíli trvat, než se převzorkuje WAV soubor (v závislosti na jeho velikosti).
prevzorkovani
Obrázek č. 4 – nastavení frekvence pro převzorkování zvukového souboru
  1. Od verze 3.5 programu Audacity následující krok není třeba, neboť proběhl automaticky při předchozím kroku!
    Dále musíme také nastavit toto nastavení pro celý projekt. Nastavení Kmitočet projektu (Hz) je v levém dolním rohu okna Audacity (viz obr. 5) Jednoduše zadáme (nebo vybereme, jednu z přednastavených možností) stejnou vzorkovací frekvenci, jako jsme zvukovou stopu převzorkovali.
kmitocet projektu
Obrázek č. 5 – nastavení vzorkovací frekvence pro celý projekt
  1. Na závěr svůj nový soubor uložíme ve formátu WAV, který potřebuje knihovna XT_DAC_Audio. Přejdeme na SouborUložit v jiném formátuUložit jako WAV. Zobrazí se dialogové okno, kde zvolíme WAV (Microsoft) a možnost kódování jako Unsigned 8-bit PCM.
ulozeni WAV
Obrázek č. 6 – uložení WAV souboru ve formátu potřebném pro knihovnu XT_DAC_Audio
  1. Po kliknutí na Uložit, se zobrazí okno s možnostmi metatagů (Uložit popisné značky), ponechte vše tak, jak je, a pokračujme kliknutím na OK.

Náš zvukový soubor je nyní uložen s požadovanou vzorkovací frekvencí a ve formátu, kterému bude XT_DAC_Audio rozumět. Čeká nás druhá část, je třeba tento právě získaný soubor dostat do našeho kódu.

Když se v prostředí Arduino IDE pořádně podíváte otevřený ukázkový kód, uvidíte, že jsou zde načtené dvě záložky. První je pojmenovaná PlayWav a druhá SoundData.h. Když se přepneme na záložku SoundData.h uvidíme, že je zde jednoduché bajtové pole nazvané Force.

Např. jako v následující ukázce:

// sound in WAV format, we're not concernet with most of the header bytes
// just samples per second and data size, we will always save in 8bit
// unsigned pcm
// sample rate is at offset 24, data size at

unsigned char PROGMEM Force[40923] = {
    0x52, 0x49, 0x46, 0x46, 0xD3, 0x9F, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45,
    0x66, 0x6D, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x80, 0x3E, 0x00, 0x00, 0x80, 0x3E, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00,
    0x64, 0x61, 0x74, 0x61, 0xAF, 0x9F, 0x00, 0x00, 0x7F, 0x7F, 0x80, 0x7F,
    0x80, 0x80, 0x81, 0x80, 0x82, 0x80, 0x82, 0x80, 0x82, 0x80, 0x81, 0x81,
    0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x7F, 0x7F, 0x7F, 0x7F,
    0x7F, 0x7F, 0x7E, 0x7F, 0x7E, 0x7E, 0x7F, 0x7E, 0x7E, 0x7E, 0x7E, 0x7F,
    0x7E, 0x7F, 0x7F, 0x7F, 0x7F, 0x80, 0x7F, 0x80, 0x80, 0x7F, 0x80, 0x80,
    0x80, 0x80, 0x7F, 0x80, 0x80, 0x80, 0x80, 0x7F, 0x80, 0x7F, 0x7F, 0x80,
    0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x81, 0x7F, 0x81, 0x7F, 0x80, 0x80, 0x80,
    0x7F, 0x81, 0x7F, 0x81, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x7F, 0x7F, 0x7E,
atd…

To je právě soubor zvukových dat. Potřebujeme tedy dostat naše nezpracovaná data ze zvoleného zvukového souboru do tohoto formátu.

K tomu použijeme editor HxD

  1. Otevřeme editor HxD a načteme soubor WAV (SouborOtevřít…). Uvidíme spoustu hexadecimálních dat (viz obr. 7) Nebojte se, nemusíme s tím nic dělat, jen potřebujeme nastavit HxD, aby nám tato data poskytl ve formátu, který můžeme vložit do Arduino IDE.
HxD editor
Obrázek č. 7 – Náhled WAV souboru v editoru HxD
  1. Nejprve vyberte všechna data (CTRL+A nebo UpravitVybrat Vše), poté vyberte UpravitKopírovat jakoC (viz obr. 8). Nyní máte uložené ve schránce nakopírovaná data ve formátu, který můžete vložit do libovolného textového editoru, v našem případě do Arduino IDE.
HxD editor
Obrázek č. 8 – Zkopírování dat WAV souboru pro vložení do prostředí Arduino IDE
  1. V prostředí Arduino IDE přejděte na kartu SoundData.h a vložíme sem (CTRL+V) data ze schránky místo původních dat. Vidíme, že původní proměnná se jmenovala Force, zatímco naše právě vložená se jmenuje rawData. Přejmenujeme ji tedy na původní jméno proměnné, kterou vyžaduje kód WAV přehrávače (tedy. Force) a máme „skoro“ hotovo.

Pozorný čtenář si jistě všiml, že původní řádka byla:

unsigned char PROGMEM Force[…

zatímco ta vložená z HxD je i po přejmenování:

unsigned char Force[…

Chybí nám tu výraz PROGMEM. Výraz PROGMEM při překladu říká, že dále uvedená proměnná (zde bajtové pole Force) se má uložit do flash paměti, stejně jako součást programu. Bez tohoto klíčového slova by se obsah proměnné Force ukládat do SRAM jako globální proměnná. Jde tu o hru s pamětí modulu ESP32. Jelikož se zde nyní zabýváme problémem přehrávání WAV souboru, nebudeme zde tento problém hospodaření s pamětí modulu ESP32 podrobněji rozebírat. Prostě tedy ještě doplníme „kouzelné“ slovo PROGMEM před název proměnné Force a už máme opravdu definitivně hotovo.

Konečně přeložíme kód programu PlayWav a nahrajeme jen do modulu ESP32. Jen je ale potřeba ještě jednou upozornit, že soubory WAV jsou skutečně dosti velké a tedy se může stát, že velikost vygenerovaného datového pole Force může přesáhnout velikost vyhrazené paměti. Takový projekt se nám prostě nepodaří přeložit. Při překladu dojde k chybovému hlášení, hlásicím, že došlo k přetečení paměťové oblasti. (něco jako na obrázku 9)

chyba preteceni
Obrázek č. 9 – Chybová hláška způsobená příliš velkým bajtovým polem se zvukovými daty.

Pokud se nám podaří kód přeložit, měli bychom slyšet „do zblbnutí“ se opakující přehrávání zvoleného zvukového souboru a zároveň na sériovém monitoru vidět vypisující se narůstající hodnotu proměnné DemoCounter.

Ještě jedna „vychytávka“ knihovny XT_DAC_Audio

Ještě než se pustíme do přehrávání souboru MP3, ještě trochu si ukážeme, co knihovna XT_DAC_Audio umí. Jako ukázkový kód nám může posloužit buď demo nazvané MusicScore (v Aruino IDE: SouborPříkladyXT_Dac_AudioMusicScore), nebo ještě lépe Mixing (SouborPříkladyXT_Dac_AudioMixing).

My se podáváme na příklad Mixing:

#include "MusicDefinitions.h"
#include "SoundData.h"
#include "XT_DAC_Audio.h"

// Data for the melody. Note followed by optional change in playing length in 1/4 beats. See documentation for more details

int8_t PROGMEM TwinkleTwinkle[] = {
    NOTE_C5,NOTE_C5,NOTE_G5,NOTE_G5,NOTE_A5,NOTE_A5,NOTE_G5,BEAT_2,
    NOTE_F5,NOTE_F5,NOTE_E5,NOTE_E5,NOTE_D5,NOTE_D5,NOTE_C5,BEAT_2,
    NOTE_G5,NOTE_G5,NOTE_F5,NOTE_F5,NOTE_E5,NOTE_E5,NOTE_D5,BEAT_2,
    NOTE_G5,NOTE_G5,NOTE_F5,NOTE_F5,NOTE_E5,NOTE_E5,NOTE_D5,BEAT_2,
    NOTE_C5,NOTE_C5,NOTE_G5,NOTE_G5,NOTE_A5,NOTE_A5,NOTE_G5,BEAT_2,
    NOTE_F5,NOTE_F5,NOTE_E5,NOTE_E5,NOTE_D5,NOTE_D5,NOTE_C5,BEAT_4,
    SCORE_END
};

XT_DAC_Audio_Class DacAudio(25,0);       // Create the main player class object. Use GPIO 25, one of the 2 DAC pins and timer 0
XT_Wav_Class ForceWithYou(Force);        // create WAV object and pass in the WAV data
XT_MusicScore_Class Music(TwinkleTwinkle,TEMPO_ALLEGRO,INSTRUMENT_PIANO);    // The music score object, pass in the Music data

void setup() {
    ForceWithYou.RepeatForever=true;     // Set this sample to play over and over again
    DacAudio.Play(&Music);               // Play the sequence, will play just the once and then stop,
                                         // See MultiPlayRepeat example for a never ending version
    DacAudio.Play(&ForceWithYou,true);   // Play the sequence, will play just the once and then stop
}

void loop() {
    DacAudio.FillBuffer();     // This needs only be in your main loop once, suggest here at the top.
    // you could write anything else here that you would normally have in your main loop
}

Ve své podstatě jde o kód předešlého WAV přehrávače, jen nám v úvodu přibylo:

#include "MusicDefinitions.h"

které připojí definice pro generování tónů. Další výrazná část, která je zde ihned vidět je bajtové pole nazvané TwinkleTwinkle, které obsahuje názvy tónů, který má modul ESP32 vyhrávat.

Kromě objektů určeným pro přehrávání WAV souboru (popsali jsme dříve) je zde i definován následující:

XT_MusicScore_Class Music(TwinkleTwinkle, TEMPO_ALLEGRO, INSTRUMENT_PIANO);

Při pohledu na tuto definici už asi začínáme tušit, o co tady půjde. Kromě standardního přehrávání WAV souboru je zde možné generovat melodii pomocí not. Vstupní parametry zde jasně říkají: Použij sekvenci not TwinkleTwinkle, s tempem allegro a snaž se zvukem napodobit piano. A proč asi se příklad jmenuje Mixing?

Pochopitelně je možné obojí přehrávat současně. Takže na pozadí se bude přehrávat nějaká „odrhovačka“ pomocí not a použitý WAV soubor bude sloužit pro něco sofistikovanějšího. Takovou ukázkovou aplikací by mohla být nějaká dětská hračka, která bude hrát některou z dětských „vypalovaček“ (Skákal pes, přes oves…) a do toho se občas ozve výkřik typu: „Ahoj, pojď si hrát!“. Jako ukázka použití knihovny XT_DAC_Audio asi dobré, ale na dětech to raději zkoušet nebudeme! 😇


Knihovna ESP32Sound

UPOZORNĚNÍ
Níže uvedená knihovna pro svůj běh využívá časovač a časovačem volané přerušení. Od jádra Arduino ESP32 verze 3.x byly tyto funkce přepracovány!
Dokud autor knihoveny nevytvoří verzi pro nové API, musíte pro použití níže uvedených kódů a knihoven downgradovat doplněk desky ESP32 zpět na verzi 2.x.
ESP-IDF
Možná se časem pokusíme knihovnu „na vlastní pěst“ upravit, jako jsme učinili v případě knihovny XT_DAC_Audio, ale zatím je návrat k ESP32-IDF verze 2 jediné řešení!

Ne, že by předchozí příklad pomocí XT_DAC_Audio nesplnil naše očekávání, ale ta příprava WAV souboru a hlavně jeho vkládání do programového kódu prostředí Arduino IDE asi není moc komfortní. Jiný slovy, nešlo by to jinak? Určitě ano. Další možností je použití knihovny ESP32Sound od autora Chrise Veigla.

Odkaz na knihovnu ESP32Sound: https://github.com/ChrisVeigl/ESP32Sound

Tato knihovna podporuje přehrávání velkých zvukových souborů z karty SD (hudba na pozadí) a současné přehrávání krátkých zvukových efektů (FX) z paměti flash. Hlasitost hudby na pozadí a FX lze nastavit samostatně. Přehrávání zvuku rovněž funguje „na pozadí“, takže hlavní smyčka může být použita pro jiné věci (řízení LCD, načítání tlačítek, WiFi atd.) Je však třeba upozornit, že vzorkovací frekvence hudby na pozadí a souborů FX musí být stejná. Přestože funkce knihovna dokáže zpracovat různé WAV soubory (např. 44,1 kHz, 16bit, stereo), i zde se doporučuje formát cca 16 hHz, mono, 8 bit.

Vidíme tedy, že tato knihovna je podobná předešlé. Rozdílem je to, že zde není možné generovat tóny pomocí předpisů not a že zde lze přehrávat WAV soubory z SD karty (jako klasické soubory) a i z flash paměti (jako pole jazyka C).

V naší ukázce využijeme možnosti přehrávání z SD karty, i když žádnou SD katu připojovat nebudeme. Jak je to možné? Místo SD karty, která by se musela k modulu ESP32 připojit, využijeme vnitřní zabudovanou paměť modulu ESP32, která se dá jako SD karta naformátovat. Je známá pod označením SPIFFS. Pro lepší pochopení následující ukázky doporučujeme nastudovat předchozí článek: Kam se soubory? Aneb SPIFFS na ESP32.

Do paměti SPIFFS nahrajeme požadovaný WAV soubor – postup popsán ve výše zmíněném článku. Nezapomeňme však na fakt, že velikost SPIFFS je asi jen 1,5 MB! Ale ani možnost zadání zvuku pomocí bajtového pole nebyla kdoví jaká! A knihovně ESP32Sound paměť SPIFFS tak trochu podstrčíme místo SD karty.

Viz následující kód:

#include "SPIFFS.h"
#include "ESP32Sound.h"

#define PLAYBACK_RATE  16000

void setup() {
    Serial.begin(115200);
    Serial.println("Now initialising SPIFFS!");
    if(!SPIFFS.begin(true)) {
       Serial.println("An Error has occurred while mounting SPIFFS");
       return;
    }

    Serial.println("Now initialising sound system!");
    ESP32Sound.begin();
    ESP32Sound.setSoundVolume(50);
}

void loop() {
    ESP32Sound.playSound(SPIFFS, "/sound.wav");
    while (ESP32Sound.isPlaying());
    delay(1000);
}

Definice PLAYBACK_RATE určuje zvolenou vzorkovací frekvenci použitého VAW souboru, který se jmenuje sound.wav a je nakopírován přímo v kořenovém adresáři prostoru SPIFFS. Po inicializaci paměťového prostoru SPIFFS je inicializovaná přehrávací funkce ESP32Sound.begin();a je nastavena i úroveň hlasitosti ESP32Sound.setSoundVolume(50);.

V hlavní smyčce je spuštěno přehrávání souboru sound.wav, posléze se ve smyčce čeká, dokud se soubor nepřehraje. Po jeho ukončení se počká jednu vteřinu a zvukový soubor je opět spuštěn.

Tento způsob řešení je asi efektnější než předchozí se zadáváním zvuku pomocí bajtového pole. Ale i to tato knihovna umožňuje. Určitě doporučujeme se na další příklady podívat na stránky autora knihovny. Určitě je opět zajímavý i způsob kombinování zvuku z SD karty a efektů z paměti modulu.

Zadávání zvuku do paměti je obdobné řešení předešlé knihovně, není tedy zde opět opakovat postup pomocí programu Audacity a editoru HxD.


Přehrávání MP3 souborů

Poslední možností, kterou se dnes ještě budeme zabývat, bude použití MP3 souborů. Soubory MP3 asi není třeba příliš představovat.

Soubor MP3 je zvukový soubor uložený v komprimovaném formátu zvuku, který používá kompresi zvuku „Layer 3“. Běžně se používá pro ukládání hudby a audioknih a jeho velikost je zhruba 1/10 velikosti souboru WAV. Kvalita a tím pádem i velikost souboru MP3 se do značné míry odvíjí od bitové rychlosti použité pro kompresi. Pro naše účely bude dobré, podobně jako u WAV souborů v předešlé kapitole, pomocí programu Audacity najít vhodné nastavení pro vzorkování a bitovou rychlost, abychom našli kompromis mezi velikostí souboru a kvalitou reprodukovaného zvuku.

Knihovna ESP32-audioI2S

UPOZORNĚNÍ
Níže uvedená knihovna ESP32-audioI2S je primárně určena pro přehrávání MP3 souborů přes zvukový výstup I2S. Do její verze 2.0.6 bylo možné tuto knihovnu použít i pro přehrávání MP3 souborů „klasicky“ přes analovový výstup modulu ESP32. Tak, jak je níže uvedeno…
Je chválihodné, že autor již na konci roku 2023 zareagoval na vznik nového a zpětně nekompatibilního doplňku ESP32 (ver. 3) prostředí Arduino IDE, leč v nové verzi této knihovny (V3.x.x) již definitivně podporuje pouze výstup I2S, který v našem případě nemůžeme použít!

DŮLEŽITÉ UPOZORNĚNÍ!
Chceme-li použít níže uvedený postup přehrávání MP3 souborů, musíme provést následující dva kroky:
  1. Je třeba si z níže uvedeného odkazu stáhnout verzi knihovny ESP32-audioI2S maximálně verze 2.0.6!
  2. Kvůli zpětné kompatibilitě verze knihovny 2.0.6 s předchozím ESP32-IDF musíte v prostředí Arduino IDE downgradovat doplněk desky ESP32 zpět na verzi 2.x.
ESP-IDF

Pro přehrávání MP3 souborů na analogovém výstupu modulu ESP32 použijeme knihovnu ESP32-audioI2S od vývojáře Schreibfaul1.

Odkaz na knihovnu ESP32-audioI2S ver. 2.0.6: https://github.com/schreibfaul1/ESP32-audioI2S/releases/tag/2.0.6
Odkaz na aktuální verzi knihovny: https://github.com/schreibfaul1/ESP32-audioI2S

Použití této knihovny je velice podobné předchozí, jen s tím rozdílem, že místo WAV souboru dokáže dekódovat a přehrávat MP3 soubory.

Pozorný čtenář si možná všimne zkratky I2S v názvu knihovny a také si možná vzpomene na žlutý rámeček, ve kterém jsme se zmínili, že tento článek se nebude zabývat I2S digitálním audio výstupem. Tak jak to tedy je? Budeme výstupu modulu ESP32 skutečně přehrávat zvuk analogový?

Odpověď zní: ANO, i když… Výše zmíněná knihovna je sice primárně určena pro použití s I2S výstupy, ale je naštěstí možné nastavit (do verze 2.0.6!) pro výstup i interní DAC převodníky, tedy získat na pinech GPIO 25 a GPIO 26 analogový zvukový výstup.

A asi nás ještě bude zajímat ještě jedna informace. Tato knihovna umožňuje přehrávat zvuk jako STEREO výstup, tedy jeden kanál na pinu GPIO 25 a druhý na pinu GPIO 26.

Podobně jako u předchozí knihovny ESP32Sound přehrajeme soubor uložený v paměťové oblasti SPIFFS, která nám bude suplovat SD kartu.

Ukázkový kód:

#include "Audio.h"
#include "SPIFFS.h"

Audio audio(true, I2S_DAC_CHANNEL_BOTH_EN);     // internal DAC = true, DAC enable both

void setup() {
    Serial.begin(115200);
    audio.setVolume(12);     // 0...21
    if (!SPIFFS.begin(true)) {
       Serial.println("An Error has occurred while mounting SPIFFS");
       return;
    }
    audio.connecttoFS(SPIFFS,"/mp3-soubor.mp3");
}

void loop() {
    audio.loop();
}

Důležitým nastavením je vytvoření objektu Audio, ve kterém nastavuje prvním parametrem (true), zda bude pro výstup použit vnitřní DAC (digitálně analogový převodník) pro analogový hudební výstup. Druhý parametr udává, zda budou přehrávány oba kanály.

Možnosti jsou:

  • I2S_DAC_CHANNEL_RIGHT_EN – povolit pravý kanál vestavěného převodníku, mapuje se na kanál DAC 1 na GPIO 25
  • I2S_DAC_CHANNEL_LEFT_EN – povolit levý kanál vestavěného převodníku, mapuje se na kanál DAC 2 na GPIO 26
  • I2S_DAC_CHANNEL_BOTH_EN – povolit oba kanály vestavěného převodníku (piny GPIO 25 a GPIO 26)

Připojení MP3 audio souboru se provádí příkazem audio.connecttoFS, kde prvním parametrem je zadaný souborový systém, např. SD karta, zde je však nastaven paměťový prostor SPIFFS. Druhý parametr je cesta ke konkrétnímu souboru.

V hlavní smyčce je pak opakovaně spouštěno cyklické přehrávání zvoleného MP3 souboru. Pochopitelně knihovna ESP32-audioI2S umí mnohem více. Určitě ji doporučujeme bližšímu průzkumu. Přehrávání MP3 souborů, které zabírají mnohem méně místa než obrovské WAV soubory, je určitě pro vývoj zvukových aplikací s modulem ESP32 jistě zajímavé.

Závěr

Ukázali jsme si několik možností, jak docílit přehrávání zvukových souborů modulem ESP32. Pokud chceme využít jen poměrně krátkých zvukových efektů, je možné využít WAV souborů a to přímo začleněním jejich obsahu do kódu programu.

Pro rozsáhlejší zvukové soubory se jako perspektivní asi ukazuje přehrávání MP3 souborů, které jsou díky své kompresi výrazně menší a je možné jich do interní paměti modulu ESP32 naskládat hned několik.

V neposlední řadě je při přehrávání zvukových souborů zajímavé využití paměti SPIFFS, která nám slouží jako jakási „falešná“ SD karta a lze ji využít přímo na modulu ESP32 bez jakéhokoliv připojení externích součástek.

Autor článku: Miroslav Panoš
UPOZORNĚNÍ:
Nesouhlasíme s vyřazením Newtonových zákonů, Ohmova zákona a zákona zachování energie z učiva fyziky základních škol v České republice!