STK add template parameter

This commit is contained in:
Phil Schatzmann 2022-09-09 11:15:16 +02:00
parent c71fb140e6
commit 0ae8e67664
5 changed files with 77 additions and 91 deletions

View File

@ -11,7 +11,7 @@
#include "AudioLibs/AudioKit.h"
Sitar instrument(440);
STKStream in(instrument);
STKStream<Instrmnt> in(instrument);
AudioKitStream out;
StreamCopy copier(out, in);
MusicalNotes notes;

View File

@ -11,7 +11,7 @@
#include "AudioLibs/AudioSTK.h"
Clarinet clarinet(440); // the stk clarinet instrument
STKGenerator<int16_t> generator(clarinet); // subclass of SoundGenerator
STKGenerator<Instrmnt, int16_t> generator(clarinet); // subclass of SoundGenerator
GeneratedSoundStream<int16_t> in(generator); // Stream generated from sine wave
AudioKitStream out;
StreamCopy copier(out, in); // copy stkStream to a2dpStream

View File

@ -0,0 +1,67 @@
/**
* @file streams-stk_loop-audiokit.ino
* @author Phil Schatzmann
* @brief We can use a MemoryLoop as input
* @version 0.1
* @date 2022-09-09
*
* @copyright Copyright (c) 2022
*
*/
#include "AudioTools.h"
#include "AudioLibs/AudioKit.h"
#include "AudioLibs/AudioSTK.h"
MemoryLoop mloop("sinewave.raw", sinewave_raw, sinewave_raw_len);
STKStream<MemoryLoop> in(mloop);
AudioKitStream out;
StreamCopy copier(out, in);
MusicalNotes notes;
static uint16_t notes_array[] = { // frequencies aleatoric C-scale
N_C3, N_D3, N_E3, N_F3, N_G3, N_A3, N_B3,
N_C4, N_D4, N_E4, N_F4, N_G4, N_A4, N_B4,
N_C5, N_D5, N_E5, N_F5, N_G5, N_A5, N_B5
};
void play() {
static bool active=true;
static float freq;
static uint64_t timeout;
if (millis()>timeout){
if (active){
// play note for 800 ms
freq = notes_array[random(sizeof(notes_array)/sizeof(uint16_t))];
mloop.setFrequency(freq);
timeout = millis()+800;
active = false;
} else {
// silence for 100 ms
mloop.setFrequency(0);
timeout = millis()+100;
active = true;
}
}
}
void setup() {
Serial.begin(115200);
AudioLogger::instance().begin(Serial,AudioLogger::Warning);
// setup input
auto icfg = in.defaultConfig();
in.begin(icfg);
// setup output
auto ocfg = out.defaultConfig(TX_MODE);
ocfg.copyFrom(icfg);
ocfg.sd_active = false;
out.begin(ocfg);
}
void loop() {
play();
copier.copy();
}

View File

@ -1,63 +0,0 @@
/**
* @file streams-stk-a2dp.ino
* @author Phil Schatzmann
* @brief The Synthesis ToolKit in C++ (STK) is a set of open source audio signal processing and algorithmic synthesis classes written in the C++ programming language.
* @author Phil Schatzmann
* @copyright GPLv3
*/
// Add this in your sketch or change the setting in AudioConfig.h
#define USE_A2DP
#define USE_STK
#include "AudioTools.h"
#include "Clarinet.h"
stk::Clarinet clarinet(440); // the stk clarinet instrument
STKGenerator<int16_t> generator(clarinet); // subclass of SoundGenerator with max amplitude of 32000
GeneratedSoundStream<int16_t> in(generator); // Stream generated from sine wave
A2DPStream a2dpStream = A2DPStream::instance(); // access A2DP as stream
StreamCopy copier(a2dpStream, in); // copy stkStream to a2dpStream
MusicalNotes notes; // notes with frequencies
// Arduino Setup
void setup(void) {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Info);
// start bluetooth
Serial.println("starting A2DP...");
auto cfgA2DP = a2dpStream.defaultConfig(TX_MODE);
cfgA2DP.name = "LEXON MINO L";
a2dpStream.setVolume(0.1);
a2dpStream.begin(cfgA2DP);
// start STK input with default configuration
Serial.println("starting STK...");
auto cfgSTK = in.defaultConfig();
cfgSTK.channels = 2;
in.setNotifyAudioChange(a2dpStream);
in.begin(cfgSTK);
}
void playNoteStk() {
static unsigned long timeout=0;
static int note = 90;
if (millis()>timeout) {
note += rand() % 10 - 5; // generate some random offset
float frequency = notes.frequency(note);
clarinet.noteOn( frequency, 0.5 );
// set time when we play next note
timeout = millis()+1000;
}
}
// Arduino loop - copy data
void loop() {
playNoteStk();
copier.copy();
}

View File

@ -22,29 +22,20 @@ namespace audio_tools {
* @tparam T
*/
template <class T>
template <class StkCls, class T>
class STKGenerator : public SoundGenerator<T> {
public:
STKGenerator() = default;
// Creates an STKGenerator for an instrument
STKGenerator(stk::Instrmnt &instrument) : SoundGenerator<T>() {
STKGenerator(StkCls &instrument) : SoundGenerator<T>() {
this->p_instrument = &instrument;
}
// Creates an STKGenerator for a voicer (combination of multiple instruments)
STKGenerator(stk::Voicer &voicer) : SoundGenerator<T>() {
this->p_voicer = &voicer;
}
void setInput(stk::Instrmnt &instrument){
void setInput(StkCls &instrument){
this->p_instrument = &instrument;
}
void setInput(stk::Voicer &voicer){
this->p_voicer = &voicer;
}
/// provides the default configuration
AudioBaseInfo defaultConfig() {
AudioBaseInfo info;
@ -69,15 +60,12 @@ class STKGenerator : public SoundGenerator<T> {
T result = 0;
if (p_instrument!=nullptr) {
result = p_instrument->tick()*max_value;
} else if (p_voicer!=nullptr){
result = p_voicer->tick()*max_value;
}
return result;
}
protected:
stk::Instrmnt *p_instrument=nullptr;
stk::Voicer *p_voicer=nullptr;
StkCls *p_instrument=nullptr;
T max_value;
};
@ -85,24 +73,18 @@ class STKGenerator : public SoundGenerator<T> {
/**
* @brief STK Stream for Instrument or Voicer
*/
template <class StkCls>
class STKStream : public GeneratedSoundStream<int16_t> {
public:
STKStream(Instrmnt &instrument){
STKStream(StkCls &instrument){
generator.setInput(instrument);
GeneratedSoundStream<int16_t>::setInput(generator);
}
STKStream(Voicer &voicer){
generator.setInput(voicer);
GeneratedSoundStream<int16_t>::setInput(generator);
}
void setInput(Instrmnt &instrument){
void setInput(StkCls &instrument){
generator.setInput(instrument);
}
void setInput(Voicer &voicer){
generator.setInput(voicer);
}
protected:
STKGenerator<int16_t> generator;
STKGenerator<StkCls,int16_t> generator;
};