AudioPlayQueue memory issue?

Status
Not open for further replies.

beermat

Well-known member
Have an issue using AudioPlayQueue on Teensy 4.0, that isn't present on Teensy 3.6. My sketch is complex, so will describe the issue seen as best I can in the hope it jogs some recollection or thought. I pulled out just the required code into a different sketch to minimize conflicts with other utilized libraries in my full sketch. Recreated the issue there.

Basically, a call to AudioPlayQueue.getBuffer() or AudioPlayQueue.playBuffer() is taking almost 3ms on the Teensy 4.0, whereas this is just a microsecond or two on the Teensy 3.6.

This latency translates into stuttering audio played via AudioMixer -> AudioAmplifier -> AudioOutputI2S2 as the code cannot stream the audio fast enough.

Further diagnostics in my sketch show this only happens if I have previously made a call to AudioPlaySdWav; if I call my video-playing code (which utilizes AudioPlayQueue) before any other call to the Audio functions, such as AudioPlaySdWav, then the getBuffer and playBuffer return within 1 or 2 microseconds, as desired. Only after a single call to AudioPlaySdWav does the latency occur in AudioPlayQueue.

AudioMemory is set to 40, and AudioMemoryUsage and AudioMemoryUsageMax report 34 during playback of the video and audio.

This is not present on the Teensy 3.6, just the 4.0, the same sketch works fine on the Teensy 3.6.

I'm using SdFat library SDIO with the builtin SD card on the 3.6, the Teensy 4.0 has a microSD hard wired to the breakouts underneath and also uses SdFat library SDIO. Using SPI to transmit an in-memory buffer to a 320x240 ILI9341 based display for the screen updates.

I realize that not providing full code, etc, and only a description is less than optimal, but if jogs an experts memory on here about similar issues or potential issues, then I'd be grateful for any pointers or help!
 
Update - this is the troublesome code snippet, it takes audio data (read from the SD card into videoAudioBuffer), and pushes it to an AudioPlayQueue

Code:
    //Process audio
    //Audio is 1839 samples*2 channels
    for (int i = 0; i < 1839; i++) {
      if (audioPos == 0) {
        lb = queue1.getBuffer();
      }
      if (lb) {
        *lb++ = videoAudioBuffer[i * 2];
        audioPos += 1;
        if (audioPos >= 128) {
          audioPos = 0;
          queue1.playBuffer();
        }
      }
    }

On the Teensy 3.6, this loop executes without issue (average execution time 195 µS) , and reports AudioMemoryUsage and AudioMemoryUsageMax between 16 and 18 for the duration

On the Teensy 4.0, the average execution time soars to ~33000 µS and reports AudioMemoryUsage and AudioMemoryUsageMax at whatever I set AudioMemory() to, up to AudioMemory(82), at which point setting AudioMemory higher has no effect, usage and max report 82.

Further timing on the Teensy 4.0 shows that it is queue1.getBuffer() that blocks for ~2200 µS for each call

Interestingly enough, on the Teensy 4.0, this only starts happening after my sketch has made calls to AudioPlaySdWav to play a wav from the SD card. If I run this code before any other audio is played, or just comment out calls to AudioPlaySdWav, then the above code works as expected on the Teensy 4.0, without the max memory and blocking issues.

Audio configuration:

Code:
AudioPlayMemory          playMem2;       //xy=161,281
AudioPlayMemory          playMem1;       //xy=166,196
AudioPlaySdWav           playSdWav1;     //xy=168,124
AudioPlayQueue           queue1;         //xy=196,368
AudioPlaySdWav           playSdWav2;     //xy=210,420
AudioMixer4              mixer2;         //xy=300,287
AudioEffectGranular      granular1;      //xy=349,489
AudioMixer4              mixer1;         //xy=525,362
AudioOutputI2S2          i2s1;           //xy=767,362
AudioConnection          patchCord1(playMem2, 0, mixer2, 1);
AudioConnection          patchCord2(playMem1, 0, mixer2, 0);
AudioConnection          patchCord3(playSdWav1, 0, mixer1, 0);
AudioConnection          patchCord4(queue1, 0, mixer1, 2);
AudioConnection          patchCord5(playSdWav2, 0, granular1, 0);
AudioConnection          patchCord6(mixer2, 0, mixer1, 1);
AudioConnection          patchCord7(granular1, 0, mixer1, 3);
AudioConnection          patchCord8(mixer1, 0, i2s1, 0);
 
Could you show your SdFat initialization code? I know you said "SdFat library SDIO" but I'm wondering if you're using SDIO mode or DMA mode.

Also, could you please show your LCD init code?

It seems like there could be some weird interaction going on between all the different libraries using DMA. Anecdotally, I have experienced strange things when using LCD, Audio, and SdFat on the 4.0 as well.
 
Last edited:
Anecdotally, I have experienced strange things when using LCD, Audio, and SdFat on the 4.0 as well.
Thanks for the moral support, I needed it :) After more digging, and hacking down my code into as simple a sketch I can get to recreate the issue with minimal variables, I did notice that my first use of SPI.Transfer(buff, buffSize) to update the TFT also caused the memory issue to occur. To your question, I am using SdioConfig(FIFO_SDIO) to initialize the SD card via SdFat-beta. Now this is where I started getting dangerous (desperation) and doing things I had no idea what they really did or the broader consequences, but in browsing the source play_sd_wav.cpp, I noticed calls to AudioStopUsingSPI and AudioStartUsingSPI in the play and stop functions, so I recklessly got my // out, rendered them useless without any idea of the consequences of what I'm doing, recompiled......and now everything is working fine, I'm starting/stopping wavs from the SD card via PlaySdWav without issue, and SPI streaming 30+fps video from the SDIO SD card to a 320x240 TFT whilst hearing beautiful non stuttering I2S audio streamed via an AudioPlayQueue from that video :)

I don't often like to shoot first and ask questions later, but at least now I have a big clue into what is wrong and can work backwards from here....
 
Hmm, that's encouraging actually. I had a thread with a very similar configuration and problem, but I moved onto other things before figuring it out.
 
Status
Not open for further replies.
Back
Top