152 lines
4.1 KiB
C++
152 lines
4.1 KiB
C++
/**
|
|
* @file streams-stk_allinstruments-audioout.ino
|
|
* @brief Test sketch which pays all notes of all instruments
|
|
* @author Phil Schatzmann
|
|
* @copyright Copyright (c) 2021
|
|
*/
|
|
#include "AudioTools.h"
|
|
#include "AudioTools/AudioLibs/AudioSTK.h" // install https://github.com/pschatzmann/Arduino-STK
|
|
#include <functional>
|
|
|
|
#ifdef IS_DESKTOP
|
|
#include "AudioTools/AudioLibs/PortAudioStream.h"
|
|
PortAudioStream out;
|
|
#else
|
|
#include "AudioTools/AudioLibs/AudioBoardStream.h" // install https://github.com/pschatzmann/arduino-audio-driver
|
|
AudioBoardStream out(AudioKitEs8388V1);
|
|
#endif
|
|
|
|
Instrmnt *p_Instrmnt=nullptr; // will be allocated dynamically
|
|
STKStream<Instrmnt> in;
|
|
StreamCopy copier(out, in);
|
|
MusicalNotes notes;
|
|
|
|
/// We do not have enough memory to allocate all instruments, so we provide an array with allocator methods
|
|
struct InstrumentInfo {
|
|
const char* name;
|
|
std::function<Instrmnt * ()> instrument;
|
|
};
|
|
|
|
InstrumentInfo instrumentArray[] = {
|
|
{"BeeThree", []() { return new BeeThree(); }},
|
|
{"BlowHole", []() { return new BlowHole(20); }},
|
|
{"Bowed", []() { return new Bowed(); }},
|
|
{"Clarinet", []() { return new Clarinet(); }},
|
|
// {"Drummer", []() { return new Drummer(); }}, // comment out for STM32 or ESP8266
|
|
{"Flute", []() { return new Flute(20); }},
|
|
{"Rhodey", []() { return new Rhodey(); }},
|
|
{"TubeBell", []() { return new TubeBell(); }},
|
|
{"Mandolin", []() { return new Mandolin(20); }},
|
|
{"ModalBar", []() { return new ModalBar(); }},
|
|
{"Moog", []() { return new Moog(); }},
|
|
{"Plucked", []() { return new Plucked(); }},
|
|
{"Saxofony", []() { return new Saxofony(20); }},
|
|
{"Shakers", []() { return new Shakers(); }},
|
|
{"Sitar", []() { return new Sitar(); }},
|
|
{"StifKarp", []() { return new StifKarp(); }},
|
|
{"TubeBell", []() { return new TubeBell(); }},
|
|
{"Wurley", []() { return new Wurley(); }},
|
|
{"BlowBotl", []() { return new BlowBotl(); }},
|
|
{"Brass", []() { return new Brass(); }},
|
|
{"FMVoices", []() { return new FMVoices(); }},
|
|
{"PercFlut", []() { return new PercFlut(); }},
|
|
{"HevyMetl", []() { return new HevyMetl(); }},
|
|
{"Recorder", []() { return new Recorder(); }},
|
|
{"Resonate", []() { return new Resonate(); }},
|
|
{"Simple", []() { return new Simple(); }},
|
|
{"Whistle", []() { return new Whistle(); }},
|
|
{nullptr, nullptr}
|
|
};
|
|
bool active = true;
|
|
uint64_t timeout = 0;
|
|
int instrumentIdx = 0;
|
|
int noteMin = 0;
|
|
int noteMax = 127;
|
|
int noteStep = 12; // 1 octave
|
|
int noteIndex = noteMin;
|
|
int onLengthMs = 400;
|
|
int offLengthMs = 50;
|
|
float amplitude = 1.0;
|
|
|
|
void selectInstrument() {
|
|
if (p_Instrmnt==nullptr){
|
|
Serial.println(instrumentArray[instrumentIdx].name);
|
|
p_Instrmnt = instrumentArray[instrumentIdx].instrument();
|
|
in.setInput(p_Instrmnt);
|
|
in.begin();
|
|
}
|
|
}
|
|
|
|
void noteOn() {
|
|
// play note for 800 ms
|
|
if (p_Instrmnt!=nullptr){
|
|
float freq = notes.stkNoteToFrequency(noteIndex);
|
|
p_Instrmnt->noteOn(freq, amplitude);
|
|
}
|
|
timeout = millis()+onLengthMs;
|
|
active = false;
|
|
}
|
|
|
|
void noteOff() {
|
|
// note off - silence for 100 ms
|
|
if (p_Instrmnt!=nullptr){
|
|
p_Instrmnt->noteOff(amplitude);
|
|
}
|
|
timeout = millis()+offLengthMs;
|
|
|
|
// select next note
|
|
noteIndex += noteStep;
|
|
// switch instrument after we played all notes
|
|
if (noteIndex>=noteMax){
|
|
noteIndex = noteMin;
|
|
instrumentIdx++;
|
|
if (instrumentArray[instrumentIdx].name==nullptr){
|
|
instrumentIdx = 0;
|
|
}
|
|
// delete old instrument
|
|
if (p_Instrmnt!=nullptr){
|
|
delete p_Instrmnt;
|
|
p_Instrmnt = nullptr;
|
|
selectInstrument();
|
|
}
|
|
}
|
|
active = true;
|
|
}
|
|
|
|
void play() {
|
|
|
|
if (millis()>timeout){
|
|
if (active){
|
|
Serial.print("- playing ");
|
|
Serial.println(noteIndex);
|
|
noteOn();
|
|
} else {
|
|
noteOff();
|
|
}
|
|
}
|
|
}
|
|
|
|
void setup() {
|
|
Serial.begin(115200);
|
|
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);
|
|
StkLogLevel = StkWarning;
|
|
|
|
// 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);
|
|
|
|
// select first instument
|
|
selectInstrument();
|
|
|
|
}
|
|
|
|
void loop() {
|
|
play();
|
|
copier.copy();
|
|
}
|