Changing effects at run time

Status
Not open for further replies.

Andy Belov

Well-known member
I'm making a guitar effect thingy based on Teensy 4 and I want the user to be able to select one or more effects and their sequence of processing.
I know some effects have a pass through mode and it's easy to add one to those which don't.

I know that AudioConnection takes src and dst in the constructor and then calls connect and disconnect on them.
I wonder if I can override the connect() to take a new src and dst, thus dynamically re-connecting things. I'll just call a disconnect() in the new connect(str, dst).

Did anybody try that yet?
 
There is no need to modify connect() in Audiostream if you do the following:

Instantiate all possible AudioConnections needed in the project(in the global scope, as usual). Multiple sources to one destination is ok.
In Setup() disconnect all AudioConnections except the ones that will never change, before enabling the audio engine.
In loop() connect and disconnect all you want while still following the connection rules & guidelines.

example:
Code:
#include <Audio.h>

AudioSynthWaveformSine   sine4;
AudioSynthWaveformSine   sine1;
AudioSynthWaveformSine   sine2;
AudioSynthWaveformSine   sine3;
AudioMixer4              mixer1;
AudioMixer4              mixer2;
AudioOutputI2S           i2s1;
// AudioOutputAnalogStereo  dacs1;

AudioConnection          patchCord1(sine1, 0, mixer1, 0);
AudioConnection          patchCord2(sine2, 0, mixer1, 0);
AudioConnection          patchCord3(sine3, 0, mixer1, 0);
AudioConnection          patchCord4(sine4, 0, mixer1, 0);
AudioConnection          patchCord5(sine4, 0, mixer2, 0);

AudioConnection          patchCord50(mixer1, 0, i2s1, 0);
AudioConnection          patchCord51(mixer2, 0, i2s1, 1);
// AudioConnection          patchCord52(mixer1, 0, dacs1, 0);
// AudioConnection          patchCord53(mixer2, 0, dacs1, 1);

AudioControlSGTL5000     sgtl5000_1;

void setup() {
  
  patchCord1.disconnect();
  patchCord2.disconnect();
  patchCord3.disconnect();
  patchCord4.disconnect();
  patchCord5.disconnect();
  
  AudioMemory(10);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5);

  sine1.frequency(500);
  sine1.amplitude(1.0);
  sine2.frequency(1000);
  sine2.amplitude(1.0);
  sine3.frequency(1500);
  sine3.amplitude(1.0);
  sine4.frequency(2000);
  sine4.amplitude(1.0);

}

const uint t = 1250; 
void loop() {

  patchCord1.connect();
  delay(t);
  patchCord1.disconnect();
  patchCord5.disconnect();
  patchCord2.connect();
  delay(t);
  patchCord2.disconnect();
  patchCord3.connect();
  delay(t);
  patchCord3.disconnect();
  patchCord4.connect();
  patchCord5.connect();
  delay(t);
  patchCord4.disconnect();

 }
 
Instantiate all possible AudioConnections needed

Thanks, @neurofun.

This is what I'm doing now. I wanted to let the users to arrange the effects in any sequence they want, so the number of all possible connections would be in a couple of hundreds.

I think this would be a good enhancement for the Audio Library with a minimal effort.
 
I never thought about the need for "a couple of hundreds" of connections.
I think this would be a good enhancement for the Audio Library with a minimal effort.
I totally agree!
Please post your findings, I'll be glad to help testing.
 
I already submitted the enhancement request.
I think the static links cripple such a unique and powerful audio library that we have here.

I was waiting for something like this for years, while working on my electronic musical instrument. Intel Edison came close on the power side, but no audio of any kind.

I'm getting very close on finishing my first pre-production PCB. This thing will be like nothing before, for it's size, computing power and the sound quality.
I'm so glad that Paul was focusing on the good sound quality from the start.

I think I'll wait and see if the library gets fixed soon. If not, I'll do it. It's just a pain to keep my own modified copy of it and update it each time.
 
When I ported the Audio Library to be floating point (for Teensy 3.6), I also added some classes to help with dynamic switching. Our library is under the name "Tympan" and is developed to work with our audio hardware that is based on the Teensy 3.6, but you use a regular Teensy 3.x with any audio hardware.

The library: https://github.com/Tympan/Tympan_Library

For switching, see AudioSwitch4_F32, which let's you choose to send one audio input stream to any of four audio output streams. You should think of each audio output stream as one of the multiple audio processing chains that you'd like to switch between at runtime. The AudioSwitch lets you switch between the different processing chains with one command (rather than making and breaking all of the individual connections).

With this switch, audio will only be sent to the one output that you care to use and so only that one processing chain will be invoked. The rest of the outputs (the rest of the audio chains) will never receive any data, so they will never be invoked, so they will not cost any CPU.

While the system is running, you can dynamically command AudioSwitch to change which of its outputs are used. This gives you the dynamic switching that you want.

At the end of your audio chains, bring them all back together by using an AudioMixer4_F32 (or AudioSummer4_F32). Again, because of the AudioSwitch, the unused processing chains create no audio, so the AudioMixer (or AudioSummer) is just giving you the one audio stream that you want, not all four.

Chip
 
Thanks, Chip.

I see what you do there and it sounds good.
Still, I want to stay with the 'standard teensyduino'. Too many things to manage for now.
So much easier to ask someone else to do it (he-he)
 
Someone on another thread just mentioned that I can create dynamic object for the connections.

I always was thinking of Arduino as "build and run" concept. Make a bunch of objects in setup() and gently pad them in the loop().
Never occurred to me to try do "new" and "delete". Hmmm...

Most of the Audio objects didn't even compile if I didn't put them as global instances and not class members.
I guess it's a trial game.

Will experiment soon, after I'm done playing with my new PCB's I got today.
 
Calling new and delete dynamically will destroy your heap, not recommended for microcontrollers, be careful :)
 
Unlikely if your memory manager isn't horrible, but if you want to be particular about it, it's left as an exercise to the reader to do it without the heap :p
 
Status
Not open for further replies.
Back
Top