Matrix Voice and Raspberry Pi Zero Audio output


Hi Yoel,

I have worked my way through the code and I am stuck comprehending this:

void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len)
static uint16_t buffer[2048];
int16_t p = (int16_t)data;

uint16_t diff;
uint16_t buffers_fifo[2];

for (int i = 0; i < len/4; i++)
    buffer[i] = p[i*2]/2+16768;
    /* code */


if(buffers_fifo[1] > buffers_fifo[0])
    diff = buffers_fifo[1] - buffers_fifo[0];
    diff = 4096 - buffers_fifo[0] + buffers_fifo[1];

if(diff > 2048){
    vTaskDelay(30 / portTICK_PERIOD_MS);
//    ESP_LOGI(BT_AV_TAG, "--- Diff %d Len:%d", diff,len/2);
wb->SpiWrite(hal::kDACBaseAddress, (uint8_t*)buffer, len/2);


I understand what it does, but I do not understand the SpiRead into buffers_fifo do?
I have chosen internal DAC in the config, assuming that the sound would come from the audio-jack.
Is that correct or should I choose external I2S?

This is because I get the buffer callback and all, but no sound is produced in the jack.
Should I upgrade firmware first?


Hi @Romkabouter,

Sorry about the code, it was meant to be a test and still requires some cleanup. A full example will be released in the coming weeks.

The audio data is sent from the ESP32 using SPI to the DAC implemented in the FPGA present in the board. So, that’s what SpiWrite does, is sending the audio.

Yes, you should use the latest version of matrix-creator-init package.



Yeah, I understand and that is no problem at all :slight_smile:
I was using that code as an example to output data but when I did not hear a sound I thought I’d made some mistake.

Code is fine to tinker with, no problems. I do not think I have the latest init code in place, so that will be my first action

update: yeuh, I could play my spotify playlist!
Although the buffers and such are not good (it’s a demo anyway), I could hear the music :slight_smile:
Lots of packets drops, but that is just a buffer problem.


For audio output I run into the same problem as bluetooth.
That is that the ESP framework only support 44100 16 bit for now, but I think I will just make this a requirement for incoming audio buffers instead of trying to resample on the fly.

Thanks for all the effort on the audio output :slight_smile:


Hi yoel,

I could use your help for a bit, because I can not seem to produce a correct sound.
My setup receives a wav file and puts the raw data part in a uint8_t buffer. For now I send a small 8bit 8kHz file, which fits in memory of the esp32.

Besides that, I have and task running which should be playing the buffer.
The code below is what I have to produce the audio, but all I got from various tries is between a ticking sound and a bit crushing sound.
Nothing is anything like it should be,

> void AudioPlayTask(void * p){
>   while(1) {
>     xEventGroupWaitBits(audioGroup,PLAY,true,true,portMAX_DELAY); //Wait for the bit before updating
>       if ( xSemaphoreTake( wbSemaphore, ( TickType_t ) 5000 ) == pdTRUE )
>       {
>         Serial.println("Play Audio");
>         //Serial.println(inRate);
>         int NUM = 512;
>         while (played < dataLength) {
>           uint8_t data[NUM];
>           for (int i = 0; i < NUM; i++) {
>             data[i] = Data[played+i];
>           }
>           played = played + NUM;         
>           wb.SpiWrite(hal::kDACBaseAddress, (uint8_t *) data, sizeof(data));
>          //delay: 1 000 000 microseconds in a second, 8000 samples / second (for a 8khz file)
>          //that will be 1 000 000 / 8000 microsecond per sample, we read NUM samples
>           delayMicroseconds( NUM *  ( 1000000 / inRate ) );
>         }
>         xEventGroupClearBits(audioGroup, PLAY);
>         xSemaphoreGive( wbSemaphore ); //Free for all
>       }
>   }
>   vTaskDelete(NULL);
> }

In this version I have a local buffer of 512, but I have also used 1 and other.
Since it is an 8bit mono file, I assumed that I could play the buffervalues as they come in.
My thoughts therefore were using NUM = 1, I would write the SPI with that data, then do a delay of 1 000 000 / 8000 microseconds and play the next value
This would result in playing 8000 samples per second, which matches the sample rate of the incoming file.
I am using an 8bit mono 8000Hz file to simplify the process for now.

  • dataLength is a global holding the length of the data, read from the wave header
  • inRate is the sample rate, read from the wav header
  • Data hold the whole raw data of the wav
  • please ignore xSemaphoreTake and other code, that works fine and I need it because this part is implemented in my Matrix Voice Audio Server. I want to output the incoming sound files to the audiojack.

I am misunderstanding the wb.SpiWrite(hal::kDACBaseAddress, (uint8_t *) data, sizeof(data)); part?