esp-adf
esp-adf copied to clipboard
Infinite loop playback WAV from sdcard (AUD-3374)
Hi, I'm trying to playback a WAV file as an infinite loop on the LyraT v4.3.
For that I have written a custom read function for the fatfs stream audio element which wraps around when it gets to the end of the file:
typedef enum {
STREAM_TYPE_UNKNOW,
STREAM_TYPE_WAV,
STREAM_TYPE_OPUS,
STREAM_TYPE_AMR,
STREAM_TYPE_AMRWB,
} wr_stream_type_t;
typedef struct fatfs_stream {
audio_stream_type_t type;
int block_size;
bool is_open;
int file;
wr_stream_type_t w_type;
bool write_header;
} fatfs_stream_t;
static int my_fatfs_read(audio_element_handle_t self, char *buffer, int len, TickType_t ticks_to_wait, void *context)
{
fatfs_stream_t *fatfs = (fatfs_stream_t *)audio_element_getdata(self);
audio_element_info_t info;
audio_element_getinfo(self, &info);
//ESP_LOGI(TAG, "read len=%d, pos=%d/%d", len, (int)info.byte_pos, (int)info.total_bytes);
int rlen = read(fatfs->file, buffer, len);
if (rlen < len) {
ESP_LOGW(TAG, "No more data, wanted %d but only got %d. Wrapping around...", len, rlen);
if (lseek(fatfs->file, 44, SEEK_SET) < 0) // skip wav header of 44 bytes
{
ESP_LOGE(TAG, "Error seek file. Error message: %s, line: %d", strerror(errno), __LINE__);
}
else
{
int remaining_from_start = len - rlen;
// add more bytes to buffer
int inc = read(fatfs->file, buffer + rlen, remaining_from_start);
audio_element_set_byte_pos(self, remaining_from_start);
ESP_LOGW(TAG, "set byte pos to %d and read %d more bytes.", remaining_from_start, inc);
rlen += inc;
}
}
if (rlen == 0) {
ESP_LOGW(TAG, "No more data, ret:%d", rlen); // should never happen
} else if (rlen == -1) {
ESP_LOGE(TAG, "The error is happened in reading data. Error message: %s", strerror(errno));
} else {
audio_element_update_byte_pos(self, rlen);
}
//ESP_LOGI(TAG, "Read %d", (int) buffer[0]);
//ESP_LOGI(TAG, "Read %d bytes", rlen);
return rlen;
}
I'm using this callback like this within a pipeline of fatfs-->wav decoder-->i2s writer:
ESP_LOGI(TAG, "[4.0] Create Fatfs stream to read input data");
fatfs_stream_cfg_t fatfs_cfg = FATFS_STREAM_CFG_DEFAULT();
fatfs_cfg.type = AUDIO_STREAM_READER;
fatfs_reader_el = fatfs_stream_init(&fatfs_cfg);
audio_element_set_uri(fatfs_reader_el, "/sdcard/test.wav");
audio_element_set_read_cb(fatfs_reader_el, my_fatfs_read, NULL);
My problem is that the sound stops anyhow after one playback. All audio elements remain in the RUNNING state though.
Here's the complete source code: https://gist.github.com/stwirth/324cc37d0e0a5258f6148db98c831803
Logs:
ets Jul 29 2019 12:21:46
rst:0x1 (POWERON_RESET),boot:0x1f (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:7016
load:0x40078000,len:14784
load:0x40080400,len:3764
0x40080400: _init at ??:?
entry 0x40080680
I (27) boot: ESP-IDF v4.3-356-g48ae2309fd 2nd stage bootloader
I (27) boot: compile time 10:13:05
I (27) boot: chip revision: 3
I (31) boot_comm: chip revision: 3, min. bootloader chip revision: 0
I (38) boot.esp32: SPI Speed : 80MHz
I (43) boot.esp32: SPI Mode : DIO
I (48) boot.esp32: SPI Flash Size : 4MB
I (52) boot: Enabling RNG early entropy source...
I (58) boot: Partition Table:
I (61) boot: ## Label Usage Type ST Offset Length
I (68) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (76) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (83) boot: 2 factory factory app 00 00 00010000 00300000
I (91) boot: End of partition table
I (95) boot_comm: chip revision: 3, min. application chip revision: 0
I (102) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=116d0h ( 71376) map
I (134) esp_image: segment 1: paddr=000216f8 vaddr=3ffb0000 size=02adch ( 10972) load
I (138) esp_image: segment 2: paddr=000241dc vaddr=40080000 size=0be3ch ( 48700) load
I (158) esp_image: segment 3: paddr=00030020 vaddr=400d0020 size=30670h (198256) map
I (222) esp_image: segment 4: paddr=00060698 vaddr=4008be3c size=05f84h ( 24452) load
I (231) esp_image: segment 5: paddr=00066624 vaddr=50000000 size=00010h ( 16) load
I (240) boot: Loaded app from partition at offset 0x10000
I (241) boot: Disabling RNG early entropy source...
I (253) psram: This chip is ESP32-D0WD
I (253) spiram: Found 64MBit SPI RAM device
I (253) spiram: SPI RAM mode: flash 80m sram 80m
I (256) spiram: PSRAM initialized, cache is in low/high (2-core) mode.
I (263) cpu_start: Pro cpu up.
I (267) cpu_start: Starting app cpu, entry point is 0x400816a0
0x400816a0: call_start_cpu1 at /home/stwirth/esp/esp-idf/components/esp_system/port/cpu_start.c:141
I (0) cpu_start: App cpu up.
I (773) spiram: SPI SRAM memory test OK
I (781) cpu_start: Pro cpu start user code
I (781) cpu_start: cpu freq: 240000000
I (781) cpu_start: Application information:
I (783) cpu_start: Project name: downmix_pipeline
I (789) cpu_start: App version: de68c3c-dirty
I (795) cpu_start: Compile time: Oct 12 2021 10:12:55
I (801) cpu_start: ELF file SHA256: a8aa35e7663a4d89...
I (807) cpu_start: ESP-IDF: v4.3-356-g48ae2309fd
I (813) heap_init: Initializing. RAM available for dynamic allocation:
I (820) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (826) heap_init: At 3FFB3670 len 0002C990 (178 KiB): DRAM
I (832) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (839) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (845) heap_init: At 40091DC0 len 0000E240 (56 KiB): IRAM
I (851) spiram: Adding pool of 4096K of external SPI memory to heap allocator
I (860) spi_flash: detected chip: gd
I (863) spi_flash: flash io: dio
W (867) spi_flash: Detected size(8192k) larger than the size in the binary image header(4096k). Using the size in the binary image header.
I (881) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (896) spiram: Reserving pool of 32K of internal memory for DMA/internal allocations
I (904) INFINITE_LOOP_PIPELINE_TEST: [1.0] Start audio codec chip
I (911) gpio: GPIO[19]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:3
I (931) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (932) ES8388_DRIVER: init,out:02, in:00
I (942) AUDIO_HAL: Codec mode is 2, Ctrl:1
I (946) INFINITE_LOOP_PIPELINE_TEST: [2.0] Start and wait for SDCARD to mount
E (949) gpio: gpio_install_isr_service(460): GPIO isr service already installed
I (957) SDCARD: Using 1-line SD mode, 4-line SD mode, base path=/sdcard
I (1033) SDCARD: CID name SC16G!
I (1465) INFINITE_LOOP_PIPELINE_TEST: [3.0] Create pipeline
I (1465) INFINITE_LOOP_PIPELINE_TEST: [4.0] Create Fatfs stream to read input data
I (1468) INFINITE_LOOP_PIPELINE_TEST: [4.1] Create wav decoder to decode wav file
I (1474) gpio: GPIO[36]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:3
I (1486) gpio: GPIO[39]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:3
W (1512) PERIPH_TOUCH: _touch_init
I (1512) INFINITE_LOOP_PIPELINE_TEST: [3.2] Create i2s stream to write audio data to codec chip
I (1515) I2S: DMA Malloc info, datalen=blocksize=1200, dma_buf_count=3
I (1521) I2S: DMA Malloc info, datalen=blocksize=1200, dma_buf_count=3
I (1549) I2S: APLL: Req RATE: 44100, real rate: 44099.988, BITS: 16, CLKM: 1, BCK_M: 8, MCLK: 11289597.000, SCLK: 1411199.625000, diva: 1, divb: 0
I (1555) LYRAT_V4_3: I2S0, MCLK output by GPIO0
I (1559) INFINITE_LOOP_PIPELINE_TEST: [3.4] Link elements together fatfs-->decoder-->i2s_stream-->[codec_chip]
I (1570) AUDIO_PIPELINE: link el->rb, el:0x3f8073f8, tag:fatfs, rb:0x3f8079b0
I (1577) AUDIO_PIPELINE: link el->rb, el:0x3f8076b4, tag:dec, rb:0x3f8099f0
I (1585) INFINITE_LOOP_PIPELINE_TEST: [5.0] Set up event listener
I (1593) INFINITE_LOOP_PIPELINE_TEST: [5.1] Listening event from peripherals
I (1618) I2S: APLL: Req RATE: 44100, real rate: 44099.988, BITS: 16, CLKM: 1, BCK_M: 8, MCLK: 11289597.000, SCLK: 1411199.625000, diva: 1, divb: 0
I (1622) AUDIO_ELEMENT: [fatfs-0x3f8073f8] Element task created
I (1628) AUDIO_ELEMENT: [dec-0x3f8076b4] Element task created
I (1636) AUDIO_ELEMENT: [i2s-0x3f807840] Element task created
I (1642) AUDIO_PIPELINE: Func:audio_pipeline_run, Line:359, MEM Total:4375899 Bytes, Inter:312363 Bytes, Dram:256595 Bytes
I (1653) AUDIO_ELEMENT: [fatfs] AEL_MSG_CMD_RESUME,state:1
I (1660) AUDIO_ELEMENT: [dec] AEL_MSG_CMD_RESUME,state:1
I (1666) AUDIO_ELEMENT: [i2s] AEL_MSG_CMD_RESUME,state:1
I (1671) I2S_STREAM: AUDIO_STREAM_WRITER
I (1676) INFINITE_LOOP_PIPELINE_TEST: Audio event 8 (AEL_STATUS_STATE_RUNNING) from i2s element
I (1686) AUDIO_PIPELINE: Pipeline started
I (1690) FATFS_STREAM: File size: 444524 byte, file position: 0
I (1696) INFINITE_LOOP_PIPELINE_TEST: Audio event 8 (AEL_STATUS_STATE_RUNNING) from fatfs element
I (1706) INFINITE_LOOP_PIPELINE_TEST: [6.0] Base stream pipeline running
I (1710) CODEC_ELEMENT_HELPER: The element is 0x3f8076b4. The reserve data 2 is 0x0.
I (1722) WAV_DECODER: a new song playing
I (1727) INFINITE_LOOP_PIPELINE_TEST: Audio event 9 from dec element
I (1733) INFINITE_LOOP_PIPELINE_TEST: Audio event 8 (AEL_STATUS_STATE_RUNNING) from dec element
I (2559) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
W (2559) HEADPHONE: Headphone jack inserted
I (2744) INFINITE_LOOP_PIPELINE_TEST: el fatfs: sample_rate: 44100, channels: 2, bits: 16, bps: 0, byte_pos: 108544, total_bytes: 444524, duration: 0
I (2747) INFINITE_LOOP_PIPELINE_TEST: el dec: sample_rate: 44100, channels: 1, bits: 16, bps: 705600, byte_pos: 99364, total_bytes: 441000, duration: 0
I (2762) INFINITE_LOOP_PIPELINE_TEST: el i2s: sample_rate: 44100, channels: 1, bits: 16, bps: 0, byte_pos: 94208, total_bytes: 0, duration: 0
I (2774) INFINITE_LOOP_PIPELINE_TEST: Element states: 3 3 3
I (5782) INFINITE_LOOP_PIPELINE_TEST: el fatfs: sample_rate: 44100, channels: 2, bits: 16, bps: 0, byte_pos: 374784, total_bytes: 444524, duration: 0
I (5785) INFINITE_LOOP_PIPELINE_TEST: el dec: sample_rate: 44100, channels: 1, bits: 16, bps: 705600, byte_pos: 367652, total_bytes: 441000, duration: 0
I (5799) INFINITE_LOOP_PIPELINE_TEST: el i2s: sample_rate: 44100, channels: 1, bits: 16, bps: 0, byte_pos: 364544, total_bytes: 0, duration: 0
I (5814) INFINITE_LOOP_PIPELINE_TEST: Element states: 3 3 3
W (6576) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 108. Wrapping around...
W (6578) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1940 and read 1940 more bytes.
W (7017) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 172. Wrapping around...
W (7018) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1876 and read 1876 more bytes.
W (7400) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 236. Wrapping around...
W (7402) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1812 and read 1812 more bytes.
W (7783) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 300. Wrapping around...
W (7785) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1748 and read 1748 more bytes.
W (8167) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 364. Wrapping around...
W (8169) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1684 and read 1684 more bytes.
W (8552) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 428. Wrapping around...
W (8554) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1620 and read 1620 more bytes.
I (8821) INFINITE_LOOP_PIPELINE_TEST: el fatfs: sample_rate: 44100, channels: 2, bits: 16, bps: 0, byte_pos: 310868, total_bytes: 444524, duration: 0
I (8824) INFINITE_LOOP_PIPELINE_TEST: el dec: sample_rate: 44100, channels: 1, bits: 16, bps: 705600, byte_pos: 441044, total_bytes: 441000, duration: 0
I (8838) INFINITE_LOOP_PIPELINE_TEST: el i2s: sample_rate: 44100, channels: 1, bits: 16, bps: 0, byte_pos: 631464, total_bytes: 0, duration: 0
I (8852) INFINITE_LOOP_PIPELINE_TEST: Element states: 3 3 3
W (8936) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 492. Wrapping around...
W (8938) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1556 and read 1556 more bytes.
W (9321) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 556. Wrapping around...
W (9323) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1492 and read 1492 more bytes.
W (9694) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 620. Wrapping around...
W (9696) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1428 and read 1428 more bytes.
W (10080) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 684. Wrapping around...
W (10081) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1364 and read 1364 more bytes.
W (10464) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 748. Wrapping around...
W (10466) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1300 and read 1300 more bytes.
W (10848) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 812. Wrapping around...
W (10849) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1236 and read 1236 more bytes.
W (11231) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 876. Wrapping around...
W (11233) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1172 and read 1172 more bytes.
W (11617) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 940. Wrapping around...
W (11618) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1108 and read 1108 more bytes.
I (11859) INFINITE_LOOP_PIPELINE_TEST: el fatfs: sample_rate: 44100, channels: 2, bits: 16, bps: 0, byte_pos: 275540, total_bytes: 444524, duration: 0
I (11863) INFINITE_LOOP_PIPELINE_TEST: el dec: sample_rate: 44100, channels: 1, bits: 16, bps: 705600, byte_pos: 441044, total_bytes: 441000, duration: 0
I (11878) INFINITE_LOOP_PIPELINE_TEST: el i2s: sample_rate: 44100, channels: 1, bits: 16, bps: 0, byte_pos: 899752, total_bytes: 0, duration: 0
I (11891) INFINITE_LOOP_PIPELINE_TEST: Element states: 3 3 3
W (12004) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 1004. Wrapping around...
W (12005) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1044 and read 1044 more bytes.
W (12387) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 1068. Wrapping around...
W (12388) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 980 and read 980 more bytes.
W (12763) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 1132. Wrapping around...
W (12764) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 916 and read 916 more bytes.
W (13149) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 1196. Wrapping around...
W (13150) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 852 and read 852 more bytes.
W (13535) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 1260. Wrapping around...
W (13537) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 788 and read 788 more bytes.
W (13919) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 1324. Wrapping around...
W (13921) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 724 and read 724 more bytes.
W (14304) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 1388. Wrapping around...
W (14305) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 660 and read 660 more bytes.
W (14687) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 1452. Wrapping around...
W (14688) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 596 and read 596 more bytes.
I (14898) INFINITE_LOOP_PIPELINE_TEST: el fatfs: sample_rate: 44100, channels: 2, bits: 16, bps: 0, byte_pos: 238164, total_bytes: 444524, duration: 0
I (14901) INFINITE_LOOP_PIPELINE_TEST: el dec: sample_rate: 44100, channels: 1, bits: 16, bps: 705600, byte_pos: 441044, total_bytes: 441000, duration: 0
I (14916) INFINITE_LOOP_PIPELINE_TEST: el i2s: sample_rate: 44100, channels: 1, bits: 16, bps: 0, byte_pos: 1168040, total_bytes: 0, duration: 0
I (14929) INFINITE_LOOP_PIPELINE_TEST: Element states: 3 3 3
W (15074) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 1516. Wrapping around...
W (15075) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 532 and read 532 more bytes.
W (15458) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 1580. Wrapping around...
W (15458) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 468 and read 468 more bytes.
If I remove the decoder from the pipeline, the sound loops fine but I can hear a crack at the wrap-around:
@@ -158,10 +158,10 @@ void app_main(void)
ESP_LOGI(TAG, "[3.4] Link elements together fatfs-->decoder-->i2s_stream-->[codec_chip]");
audio_pipeline_register(pipeline, fatfs_reader_el, "fatfs");
- audio_pipeline_register(pipeline, wav_decoder_el, "dec");
audio_pipeline_register(pipeline, i2s_writer_el, "i2s");
- const char *link[3] = {"fatfs", "dec", "i2s"};
- audio_pipeline_link(pipeline, &link[0], 3);
+
+ const char *link[2] = {"fatfs", "i2s"};
+ audio_pipeline_link(pipeline, &link[0], 2);
ESP_LOGI(TAG, "[5.0] Set up event listener");
audio_event_iface_cfg_t evt_cfg = AUDIO_EVENT_IFACE_DEFAULT_CFG();
Any idea on how I can achieve an infinite loop without cracking?
Hi @stwirth
Did you refer to this example play_mp3_control? I think this example should be very close to your needs.
W (6576) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 108. Wrapping around...
W (6578) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1940 and read 1940 more bytes.
W (7017) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 172. Wrapping around...
W (7018) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1876 and read 1876 more bytes.
W (7400) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 236. Wrapping around...
W (7402) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1812 and read 1812 more bytes.
W (7783) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 300. Wrapping around...
W (7785) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1748 and read 1748 more bytes.
W (8167) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 364. Wrapping around...
W (8169) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1684 and read 1684 more bytes.
W (8552) INFINITE_LOOP_PIPELINE_TEST: No more data, wanted 2048 but only got 428. Wrapping around...
W (8554) INFINITE_LOOP_PIPELINE_TEST: set byte pos to 1620 and read 1620 more bytes.
I think your cb function has actually read to the end of the file, but it seems that you haven't done any further processing. If the file reading head and tail can be detected, then it should be possible to achieve endless loop playback.
@HengYongChao thanks for your reply.
I think your cb function has actually read to the end of the file, but it seems that you haven't done any further processing. If the file reading head and tail can be detected, then it should be possible to achieve endless loop playback.
I wrote the callback function to wrap around when read cannot read the block that was requested. It then resets the file pointer to be just after the WAV header and continue to read from there into the provided buffer. I don't see why this would fail. My logs show that the wrapping around works and that it has read more bytes from the start of the file. Do you see any error in my source code?
Maybe the MP3 decoder used in the play_mp3_control example does not have this problem, I'll try what happens when I replace the WAV decoder element with an MP3 decoder element and change the source file to be in mp3 format.
@HengYongChao I had a closer look at play_mp3_control and refactored my test program to work in a similar way by using a custom read callback for the decoder element.
When I use the mp3 decoder, wrapping around works but the transition is not smooth. I can hear a gap. I used the fatfs stream writer to write the output to the sd card and it looks like this:
Zoomed in on the gap:
I experimented with jumping back to a particular position in the file instead of the beginning but I could not get rid of the gap.
When I use the wav decoder, the sound stops and does not loop at all, although I am sure that the read callback delivers data. You can find my source code here. Thanks in advance for your help.
Using the OGG decoder the audio loops fine and the gap is a little smaller (but still audible) than when using the MP3 decoder:

Currently, we are looking into the same problem. Have you found a solution yet, that makes the gap inaudible?
Unfortunately not.
@stwirth @sqrtroot Hi guys, please try follow method. For normally, fatfs stream post the finished state when at file EOF to complete the linked element, so the gap occured. If want to infinite loop playback, let the read callback do not return AEL_IO_DONE and AEL_IO_OK, to seek the beginning when get EOF for consecutive read the file.
@jason-mao thanks for your comment. I am doing exactly what you describe:
int looping_file_read_cb (audio_element_handle_t el, char *buf, int len, TickType_t wait_time, void *ctx)
{
file_info_t *finfo = (file_info_t *)ctx;
if (finfo->fp == NULL) {
return AEL_IO_DONE;
}
int read_size = fread(buf, 1, len, finfo->fp);
//if (read_size < len || ftell(finfo->fp) > finfo->len - len) {
if (read_size < len) {
ESP_LOGI(TAG, "Read only %d instead of %d bytes. Rewinding to %d to read more...", read_size, len, finfo->offset);
fseek(finfo->fp, finfo->offset, SEEK_SET);
read_size += fread(buf + read_size, len - read_size, 1, finfo->fp);
}
return read_size;
}
ESP_LOGI(TAG, "[2.2] Create MP3 decoder and set custom read callback");
mp3_decoder_cfg_t mp3_cfg = DEFAULT_MP3_DECODER_CONFIG();
decoder = mp3_decoder_init(&mp3_cfg);
audio_element_set_read_cb(decoder, looping_file_read_cb, &finfo);
The infinite file reading seems to work fine but the decoder elements have problems with that input:
- The wav decoder stops after the first loop
- The MP3 decoder outputs an audible gap
- The OGG decoder outputs an audible gap (slightly smaller than with the MP3 decoder)
@stwirth I think the error is due to the wrapped header in the beginning of file. MP3 and OGG header is too complex to skip, suggest use the wav, which is 44 byte header normally, skip it infinite reading.
@stwirth So appreciate any progress update from your side.
No progress, project was abandoned.
@jason-mao The WAV decoder does not use data size provided in the audio file header? If the decoder is limited by the size of the WAV file specified in the header, then infinite appending won't work and the audio will play only once, right?
Trying to loop audio too (without gaps). I am not entirely sure how the library works under the hood yet.
Same #996, loop playback example is provided.