Changing DC level freezes Teensy

Status
Not open for further replies.

i2sflew

Active member
Hi,

I'm trying to control the shape of the modulated waveforms by using a DC block connected to the second input and changing the amplitude values on the fly, by serial commands. However using the amplitude function freezes the Teensy, both with and without a time period in which it changes. Do I have to stop the waveforms from playing while changing the DC value?
Here is some of my code:

initializing the struct for my objects:
Code:
void initSynthObjects(void)
{
    synth_objects.pwm1 = &shape1;
    synth_objects.pwm2 = &shape2;
    synth_objects.amp_lfo = &lfo_amp;
    synth_objects.phase_lfo1 = &lfo_phase1;
    synth_objects.phase_lfo2 = &lfo_phase2;
}

This is the call to the function with osc1_pwm being a float. I also tried this with a fixed value of 0.2, which also freezes the Teensy
Code:
synth_objects.pwm1->amplitude(osc1_pwm, 250.0f);
 
First, to answer your question...

Do I have to stop the waveforms from playing while changing the DC value?

No, that is not supposed to be necessary.


Here is some of my code:

I don't see anything specifically wrong in this tiny code fragment.

It's possible you've found a previously unknown bug in the library. Or if could be a mistake or misunderstanding in your code. I have no idea which. I hope you can understand I don't investigate these sorts of issues unless a complete program I can copy into Arduino and run on a Teensy to reproduce the problem is posted.
 
Sure I could give you the complete code, althoug still very bare and unfinished. How would I upload the files?
 
View attachment msgHandler.cppView attachment sketch_dec16a.cppView attachment synthesizer.cppView attachment voices.cppView attachment audioObjects.hView attachment msgHandler.hView attachment pitches.hView attachment synth_vars.hView attachment synthesizer.h

For some reason it would not let me upload voices.hpp so here are the contents of that:
Code:
#ifndef VOICES_HPP
#define VOICES_HPP

#include <Audio.h>

#define NUM_VOICES  12

typedef struct
{
	uint8_t state;

    AudioSynthWaveformModulated* osc1;
	AudioSynthWaveformModulated* osc2;

    AudioMixer4* mixer;
    AudioEffectEnvelope* env;

    uint8_t pitch_no;
}voice_t;

typedef struct
{
    AudioSynthWaveformDc* pwm1;
    AudioSynthWaveformDc* pwm2;
    AudioSynthWaveform* phase_lfo1;
    AudioSynthWaveform* phase_lfo2;
    AudioSynthWaveform* amp_lfo;
    //extend with effects
}synth_objects_t;

extern voice_t voices[NUM_VOICES];

extern synth_objects_t synth_objects;

extern int16_t arbitrary_waveform[256];

void initVoices(void);

void startVoice(voice_t* vc, uint8_t voice_no);

void stopVoice(voice_t* vc);

#endif

Opening a Terminal with 921600 baud and sending the following bytes should jump to the correct switch-case in which the dc value is to be changed:
FF, 02, 15, 00 or FF, 02, 25, 00
For Oscillator1 and 2 respectively, with the last byte being a value from 0 to 100.

The reason I am thinking it has to do with the DC block, is that once the amplitude-function call is commented out, the switch case works fine and the Teensy continues working. Uncommented causes it to freeze.
 
Could it be that some objects aren't meant to have too many outputs? Right now I am having the same problem when trying to change my LFO frequency, which is used for frequency modulation of the main oscillators.
To confuse everyone a little bit more, here is my setup of all blocks:
audioObjects.PNG
Seems like if one object connects to too many inputs, there are problems
 
Could it be that some objects aren't meant to have too many outputs?

No. That's not how it works. Each object has no way to know how many others are receiving its output. It does exactly the same work regardless of whether 1 or 100 other objects will use its output data.


Seems like if one object connects to too many inputs, there are problems

Try increasing your AudioMemory allocation.

The connections are implemented using shared copy-on-write buffers. So if you transmit an output to 100 inputs, and all 100 of them do not modify the data, then they all read from the same buffer the output wrote. But if 95 of them modify the data, then 95 copies of the buffer are made, drawing upon the pool of buffers you allocated with AudioMemory(), and the 5 which don't change anything read the original buffer.

If the audio library needs to make 95 copies of you data and there aren't 95 buffers available, then it uses up all the memory it can and the rest of those objects get nothing at their inputs. And if the last one to get an input needs to allocate memory to do its work, it gets nothing and probably gives no output. Generally, when memory runs out, you get difficult-to-predict audio dropouts from various places in your audio system.

The library has memory usage functions to help you. Details here:

https://www.pjrc.com/teensy/td_libs_AudioConnection.html

The most useful is AudioMemoryUsageMax(), which tells you the most buffers which have ever been in use at the same moment. Increase AudioMemory() until it is equal to or slightly more than the largest number you ever see from AudioMemoryUsageMax().

But don't go crazy with extra memory you don't need. Don't fall into the trap of believing extra memory helps. It does not work like a cache where more memory improves performance. Anything beyond the largest AudioMemoryUsageMax number just sits unused.
 
Yeah, the assumption that more memory would help is what I had earlier. In the uploaded code I upped the memory as well to very high levels in the hopes to get things working again.
Using AudioMemoryUsageMax() gives me a steady reading of 49, which is less, than my number of blocks, but doesn't increase even with all envelopes started, so it should be alright. After reading this I tried it with 52, but still no luck.
I tried to alter the frequency of the amp_lfo, which has no connection to the modulated waveform blocks, and this also causes the Teensy to freeze.
I also noticed, that the Teensy does not seem to freeze completely. When I press a key while changing any of the settings, that are faulty. I get something like a square signal on the i2s line, so there is still something being pushed out, hust not the correct signal. I also can't send any other command via USB, it just breaks my Terminal.
Seems more like an infinite loop being entered?
 
You're running with a lot of audio objects. Might you be running out of CPU?

Which teensy are you using? And, when you asked what the memory usage was, did you also ask what the CPU usage was?
 
I'm using a Teensy 4.0. CPU load seems to be ok, and it seems to be tied with the signal amplitude as well? When I am playing sounds with lower amplitude it shows a load of about 3 %, when using the full amplitude it shows about 5-6 %.
 
I reduced the setup to the following, to reduce the likelihood of it being a lack of resources:
audioObjects.PNG

The problem still persists. I have no idea what could be causing this, since I can alter the parameters of my main oscillator blocks just fine, even with all 12 voices. Only the DC blocks and the waveforms are problematic.
 
Using AudioMemoryUsageMax() gives me a steady reading of 49, which is less, than my number of blocks

Yes, it's normal to use very little memory when all your blocks are lined up in a left to right manner (the instances are created in Arduino in the order they process your audio).

Most effects allocate nothing, they just change the data and pass it along. Mixers take multiple blocks in and return all but 1 to the free memory pool. Pure oscillators allocate 1 block. But modulated oscillators receive 2 blocks, allocate 1, then return both the inputs to the free memory pool, for a net allocation of -1 blocks. Connections to objects which don't write to the input just reuse the same data without any extra allocation. Connections to many effects need to duplicate blocks, which is probably where most of your 49 block usage is happening.

Why it's crashing is a mystery. I'll try to take a look this afternoon. If you can reproduce the crash with smaller code, that'll save me some time and improve the odds I'll manage to get the bottom of what's going wrong.
 
Thanks in advance.

Easiest way to induce the behaviour is setting a Terminal to 921600 and sending 0xFF 0x03 0x15 0x00 0x00. This should freeze the Teensy and in the case of hterm cause the terminal to stop responding.
Sending other commands such as 0xFF 0x03 0x11 0x00 0x00 will give you a response.

View attachment 201217-190117-teensy40.zip
 
Ok, I looked through this code and found the problem. You're not calling initSynthObjects(), so synth_objects.pwm1 never gets initialized. But then in updateOscillatorPWM(), you're depending on it being a valid pointer.

Code:
        synth_objects.pwm1->amplitude(0.2f, 250.0f);

Just adding a call to initSynthObjects() from setup() cures the crashing problem.


As a double check, you can try adding this at the end of setup()


Code:
  while (!Serial) ; // wait for arduino serial monitor
  Serial.printf("synth_objects.pwm1 = %08X\n", (int)(synth_objects.pwm1));

If it prints 00000000, that's a sure sign your program will crash when you try to actually use pwm1 in any way.

If it prints something like 20002A84, your program will (probably) work. :)
 
Oh, how stupid! Sorry for thinking this was a problem with the library, and thank you for fixing my code!
 
Status
Not open for further replies.
Back
Top