Memory issue with AudioLibrary Teensyduino since 1.52-1.54b

Status
Not open for further replies.
Hi there! I already tried explaining my issue some time ago when the beta for Teensyduino 1.52 came out, but failed to give a reproducible scenario, which I hope I'm doing now:

My current setup is a Teensy 4.1 with WM8731 as master(44.1khz) BUT initially the issue was spotted with an Teensy 4.0 with the official audioboard. I'm using FAUST to generate an Audio Library object, which gives two outputs: a 1-sample impulse with a period of 10E4 samples and the same impulse going through a 16^2 sample delay on the other channel. That's what the FAUST code looks like:

Code:
DT = 2^16;
process = ba.pulsen(1, 100000) <: _, de.delay(DT-1,DT);

The size of all buffers (in the generated .cpp file) is therefore 262'176 bytes, which makes sense, as the delay is 2^16 samples * 32bit, which should be 262’144 bytes. Perfect. As soon as I add 1 sample to the delay time (DT = (2^16) + 1), the summed buffer size jumps to around 524kB - which is to be expected, as the delay buffer works around bit masking, so 1 added sample doubles the buffer size. But please bear with me:

FAUST has a compilation option to switch from the bit masking to a wrapping index mode for buffers. This reduces the memory footprint in this case enormously, as the buffer doesn't double in size! So to speak in numbers, the size of the optimized buffers is now 262'184 bytes. Following to my problem:

This worked FLAWLESS before Teensyduino 1.52. I had also other FAUST generated Audio Library objects, which worked with multiple buffers and as long as I kept the size of all summed buffer under around 490kB (which is not too far away from the 512kB free space for DMAMEM variables in RAM2) everything was running fine!

Same code compiled with Teensyduino 1.52 suddenly started bricking the teensy. Was there a new way introduced of generating the buffers from the Audio Library or what happened?

I attached following files in View attachment pulseDelay.zip:
- .dsp Faust Code with 2^16 delay
- generated Audio Library compatible .cpp & .h WORKING with 2^16 delay
- generated Audio Library compatible .cpp & .h NON-WORKING with 2^16+1 delay (optimized version)
- .ino file


If there is anything else I missed to include or explain please tell me, I want to resolve this issue and appreciate every little clue!

Thanks a lot and all the best
 
new insights

Well it seems what I thought was the problem in the first post turned out to be wrong, so please ignore the attached code from the first post!

However at least it led to a minor fix in the faust2teensy script, where compiler options were ignored. Additionally, with the help from one of the Faust developers I managed using FAUST generated audio objects with the new EXTMEM attribute on the Teensy 4.1 :D

Now to my actual problem. Even though generating audio inside a FAUST compiled object is working perfectly fine, processing incoming sound isn't. Absolutely reduced and simple scenario: ADC→FAUST→DAC where the FAUST object only feeds through 2 channels of audio. While

Code:
AudioInputI2Sslave i2sIN;    // Audio Input from WM8731 in master
test faustObj;               // FAUST generated audio object with 2in/2out
AudioOutputI2Sslave i2sOUT;  // Audio Output from WM8731 in master
with
Code:
AudioConnection patchCord1(i2sIN, 0, i2sOUT, 0); // connect ADC1 to DAC1
AudioConnection patchCord2(i2sIN, 1, i2sOUT, 1); // connect ADC2 to DAC2
works flawlessly, it crashes my teensy (and even starts periodically freezing my macbook for 0.5s if I don’t reset the teensy or unplug the usb cable) with following AudioConnections
Code:
AudioConnection patchCord1(i2sIN, 0, faustObj, 0);  // connect ADC1 to FAUST IN1
AudioConnection patchCord2(i2sIN, 1, faustObj, 1);  // connect ADC2 to FAUST IN2
AudioConnection patchCord3(faustObj, 0, i2sOUT, 0); // connect DAC1 to FAUST OUT1
AudioConnection patchCord4(faustObj, 1, i2sOUT, 1); // connect DAC2 to FAUST OUT2
the reason why I thought this was connected to a memory issue, was because the side effects were exactly the same (teensy freezing).
As for the audio library and core files I'm using the newest ones from github. I attached the .cpp and .h file of the audio object. Allmost all the code above line 7890 can be ignored but gets interesting after line 8043 where the DSP process gets initialised/allocated.

I tried comparing the part from line 8117
Code:
    if (INPUTS > 0) {
        audio_block_t* inBlock[INPUTS];
        for (int channel = 0; channel < INPUTS; channel++) {
            inBlock[channel] = receiveReadOnly(channel);
            for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
                int32_t val = inBlock[channel]->data[i] << 16;
                fInChannel[channel][i] = val*DIV_16;
            }
            release(inBlock[channel]);
        }
    }
with other teensy audio objects, but I can't figure out what could be wrong, as everything seems to make sense. Commenting this section leaves the teensy "alive" when uploaded, but obviously not processing any incoming sound.

ANY HELP would be enormously appreciated, as I think this would be an awesome platform if just everything worked. Like I wrote in my last post, audio processing used to work as I had it running with the Teensy 4 and the audioboard, but with the Teensy 4.1 I cant use the older Teensyduino anymore and comparing some library files didn't really help.
 

Attachments

  • test.cpp
    273.2 KB · Views: 1,219
  • test.h
    1.9 KB · Views: 66
This might be a possible cause:
Incoming blocks can be NULL, you should deal with this gracefully. Especially at start up before there's any AudioMemory allocated,
then there are no blocks at all.

I'd suggest:
Code:
    if (INPUTS > 0) {
        audio_block_t* inBlock[INPUTS];
        for (int channel = 0; channel < INPUTS; channel++) {
            inBlock[channel] = receiveReadOnly(channel);
            if (inBlock[channel] == NULL)
                continue ;
            for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
                int32_t val = inBlock[channel]->data[i] << 16;
                fInChannel[channel][i] = val*DIV_16;
            }
            release(inBlock[channel]);
        }
    }
Although more properly you'd treat NULL as equivalent to an all-zero block.
 
HOLY GUACAMOLE! I already tried to achieve that using the method used in effect_freeverb.cpp, but as that didn't help I removed it again. But somehow your simple solution made it work, I can't believe it! I'll investigate further if that really solved all problems, but AFAICT IT WORKS!!!
 
This might be a possible cause:
Incoming blocks can be NULL, you should deal with this gracefully. Especially at start up before there's any AudioMemory allocated,
then there are no blocks at all.

I'd suggest:
Code:
    if (INPUTS > 0) {
        audio_block_t* inBlock[INPUTS];
        for (int channel = 0; channel < INPUTS; channel++) {
            inBlock[channel] = receiveReadOnly(channel);
            if (inBlock[channel] == NULL)
                continue ;
            for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
                int32_t val = inBlock[channel]->data[i] << 16;
                fInChannel[channel][i] = val*DIV_16;
            }
            release(inBlock[channel]);
        }
    }
Although more properly you'd treat NULL as equivalent to an all-zero block.
Thanks so much for this, I was having the same problem as MovingAverage after moving from Teensy 4.0 to 4.1.
 
Well it seems what I thought was the problem in the first post turned out to be wrong, so please ignore the attached code from the first post!

However at least it led to a minor fix in the faust2teensy script, where compiler options were ignored. Additionally, with the help from one of the Faust developers I managed using FAUST generated audio objects with the new EXTMEM attribute on the Teensy 4.1 :D

Hey, could you share the code to use EXTMEM with FAUST objects? Thanks
 
Hey, could you share the code to use EXTMEM with FAUST objects? Thanks

you can check my fork of FAUST, especially my last commit f84a55c. It adds a new option to the FAUST compiler wether or not it should use the external PSRAM. Keep in mind that this is not a very efficient solution, but at least it works :) Are you on the FAUST slack btw? I'd recommend you joining it, so we can keep in touch and discuss teensy/faust related stuff!
 
Status
Not open for further replies.
Back
Top