Fyzikální kabinet FyzKAB

Zvukový výstup na ESP32

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.

Odkaz na knihovnu XT_DAC_Audio: https://www.xtronical.com/the-dacaudio-library-download-and-installation/

DŮLEŽITÉ UPOZORNĚNÍ!
Pokud máte ve svém prostředí Arduino IDE v manažéru desek nainstalovaný balík pro desky ESP32 verze 2.0.0 a vyšší, je nutné po stažení knihovny XT_DAC_Audio (ver. 4.2.1 a starší) 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

Tato informace se týká knihovny XT_DAC_Audio (verze 4.2.1 a nižší), pokud máte v prostředí Arduino IDE nainstalovaný balík pro desky ESP32 ve verzi 2.0.0 a vyšší. Je možné, že další verze knihovny XT_DAC_Audio již budou mít tuto chyby opravenou – v okamžiku psaní tohoto článku (3. ledna 2023) to však ještě není.

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 nižší než 50 000 vzorků za sekundu, protože knihovna XT_DAC_Audio může pracovat pouze se vzorkovací frekvencí do 50 kHz. Běžné nastavení zvukových souborů je 44100 Hz. To však zabere značné množství paměti RAM, takže bychom se měli snažit co nejvíce soubor zmenšit a přitom zachovat kvalitu, kterou pro svůj konkrétní projekt požadujete. Snížení vzorkovací frekvence bude mít určitý negativní účinek, ale je otázkou, zda se to vůbec projeví – rozhodně se nebojme experimentovat! Vzorkování některých zvukových souborů lze snížit více, jiné moc ne – to záleží na jejich obsahu. U našeho ukázkového souboru vzorkovací frekvenci snížíme na 10 kHz. Vyberte celý soubor (buď CTRL+A nebo VybratVšechno) a přejděte na StopyPřevzorkovat. Poté můžete buď vybrat možnost z rozbalovací nabídky (viz obr. 4), nebo zadat vlastní hodnotu. Klepněte 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. 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

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

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: 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 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.

Reklama:
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!