Skip to content

Interactive Audio

Phil Schatzmann edited this page Mar 25, 2024 · 35 revisions

It is quite easy to build some simple interactive audio. In the next example I will use a sine generator as audio source together with some buttons. When the button is pressed you should get some audio, when it is released the tone should stop. You can write your own button control, but to make things easy, I have added the AudioActions class.

The Objects

We define the global objects.

#include "AudioTools.h"

I2SStream i2s;
SineWaveGenerator<int16_t> sine;
GeneratedSoundStream<int16_t> in(sine); 
StreamCopy copier(i2s, in); 
AudioActions action;

Nothing fancy so far: we just copy the sine tone to the I2S output. The AudioActions is the new thing here. Check out the documentation: it is possible to add only one action method instead of two.

The Actions

We want to play a tone when we press a key and stop when we release it. So we define a separate method for each. Please note that the method have the active, the pin number and some additional information as parameters:

void actionKeyOn(bool active, int pin, void* ptr){
  int freq = *((float*)ptr);
  sine.setFrequency(freq);
  in.begin();
}

void actionKeyOff(bool active, int pin, void* ptr){
  in.end();
}

On the Key On action, we just define the frequency and start the sound stream. To stop the output of sound we just call end

Setting up the Actions

Next we define the actions that should be executed for each pin: as additional parameter we just provide a pointer to a frequency value.

// We want to play some notes on the Audioi2s keys 
void setupActions(){
  // assign buttons to notes
  auto act_low = AudioActions::ActiveLow;
  static float note[] = {N_C3, N_D3, N_E3, N_F3, N_G3, N_A3}; // frequencies
  action.add(6, actionKeyOn, actionKeyOff, ActiveLow, &(note[0])); // C3
  action.add(7, actionKeyOn, actionKeyOff, ActiveLow, &(note[1])); // D3
  action.add(8, actionKeyOn, actionKeyOff, ActiveLow, &(note[2])); // E3
  action.add(9, actionKeyOn, actionKeyOff, ActiveLow, &(note[3])); // F3
  action.add(10, actionKeyOn, actionKeyOff, ActiveLow, &(note[4])); // G3
  action.add(11, actionKeyOn, actionKeyOff, ActiveLow, &(note[5])); // A3
}

## The Arduino Setup

No surprises here as well, we just setup I2S and make sure that the sound generation uses the same sample rate, channels and bits_per_sample as like i2s. As a last thing we just call the setupActions() that has been explained in the last chapter.
 
```C++
void setup() {
  Serial.begin(115200);
  AudioLogger::instance().begin(Serial,AudioLogger::Info);

  // Setup output
  auto cfg = i2s.defaultConfig(TX_MODE);
  // add additional settings e.g. to define your pins or a different sample rate
  i2s.begin(cfg);

  // Setup sound generation based on Audioi2s settings
  in.begin(cfg);

  // activate keys
  setupActions();

}

The Arduino Loop

In the loop we just copy the audio source to the audio sink. The critical thing here is that we need to call processActions() which handles the magic of calling our key press and key release methods.

// copy the data
void loop() {
  copier.copy();
  action.processActions();
}
Clone this wiki locally