As you might know from my last posts I am currently extending my Arduino Audio Tools library to support the AI Thinker Audio Kit which is based on the ES8388 audio chip.

I didn’t do much with my Arduino STK project lately, so I think this is the perfect opportunity to promote it a little bit.

The STK Synthesizer

First we import the libraries and declare the variables that we use:

#include "AudioTools.h"
#include "AudioLibs/AudioKit.h"
#include "StkAll.h"

AudioKitStream kit;
Clarinet clarinet(440);
Voicer voicer;
ArdStreamOut output(&kit);
float noteAmplitude = 128;
int group = 0;

We use a clarinet which is one of the many [STK instruments]{https://pschatzmann.github.io/Arduino-STK/html/classstk_1_1Instrmnt.html}. We will assign it later to the voicer. To output the data into a Stream we use the ArdStreamOut class. Next we need to deal with the key logic:

void actionKeyOn(bool active, int pin, void* ptr){
  int note = *((int*)ptr);
  voicer.noteOn(note, noteAmplitude, group);
}

void actionKeyOff(bool active, int pin, void* ptr){
  int note = *((int*)ptr);
  voicer.noteOff(note, noteAmplitude, group);
}

// We want to play some notes on the AudioKit keys 
void setupActions(){
  // assign buttons to notes
  auto act_low = AudioActions::ActiveLow;
  static int note[] = {48,50,52,53,55,57}; // midi keys
  kit.audioActions().add(PIN_KEY1, actionKeyOn, actionKeyOff, act_low, &(note[0])); // C3
  kit.audioActions().add(PIN_KEY2, actionKeyOn, actionKeyOff, act_low, &(note[1])); // D3
  kit.audioActions().add(PIN_KEY3, actionKeyOn, actionKeyOff, act_low, &(note[2])); // E3
  kit.audioActions().add(PIN_KEY4, actionKeyOn, actionKeyOff, act_low, &(note[3])); // F3
  kit.audioActions().add(PIN_KEY5, actionKeyOn, actionKeyOff, act_low, &(note[4])); // G3
  kit.audioActions().add(PIN_KEY6, actionKeyOn, actionKeyOff, act_low, &(note[5])); // A3
}

We use a callback function when a key is pressed and another one when the key is released. There we can just forward these events to the STK voicer. Please note that the voicer deals with Midi notes, so that’s what we need to provide as additional parameter in your action setup.

Finally we move to the Arduino setup and loop methods:

void setup() {
  Serial.begin(115200);
  AudioLogger::instance().begin(Serial,AudioLogger::Warning);

  voicer.addInstrument(&clarinet, group);

  // define data format
  auto cfg = kit.defaultConfig(TX_MODE);
  cfg.channels = 1;
  cfg.bits_per_sample = 16;
  cfg.sample_rate = Stk::sampleRate();
  kit.begin(cfg);

  // play notes with keys
  setupActions();

}

void loop() {
   for (j=0;j<1024;j++) {
      output.tick( voicer.tick() );
   }
   kit.processActions();
}

We add the instrument to the voicer, and setup the output of the AudioKit as one channel. Finally we call our setupActions() that we have seen above.

In the loop we just output the audio data to the the stream output and handle the keyboard events.

Source Code

The (potentially updated) source code can be found in the examples directory.


0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *