Adding and removing AudioStream and AudioConnections during program execution

Status
Not open for further replies.
Hi, I'm using a Teensy to make a little multi effects unit. In this I'm planning to have "modes", where each mode is basically a set of effects / mixers etc with connections between them. A couple of buttons will allow selecting a different mode during program execution. No need for two modes to run at the same time, however a mode will obviously contain multiple AudioStream and AudioConnection objects. It'd be cool to choose a Chorus effect and then flick over to a Low Pass Filter etc. all in one little box.

Now there are two ways I can think of making something like this work.
  1. Create necessary AudioStream and AudioConnection objects when changing to a new mode. This requires the ability to remove those objects later when a different mode is selected. Also need to allocate objects on the heap, I've never seen examples do this but it seems to work. Not sure how it affects performance.
  2. Create all AudioStream and AudioConnection objects and set up a mechanism to allow most presets to be bypassed at any given time. This seems wasteful (not sure if it actually is), and given the amount of modes I want to potentially use (hopefully 10-20!) I'm not sure if it's a suitable option. I don't know just how much memory or processor usage these objects take up if they are bypassed, or even if there is a mechanism to toggle an AudioStream object to be bypassed or not.

So right now I'm aiming for option 1. Any ideas if that's possible? So far I've thought of a couple of things:
 
Last edited:
Dynamically creating connections and audio objects at runtime might work, but destroying them at runtime is almost certain to crash. If you want to dig into the very lowest level of the library to add this functionality (and do it well/efficiently), it'd certainly be a welcome contribution to the library. But this is certainly the long and difficult path to take.

Create all AudioStream and AudioConnection objects and set up a mechanism to allow most presets to be bypassed at any given time. This seems wasteful (not sure if it actually is)

It might be wasteful, or it might not, depending on how you implement it.

The library provides functions you can use to observe the CPU usage. You should experiment and use these to guide your efforts. They will give you much better insight than guesswork.

http://www.pjrc.com/teensy/td_libs_AudioProcessorUsage.html

Many of the objects, like the mixers, have code to recognize certain settings like gain == 0, where they skip doing the work and they avoid sending data, which also saves CPU time on whatever other objects are connected.

My main advice is "don't sweat the small stuff". Really, it's easy to spend spend a ton of your time chasing after minor details that consume less than 1% of the CPU time if you base your opinions on reading the source code. Use the CPU usage measurements!
 
Awesome thanks for the advice. Depends how low level I'd have to go on option 1, may be out of my depth on that one! I'll take a look at option 2 as a start point instead if it's going to be a little easier.

Just to confirm, there's no kind of standardised bypass toggle on the AudioStream base class is there? Looks like most effects have a non-standard setting of their own that can set the signal to pass through which should do the trick. Actually that makes sense when you have things like delay lines that might still need to think while being bypassed.

I can think of a few topologies that could turn certain chains of effects on and off. Probably the simplest design would be to connect the input to every chain of effects, and having a bunch of mixers at the end to let a single chain's signal through to the output, depending on the mode chosen. At least to get something working.

When you say "avoid sending data", do you mean that AudioStream objects have the option to just not bother calling transmit()**? Does that mean that the next effect in the chain won't have anything to process and will just skip doing any work? If that's the case then maybe having a mixer or some object that chooses not to pass on audio blocks could be placed at the start of every effects chain to turn each chain off.

**EDIT: just found that the fade effect does this when completely faded, definitely trying this way of doing it.

I'll definitely use the CPU measurements, I'll be completely loading this thing up with many effects combinations!
 
Last edited:
Just to confirm, there's no kind of standardised bypass toggle on the AudioStream base class is there?

There are several ways to read this question....

Today, the AudioStream base class does not provide any API meant to be accessed from Arduino sketches. It is meant only to provide the lower-level functionality needed by the audio objects. In other words, its functions are meant to be used only from within the audio objects in the library, not from Arduino.

When you say "avoid sending data", do you mean that AudioStream objects have the option to just not bother calling transmit()**? Does that mean that the next effect in the chain won't have anything to process and will just skip doing any work? If that's the case then maybe having a mixer or some object that chooses not to pass on audio blocks could be placed at the start of every effects chain to turn each chain off.

Yes, exactly.

I'll definitely use the CPU measurements, I'll be completely loading this thing up with many effects combinations!

Indeed, the CPU measurements exist because it's so very easy to get caught up in minor details that consume less than 1% when you just look at source code... and miss the heavy usage that really matters.
 
Status
Not open for further replies.
Back
Top