snapshot
This commit is contained in:
@@ -0,0 +1 @@
|
||||
# STK Examples
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* @file streams-stk-audioout.ino
|
||||
* @brief Plays random notes on instrument. For available instruments
|
||||
* see https://pschatzmann.github.io/Arduino-STK/html/classstk_1_1Instrmnt.html
|
||||
* I used an AudioBoardStream to test the output, but you can replace it with any other output class (e.g. I2SStream)
|
||||
* @author Phil Schatzmann
|
||||
* @copyright Copyright (c) 2021
|
||||
*/
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioLibs/AudioSTK.h" // install https://github.com/pschatzmann/Arduino-STK
|
||||
#include "AudioTools/AudioLibs/AudioBoardStream.h" // install https://github.com/pschatzmann/arduino-audio-driver
|
||||
|
||||
Sitar instrument(440);
|
||||
STKStream<Instrmnt> in(instrument);
|
||||
AudioBoardStream out(AudioKitEs8388V1);
|
||||
StreamCopy copier(out, in);
|
||||
MusicalNotes notes;
|
||||
|
||||
float note_amplitude = 0.5;
|
||||
static float 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
|
||||
int count = sizeof(notes_array)/sizeof(float);
|
||||
freq = notes_array[random(count)]; // generate random number from 0 to count-1
|
||||
instrument.noteOn(freq, note_amplitude);
|
||||
timeout = millis()+800;
|
||||
active = false;
|
||||
} else {
|
||||
// silence for 100 ms
|
||||
instrument.noteOff(note_amplitude);
|
||||
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();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
# set the project name
|
||||
project(stk_example)
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
set (DCMAKE_CXX_FLAGS "-Werror")
|
||||
|
||||
include(FetchContent)
|
||||
option(BUILD_SHARED_LIBS "Build using shared libraries" OFF)
|
||||
|
||||
FetchContent_Declare(arduino-stk GIT_REPOSITORY "https://github.com/pschatzmann/Arduino-STK.git" )
|
||||
FetchContent_GetProperties(arduino-stk)
|
||||
if(NOT arduino-stk_POPULATED)
|
||||
FetchContent_Populate(arduino-stk)
|
||||
add_subdirectory(${arduino-stk_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/arduino-stk)
|
||||
endif()
|
||||
|
||||
# Build with arduino-audio-tools
|
||||
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../../.. ${CMAKE_CURRENT_BINARY_DIR}/arduino-audio-tools )
|
||||
endif()
|
||||
|
||||
# build sketch as executable
|
||||
set_source_files_properties(streams-stk-desktop.ino PROPERTIES LANGUAGE CXX)
|
||||
add_executable (stk_example streams-stk-desktop.ino)
|
||||
|
||||
# set preprocessor defines
|
||||
target_compile_definitions(arduino_emulator PUBLIC -DDEFINE_MAIN)
|
||||
target_compile_definitions(stk_example PUBLIC -DARDUINO -DIS_DESKTOP)
|
||||
target_compile_definitions(arduino-stk PUBLIC -DIS_DESKTOP)
|
||||
|
||||
# OS/X might need this setting for core audio
|
||||
target_compile_options(portaudio PRIVATE -Wno-deprecated)
|
||||
|
||||
# specify libraries
|
||||
target_link_libraries(stk_example arduino-stk portaudio arduino_emulator arduino-audio-tools )
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* @file streams-stk-desktop.ino
|
||||
* @brief Build and run on desktop using PortAudio
|
||||
* build with
|
||||
* - mkdir build
|
||||
* - cd build
|
||||
* - cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||
* - make
|
||||
* @author Phil Schatzmann
|
||||
* @copyright Copyright (c) 2021
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioLibs/AudioSTK.h" // install https://github.com/pschatzmann/Arduino-STK3
|
||||
#include "AudioTools/AudioLibs/PortAudioStream.h"
|
||||
|
||||
Flute insturment(50);
|
||||
STKStream<Instrmnt> in(insturment);
|
||||
PortAudioStream out;
|
||||
StreamCopy copier(out, in);
|
||||
MusicalNotes notes;
|
||||
|
||||
float note_amplitude = 0.5;
|
||||
static float 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(static_cast<long>(sizeof(notes_array)/sizeof(float)))];
|
||||
|
||||
Serial.print("playing ");
|
||||
Serial.println(freq);
|
||||
|
||||
insturment.noteOn(freq, note_amplitude);
|
||||
timeout = millis()+800;
|
||||
active = false;
|
||||
} else {
|
||||
// silence for 100 ms
|
||||
insturment.noteOff(note_amplitude);
|
||||
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);
|
||||
out.begin(ocfg);
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
play();
|
||||
copier.copy();
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
# set the project name
|
||||
project(arduino_sketch)
|
||||
set (SKETCH "streams-stk_allinstruments-audiokit.ino")
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
set (DCMAKE_CXX_FLAGS "-Werror")
|
||||
|
||||
include(FetchContent)
|
||||
option(BUILD_SHARED_LIBS "Build using shared libraries" OFF)
|
||||
|
||||
FetchContent_Declare(arduino-stk GIT_REPOSITORY "https://github.com/pschatzmann/arduino-stk.git" )
|
||||
FetchContent_GetProperties(arduino-stk)
|
||||
if(NOT arduino-stk_POPULATED)
|
||||
FetchContent_Populate(arduino-stk)
|
||||
add_subdirectory(${arduino-stk_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/arduino-stk)
|
||||
endif()
|
||||
|
||||
# Build with arduino-audio-tools
|
||||
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../../.. ${CMAKE_CURRENT_BINARY_DIR}/arduino-audio-tools )
|
||||
endif()
|
||||
|
||||
# build sketch as executable
|
||||
set_source_files_properties(${SKETCH} PROPERTIES LANGUAGE CXX)
|
||||
add_executable (arduino_sketch ${SKETCH})
|
||||
|
||||
# set preprocessor defines
|
||||
target_compile_definitions(arduino_emulator PUBLIC -DDEFINE_MAIN)
|
||||
target_compile_definitions(arduino_sketch PUBLIC -DARDUINO -DIS_DESKTOP)
|
||||
target_compile_definitions(arduino-stk PUBLIC -DIS_DESKTOP)
|
||||
|
||||
# OS/X might need this setting for core audio
|
||||
target_compile_options(portaudio PRIVATE -Wno-deprecated)
|
||||
|
||||
# specify libraries
|
||||
target_link_libraries(arduino_sketch arduino-stk portaudio arduino_emulator arduino-audio-tools )
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* @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();
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* @file streams-stk_files-audiokit.ino
|
||||
* @brief Example which Loads raw samples from the SDMMC file system
|
||||
* 1. Make sure that files are stored on SD in the /rawwaves directory
|
||||
* 2. In ArdConfig.h make sure that we used #define STK_USE_FILES
|
||||
* 3. On AudiKit all switches must be switched on
|
||||
* @author Phil Schatzmann
|
||||
* @copyright Copyright (c) 2021
|
||||
*/
|
||||
|
||||
#include "SD_MMC.h"
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioLibs/AudioSTK.h" // install https://github.com/pschatzmann/Arduino-STK
|
||||
#include "AudioTools/AudioLibs/AudioBoardStream.h" // install https://github.com/pschatzmann/arduino-audio-driver
|
||||
|
||||
|
||||
STKStream<Instrmnt> in;
|
||||
AudioBoardStream out(AudioKitEs8388V1);
|
||||
StreamCopy copier(out, in);
|
||||
MusicalNotes notes;
|
||||
Instrmnt* p_instrument=nullptr; // instrument depends on file system
|
||||
|
||||
float note_amplitude = 0.5;
|
||||
static float 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(float))];
|
||||
|
||||
Serial.print("playing ");
|
||||
Serial.println(freq);
|
||||
|
||||
p_instrument->noteOn(freq, note_amplitude);
|
||||
timeout = millis()+800;
|
||||
active = false;
|
||||
} else {
|
||||
// silence for 100 ms
|
||||
p_instrument->noteOff(note_amplitude);
|
||||
timeout = millis()+100;
|
||||
active = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial,AudioLogger::Warning);
|
||||
|
||||
if(!SD_MMC.begin("/sdcard", true)){ // 1-bit mode
|
||||
LOGE("Could not open SD_MMC");
|
||||
return;
|
||||
}
|
||||
|
||||
// We can allocate the incstument only after SD_M
|
||||
p_instrument = new BeeThree();
|
||||
in.setInput(p_instrument);;
|
||||
|
||||
// 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();
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioLibs/AudioSTK.h" // install https://github.com/pschatzmann/Arduino-STK
|
||||
#include "AudioTools/AudioLibs/AudioBoardStream.h" // install https://github.com/pschatzmann/arduino-audio-driver
|
||||
|
||||
Clarinet clarinet(440); // the stk clarinet instrument
|
||||
STKGenerator<Instrmnt, int16_t> generator(clarinet); // subclass of SoundGenerator
|
||||
GeneratedSoundStream<int16_t> in(generator); // Stream generated from sine wave
|
||||
AudioBoardStream out(AudioKitEs8388V1);
|
||||
StreamCopy copier(out, in); // copy stkStream to a2dpStream
|
||||
MusicalNotes notes; // notes with frequencies
|
||||
|
||||
// Arduino Setup
|
||||
void setup(void) {
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);
|
||||
|
||||
// start Output
|
||||
Serial.println("starting Analog Output...");
|
||||
out.begin(out.defaultConfig());
|
||||
|
||||
// start STK input with default configuration
|
||||
Serial.println("starting STK...");
|
||||
auto cfgSTK = in.defaultConfig();
|
||||
cfgSTK.channels = 2;
|
||||
in.addNotifyAudioChange(out);
|
||||
in.begin(cfgSTK);
|
||||
|
||||
}
|
||||
|
||||
void playNoteStk() {
|
||||
static unsigned long timeout=0;
|
||||
static int note = 60;
|
||||
static bool isNoteOn = false;
|
||||
|
||||
if (!isNoteOn) {
|
||||
if (millis()>timeout) {
|
||||
// play note for 1000 ms
|
||||
note += rand() % 10 - 5; // generate some random offset
|
||||
float frequency = notes.frequency(note);
|
||||
clarinet.noteOn( frequency, 0.5 );
|
||||
|
||||
// set timeout
|
||||
timeout = millis()+1000;
|
||||
}
|
||||
} else {
|
||||
if (millis()>timeout) {
|
||||
// switch note off for 200 ms
|
||||
clarinet.noteOff(0.5);
|
||||
|
||||
// set timeout
|
||||
timeout = millis()+200;
|
||||
}
|
||||
}
|
||||
isNoteOn = !isNoteOn;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Arduino loop - copy data
|
||||
void loop() {
|
||||
playNoteStk();
|
||||
copier.copy();
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @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 "AudioTools/AudioLibs/AudioSTK.h" // install https://github.com/pschatzmann/Arduino-STK
|
||||
#include "AudioTools/AudioLibs/AudioBoardStream.h" // install https://github.com/pschatzmann/arduino-audio-driver
|
||||
|
||||
MemoryLoop mloop("crashcym.raw", crashcym_raw, crashcym_raw_len);
|
||||
STKStream<MemoryLoop> in(mloop);
|
||||
AudioBoardStream out(AudioKitEs8388V1);
|
||||
StreamCopy copier(out, in);
|
||||
|
||||
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() {
|
||||
copier.copy();
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include "StkAll.h"
|
||||
|
||||
/**
|
||||
* @brief Demo how you can compose your own instrument
|
||||
* @author Phil Schatzmann
|
||||
*/
|
||||
class MyFirstInstrument : public Instrmnt {
|
||||
public:
|
||||
MyFirstInstrument() {
|
||||
adsr.setAllTimes( 0.005, 0.01, 0.8, 0.010 );
|
||||
echo.setDelay(1024);
|
||||
}
|
||||
|
||||
//! Start a note with the given frequency and amplitude.
|
||||
void noteOn( StkFloat frequency, StkFloat amplitude ) {
|
||||
wave.setFrequency(frequency);
|
||||
adsr.keyOn();
|
||||
}
|
||||
|
||||
//! Stop a note with the given amplitude (speed of decay).
|
||||
void noteOff( StkFloat amplitude ){
|
||||
adsr.keyOff();
|
||||
}
|
||||
|
||||
float tick( unsigned int channel = 0) override {
|
||||
return echo.tick(wave.tick()) * adsr.tick();
|
||||
};
|
||||
|
||||
protected:
|
||||
stk::SineWave wave;
|
||||
stk::ADSR adsr;
|
||||
stk::Echo echo {1024};
|
||||
};
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @file streams-stk-audioout.ino
|
||||
* @brief Plays random notes on self designed instrument: see https://github.com/pschatzmann/Arduino-STK/wiki/Building-your-own-Instrument
|
||||
* @author Phil Schatzmann
|
||||
* @copyright Copyright (c) 2021
|
||||
*/
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioLibs/AudioSTK.h" // install https://github.com/pschatzmann/Arduino-STK
|
||||
#include "AudioTools/AudioLibs/AudioBoardStream.h" // install https://github.com/pschatzmann/arduino-audio-driver
|
||||
#include "MyFirstInstrument.h"
|
||||
|
||||
MyFirstInstrument instrument;
|
||||
STKStream<Instrmnt> in(instrument);
|
||||
AudioBoardStream out(AudioKitEs8388V1);
|
||||
StreamCopy copier(out, in);
|
||||
MusicalNotes notes;
|
||||
|
||||
float note_amplitude = 0.5;
|
||||
static float 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(float))];
|
||||
instrument.noteOn(freq, note_amplitude);
|
||||
timeout = millis()+800;
|
||||
active = false;
|
||||
} else {
|
||||
// silence for 100 ms
|
||||
instrument.noteOff(note_amplitude);
|
||||
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();
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* @file streams-sine-audiokit.ino
|
||||
* @brief We just use the sine generator from STK
|
||||
* @author Phil Schatzmann
|
||||
* @copyright Copyright (c) 2021
|
||||
*/
|
||||
|
||||
#include "SD_MMC.h"
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioLibs/AudioSTK.h" // install https://github.com/pschatzmann/Arduino-STK
|
||||
#include "AudioTools/AudioLibs/AudioBoardStream.h" // install https://github.com/pschatzmann/arduino-audio-driver
|
||||
|
||||
SineWave sine;
|
||||
STKStream<SineWave> in(sine);
|
||||
AudioBoardStream out(AudioKitEs8388V1);
|
||||
StreamCopy copier(out, in);
|
||||
MusicalNotes notes;
|
||||
|
||||
float note_amplitude = 0.5;
|
||||
static float 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(float))];
|
||||
|
||||
Serial.print("playing ");
|
||||
Serial.println(freq);
|
||||
|
||||
sine.setFrequency(freq);
|
||||
timeout = millis()+800;
|
||||
active = false;
|
||||
} else {
|
||||
// silence for 100 ms
|
||||
sine.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();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# Implementing a Synthesizer using the STK Framwork
|
||||
|
||||
We can use the STK framework to implement a Synthesizer which receives Midi Messages and translates them
|
||||
into sound. Here we use a Clarinet...
|
||||
|
||||
We demo how to use the Stream output classes provided by STK.
|
||||
|
||||
For [further info see my blog](https://www.pschatzmann.ch/home/2021/12/21/ai-thinker-audiokit-a-simply-synthesizer-with-stk/)
|
||||
|
||||
### Dependencies
|
||||
|
||||
- https://github.com/pschatzmann/arduino-audio-tools
|
||||
- https://github.com/pschatzmann/arduino-audio-driver
|
||||
- https://github.com/pschatzmann/arduino-midi
|
||||
- https://github.com/pschatzmann/Arduino-STK
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @file streams-synthstk-audiokit.ino
|
||||
* @brief see https://www.pschatzmann.ch/home/2021/12/17/ai-thinker-audiokit-a-simple-synthesizer-with-stk/
|
||||
* @author Phil Schatzmann
|
||||
* @copyright Copyright (c) 2021
|
||||
*/
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioLibs/AudioBoardStream.h" // install https://github.com/pschatzmann/arduino-audio-driver
|
||||
#include "StkAll.h" // install https://github.com/pschatzmann/Arduino-STK
|
||||
|
||||
AudioBoardStream kit(AudioKitEs8388V1);
|
||||
Clarinet clarinet(440);
|
||||
Voicer voicer;
|
||||
ArdStreamOut output(&kit);
|
||||
float noteAmplitude = 128;
|
||||
int group = 0;
|
||||
|
||||
void actionKeyOn(bool active, int pin, void* ptr){
|
||||
float note = *((float*)ptr);
|
||||
voicer.noteOn(note, noteAmplitude, group);
|
||||
}
|
||||
|
||||
void actionKeyOff(bool active, int pin, void* ptr){
|
||||
float note = *((float*)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(kit.getKey(1), actionKeyOn, actionKeyOff, act_low, &(note[0])); // C3
|
||||
kit.audioActions().add(kit.getKey(2), actionKeyOn, actionKeyOff, act_low, &(note[1])); // D3
|
||||
kit.audioActions().add(kit.getKey(3), actionKeyOn, actionKeyOff, act_low, &(note[2])); // E3
|
||||
kit.audioActions().add(kit.getKey(4), actionKeyOn, actionKeyOff, act_low, &(note[3])); // F3
|
||||
kit.audioActions().add(kit.getKey(5), actionKeyOn, actionKeyOff, act_low, &(note[4])); // G3
|
||||
kit.audioActions().add(kit.getKey(6), actionKeyOn, actionKeyOff, act_low, &(note[5])); // A3
|
||||
}
|
||||
|
||||
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();
|
||||
cfg.sd_active = false;
|
||||
kit.begin(cfg);
|
||||
|
||||
// play notes with keys
|
||||
setupActions();
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
for (int j=0;j<1024;j++) {
|
||||
output.tick( voicer.tick() );
|
||||
}
|
||||
kit.processActions();
|
||||
}
|
||||
Reference in New Issue
Block a user