Esp32 ADF - Audio Dev Framework - Please Help

Hi. I’m new to platformio.

I’m trying to compile esp-adf (audio dev framework) example projects using platformio.

I can’t seem to figure out how to properly set up the esp-adf libraries to work in platformio.

Can someone please help me or point me in the right direction?

I’m stuck at this:
src/play_mp3_example.c:15:27: fatal error: audio_element.h: No such file or directory

For reference:

Cheers,
Cooper

ESP-ADF framework is not yet officially supported by PIO. See Espressif 32 — PlatformIO latest documentation.

However, that doesn’t mean that you can’t get this to work. I simply added all the ESP-ADFs “components” as libraries in a project, added the needed include (-I), library paths (-L) and defines (-D) and the play_mp3_dac example compiles fine.

Repo: GitHub - maxgerhardt/pio-esp-adf-example: An example how to use ESP-ADF with PIO.

Gotchas:

  • when embedding files, they should be in the top root of the project, not in src. When you put them in src/ the name of the object will change to include the src path, and examples don’t work unless you change the filename in the asm statement
  • the esp_http_client libraries is inside there twice, in newer ESP-IDF and as a component in ESP-ADF. I haven’t found a pretty way to un-include it automatically except with a static build_unflags. You need to change the path to match your system. (using $PIOHOME_DIR inside the build_unflags failed :confused:)

When you want to use other ESP-ADF components, modify the platformio.ini

  • add the components include/ folder to the -I flags
  • add the lib name to lib_deps
  • if the library contains a static library file (*.a), add the path to it to the library search path using -L and -l

The clean way would be to add this as “framework”. Since ESP-ADF is on top of the ESP-IDF framework, this works too…

Compiling should give you at the end a

Processing esp32dev (platform: espressif32; board: esp32dev; framework: espidf)
[..]
xtensa-esp32-elf-gcc -o .pioenvs\esp32dev\firmware.elf -T esp32_out.ld -nostdlib -Wl,-static -u call_user_start_cpu0 -Wl,--undefined=uxTopUsedPriority -Wl,--gc-sections -u __cxa_guard_dummy -u ld_include_panic_highint_hdl -T esp32.common.ld -T esp32.rom.ld -T esp32.peripherals.ld -T esp32.rom.libgcc.ld -T esp32.rom.spiram_incompatible_fns.ld -u __cxx_fatal_exception .pioenvs\esp32dev\adf_music.mp3.txt.o .pioenvs\esp32dev\lib3c9\audio_pipeline\audio_element.o .pioenvs\esp32dev\lib3c9\audio_pipeline\audio_event_iface.o .pioenvs\esp32dev\lib3c9\audio_pipeline\audio_pipeline.o .pioenvs\esp32dev\lib3c9\audio_pipeline\ringbuf.o .pioenvs\esp32dev\libb07\audio_hal\audio_hal.o .pioenvs\esp32dev\libb07\audio_hal\driver\es8374\es8374.o .pioenvs\esp32dev\libb07\audio_hal\driver\es8388\es8388.o .pioenvs\esp32dev\libb07\audio_hal\driver\es8388\headphone_detect.o .pioenvs\esp32dev\lib632\audio_sal\audio_mem.o .pioenvs\esp32dev\libb0a\audio_stream\fatfs_stream.o .pioenvs\esp32dev\libb0a\audio_stream\http_stream.o .pioenvs\esp32dev\libb0a\audio_stream\i2s_stream.o .pioenvs\esp32dev\libb0a\audio_stream\raw_stream.o .pioenvs\esp32dev\lib22f\esp_codec\filter_resample.o .pioenvs\esp32dev\lib22f\esp_codec\wav_decoder.o .pioenvs\esp32dev\lib22f\esp_codec\wav_encoder.o .pioenvs\esp32dev\lib632\esp_http_client\esp_http_client.o .pioenvs\esp32dev\lib632\esp_http_client\lib\http_auth.o .pioenvs\esp32dev\lib632\esp_http_client\lib\http_header.o .pioenvs\esp32dev\lib632\esp_http_client\lib\http_utils.o .pioenvs\esp32dev\lib632\esp_http_client\lib\transport.o .pioenvs\esp32dev\lib632\esp_http_client\lib\transport_ssl.o .pioenvs\esp32dev\lib632\esp_http_client\lib\transport_tcp.o .pioenvs\esp32dev\src\play_mp3_dac_example.o -LC:\Users\Maxi\.platformio\packages\framework-espidf\components\esp32 -LC:\Users\Maxi\.platformio\packages\framework-espidf\components\esp32\ld -LC:\Users\Maxi\.platformio\packages\framework-espidf\components\esp32\lib -LC:\Users\Maxi\.platformio\packages\framework-espidf\components\bt\lib -LC:\Users\Maxi\.platformio\packages\framework-espidf\components\newlib\lib -L.pioenvs\esp32dev -L.pioenvs\esp32dev -Llib\esp_codec\lib -Wl,--start-group .pioenvs\esp32dev\libapp_update.a .pioenvs\esp32dev\libbootloader_support.a .pioenvs\esp32dev\libbt.a .pioenvs\esp32dev\libcoap.a .pioenvs\esp32dev\libconsole.a .pioenvs\esp32dev\libcxx.a .pioenvs\esp32dev\libdriver.a .pioenvs\esp32dev\libesp-tls.a .pioenvs\esp32dev\libesp32.a .pioenvs\esp32dev\libesp_adc_cal.a .pioenvs\esp32dev\libesp_https_ota.a .pioenvs\esp32dev\libesp_http_client.a .pioenvs\esp32dev\libethernet.a .pioenvs\esp32dev\libexpat.a .pioenvs\esp32dev\libfatfs.a .pioenvs\esp32dev\libfreertos.a .pioenvs\esp32dev\libjsmn.a .pioenvs\esp32dev\libjson.a .pioenvs\esp32dev\liblog.a .pioenvs\esp32dev\liblwip.a .pioenvs\esp32dev\libmbedtls.a .pioenvs\esp32dev\libmdns.a .pioenvs\esp32dev\libmicro-ecc.a .pioenvs\esp32dev\libnewlib.a .pioenvs\esp32dev\libnvs_flash.a .pioenvs\esp32dev\libopenssl.a .pioenvs\esp32dev\libpthread.a .pioenvs\esp32dev\libsdmmc.a .pioenvs\esp32dev\libsmartconfig_ack.a .pioenvs\esp32dev\libspiffs.a .pioenvs\esp32dev\libtcpip_adapter.a .pioenvs\esp32dev\libulp.a .pioenvs\esp32dev\libvfs.a .pioenvs\esp32dev\libwear_levelling.a .pioenvs\esp32dev\libxtensa-debug-module.a .pioenvs\esp32dev\libspi_flash.a .pioenvs\esp32dev\libapp_trace.a .pioenvs\esp32dev\libsoc.a .pioenvs\esp32dev\libheap.a .pioenvs\esp32dev\libaws_iot.a .pioenvs\esp32dev\libsodium.a .pioenvs\esp32dev\libwpa_supplicant.a -lbtdm_app -lhal -lcoexist -lcore -lnet80211 -lphy -lrtc -lpp -lwpa -lwpa2 -lespnow -lwps -lsmartconfig -lmesh -lc -lm -lgcc -lstdc++ -lesp_codec -Wl,--end-group
"c:\python27\python.exe" "C:\Users\Maxi\.platformio\packages\tool-esptoolpy\esptool.py" --chip esp32 elf2image --flash_mode dio --flash_freq 40m --flash_size 4MB -o .pioenvs\esp32dev\firmware.bin .pioenvs\esp32dev\firmware.elf
MethodWrapper(["checkprogsize"], [".pioenvs\esp32dev\firmware.elf"])
Memory Usage -> http://bit.ly/pio-memory-usage
DATA:    [          ]   3.8% (used 12444 bytes from 327680 bytes)
PROGRAM: [===       ]  27.1% (used 284248 bytes from 1048576 bytes)
.pioenvs\esp32dev\firmware.elf  :
section                                  size         addr
.rtc.text                                   0   1074528256
.rtc_noinit                                 0   1342177280
.iram0.vectors                           1024   1074266112
.iram0.text                             33092   1074267136
.dram0.data                              8220   1073479680
.noinit                                     0   1073487900
.dram0.bss                               4224   1073487904
.flash.rodata                          124584   1061158944
.flash.text                            117328   1074593816
.comment                                  361            0
.xtensa.info                               56            0
.xt.prop._Z11fillDataBufP8tmp3Bitsj        36            0
.xt.lit.saturate16                          8            0
.xt.prop.saturate16                        60            0
.debug_line                            184459            0
.debug_info                            283826            0
.debug_abbrev                           51743            0
.debug_aranges                           6760            0
.debug_str                              46409            0
.debug_frame                            15208            0
.debug_loc                             168799            0
.debug_ranges                            8296            0
Total                                 1054493
 [SUCCESS] Took 258.77 seconds 
1 Like

This is excellent.

Amazingly prompt reply and very helpful info. Thank you so much.

Just got the project to compile and flash to a nodemcu-32s.

How difficult is making a framework?

I haven’t attempted such a thing myself. But there’s documentation available on setting up a custom platform and board (here); A platform would include a range of frameworks (and toolchains). However in this case we already have the espressif32 platform and its espidf framework, so you don’t want to create a new platform from scratch. You just want to add a new framework (which is 99% based on ESP-IDF). For that, the starting point would be platform-espressif32/builder/frameworks at develop · platformio/platform-espressif32 · GitHub. Reading the espidf.py it seems for ESP-ADF you’d just need a few more components entries.

Or file a feature request in Issues · platformio/platform-espressif32 · GitHub.

This used to work until espressif updated esp-adf a few days ago and now I can’t get your git-hub example code working anymore … I fixed all the missing include paths but now i get a ton of linker errors that I can’t solve

Any chance you could update it to work again?

Thanks!

.pioenvs\esp32dev\lib82d\audio_hal\driver\zl38063\example_apps\tw_ldfw.o: In function main': tw_ldfw.c:(.text.startup.main+0x0): multiple definition ofmain’
.pioenvs\esp32dev\lib82d\audio_hal\driver\zl38063\example_apps\tw_ldcfg.o:tw_ldcfg.c:(.text.startup.main+0x0): first defined here
.pioenvs\esp32dev\lib82d\audio_hal\driver\zl38063\example_apps\tw_ldfwcfg.o: In function main': tw_ldfwcfg.c:(.text.startup.main+0x0): multiple definition ofmain’
.pioenvs\esp32dev\lib82d\audio_hal\driver\zl38063\example_apps\tw_ldcfg.o:tw_ldcfg.c:(.text.startup.main+0x0): first defined here
.pioenvs\esp32dev\src\play_sdcard_mp3_example.o:(.literal.app_main+0x78): undefined reference to mp3_decoder_init' .pioenvs\esp32dev\src\play_sdcard_mp3_example.o: In functionapp_main’:
play_sdcard_mp3_example.c:(.text.app_main+0x198): undefined reference to mp3_decoder_init' .pioenvs\esp32dev\lib82d\audio_hal\driver\zl38063\example_apps\tw_spi_access.o:(.literal.tw_upload_dsp_firmware+0x14): undefined reference tost_twFirmware’
.pioenvs\esp32dev\lib82d\audio_hal\driver\zl38063\example_apps\tw_spi_access.o:(.literal.tw_upload_dsp_firmware+0x18): undefined reference to firmwareStreamLen' .pioenvs\esp32dev\lib82d\audio_hal\driver\zl38063\example_apps\tw_spi_access.o:(.literal.tw_upload_dsp_firmware+0x1c): undefined reference toexecutionAddress’
.pioenvs\esp32dev\lib82d\audio_hal\driver\zl38063\example_apps\tw_spi_access.o:(.literal.tw_upload_dsp_firmware+0x20): undefined reference to haveProgramBaseAddress' .pioenvs\esp32dev\lib82d\audio_hal\driver\zl38063\example_apps\tw_spi_access.o:(.literal.tw_upload_dsp_firmware+0x24): undefined reference toprogramBaseAddress’
.pioenvs\esp32dev\lib82d\audio_hal\driver\zl38063\example_apps\tw_spi_access.o:(.literal.tw_upload_dsp_firmware+0x48): undefined reference to configStreamLen' .pioenvs\esp32dev\lib82d\audio_hal\driver\zl38063\example_apps\tw_spi_access.o:(.literal.tw_upload_dsp_firmware+0x4c): undefined reference tost_twConfig’
.pioenvs\esp32dev\lib6bd\audio_stream\fatfs_stream.o:(.literal._fatfs_close+0x14): undefined reference to wav_head_init' .pioenvs\esp32dev\lib6bd\audio_stream\fatfs_stream.o:(.literal._fatfs_close+0x18): undefined reference towav_head_size’
.pioenvs\esp32dev\lib6bd\audio_stream\fatfs_stream.o: In function _fatfs_close': fatfs_stream.c:(.text._fatfs_close+0x85): undefined reference towav_head_init’
fatfs_stream.c:(.text._fatfs_close+0x8f): undefined reference to `wav_head_size’

1 Like

Recheck with the Github issue update.

Thank you thank you thank you!

That means it worked for you?

Yes! It was mostly just the platformIO.ini that i needed to fix

You seem to be so knowledgeable about ESP-ADF I was wondering if you could suggest changes needed to support an audio sampling rate of 96 kHz which the ES8388 codec is capable of - but ADF limits it to 48 kHz. I need this for a non-audio application. It appears as though changes are needed in the driver section - registers need to be modified to work at double speed. Thanks

If the codec and the ESP32 I2S bus support it, it should be possible. But please file an issue at Issues · espressif/esp-adf · GitHub so that Espressif’s developers can integrate it instead of me building a quick hack.

I did report it to Espressif developers - they say that unless we have an audio sample available at that sampling rate they will not be able to verify it.

In the function “esp_err_t es8388_init(audio_hal_codec_config_t *cfg)” there is a line that sets the rate:

res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL2, 0x02); //DACFsMode,SINGLE SPEED; DACFsRatio,256

I think this needs to be modified as Table 1 on page 7 of the data sheet indicates:

http://www.everest-semi.com/pdf/ES8388%20DS.pdf

Sounds like a cheap excuse to not implement something. Send them a sinewave sampled at 96KHz then? :slight_smile:

The ESP32’s I2S is capable of even much, much more btw, see https://www.youtube.com/watch?v=5t1_XNc3vNw.

Did you try it? I don’t have the hardware, I only have one with a ZL38063 codec.

But the change makes sense though, see page 23. Writing 0x02 to DAC control 2 will cause single speed & 256 MCLK sampling frequency. With table table 2 you can get the needed ratio, so overall you’d need to write (1 << 5) | 0B0000) (MCLK/128) or (1 << 5) | 0B0001) (MCLK/192) depending on the MCLK frequency. You’d then also need to modify the register holding ADCFsRatio (“Master mode ADC MCLK to sampling frequency ratio”) according to table 2. Finally, you’ll have to a change the I2S setings to send the data at that new data frequency.

I am also waiting for the Lyra board! I will try it when I get it. Thanks.

I could have used the ADC in the ESP32 for my project - unfortunately the linearity of the ADC is not that great as many in this forum have reported. It works well even at 1 Mbps sampling rate - I have checked this out. The other drawback is the 8-bit DAC. My application requires generating a sine wave from the DAC, drive a BLUE LED to excite a fluoroscent material. The resulting fluoroscent RED light is detected by a photodiode amplifier. This is captured by the ADC and phase shift of the sine wave modulation relative to the BLUE light is measured.

I got the LyraT 4.3 board and tried your MP3 example. Everything works perfectly but no output through my headphones. Is there a setting to direct output to headphones rather than speakers?
I even modified the location of the .mp3 file and tried. After “Receive music…” there is a 7 second pause which means something is happening! After that the pipeline is stopped.

The example is for MP3 DAC. If you want to use your I2S DAC which is connected to the amplifier and the headphones, which you must replace the main.c with the following code: esp-adf/play_mp3_example.c at 6606f4ee32360f2e8fd1e5d16b14fe1d820677fa · espressif/esp-adf · GitHub

I plan to update my ESP-ADF ‘lib’ btw with the current version and more examples.

There are a couple of lines of code to start the codec missing in your example file. Once I fixed it it is working.

It probably didn’t even start the codec because it was setup for DAC playing from esp-adf/play_mp3_dac_example.c at 6606f4ee32360f2e8fd1e5d16b14fe1d820677fa · espressif/esp-adf · GitHub :stuck_out_tongue:

Got it - I used the play_mp3_example.c and it works as expected.

Do you have an example of audio recording using the microphone on the LyraT board?