Teensy 4.0 audioEffectDelay - incorrect maximum limit?

JeppeRas

Member
Hi friends!

I'm using a Teensy 4.0 with the audio adapter for a new instrument, and as part of the project I've incorporated an audioEffectDelay object.
It works great, but I'm having a problem getting the stated 4 seconds of delay time out of it.
This is the section in delay.h which talks about limits:
Code:
#if defined(__IMXRT1062__)
  // 4.00 second maximum on Teensy 4.0
  #define DELAY_QUEUE_SIZE  (176512 / AUDIO_BLOCK_SAMPLES)
#elif defined(__MK66FX1M0__)
  // 2.41 second maximum on Teensy 3.6
  #define DELAY_QUEUE_SIZE  (106496 / AUDIO_BLOCK_SAMPLES)
#elif defined(__MK64FX512__)
  // 1.67 second maximum on Teensy 3.5
  #define DELAY_QUEUE_SIZE  (73728 / AUDIO_BLOCK_SAMPLES)
#elif defined(__MK20DX256__)
  // 0.45 second maximum on Teensy 3.1 & 3.2
  #define DELAY_QUEUE_SIZE  (19826 / AUDIO_BLOCK_SAMPLES)
#else
  // 0.14 second maximum on Teensy 3.0
  #define DELAY_QUEUE_SIZE  (6144 / AUDIO_BLOCK_SAMPLES)
#endif

As far as I can tell, these numbers check out, and should let the T4 do 4 seconds of delay. However, I run into a limit at about 2.4 seconds.
This simple code example demonstrates the issue, by running a simple drum through a delay object, and having a potentiometer connected on pin 15 to change the delay time:

Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

#include <synth_simple_drum.h>

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <ResponsiveAnalogRead.h>

ResponsiveAnalogRead timeKnob(15, true);

// GUItool: begin automatically generated code
AudioSynthSimpleDrum     drum;
AudioEffectDelay         delay1;
AudioMixer4              mixer;
AudioOutputI2S           i2s1;

AudioConnection          patchCord1(drum, 0, mixer, 0);
AudioConnection          patchCord2(drum, 0, delay1, 0);
AudioConnection          patchCord3(delay1, 0, mixer, 1);
AudioConnection          patchCord4(mixer, 0, i2s1, 0);
AudioConnection          patchCord5(mixer, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;
// GUItool: end automatically generated code

static uint32_t next;
int16_t delayTime = 1000;

void setup() {

  Serial.begin(115200);

  // audio library init
  AudioMemory(1500);

  next = millis() + 1000;

  AudioNoInterrupts();

  drum.frequency(60);
  drum.length(300);
  drum.secondMix(0.0);
  drum.pitchMod(1.0);

  mixer.gain(0, 0.5);
  mixer.gain(1, 0.5);

  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5);

  delay1.delay(0, delayTime);

  AudioInterrupts();

}

void loop() {
  timeKnob.update();

  if(timeKnob.hasChanged()){
    int tempVal = timeKnob.getValue();
    delayTime = map(tempVal, 0, 1023, 100, 4000);
    delay1.delay(0, delayTime);
  }
  if(millis() == next){
    next = millis() + 1000;
    drum.noteOn();
  }

  Serial.print("Diagnostics: ");
  Serial.print(AudioMemoryUsage());
  Serial.print(" ");
  Serial.println(AudioMemoryUsageMax());
}

When running this code, the audioMemoryUsageMax, as shown in the serial monitor tops out at 896 blocks, which is about 2.4 seconds.
I've tried different values for audioMemory, but that doesn't change this limit.

Digging into the forum a bit to figure this out, I found a thread from 2019 where Paul talks about updating the limits for T4. Here's the thread: https://forum.pjrc.com/threads/58295-Maximum-delay-for-Teensy-4-0
But when I look at the github commit he mentions (in post#3), I can see that the T4 limit is updated to the same value as the T3.6: https://github.com/PaulStoffregen/Audio/commit/9712139aedde94989218b7dccfe3e114ce763a15
In the latest version of the library it's higher for the T4, so it was obviously changed again at a later date.
He also mentions that you can change the limit to whatever you want in delay.cpp, but I don't see how that's possible, as it just calls the DELAY_QUEUE_SIZE from delay.h, and those limits don't seem to respected anyway.

But to thicken the plot even further, I found this thread from 2017, where Paul specifically mentions (in post#6) setting a limit for the T3.6 at 896 blocks, exactly the number that I get in my tests..... : https://forum.pjrc.com/threads/45053-Problems-with-AudioEffectDelay-Teensy3-2-vs-Teensy3-6
Is it possible that there is a hard limit still hiding somewhere in the library, that's keeping the Teensy 4.0 from reaching its full awesome delay potential?

I'm probably missing some very obvious detail, which is usually the case, so thanks in advance for any guidance or helpful suggestions.
Jeppe
 
Oh....
I just found this in cores/teensy4/AudioStream.cpp:

Code:
#if defined(__IMXRT1062__)
  #define MAX_AUDIO_MEMORY 229376
#endif

#define NUM_MASKS  (((MAX_AUDIO_MEMORY / AUDIO_BLOCK_SAMPLES / 2) + 31) / 32)

"MAX_AUDIO_MEMORY 229376" for the T4 seems to be the same as for the T3.6, which I found in cores/teensy3/AudioStream.cpp:

Code:
#if defined(__MKL26Z64__)
  #define MAX_AUDIO_MEMORY 6144
#elif defined(__MK20DX128__)
  #define MAX_AUDIO_MEMORY 12288
#elif defined(__MK20DX256__)
  #define MAX_AUDIO_MEMORY 49152
#elif defined(__MK64FX512__)
  #define MAX_AUDIO_MEMORY 163840
#elif defined(__MK66FX1M0__)
  #define MAX_AUDIO_MEMORY 229376
#endif

I'm going to have a go at bumping up this value.
I'll let you know if anything blows up.
 
Last edited:
Yes, the T4.x and the T3.6 use the same amount of audio memory: 229376 bytes

Not sure if it helps to increase this number for T4.0 as it needs RAM for program.

IMO, for longer delays you would need a T4.1 with 16 MB of SRAM and changes to delay allowing use of EXTMEM
 
Yes, the T4.x and the T3.6 use the same amount of audio memory: 229376 bytes

Not sure if it helps to increase this number for T4.0 as it needs RAM for program.

IMO, for longer delays you would need a T4.1 with 16 MB of SRAM and changes to delay allowing use of EXTMEM

Turns out that it DOES work. You don't need a T4.1.
I cranked the "MAX_AUDIO_MEMORY" up to 360000 in AudioStream.cpp:
Code:
#if defined(__IMXRT1062__)
  #define MAX_AUDIO_MEMORY 360000 //229376
#endif
And now I have a perfect 4000 ms of delay.
I had to increase the AudioMemory in my sketch. AudioMemoryUsageMax() shows 1384, so it's now set to 1400. This pretty much maxes out the memory of my T4 anyway, with the sketch having tons of samples and stuff. Time and testing will tell if I've caused any other problems by doing this. If that's the case, I'll be back here to report.

Hope this helps someone else with the same problem.
Cheers,
Jeppe
 
For longer delays you would need a T4.1 with 16 MB of SRAM and changes to delay allowing use of EXTMEM
...such as my modified AudioEffectDelayExternal which can be found in my repo, or languishing as PR#433 in Paul's. This not only allows PSRAM, but heap memory, so if your application doesn't use much heap you could get nearly 6s of delay time.

EDIT: for a T4.0 you could put a PSRAM on the audio adaptor, but it's way slower than EXTMEM on the T4.1. You can still use the heap option on a T4.0
 
Turns out that it DOES work. You don't need a T4.1.
I cranked the "MAX_AUDIO_MEMORY" up to 360000 in AudioStream.cpp:
Code:
#if defined(__IMXRT1062__)
  #define MAX_AUDIO_MEMORY 360000 //229376
#endif
And now I have a perfect 4000 ms of delay.
I had to increase the AudioMemory in my sketch. AudioMemoryUsageMax() shows 1384, so it's now set to 1400. This pretty much maxes out the memory of my T4 anyway, with the sketch having tons of samples and stuff. Time and testing will tell if I've caused any other problems by doing this. If that's the case, I'll be back here to report.

Hope this helps someone else with the same problem.
Cheers,
Jeppe
Thanks very much for this. I ran into the same problem about a week ago on a T4.1 where I assumed I could get a stereo delay time of 2 seconds, but could only make it work up to about 1.2 sec until I changed the AudioStream.cpp define value for MAX_AUDIO_MEMORY as you suggested.

As long as you keep an eye on your total RAM2 usage I don't see a reason for the lower limit in AudioStream.cpp. Is it an oversight, or is it intentional? If the latter, there should probably be a warning in the delay code where a comment says it allows 4 sec max for T4.

Other members have suggested using external ram to get longer sampling times, but 4 seconds is probably sufficient for many applications, and I assume (perhaps wrongly?) that using external memory within the context of the DMA based audio library would be slower/less efficient than using RAM2.
 
Last edited:
Back
Top