i2s internal dac throughput / overflow somewhere ?
Posted: Mon Jan 10, 2022 5:46 pm
Hi all !
I'm coding a small app that generate a real time audio signal on internal dac.
Then in a nutshell, the busy loop is something like that :
- AUDIO_BUFFER_SIZE is 64 and the i2s driver is configured to use 4 buffers of 64 samples
- "Compute stuff" duration is around 780 micro seconds
- Sample rate is 44100
Each second I display the samples_proceeded variable, and I'm always around 202000 samples per second proceeded - far far over from 44100. How is it possible ???
For what I understand, if there's no free DMA buffer available, the loop would block on i2s_write() or xQueueReceive() would not return I2S_EVENT_TX_DONE and I would never be allowed to produce more data than consumed by the driver.
I might add that the not_written variable is always zero.
What am I missing ?
Note : the code runs on a CORE 1 task (priority 1) with watchdog disabled on CORE 1 and no other task running on the same core except IDLE1
I'm coding a small app that generate a real time audio signal on internal dac.
Then in a nutshell, the busy loop is something like that :
- while (true) {
- xSemaphoreTake(mutex, portMAX_DELAY);
- for (int i = 0; i < AUDIO_BUFFER_SIZE; i++) {
- // compute_stuff
- }
- xSemaphoreGive(mutex);
- samples_proceeded += AUDIO_BUFFER_SIZE;
- size_t i2s_bytes_write = 0;
- ret = i2s_write(I2S_NUM, &samples_buffer, AUDIO_BUFFER_SIZE * 2, &i2s_bytes_write, 100); // size is in bytes - 16bits = 2 x bytes
- if (ret != ESP_OK)
- printf("!"); //Never happened, even once
- not_written += (AUDIO_BUFFER_SIZE * 2) - i2s_bytes_write;
- bool done = false;
- while (!done) {
- if (xQueueReceive(i2s_queue, &i2s_event, 100) != pdFALSE) {
- if (i2s_event.type == I2S_EVENT_TX_Q_OVF)
- printf("*"); // Never happened, even once
- done = (i2s_event.type == I2S_EVENT_TX_DONE);
- } else
- printf("#"); // Never happened, even once
- }
- }
- "Compute stuff" duration is around 780 micro seconds
- Sample rate is 44100
Each second I display the samples_proceeded variable, and I'm always around 202000 samples per second proceeded - far far over from 44100. How is it possible ???
For what I understand, if there's no free DMA buffer available, the loop would block on i2s_write() or xQueueReceive() would not return I2S_EVENT_TX_DONE and I would never be allowed to produce more data than consumed by the driver.
I might add that the not_written variable is always zero.
What am I missing ?
Note : the code runs on a CORE 1 task (priority 1) with watchdog disabled on CORE 1 and no other task running on the same core except IDLE1