Audio output other than 44100Hz

Hi,

As I have stated in my project topic about the Audio Streamer, I have now output over the headphone Jack.
While this is great I have problems with audio other than 44100, 16bit stereo

My AudioPlay task is using a ringbuffer, filled via MQTT. Messages with wave files vary in samplerate from 22050 to 16000. They sound too fast.

My Task:

void AudioPlayTask(void * p){
  while(1) {
    xEventGroupWaitBits(audioGroup,PLAY,true,true,portMAX_DELAY); //Wait for the bit before updating
      if ( xSemaphoreTake( wbSemaphore, ( TickType_t ) 10000 ) == pdTRUE )
      {
        Serial.println("Play Audio");
        //devcfg.clock_speed_hz = 8 * 1000 * 1000; ==> not sure why sleep should be this????
        float sleep = 8000000 / kMaxWriteLength / 2;
        while(!audioData.isEmpty())
        {
            int frames = 1024;
            for (int i = 0; i < frames; i++) 
            {
              if (!audioData.isEmpty()) {
                audioData.pop(data[i]);
              }
            }
            wb.SpiWrite(hal::kDACBaseAddress,(const uint8_t *)data, sizeof(uint8_t) * frames);
            std::this_thread::sleep_for(std::chrono::microseconds((int)sleep));
        }
        if (asyncClient.connected()) {
          asyncClient.publish(playFinishedTopic.c_str(), 0, false, finishedMsg.c_str());
        }      
        uint8_t b = 0;
        for (int i = 0; i < kMaxWriteLength* 4;i++) {
          audioData.push(b);
        }
        audioData.clear();
        xEventGroupClearBits(audioGroup, PLAY);
        xSemaphoreGive( wbSemaphore ); //Free for all
      }
  }
  vTaskDelete(NULL);
}

Some of the code is not needed, but that is a result of me trying different things.
Can any of the dev’s help me out in understanding why I need the sleed after SpiWrite?
I think it has something to do with the devcfg.clock_speed_hz = 8 * 1000 * 1000; in the whisbonebus but I fail to see why.

Is it even possible to correctly output audio other than 44100?

Just a little extra info.
In theory, I think this code:

    while(!audioData.isEmpty())
    {
        int frames = 1024;
        for (int i = 0; i < frames; i++) 
        {
          if (!audioData.isEmpty()) {
            audioData.pop(data[i]);
          }
        }
        wb.SpiWrite(hal::kDACBaseAddress,(const uint8_t *)data, sizeof(uint8_t) * frames);
        std::this_thread::sleep_for(std::chrono::microseconds((int)sleep));
    }

should be a bit different.

With a 44100, 16 bit stereo audio file, I think I should have 4 bytes per sample.
This means for 1 sample 1 / 44100 seconds ~ 23 microseconds.
1 sample has 4 bytes, since it is 16 bit and 2 channels

My first try was:

    while(!audioData.isEmpty())
    {
        int frames = 4;
        float sleep = 1 / 44100 * 2 * 2 * 1000 * 1000; //  ca 90 microsecs
        for (int i = 0; i < frames; i++) 
        {
          if (!audioData.isEmpty()) {
            audioData.pop(data[i]);
          }
        }
        wb.SpiWrite(hal::kDACBaseAddress,(const uint8_t *)data, sizeof(uint8_t) * frames);
        std::this_thread::sleep_for(std::chrono::microseconds((int)sleep));
    }

This produces way to slow audio however… so I am missing something here but I can’t figure out what. I also tried lower values for sleep, like 23 but still no luck

Hi @Romkabouter,

How I can test this myself? Do you have this code on github?

I am also doing some additional test around this to see what is the best solution.

Will get back to you later with an answer on this.

-Yoel

Hey yoel, it’s here:

I ran into an issue yesterday that audio output did not work anymore when the MV was attached to the Pi, but worked ok when running esp32.
FYI :slight_smile:

You can follow the instructions from the repo to get m going, adjust the code to whatever suits you.
The code connects to a MQTT broker and starts listening to the topics hermes/audioServer/matrixvoice/playBytes/#.
So you can inject a wave file to hermes/audioServer/matrixvoice/playBytes/test and the AudioPlay task should pick that up.
Sometime the audio is a big mess, probably an issue with the messages arriving or so, but I think you will figure it out :slight_smile:

Glad you can help, you can also PM me if you want.

Why I need different samplerates is that I am using the MV for Snips, which had some feedback sounds (22050) and plays Text To Speech at 16000. Some are mono and stereo as well, but that is another problem to tackle.
The code now plays the feedback sounds to fast and the speech way to fast

Hi yoel,

I have created a quick tool which might help:

I have tried to port the audio_output from the HAL repo, I get output but the sound is not as expected.

When I read the audio_output demo:

it says that the only supported sample rates are:
“Sampling PCM Frequency: 8000,16000,32000,44100,48000,88200,96000”);

When I run the demo, 16000, 16 bit stereo runs ok. Mono plays too fast, but sounds like the stereo file when setting samplerate to 8000 (which makes sense)

44100 16 bit stereo also runs fine, mono too fast (and 22050 is not supported, setting to 16000 is too slow)

Why is 22050 not supported?

Hope it helps

Hey joel,

Any news on this?