ESP32・arduinoとmozziで作る電子楽器制作_メモ_備忘録2
fendoap_Passing Scenery :Buffer Zone recorsより
Mozziはarduinoの音響ライブラリーです。それを用いるとシンセサイザーなどが作れます。制作のメモなどをまとめています。
備忘録1はこちら:
周波数で円の大きさが変わるドローンシンセ_制作テスト3
制作しました。
はじめOLEDの表示の遅延だと思いますがノイズが発生していましたがESP32のマルチタスクでOLEDの処理を分けると解消しました。一応まだ実験途中です。
ここから少し加えてみたのが以下の動画です。
以下がスケッチです。
void TaskBlink( void *pvParameters );
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 22, /* data=*/ 21, /* cs=*/ 15, /* dc=*/ 2, /* reset=*/ 17);
#define SECONDS 4;
#include <MozziGuts.h>
#include <Oscil.h> // oscillator template
#include <mozzi_midi.h>
#include <mozzi_rand.h>
#include <tables/sin2048_int8.h> // sine table for oscillator
#include <tables/sin2048_int8.h> // sine table for oscillator
#include <tables/SAW2048_int8.h>
#include <tables/SQUARE_NO_ALIAS_2048_int8.h>
#include <tables/triangle_warm8192_int8.h>
#include <tables/TRIANGLE_VALVE_2_2048_int8.h>
#include <tables/SMOOTHSQUARE8192_int8.h>
#include <tables/SAW_ANALOGUE512_int8.h>
#include <tables/SIN2048_int8.h>
#include <tables/BROWNNOISE8192_int8.h>
#include <tables/water1.h>
// use: Oscil <table_size, update_rate> oscilName (wavetable), look in .h file of table #included above
Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aSin1(SIN2048_DATA);
Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aSin2(SIN2048_DATA);
Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aSin3(SIN2048_DATA);
Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aSin4(SIN2048_DATA);
Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aSin5(SIN2048_DATA);
Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aSin6(SIN2048_DATA);
Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aSin7(SIN2048_DATA);
Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aSin8(SIN2048_DATA);
Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aSin9(SIN2048_DATA);
Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aSin10(SIN2048_DATA);
Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aSin11(SIN2048_DATA);
Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aSin12(SIN2048_DATA);
#include <EventDelay.h>
EventDelay kTriggerDelay;
/*
Oscil <TRIANGLE_VALVE_2_2048_NUM_CELLS, AUDIO_RATE> aSin1(TRIANGLE_VALVE_2_2048_DATA);
Oscil <TRIANGLE_VALVE_2_2048_NUM_CELLS, AUDIO_RATE> aSin2(TRIANGLE_VALVE_2_2048_DATA);
Oscil <TRIANGLE_VALVE_2_2048_NUM_CELLS, AUDIO_RATE> aSin3(TRIANGLE_VALVE_2_2048_DATA);
Oscil <TRIANGLE_VALVE_2_2048_NUM_CELLS, AUDIO_RATE> aSin4(TRIANGLE_VALVE_2_2048_DATA);
Oscil <TRIANGLE_VALVE_2_2048_NUM_CELLS, AUDIO_RATE> aSin5(TRIANGLE_VALVE_2_2048_DATA);
Oscil <TRIANGLE_VALVE_2_2048_NUM_CELLS, AUDIO_RATE> aSin6(TRIANGLE_VALVE_2_2048_DATA);
Oscil <TRIANGLE_VALVE_2_2048_NUM_CELLS, AUDIO_RATE> aSin7(TRIANGLE_VALVE_2_2048_DATA);
Oscil <TRIANGLE_VALVE_2_2048_NUM_CELLS, AUDIO_RATE> aSin8(TRIANGLE_VALVE_2_2048_DATA);
Oscil <TRIANGLE_VALVE_2_2048_NUM_CELLS, AUDIO_RATE> aSin9(TRIANGLE_VALVE_2_2048_DATA);
Oscil <TRIANGLE_VALVE_2_2048_NUM_CELLS, AUDIO_RATE> aSin10(TRIANGLE_VALVE_2_2048_DATA);
Oscil <TRIANGLE_VALVE_2_2048_NUM_CELLS, AUDIO_RATE> aSin11(TRIANGLE_VALVE_2_2048_DATA);
Oscil <TRIANGLE_VALVE_2_2048_NUM_CELLS, AUDIO_RATE> aSin12(TRIANGLE_VALVE_2_2048_DATA);
*/
int freq1;
int freq2;
int freq3;
int freq4;
int freq5;
int freq6;
int freq1p;
int freq2p;
int freq3p;
int freq4p;
int freq5p;
int freq6p;
int freq_base=0;
int rand_base=0;
// use #define for CONTROL_RATE, not a constant
#define CONTROL_RATE 1024 // Hz, powers of 2 are most reliable
void setup(){
startMozzi(CONTROL_RATE); // :)
u8g2.setBusClock(400000000);
xTaskCreatePinnedToCore(
TaskBlink
, "TaskBlink" // A name just for humans
, 16384 // This stack size can be checked & adjusted by reading the Stack Highwater
, NULL
, 2 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
, NULL
, 0);
// Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started.
}
void updateControl(){
// put changing controls in here
/*
aSin1.setFreq(mtof(52+aa)+1+bb+(float)(cc*0.1*dd));
aSin2.setFreq(mtof(69+aa)+4+bb+(float)(cc*0.2*dd));
aSin3.setFreq(mtof(71+aa)+3+bb+(float)(cc*0.3*dd));
aSin4.setFreq(mtof(44+aa)+4+bb+(float)(cc*0.4*dd));
aSin5.setFreq(mtof(47+aa)+4+bb+(float)(cc*0.5*dd));
aSin6.setFreq(mtof(48+aa)-2+bb+(float)(cc*0.6*dd));
aSin7.setFreq(mtof(52+aa)-5+bb+(float)(cc*0.7*dd));
aSin8.setFreq(mtof(55+aa)+3+bb+(float)(cc*0.8*dd));
aSin9.setFreq(mtof(59+aa)+1+bb+(float)(cc*0.9*dd));
aSin10.setFreq(mtof(64+aa)+5+bb+cc*dd);
*/
freq1=map(mozziAnalogRead(39),0,4024,10,500);
freq2=map(mozziAnalogRead(34),0,4024,10,500);
freq3=map(mozziAnalogRead(35),0,4024,10,500);
freq4=map(mozziAnalogRead(32),0,4024,10,500);
freq5=map(mozziAnalogRead(33),0,4024,10,500);
freq6=map(mozziAnalogRead(27),0,4024,10,500);
freq1p=freq1+map(rand(1000),0,999,0,rand_base);
freq2p=freq2+map(rand(1000),0,999,0,rand_base);
freq3p=freq3+map(rand(1000),0,999,0,rand_base);
freq4p=freq4+map(rand(1000),0,999,0,rand_base);
freq5p=freq5+map(rand(1000),0,999,0,rand_base);
freq6p=freq6+map(rand(1000),0,999,0,rand_base);
aSin1.setFreq(freq_base+freq1);
aSin2.setFreq(freq_base+freq2);
aSin3.setFreq(freq_base+freq1);
aSin4.setFreq(freq_base+freq2);
aSin5.setFreq(freq_base+freq1);
aSin6.setFreq(freq_base+freq2);
aSin7.setFreq(freq1p);
aSin8.setFreq(freq2p);
aSin9.setFreq(freq3p);
aSin10.setFreq(freq4p);
aSin11.setFreq(freq5p);
aSin12.setFreq(freq6p);
}
int updateAudio(){
//int ret1=aSin1.next()+aSin2.next()+aSin3.next()+aSin4.next()+aSin5.next()+aSin6.next();
int ret1=aSin1.next()+aSin2.next()+aSin3.next()+aSin4.next()+aSin5.next()+aSin6.next()+aSin7.next()+aSin8.next()+aSin9.next()+aSin10.next()+aSin11.next()+aSin12.next();
// aSin11.next()+aSin12.next()+aSin13.next()+aSin14.next()+aSin15.next()+aSin16.next()+aSin17.next()+aSin18.next()+aSin19.next()+aSin20.next();
// int ret3=aSin21.next()+aSin22.next()+aSin23.next()+aSin24.next()+aSin25.next()+aSin26.next()+aSin27.next()+aSin28.next()+aSin29.next()+aSin30.next();
// int ret4=aSin31.next()+aSin32.next()+aSin33.next()+aSin34.next()+aSin35.next()+aSin36.next()+aSin37.next()+aSin38.next()+aSin39.next()+aSin40.next();
// int ret5=aSin41.next()+aSin42.next()+aSin43.next()+aSin44.next()+aSin45.next()+aSin46.next()+aSin47.next()+aSin48.next()+aSin49.next()+aSin50.next();
return (ret1)>>4;
// return (aSin1.next()+aSin2.next()+aSin3.next()+aSin4.next()+aSin5.next()+aSin6.next()+aSin7.next()+aSin8.next()+aSin9.next()+aSin10.next()+aSin11.next()+aSin12.next()+aSin13.next()+aSin14.next()+aSin15.next()+aSin16.next()+aSin17.next()+aSin18.next()+aSin19.next()+aSin20.next()+aSin21.next()+aSin22.next()+aSin23.next()+aSin24.next()+aSin25.next()+aSin26.next()+aSin27.next()+aSin28.next()+aSin29.next()+aSin30.next() )>>5;
}
void loop(){
audioHook(); // required here
}
void TaskBlink(void *pvParameters) // This is a task.
{
(void) pvParameters;
u8g2.begin();
pinMode(13,INPUT);
pinMode(23,INPUT);
pinMode(19,INPUT);
pinMode(18,INPUT);
gpio_set_pull_mode(GPIO_NUM_13, GPIO_PULLDOWN_ONLY);
gpio_set_pull_mode(GPIO_NUM_23, GPIO_PULLDOWN_ONLY);
gpio_set_pull_mode(GPIO_NUM_19, GPIO_PULLDOWN_ONLY);
gpio_set_pull_mode(GPIO_NUM_18, GPIO_PULLDOWN_ONLY);
int yrand1=random(64);
int yrand2=random(64);
int yrand3=random(64);
int yrand4=random(64);
int yrand5=random(64);
int yrand6=random(64);
int yrand7=random(64);
int yrand8=random(64);
int xrand1=random(64);
int xrand2=random(64);
int xrand3=random(64);
int xrand4=random(64);
int xrand5=random(64);
int xrand6=random(64);
int xrand7=random(64);
int xrand8=random(64);
int gr_count=0;
for (;;) // A Task shall never return or exit.
{
if(digitalRead(13)){
yrand1+=-2;
}
if(digitalRead(19)){
yrand1+=2;
}
if(digitalRead(18)){
xrand1+=2;
}
if(digitalRead(23)){
xrand1+=-2;
}
rand_base=abs(yrand1);
freq_base=abs(map(xrand1,0,128,-2000,2000));
u8g2.clearBuffer();
u8g2.drawCircle(xrand1,yrand1,map(freq1,10,500,0,60));
u8g2.drawCircle(xrand1,yrand1,map(freq2,10,500,0,60));
u8g2.drawCircle(xrand1,yrand1,map(freq3,10,500,0,60));
u8g2.drawCircle(xrand1,yrand1,map(freq4,10,500,0,60));
u8g2.drawCircle(xrand1,yrand1,map(freq5,10,500,0,60));
u8g2.drawCircle(xrand1,yrand1,map(freq6,10,500,0,60));
u8g2.sendBuffer();
vTaskDelay(20);
}
}
16stepサンプルドラムマシン_+4voice_シンセ
16stepのドラムマシンと4音シンセの電子楽器を作りました。
ドラム部分はこんな感じ
4音ポリ部分とかと合わせるとこんな感じ
以下がスケッチです。
#define A0_meter 39
#define A1_meter 34
#define A2_meter 35
#define A3_meter 32
#define A4_meter 33
#define A5_meter 27
#define cross_button_up 13
#define cross_button_down 19
#define cross_button_left 23
#define cross_button_right 18
#define button_0 5
#define button_1 17
#define button_2 16
#define button_3 4
#include <Arduino.h>
#include <U8g2lib.h>
#define CONTROL_RATE 1024
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
void TaskBlink( void *pvParameters );
U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 22, /* data=*/ 21, /* cs=*/ 15, /* dc=*/ 2, /* reset=*/ 17);
#define SECONDS 4;
boolean seq_drum[8][16] = {
{ 0, 0, 0, 0, 0, 0, 0, 0 ,0,0,0,0,0,0,0,0}, //kick
{ 0, 0, 0, 0, 0, 0, 0, 0 ,0,0,0,0,0,0,0,0}, //snare3
{ 0, 0, 0, 0, 0, 0, 0, 0 ,0,0,0,0,0,0,0,0}, //snare4
{ 0, 0, 0, 0, 0, 0, 0, 0 ,0,0,0,0,0,0,0,0}, //hihat1
{ 0, 0, 0, 0, 0, 0, 0, 0 ,0,0,0,0,0,0,0,0}, //hihat2
{ 0, 0, 0, 0, 0, 0, 0, 0 ,0,0,0,0,0,0,0,0}, //clap1
{ 0, 0, 0, 0, 0, 0, 0, 0 ,0,0,0,0,0,0,0,0}, //water1
{ 0, 0, 0, 0, 0, 0, 0, 0 ,0,0,0,0,0,0,0,0} //snap1
};
int seq_melo[4][16] = {
{ 0, 0, 0, 0, 0, 0, 0, 0 ,0,0,0,0,0,0,0,0},
{ 0, 0, 0, 0, 0, 0, 0, 0 ,0,0,0,0,0,0,0,0},
{ 0, 0, 0, 0, 0, 0, 0, 0 ,0,0,0,0,0,0,0,0},
{ 0, 0, 0, 0, 0, 0, 0, 0 ,0,0,0,0,0,0,0,0}
};
boolean seq_melo_trig[4][16] = {
{ 0, 0, 0, 0, 0, 0, 0, 0 ,0,0,0,0,0,0,0,0},
{ 0, 0, 0, 0, 0, 0, 0, 0 ,0,0,0,0,0,0,0,0},
{ 0, 0, 0, 0, 0, 0, 0, 0 ,0,0,0,0,0,0,0,0},
{ 0, 0, 0, 0, 0, 0, 0, 0 ,0,0,0,0,0,0,0,0}
};
String note_name[]={"C_","C#","D_","D#","E_","F_","F#","G_","G#","A_","A#","B_"};
String oct_name[]={"00","01","02","03","04","05","06","07","08","09","10","11","12"};
String seq_drum_kick="----------------";
String seq_drum_snare3="----------------";
String seq_drum_snare4="----------------";
String seq_drum_hihat1="----------------";
String seq_drum_hihat2="----------------";
String seq_drum_clap1="----------------";
String seq_drum_water1="----------------";
String seq_drum_snap1="----------------";
String seq_melo_oct0_8="";
String seq_melo_key0_8="";
String seq_melo_oct1_8="";
String seq_melo_key1_8="";
String seq_melo_oct2_8="";
String seq_melo_key2_8="";
String seq_melo_oct3_8="";
String seq_melo_key3_8="";
String seq_melo_oct0_16="";
String seq_melo_key0_16="";
String seq_melo_oct1_16="";
String seq_melo_key1_16="";
String seq_melo_oct2_16="";
String seq_melo_key2_16="";
String seq_melo_oct3_16="";
String seq_melo_key3_16="";
#include <MozziGuts.h> // Mozziの基本ヘッダファイル
#include <Oscil.h> // オシレータのテンプレート
#include <mozzi_rand.h>
#include <ADSR.h> //エンベロープ
ADSR <AUDIO_RATE, AUDIO_RATE> envB0;
ADSR <AUDIO_RATE, AUDIO_RATE> envB1;
ADSR <AUDIO_RATE, AUDIO_RATE> envB2;
ADSR <AUDIO_RATE, AUDIO_RATE> envB3;
ADSR <AUDIO_RATE, AUDIO_RATE> envB4;
ADSR <AUDIO_RATE, AUDIO_RATE> envB5;
ADSR <AUDIO_RATE, AUDIO_RATE> envB6;
ADSR <AUDIO_RATE, AUDIO_RATE> envB7;
#include <mozzi_midi.h>
#include <Portamento.h>
//Portamento <CONTROL_RATE, AUDIO_RATE> aPortamentoA;
#include <Line.h> // for smooth transitions
Line <long> aGliss;
#include <Smooth.h>
const unsigned int AUDIO_STEPS_PER_CONTROL = AUDIO_RATE / CONTROL_RATE;
float smoothness = 0.01f;
Smooth <unsigned int> aSmooth(smoothness); // to smooth frequency for aSin1
volatile unsigned int freq1;
long audio_steps_per_gliss = AUDIO_RATE / 64; // ie. 4 glisses per second
long control_steps_per_gliss = CONTROL_RATE / 4;
long gliss_start;
long gliss_end;
#include <tables/SQUARE_NO_ALIAS_2048_int8.h>
#include <tables/TRIANGLE_DIST_CUBED_2048_int8.h>
#include <tables/triangle_warm8192_int8.h>
#include <tables/SMOOTHSQUARE8192_int8.h>
#include <tables/snaretable.h>
#include <tables/kicktable.h>
#include <tables/hihattable.h>
#include <tables/clap2.h>
#include <tables/snare2.h>
#include <tables/snare3.h>
#include <tables/snare4.h>
#include <tables/noise2.h>
#include <tables/noise3.h>
#include <tables/test1.h>
#include <tables/test2.h>
#include <tables/test3.h>
#include <tables/snap1.h>
#include <tables/kick9.h>
#include <tables/chihat2.h>
#include <tables/water1.h>
Oscil <TRIANGLE_DIST_CUBED_2048_NUM_CELLS, AUDIO_RATE> triWarm0(TRIANGLE_DIST_CUBED_2048_DATA);
Oscil <TRIANGLE_DIST_CUBED_2048_NUM_CELLS, AUDIO_RATE> triWarm1(TRIANGLE_DIST_CUBED_2048_DATA);
Oscil <TRIANGLE_DIST_CUBED_2048_NUM_CELLS, AUDIO_RATE> triWarm2(TRIANGLE_DIST_CUBED_2048_DATA);
Oscil <TRIANGLE_DIST_CUBED_2048_NUM_CELLS, AUDIO_RATE> triWarm3(TRIANGLE_DIST_CUBED_2048_DATA);
/*
Oscil <TRIANGLE_DIST_CUBED_2048_NUM_CELLS, AUDIO_RATE> triWarm4(TRIANGLE_DIST_CUBED_2048_DATA);
Oscil <TRIANGLE_DIST_CUBED_2048_NUM_CELLS, AUDIO_RATE> triWarm5(TRIANGLE_DIST_CUBED_2048_DATA);
Oscil <TRIANGLE_DIST_CUBED_2048_NUM_CELLS, AUDIO_RATE> triWarm6(TRIANGLE_DIST_CUBED_2048_DATA);
Oscil <TRIANGLE_DIST_CUBED_2048_NUM_CELLS, AUDIO_RATE> triWarm7(TRIANGLE_DIST_CUBED_2048_DATA);
//Oscil <SMOOTHSQUARE8192_NUM_CELLS, AUDIO_RATE> triWarm4(SMOOTHSQUARE8192_DATA);
Oscil <SMOOTHSQUARE8192_NUM_CELLS, AUDIO_RATE> triWarm5(SMOOTHSQUARE8192_DATA);
Oscil <SMOOTHSQUARE8192_NUM_CELLS, AUDIO_RATE> triWarm6(SMOOTHSQUARE8192_DATA);
Oscil <SMOOTHSQUARE8192_NUM_CELLS, AUDIO_RATE> triWarm7(SMOOTHSQUARE8192_DATA);
Oscil <SMOOTHSQUARE8192_NUM_CELLS, AUDIO_RATE> triWarm8(SMOOTHSQUARE8192_DATA);
*/
#include <Sample.h> // Sample template
Sample <SNARETABLE_NUM_CELLS, AUDIO_RATE> snare(SNARETABLE_DATA);
Sample <KICKTABLE_NUM_CELLS, AUDIO_RATE> kick(KICKTABLE_DATA);
Sample <HIHATTABLE_NUM_CELLS, AUDIO_RATE> hihat1(HIHATTABLE_DATA);
Sample <clap2_NUM_CELLS, AUDIO_RATE> clap(clap2_DATA);
Sample <test1_NUM_CELLS, AUDIO_RATE> test1(test1_DATA);
Sample <test2_NUM_CELLS, AUDIO_RATE> test2(test2_DATA);
Sample <test3_NUM_CELLS, AUDIO_RATE> test3(test3_DATA);
Sample <snare2_NUM_CELLS, AUDIO_RATE> snare2(snare2_DATA);
Sample <snare3_NUM_CELLS, AUDIO_RATE> snare3(snare3_DATA);
Sample <snare4_NUM_CELLS, AUDIO_RATE> snare4(snare4_DATA);
Sample <snap1_NUM_CELLS, AUDIO_RATE> snap1(snap1_DATA);
Sample <kick9_NUM_CELLS, AUDIO_RATE> kick9(kick9_DATA);
Sample <chihat2_NUM_CELLS, AUDIO_RATE> hihat2(chihat2_DATA);
Sample <water1_NUM_CELLS, AUDIO_RATE> water1(water1_DATA);
Sample <noise2_NUM_CELLS, AUDIO_RATE> noise2(noise2_DATA);
Sample <noise3_NUM_CELLS, AUDIO_RATE> noise3(noise3_DATA);
// トリガー(発音タイミング)のためのヘッダ
#include <EventDelay.h>
EventDelay kTriggerDelay;
EventDelay kTriggerDelay1;
#include <StateVariable.h>
StateVariable <LOWPASS> svf;
// スムースに値を変化させるためのヘッダ
int master_count=0;
int kleady=0;
byte pin5;
byte pulse;
int tempo;
int tempo1=0;
bool trigger;
byte check; //パルスの立ち上がりの判定用
int cursor_x_drum=0;
int cursor_y_drum=0;
int cursor_x_melo_12=0;
int cursor_y_melo_12=0;
int cursor_x_melo_34=0;
int cursor_y_melo_34=0;
int cursor_select=0;
int attack_time=5;
int decay_time=0;
int sustain_time=0;
int release_time=0;
void setup(){
u8g2.begin();
pinMode(8,INPUT_PULLUP);
// u8g2.setBusClock(400000000);
// Wire.setClock(400000);
startMozzi(CONTROL_RATE);
kTriggerDelay.start(100);// トリガーのタイミング指定(100ms)
set_freq();
u8g2.setFontMode(1);
u8g2.enableUTF8Print();
u8g2.setFont(u8g2_font_b10_t_japanese1);
u8g2.setFontDirection(0);
//aPortamentoA.setTime(300u);
xTaskCreatePinnedToCore(
TaskBlink
, "TaskBlink" // A name just for humans
, 16384 // This stack size can be checked & adjusted by reading the Stack Highwater
, NULL
, 2 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
, NULL
, 0);
}
void updateControl(){
decay_time=map(mozziAnalogRead(A2_meter),0,4095,500,5);
sustain_time=map(mozziAnalogRead(A3_meter),0,4095,500,5);
release_time=map(mozziAnalogRead(A4_meter),0,4095,500,5);
if(kTriggerDelay.ready()){
drum_part();
melo_part();
master_count+=1;
if(master_count==16){
master_count=0;
}
kTriggerDelay.start(map(mozziAnalogRead(39),0,4096,10,500));
}// kTrigger if文終わり
} //void updateControl()終わり
int updateAudio(){
envB0.update();
envB1.update();
envB2.update();
envB3.update();
envB4.update();
//triWarm1.setPhaseInc(aGliss.next());
int smoothedFreq = aSmooth.next(freq1);
// int low=(svf.next((envB2.next()*(triWarm2.next()>>4))>>3));
int code=envB0.next()*(triWarm0.next()>>8)+envB1.next()*(triWarm1.next()>>8)+envB2.next()*(triWarm2.next()>>8)+envB3.next()*(triWarm3.next()>>8);
return ( (code>>2)+ snare3.next()+snare4.next() +snap1.next()+ +kick9.next()+(hihat1.next())+(hihat2.next()) +clap.next() +water1.next() )>>2;
}
void loop(){
audioHook();
}
void TaskBlink(void *pvParameters) // This is a task.
{
(void) pvParameters;
u8g2.begin();
set_pinmode();
for (;;) // A Task shall never return or exit.
{
cursor_select=map(mozziAnalogRead(A1_meter),0,4095,0,2);
switch(cursor_select){
case 0:
drum_seq_disp();
break;
case 1:
melo_seq_disp_12();
break;
case 2:
melo_seq_disp_34();
break;
}
vTaskDelay(10);
} //for(;;)終わり
}
void set_drum_seq(){
if(digitalRead(cross_button_up))cursor_y_drum+=-1;
if(digitalRead(cross_button_down))cursor_y_drum+=1;
if(digitalRead(cross_button_right))cursor_x_drum+=1;
if(digitalRead(cross_button_left))cursor_x_drum+=-1;
if(cursor_x_drum<0)cursor_x_drum=0;
if(cursor_x_drum>15)cursor_x_drum=15;
if(cursor_y_drum<0)cursor_y_drum=0;
if(cursor_y_drum>7)cursor_y_drum=7;
if(digitalRead(5)){
seq_drum[cursor_y_drum][cursor_x_drum]=true;
}
if(digitalRead(17)){
seq_drum[cursor_y_drum][cursor_x_drum]=false;
}
seq_drum_kick="";
seq_drum_snare3="";
seq_drum_snare4="";
seq_drum_hihat1="";
seq_drum_hihat2="";
seq_drum_clap1="";
seq_drum_water1="";
seq_drum_snap1="";
for(int i=0;i<16;i++){
if(seq_drum[0][i]){
seq_drum_kick+="X";
}else if(seq_drum[0][i]==0){
seq_drum_kick+=".";
}
if(seq_drum[1][i]){
seq_drum_snare3+="X";
}else if(seq_drum[1][i]==0){
seq_drum_snare3+="_";
}
if(seq_drum[2][i]){
seq_drum_snare4+="X";
}else if(seq_drum[2][i]==0){
seq_drum_snare4+=".";
}
if(seq_drum[3][i]){
seq_drum_hihat1+="X";
}else if(seq_drum[3][i]==0){
seq_drum_hihat1+="_";
}
if(seq_drum[4][i]){
seq_drum_hihat2+="X";
}else if(seq_drum[4][i]==0){
seq_drum_hihat2+=".";
}
if(seq_drum[5][i]){
seq_drum_clap1+="X";
}else if(seq_drum[5][i]==0){
seq_drum_clap1+="_";
}
if(seq_drum[6][i]){
seq_drum_water1+="X";
}else if(seq_drum[6][i]==0){
seq_drum_water1+=".";
}
if(seq_drum[7][i]){
seq_drum_snap1+="X";
}else if(seq_drum[7][i]==0){
seq_drum_snap1+="_";
}
}
}
void drum_seq_disp(){
u8g2.clearBuffer();
set_drum_seq();
u8g2.setFont(u8g2_font_amstrad_cpc_extended_8f );
u8g2.drawFrame(master_count*8,0,8,8);
u8g2.drawFrame(master_count*8,7,8,8);
u8g2.drawFrame(master_count*8,15,8,8);
u8g2.drawFrame(master_count*8,23,8,8);
u8g2.drawFrame(master_count*8,31,8,8);
u8g2.drawFrame(master_count*8,39,8,8);
u8g2.drawFrame(master_count*8,47,8,8);
u8g2.drawFrame(master_count*8,53,8,8);
u8g2.drawFrame(master_count*8,63,8,8);
u8g2.drawFrame(cursor_x_drum*8,cursor_y_drum*8,8,8);
// u8g2.setCursor(master_count*5,10);
// u8g2.print(master_count+1);
u8g2.setCursor(0,7);
u8g2.print(seq_drum_kick);
u8g2.setCursor(0,15);
u8g2.print(seq_drum_snare3);
u8g2.setCursor(0,23);
u8g2.print(seq_drum_snare4);
u8g2.setCursor(0,31);
u8g2.print(seq_drum_hihat1);
u8g2.setCursor(0,39);
u8g2.print(seq_drum_hihat2);
u8g2.setCursor(0,47);
u8g2.print(seq_drum_clap1);
u8g2.setCursor(0,53);
u8g2.print(seq_drum_water1);
u8g2.setCursor(0,63);
u8g2.print(seq_drum_snap1);
u8g2.sendBuffer();
}
void drum_part(){
if(seq_drum[0][master_count]) {
kick9.start();
}
if(seq_drum[1][master_count]) {
snare3.start();
}
if(seq_drum[2][master_count]) {
snare4.start();
}
if(seq_drum[3][master_count]) {
hihat1.start();
}
if(seq_drum[4][master_count]) {
hihat2.start();
}
if(seq_drum[5][master_count]) {
clap.start();
}
if(seq_drum[6][master_count]) {
water1.start();
}
if(seq_drum[7][master_count]) {
snap1.start();
}
}
void melo_part(){
if(seq_melo_trig[0][master_count]){
triWarm0.setFreq( mtof(seq_melo[0][master_count]) ) ;
envB0.setADLevels((byte)180, (byte)100); // bassのエンベロープレベル 0~255
envB0.setTimes(attack_time,decay_time,sustain_time,release_time); // bassのエンベロープタイム
envB0.noteOn();
}
if(seq_melo_trig[1][master_count]){
triWarm1.setFreq( mtof(seq_melo[1][master_count]) ) ;
envB1.setADLevels((byte)180, (byte)100); // bassのエンベロープレベル 0~255
envB1.setTimes(attack_time,decay_time,sustain_time,release_time); // bassのエンベロープタイム
envB1.noteOn();
}
if(seq_melo_trig[2][master_count]){
triWarm2.setFreq( mtof(seq_melo[2][master_count]) ) ;
envB2.setADLevels((byte)180, (byte)100); // bassのエンベロープレベル 0~255
envB2.setTimes(attack_time,decay_time,sustain_time,release_time); // bassのエンベロープタイム
envB2.noteOn();
}
if(seq_melo_trig[3][master_count]){
triWarm3.setFreq( mtof(seq_melo[3][master_count]) ) ;
envB3.setADLevels((byte)180, (byte)100); // bassのエンベロープレベル 0~255
envB3.setTimes(attack_time,decay_time,sustain_time,release_time); // bassのエンベロープタイム
envB3.noteOn();
}
}
void set_melo_seq_12(){
if(digitalRead(cross_button_up)&&digitalRead(button_0)==0)cursor_y_melo_12+=-1;
if(digitalRead(cross_button_down)&&digitalRead(button_0)==0)cursor_y_melo_12+=1;
if(digitalRead(cross_button_right)&&digitalRead(button_0)==0)cursor_x_melo_12+=1;
if(digitalRead(cross_button_left)&&digitalRead(button_0)==0)cursor_x_melo_12+=-1;
if(cursor_x_melo_12<0)cursor_x_melo_12=0;
if(cursor_x_melo_12>7)cursor_x_melo_12=7;
if(cursor_y_melo_12<0)cursor_y_melo_12=0;
if(cursor_y_melo_12>3)cursor_y_melo_12=3;
if(cursor_y_melo_12<2){
if(digitalRead(button_0)&&digitalRead(cross_button_up)){
seq_melo[cursor_y_melo_12][cursor_x_melo_12]+=1;
seq_melo[cursor_y_melo_12][cursor_x_melo_12]=constrain(seq_melo[cursor_y_melo_12][cursor_x_melo_12], 0, 128);
seq_melo_trig[cursor_y_melo_12][cursor_x_melo_12]=true;
}
if(digitalRead(button_0)&&digitalRead(cross_button_down)){
seq_melo[cursor_y_melo_12][cursor_x_melo_12]+=-1;
seq_melo[cursor_y_melo_12][cursor_x_melo_12]=constrain(seq_melo[cursor_y_melo_12][cursor_x_melo_12], 0, 128);
seq_melo_trig[cursor_y_melo_12][cursor_x_melo_12]=true;
}
if(digitalRead(button_0)&&digitalRead(cross_button_right)){
seq_melo[cursor_y_melo_12][cursor_x_melo_12]+=12;
seq_melo[cursor_y_melo_12][cursor_x_melo_12]=constrain(seq_melo[cursor_y_melo_12][cursor_x_melo_12], 0, 128);
seq_melo_trig[cursor_y_melo_12][cursor_x_melo_12]=true;
}
if(digitalRead(button_0)&&digitalRead(cross_button_left)){
seq_melo[cursor_y_melo_12][cursor_x_melo_12]+=-12;
seq_melo[cursor_y_melo_12][cursor_x_melo_12]=constrain(seq_melo[cursor_y_melo_12][cursor_x_melo_12], 0, 128);
seq_melo_trig[cursor_y_melo_12][cursor_x_melo_12]=true;
}
if(digitalRead(button_1)){
seq_melo_trig[cursor_y_melo_12][cursor_x_melo_12]=false;
}
if(digitalRead(button_0)){
seq_melo_trig[cursor_y_melo_12][cursor_x_melo_12]=true;
}
}else{
if(digitalRead(button_0)&&digitalRead(cross_button_up)){
seq_melo[cursor_y_melo_12-2][cursor_x_melo_12+8]+=1;
seq_melo[cursor_y_melo_12-2][cursor_x_melo_12+8]=constrain(seq_melo[cursor_y_melo_12-2][cursor_x_melo_12+8], 0, 128);
seq_melo_trig[cursor_y_melo_12-2][cursor_x_melo_12+8]=true;
}
if(digitalRead(button_0)&&digitalRead(cross_button_down)){
seq_melo[cursor_y_melo_12-2][cursor_x_melo_12+8]+=-1;
seq_melo[cursor_y_melo_12-2][cursor_x_melo_12+8]=constrain(seq_melo[cursor_y_melo_12-2][cursor_x_melo_12+8], 0, 128);
seq_melo_trig[cursor_y_melo_12-2][cursor_x_melo_12+8]=true;
}
if(digitalRead(button_0)&&digitalRead(cross_button_right)){
seq_melo[cursor_y_melo_12-2][cursor_x_melo_12+8]+=12;
seq_melo[cursor_y_melo_12-2][cursor_x_melo_12+8]=constrain(seq_melo[cursor_y_melo_12-2][cursor_x_melo_12+8], 0, 128);
seq_melo_trig[cursor_y_melo_12-2][cursor_x_melo_12+8]=true;
}
if(digitalRead(button_0)&&digitalRead(cross_button_left)){
seq_melo[cursor_y_melo_12-2][cursor_x_melo_12+8]+=-12;
seq_melo[cursor_y_melo_12-2][cursor_x_melo_12+8]=constrain(seq_melo[cursor_y_melo_12-2][cursor_x_melo_12+8], 0, 128);
seq_melo_trig[cursor_y_melo_12-2][cursor_x_melo_12+8]=true;
}
if(digitalRead(button_1)){
seq_melo_trig[cursor_y_melo_12-2][cursor_x_melo_12+8]=false;
}
if(digitalRead(button_0)){
seq_melo_trig[cursor_y_melo_12-2][cursor_x_melo_12+8]=true;
}
}
seq_melo_oct0_8="";
seq_melo_key0_8="";
seq_melo_oct1_8="";
seq_melo_key1_8="";
seq_melo_oct0_16="";
seq_melo_key0_16="";
seq_melo_oct1_16="";
seq_melo_key1_16="";
for(int i=0;i<16;i++){
if(i<8){
if(seq_melo_trig[0][i]){
seq_melo_oct0_8+=oct_name[(int)seq_melo[0][i]/12];
}else if(seq_melo_trig[0][i]==0){
seq_melo_oct0_8+="__";
}
if(seq_melo_trig[0][i]){
seq_melo_key0_8+=note_name[(int)seq_melo[0][i]%12];
}else if(seq_melo_trig[0][i]==0){
seq_melo_key0_8+="__";
}
if(seq_melo_trig[1][i]){
seq_melo_oct1_8+=oct_name[(int)seq_melo[1][i]/12];
}else if(seq_melo_trig[1][i]==0){
seq_melo_oct1_8+="__";
}
if(seq_melo_trig[1][i]){
seq_melo_key1_8+=note_name[(int)seq_melo[1][i]%12];
}else if(seq_melo_trig[1][i]==0){
seq_melo_key1_8+="__";
}
} else{
if(seq_melo_trig[0][i]){
seq_melo_oct0_16+=oct_name[(int)seq_melo[0][i]/12];
}else if(seq_melo_trig[0][i]==0){
seq_melo_oct0_16+="__";
}
if(seq_melo_trig[0][i]){
seq_melo_key0_16+=note_name[(int)seq_melo[0][i]%12];
}else if(seq_melo_trig[0][i]==0){
seq_melo_key0_16+="__";
}
if(seq_melo_trig[1][i]){
seq_melo_oct1_16+=oct_name[(int)seq_melo[1][i]/12];
}else if(seq_melo_trig[1][i]==0){
seq_melo_oct1_16+="__";
}
if(seq_melo_trig[1][i]){
seq_melo_key1_16+=note_name[(int)seq_melo[1][i]%12];
}else if(seq_melo_trig[1][i]==0){
seq_melo_key1_16+="__";
}
}
} //for終わり
}//set_melo_seq()終わり
void melo_seq_disp_12(){
u8g2.clearBuffer();
set_melo_seq_12();
u8g2.setFont(u8g2_font_amstrad_cpc_extended_8f );
if(master_count<8){
u8g2.drawFrame(master_count*16,0,8,8);
u8g2.drawFrame(master_count*16,7,8,8);
u8g2.drawFrame(master_count*16,15,8,8);
u8g2.drawFrame(master_count*16,23,8,8);
}
if(master_count>=8){
u8g2.drawFrame((master_count-8)*16,31,8,8);
u8g2.drawFrame((master_count-8)*16,39,8,8);
u8g2.drawFrame((master_count-8)*16,47,8,8);
u8g2.drawFrame((master_count-8)*16,53,8,8);
}
u8g2.drawFrame(cursor_x_melo_12*16,cursor_y_melo_12*16,8,8);
// u8g2.setCursor(master_count*5,10);
// u8g2.print(master_count+1);
u8g2.setCursor(0,7);
u8g2.print(seq_melo_oct0_8);
u8g2.setCursor(0,15);
u8g2.print(seq_melo_key0_8);
u8g2.setCursor(0,23);
u8g2.print(seq_melo_oct1_8);
u8g2.setCursor(0,31);
u8g2.print(seq_melo_key1_8);
u8g2.setCursor(0,39);
u8g2.print(seq_melo_oct0_16);
u8g2.setCursor(0,47);
u8g2.print(seq_melo_key0_16);
u8g2.setCursor(0,53);
u8g2.print(seq_melo_oct1_16);
u8g2.setCursor(0,63);
u8g2.print(seq_melo_key1_16);
u8g2.sendBuffer();
}
void set_melo_seq_34(){
if(digitalRead(cross_button_up)&&digitalRead(button_0)==0)cursor_y_melo_34+=-1;
if(digitalRead(cross_button_down)&&digitalRead(button_0)==0)cursor_y_melo_34+=1;
if(digitalRead(cross_button_right)&&digitalRead(button_0)==0)cursor_x_melo_34+=1;
if(digitalRead(cross_button_left)&&digitalRead(button_0)==0)cursor_x_melo_34+=-1;
if(cursor_x_melo_34<0)cursor_x_melo_34=0;
if(cursor_x_melo_34>7)cursor_x_melo_34=7;
if(cursor_y_melo_34<0)cursor_y_melo_34=0;
if(cursor_y_melo_34>3)cursor_y_melo_34=3;
if(cursor_y_melo_34<2){
if(digitalRead(button_0)&&digitalRead(cross_button_up)){
seq_melo[cursor_y_melo_34+2][cursor_x_melo_34]+=1;
seq_melo[cursor_y_melo_34+2][cursor_x_melo_34]=constrain(seq_melo[cursor_y_melo_34+2][cursor_x_melo_34], 0, 128);
seq_melo_trig[cursor_y_melo_34+2][cursor_x_melo_34]=true;
}
if(digitalRead(button_0)&&digitalRead(cross_button_down)){
seq_melo[cursor_y_melo_34+2][cursor_x_melo_34]+=-1;
seq_melo[cursor_y_melo_34+2][cursor_x_melo_34]=constrain(seq_melo[cursor_y_melo_34+2][cursor_x_melo_34], 0, 128);
seq_melo_trig[cursor_y_melo_34+2][cursor_x_melo_34]=true;
}
if(digitalRead(button_0)&&digitalRead(cross_button_right)){
seq_melo[cursor_y_melo_34+2][cursor_x_melo_34]+=12;
seq_melo[cursor_y_melo_34+2][cursor_x_melo_34]=constrain(seq_melo[cursor_y_melo_34+2][cursor_x_melo_34], 0, 128);
seq_melo_trig[cursor_y_melo_34+2][cursor_x_melo_34]=true;
}
if(digitalRead(button_0)&&digitalRead(cross_button_left)){
seq_melo[cursor_y_melo_34+2][cursor_x_melo_34]+=-12;
seq_melo[cursor_y_melo_34+2][cursor_x_melo_34]=constrain(seq_melo[cursor_y_melo_34+2][cursor_x_melo_34], 0, 128);
seq_melo_trig[cursor_y_melo_34+2][cursor_x_melo_34]=true;
}
if(digitalRead(button_1)){
seq_melo_trig[cursor_y_melo_34+2][cursor_x_melo_34]=false;
}
if(digitalRead(button_0)){
seq_melo_trig[cursor_y_melo_34+2][cursor_x_melo_34]=true;
}
}else{
if(digitalRead(button_0)&&digitalRead(cross_button_up)){
seq_melo[cursor_y_melo_34][cursor_x_melo_34+8]+=1;
seq_melo[cursor_y_melo_34][cursor_x_melo_34+8]=constrain(seq_melo[cursor_y_melo_34][cursor_x_melo_34+8], 0, 128);
seq_melo_trig[cursor_y_melo_34][cursor_x_melo_34+8]=true;
}
if(digitalRead(button_0)&&digitalRead(cross_button_down)){
seq_melo[cursor_y_melo_34][cursor_x_melo_34+8]+=-1;
seq_melo[cursor_y_melo_34][cursor_x_melo_34+8]=constrain(seq_melo[cursor_y_melo_34][cursor_x_melo_34+8], 0, 128);
seq_melo_trig[cursor_y_melo_34][cursor_x_melo_34+8]=true;
}
if(digitalRead(button_0)&&digitalRead(cross_button_right)){
seq_melo[cursor_y_melo_34][cursor_x_melo_34+8]+=12;
seq_melo[cursor_y_melo_34][cursor_x_melo_34+8]=constrain(seq_melo[cursor_y_melo_34][cursor_x_melo_34+8], 0, 128);
seq_melo_trig[cursor_y_melo_34][cursor_x_melo_34+8]=true;
}
if(digitalRead(button_0)&&digitalRead(cross_button_left)){
seq_melo[cursor_y_melo_34][cursor_x_melo_34+8]+=-12;
seq_melo[cursor_y_melo_34][cursor_x_melo_34+8]=constrain(seq_melo[cursor_y_melo_34][cursor_x_melo_34+8], 0, 128);
seq_melo_trig[cursor_y_melo_34][cursor_x_melo_34+8]=true;
}
if(digitalRead(button_1)){
seq_melo_trig[cursor_y_melo_34][cursor_x_melo_34+8]=false;
}
if(digitalRead(button_0)){
seq_melo_trig[cursor_y_melo_34][cursor_x_melo_34+8]=true;
}
}
seq_melo_oct2_8="";
seq_melo_key2_8="";
seq_melo_oct3_8="";
seq_melo_key3_8="";
seq_melo_oct2_16="";
seq_melo_key2_16="";
seq_melo_oct3_16="";
seq_melo_key3_16="";
for(int i=0;i<16;i++){
if(i<8){
if(seq_melo_trig[2][i]){
seq_melo_oct2_8+=oct_name[(int)seq_melo[2][i]/12];
}else if(seq_melo_trig[2][i]==0){
seq_melo_oct2_8+="__";
}
if(seq_melo_trig[2][i]){
seq_melo_key2_8+=note_name[(int)seq_melo[2][i]%12];
}else if(seq_melo_trig[2][i]==0){
seq_melo_key2_8+="__";
}
if(seq_melo_trig[3][i]){
seq_melo_oct3_8+=oct_name[(int)seq_melo[3][i]/12];
}else if(seq_melo_trig[3][i]==0){
seq_melo_oct3_8+="__";
}
if(seq_melo_trig[3][i]){
seq_melo_key3_8+=note_name[(int)seq_melo[3][i]%12];
}else if(seq_melo_trig[3][i]==0){
seq_melo_key3_8+="__";
}
} else{
if(seq_melo_trig[2][i]){
seq_melo_oct2_16+=oct_name[(int)seq_melo[2][i]/12];
}else if(seq_melo_trig[2][i]==0){
seq_melo_oct2_16+="__";
}
if(seq_melo_trig[2][i]){
seq_melo_key2_16+=note_name[(int)seq_melo[2][i]%12];
}else if(seq_melo_trig[2][i]==0){
seq_melo_key2_16+="__";
}
if(seq_melo_trig[3][i]){
seq_melo_oct3_16+=oct_name[(int)seq_melo[3][i]/12];
}else if(seq_melo_trig[3][i]==0){
seq_melo_oct3_16+="__";
}
if(seq_melo_trig[3][i]){
seq_melo_key3_16+=note_name[(int)seq_melo[3][i]%12];
}else if(seq_melo_trig[3][i]==0){
seq_melo_key3_16+="__";
}
}
} //for終わり
}//set_melo_seq()終わり
void melo_seq_disp_34(){
u8g2.clearBuffer();
set_melo_seq_34();
u8g2.setFont(u8g2_font_amstrad_cpc_extended_8f );
if(master_count<8){
u8g2.drawFrame(master_count*16,0,8,8);
u8g2.drawFrame(master_count*16,7,8,8);
u8g2.drawFrame(master_count*16,15,8,8);
u8g2.drawFrame(master_count*16,23,8,8);
}
if(master_count>=8){
u8g2.drawFrame((master_count-8)*16,31,8,8);
u8g2.drawFrame((master_count-8)*16,39,8,8);
u8g2.drawFrame((master_count-8)*16,47,8,8);
u8g2.drawFrame((master_count-8)*16,53,8,8);
}
u8g2.drawFrame(cursor_x_melo_34*16,cursor_y_melo_34*16,8,8);
// u8g2.setCursor(master_count*5,10);
// u8g2.print(master_count+1);
u8g2.setCursor(0,7);
u8g2.print(seq_melo_oct2_8);
u8g2.setCursor(0,15);
u8g2.print(seq_melo_key2_8);
u8g2.setCursor(0,23);
u8g2.print(seq_melo_oct3_8);
u8g2.setCursor(0,31);
u8g2.print(seq_melo_key3_8);
u8g2.setCursor(0,39);
u8g2.print(seq_melo_oct2_16);
u8g2.setCursor(0,47);
u8g2.print(seq_melo_key2_16);
u8g2.setCursor(0,53);
u8g2.print(seq_melo_oct3_16);
u8g2.setCursor(0,63);
u8g2.print(seq_melo_key3_16);
u8g2.sendBuffer();
}
void set_freq(){
snare2.setFreq( 6*(float)snare2_SAMPLERATE/(float)snare2_NUM_CELLS );
snare3.setFreq( 6*(float)snare3_SAMPLERATE/(float)snare3_NUM_CELLS );
snare4.setFreq( 6*(float)snare4_SAMPLERATE/(float)snare4_NUM_CELLS );
kick.setFreq( 16*(float)KICKTABLE_SAMPLERATE/(float)KICKTABLE_NUM_CELLS );
hihat1.setFreq( 16*(float)HIHATTABLE_SAMPLERATE/(float)HIHATTABLE_NUM_CELLS );
clap.setFreq( 6*(float)clap2_SAMPLERATE/(float)clap2_NUM_CELLS );
test2.setFreq( (float)5.1*(float)test2_SAMPLERATE/(float)test2_NUM_CELLS );
test3.setFreq( 3*(float)test3_SAMPLERATE/(float)test3_NUM_CELLS );
water1.setFreq( 5*(float)water1_SAMPLERATE/(float)water1_NUM_CELLS );
snap1.setFreq( (float)6*(float)snap1_SAMPLERATE/(float)snap1_NUM_CELLS );
kick9.setFreq( (float)6*(float)kick9_SAMPLERATE/(float)kick9_NUM_CELLS );
hihat2.setFreq( (float)7*(float)chihat2_SAMPLERATE/(float)chihat2_NUM_CELLS );
}
void set_pinmode(){
pinMode(cross_button_up,INPUT);
pinMode(cross_button_down,INPUT);
pinMode(cross_button_left,INPUT);
pinMode(cross_button_right,INPUT);
pinMode(button_0,INPUT);
pinMode(button_1,INPUT);
pinMode(button_2,INPUT);
pinMode(button_3,INPUT);
gpio_set_pull_mode(GPIO_NUM_13, GPIO_PULLDOWN_ONLY);
gpio_set_pull_mode(GPIO_NUM_23, GPIO_PULLDOWN_ONLY);
gpio_set_pull_mode(GPIO_NUM_19, GPIO_PULLDOWN_ONLY);
gpio_set_pull_mode(GPIO_NUM_18, GPIO_PULLDOWN_ONLY);
gpio_set_pull_mode(GPIO_NUM_5, GPIO_PULLDOWN_ONLY);
gpio_set_pull_mode(GPIO_NUM_17, GPIO_PULLDOWN_ONLY);
gpio_set_pull_mode(GPIO_NUM_16, GPIO_PULLDOWN_ONLY);
gpio_set_pull_mode(GPIO_NUM_4, GPIO_PULLDOWN_ONLY);
}
ピンと可変抵抗、タクトスイッチなどの対応です。
bluetooth通信ワイヤレスコントローラを作りました。
maxパッチを制御できます。
#define A0_meter 39
#define A1_meter 34
#define A2_meter 35
#define A3_meter 32
#define A4_meter 33
#define A5_meter 27
#define cross_button_up 13
#define cross_button_down 19
#define cross_button_left 23
#define cross_button_right 18
#define button_0 5
#define button_1 17
#define button_2 16
#define button_3 4
#include "BluetoothSerial.h"
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
BluetoothSerial SerialBT;
void setup() {
Serial.begin(115200);
SerialBT.begin("ESP33"); //Bluetooth device name
set_pinmode();
}
void loop() {
SerialBT.print(analogRead(39));
SerialBT.print(" ");
SerialBT.print(analogRead(34));
SerialBT.print(" ");
SerialBT.print(analogRead(35));
SerialBT.print(" ");
SerialBT.print(analogRead(32));
SerialBT.print(" ");
SerialBT.print(analogRead(33));
SerialBT.print(" ");
SerialBT.print(analogRead(27));
SerialBT.print(" ");
SerialBT.print(digitalRead(cross_button_up));
SerialBT.print(" ");
SerialBT.print(digitalRead(cross_button_down));
SerialBT.print(" ");
SerialBT.print(digitalRead(cross_button_left));
SerialBT.print(" ");
SerialBT.print(digitalRead(cross_button_right));
SerialBT.print(" ");
SerialBT.print(digitalRead(button_0));
SerialBT.print(" ");
SerialBT.print(digitalRead(button_1));
SerialBT.print(" ");
SerialBT.print(digitalRead(button_2));
SerialBT.print(" ");
SerialBT.print(digitalRead(button_3));
SerialBT.println();
}
void set_pinmode(){
pinMode(cross_button_up,INPUT);
pinMode(cross_button_down,INPUT);
pinMode(cross_button_left,INPUT);
pinMode(cross_button_right,INPUT);
pinMode(button_0,INPUT);
pinMode(button_1,INPUT);
pinMode(button_2,INPUT);
pinMode(button_3,INPUT);
gpio_set_pull_mode(GPIO_NUM_13, GPIO_PULLDOWN_ONLY);
gpio_set_pull_mode(GPIO_NUM_23, GPIO_PULLDOWN_ONLY);
gpio_set_pull_mode(GPIO_NUM_19, GPIO_PULLDOWN_ONLY);
gpio_set_pull_mode(GPIO_NUM_18, GPIO_PULLDOWN_ONLY);
gpio_set_pull_mode(GPIO_NUM_5, GPIO_PULLDOWN_ONLY);
gpio_set_pull_mode(GPIO_NUM_17, GPIO_PULLDOWN_ONLY);
gpio_set_pull_mode(GPIO_NUM_16, GPIO_PULLDOWN_ONLY);
gpio_set_pull_mode(GPIO_NUM_4, GPIO_PULLDOWN_ONLY);
}
arduino nanoでミニシンセを作る
可変抵抗など余っていたのでnanoで組みました。小さいです。重さは60gくらい。中身は前に作ったunoとmozziのスケッチの改変。4ステップモノフォニックシーケンサ•ローパス•波形は2つ•パルスシンクと内部テンポの切り替えが出来ます。シーケンサは音的には4ステップだけど再生パターンを切り替えたりして1~8ステップになったりできて再生パターンは10パターンです。
下の4つの可変抵抗は4ステップの音の高さ。
上は再生パターン・テンポ・フィルタ・エンベロープです。
下はserumのウェーブテーブルを切り貼りして入れてみたものです。いずれウェーブテーブル波形を可変出来たらよいですがまだです。
以下がスケッチです。Oscilの所はserumのウェーブテーブルなのでそこだけプリセットなどののテーブルに替える必要があります。
/*
monosynth
*/
#define upper_switch 7
#define under_switch 12
#define knob_upper_0 4
#define knob_upper_1 5
#define knob_upper_2 6
#define knob_upper_3 7
#define knob_under_0 0
#define knob_under_1 1
#define knob_under_2 2
#define knob_under_3 3
#define led_0 3
#define led_1 11
#define led_2 5
#define led_3 6
#define gate_jack 8
#include <MozziGuts.h> // Mozziの基本ヘッダファイル
#include <Oscil.h> // オシレータのテンプレート
#include <tables/SQUARE_NO_ALIAS_2048_int8.h>
#include <tables/SAW2048_int8.h>
#include <tables/SAW8192_int8.h>
#include <tables/saw_dist_8192.h>
#include <tables/bipole_harmonic_8192.h>
#include <tables/debussy_8192.h>
#include <tables/shubby_saw_8192.h>
#include <tables/triangle_warm8192_int8.h>
#include <tables/TRIANGLE_DIST_CUBED_2048_int8.h>
#include <tables/TRIANGLE_DIST_SQUARED_2048_int8.h>
#include <tables/dist_doot_8192.h>
#include <tables/SMOOTHSQUARE8192_int8.h>
#include <tables/SAW_ANALOGUE512_int8.h>
#include <mozzi_rand.h>
#include <LowPassFilter.h>
LowPassFilter lpf;
char resonance = 230; // range 0-255, 255 is most resonant
#include <StateVariable.h>
StateVariable <LOWPASS> svf;
#include <ADSR.h> //エンベロープ
ADSR <AUDIO_RATE, AUDIO_RATE> envB1;
ADSR <AUDIO_RATE, AUDIO_RATE> envB2;
#include <mozzi_midi.h>
// SIN2048_DATA2048のデータをaSinに格納 その他も同様
/*
Oscil <SQUARE_NO_ALIAS_2048_NUM_CELLS, AUDIO_RATE> triWarm1(SQUARE_NO_ALIAS_2048_DATA);
Oscil <SQUARE_NO_ALIAS_2048_NUM_CELLS, AUDIO_RATE> triWarm2(SQUARE_NO_ALIAS_2048_DATA);
Oscil <SQUARE_NO_ALIAS_2048_NUM_CELLS, AUDIO_RATE> triWarm3(SQUARE_NO_ALIAS_2048_DATA);
Oscil <SQUARE_NO_ALIAS_2048_NUM_CELLS, AUDIO_RATE> triWarm4(SQUARE_NO_ALIAS_2048_DATA);
*/
//Oscil <SAW8192_NUM_CELLS, AUDIO_RATE> oscil_1(SAW8192_DATA);
//Oscil <saw_dist_8192_NUM_CELLS,AUDIO_RATE> oscil_1(saw_dist_8192_DATA);
Oscil <shubby_saw_8192_NUM_CELLS,AUDIO_RATE> oscil_1(saw_dist_8192_DATA);
//Oscil <debussy_8192_NUM_CELLS,AUDIO_RATE> oscil_1(debussy_8192_DATA);
Oscil <dist_doot_8192_NUM_CELLS,AUDIO_RATE> oscil_2(dist_doot_8192_DATA);
//Oscil <bipole_harmonic_8192_NUM_CELLS,AUDIO_RATE> oscil_2(bipole_harmonic_8192_DATA);
//Oscil <SMOOTHSQUARE8192_NUM_CELLS, AUDIO_RATE> oscil_2(SMOOTHSQUARE8192_DATA);
//Oscil <SQUARE_NO_ALIAS_2048_NUM_CELLS, AUDIO_RATE> oscil_2(SQUARE_NO_ALIAS_2048_DATA);
//Oscil <TRIANGLE_DIST_CUBED_2048_NUM_CELLS, AUDIO_RATE> triWarm1(TRIANGLE_DIST_CUBED_2048_DATA);
//Oscil <TRIANGLE_DIST_SQUARED_2048_NUM_CELLS, AUDIO_RATE> oscil_1(TRIANGLE_DIST_SQUARED_2048_DATA);
/*
Oscil <SAW2048_NUM_CELLS, AUDIO_RATE> triWarm1(SAW2048_DATA);
Oscil <SAW2048_NUM_CELLS, AUDIO_RATE> triWarm2(SAW2048_DATA);
Oscil <SAW2048_NUM_CELLS, AUDIO_RATE> triWarm3(SAW2048_DATA);
Oscil <SAW2048_NUM_CELLS, AUDIO_RATE> triWarm4(SAW2048_DATA);
*/
/*
Oscil <TRIANGLE_WARM8192_NUM_CELLS, AUDIO_RATE> triWarm1(TRIANGLE_WARM8192_DATA);
Oscil <TRIANGLE_WARM8192_NUM_CELLS, AUDIO_RATE> triWarm2(TRIANGLE_WARM8192_DATA);
Oscil <TRIANGLE_WARM8192_NUM_CELLS, AUDIO_RATE> triWarm3(TRIANGLE_WARM8192_DATA);
Oscil <TRIANGLE_WARM8192_NUM_CELLS, AUDIO_RATE> triWarm4(TRIANGLE_WARM8192_DATA);
*/
/*
Oscil <TRIANGLE_VALVE_2_2048_NUM_CELLS, AUDIO_RATE> triWarm1(TRIANGLE_VALVE_2_2048_DATA);
Oscil <TRIANGLE_VALVE_2_2048_NUM_CELLS, AUDIO_RATE> triWarm2(TRIANGLE_VALVE_2_2048_DATA);
Oscil <TRIANGLE_VALVE_2_2048_NUM_CELLS, AUDIO_RATE> triWarm3(TRIANGLE_VALVE_2_2048_DATA);
Oscil <TRIANGLE_VALVE_2_2048_NUM_CELLS, AUDIO_RATE> triWarm4(TRIANGLE_VALVE_2_2048_DATA);
*/
/*
Oscil <SMOOTHSQUARE8192_NUM_CELLS, AUDIO_RATE> triWarm1(SMOOTHSQUARE8192_DATA);
Oscil <SMOOTHSQUARE8192_NUM_CELLS, AUDIO_RATE> triWarm2(SMOOTHSQUARE8192_DATA);
Oscil <SMOOTHSQUARE8192_NUM_CELLS, AUDIO_RATE> triWarm3(SMOOTHSQUARE8192_DATA);
Oscil <SMOOTHSQUARE8192_NUM_CELLS, AUDIO_RATE> triWarm4(SMOOTHSQUARE8192_DATA);
*/
/*
Oscil <SAW_ANALOGUE512_NUM_CELLS, AUDIO_RATE> triWarm1(SAW_ANALOGUE512_DATA);
Oscil <SAW_ANALOGUE512_NUM_CELLS, AUDIO_RATE> triWarm2(SAW_ANALOGUE512_DATA);
Oscil <SAW_ANALOGUE512_NUM_CELLS, AUDIO_RATE> triWarm3(SAW_ANALOGUE512_DATA);
Oscil <SAW_ANALOGUE512_NUM_CELLS, AUDIO_RATE> triWarm4(SAW_ANALOGUE512_DATA);
*/
// トリガー(発音タイミング)のためのヘッダ
#include <EventDelay.h>
EventDelay kTriggerDelay;
EventDelay LEDdelay;
// スムースに値を変化させるためのヘッダ
int gainF=240; //ゲイン調整用
byte seq_counter_master=0; //シーケンス用変数
byte seq_counter_melo=0; //シーケンス用変数
byte seq_select=0; //シーケンスパターン選択用変数
int note_number=0; //ノートナンバー用変数
byte seq_step[10]={8,8,8,6,8,8,8,6,8,8 };
int note_seq_0=0; // ノートナンバー0ステップ目読み取り変数
int note_seq_1=0; //
int note_seq_2=0; //
int note_seq_3=0; //
byte seq_data[10][8]={{0,1,2,3,0,1,2,3},
{3,2,1,0,3,2,1,0},
{0,1,2,3,3,2,1,0},
{0,1,2,3,2,1,0,1},
{0,2,1,3,2,3,0,3},
{0,3,1,2,0,3,2,1},
{0,3,2,1,3,0,1,2},
{0,1,2,0,1,2,0,1},
{0,1,0,1,0,1,0,1},
{0,0,0,0,0,0,0,0}};
int filt_freq; //フィルター周波数変数
byte gate_clock_switch; //スイッチ切り替え変数
byte pulse;
int tempo;
bool trigger;
byte check; //パルスの立ち上がりの判定用
bool note_on_1,note_on_2;
unsigned int attackBa1, decayBa1, sustainBa1, releaseBa1;
unsigned int att_fil,dec_fil,sus_fil,rel_fil;
int att1,de1,sus1,re1,att2,de2,sus2,re2;
// コントロールレートをあらかじめ定義
#define CONTROL_RATE 128
void setup(){
startMozzi(CONTROL_RATE);
kTriggerDelay.start(100);// トリガーのタイミング指定(100ms)
LEDdelay.start(10);
randSeed();
// pinMode(3,INPUT_PULLUP);
pinMode(upper_switch,INPUT_PULLUP); //トグルスイッチ
pinMode(gate_jack,INPUT); //パルス用
pinMode(under_switch,INPUT_PULLUP);
pinMode(led_0,OUTPUT);
pinMode(led_1,OUTPUT);
pinMode(led_2,OUTPUT);
pinMode(led_3,OUTPUT);
check=0;
}
void updateControl(){
gate_clock_switch=digitalRead(upper_switch); //トグルスイッチ
pulse=digitalRead(gate_jack); // パルス入力
if(gate_clock_switch==1){ //トグルスイッチの切り替えの判断
trigger=kTriggerDelay.ready(); //シンセに内蔵のテンポで
}else{
if(pulse==0&&check==0){ //パルスが来て、かつチェックが0なら
trigger=true; //トリガーする
check=1; //チェックを1にして次はトリガーしないようにする
}else{
trigger=false;
}
if(pulse==1){ //パルスが0ならチェックを0にして次にパルスが1になった時にトリガー出来るようにする.
check=0;
}
}
// gainF=map(mozziAnalogRead(knob_upper_0),0,1030,0,50);
int tempo=map(mozziAnalogRead(knob_upper_1),0,1030,1000,1);
/*
char mod1=rand(9)-4; //オシレーターの周波数を少しずらすため(-4~4の範囲で)
char mod2=rand(9)-4;
char mod3=rand(9)-4;
char mod4=rand(9)-4;
*/
byte lf1=map(mozziAnalogRead(knob_upper_2),0,1030,10,220);;
byte lf2=map(lf1,10,240,10,100);;
// byte freqrange=map(mozziAnalogRead(3),0,1024,0,7);;
// int count2=areadAds(mozziAnalogRead(1));
int ads2=map(mozziAnalogRead(knob_upper_3),0,1030,10,2000);
if (ads2<=500){ // adsrのパラメーター
att1=0;
de1=0;
sus1=0;
re1=ads2;
att2=0;
de2=ads2;
sus2=0;
re2=0;
}else if(500<ads2&&ads2<=650){
att1=ads2-500;
de1=0;
sus1=0;
re1=500;
att2=ads2-500;
de2=450;
sus2=0;
re2=0;
}else if(650<ads2&&ads2<=750){
att1=100-(ads2-650);
de1=0;
sus1=ads2-650;
re1=500;
att2=100-(ads2-650);
de2=500;
sus2=0;
re2=ads2-650;
}else if(750<ads2){
att1=0;
de1=0;
sus1=ads2;
re1=500;
att2=0;
de2=ads2;
sus2=0;
re2=500;
} //adsrのパラメーター終わり
note_seq_0=map(mozziAnalogRead(knob_under_0),0,1024,0,100);
note_seq_1=map(mozziAnalogRead(knob_under_1),0,1024,0,100);
note_seq_2=map(mozziAnalogRead(knob_under_2),0,1024,0,100);
note_seq_3=map(mozziAnalogRead(knob_under_3),0,1024,0,100);
seq_select=map(mozziAnalogRead(knob_upper_0),0,1024,0,10);
attackBa1=att1; //ADSRの値を設定する
decayBa1=de1;
sustainBa1=sus1;
releaseBa1=re1;
att_fil=att2; //フィルターのADSRの値を設定する
dec_fil=de2;
sus_fil=sus2;
rel_fil=re2;
if(trigger){
seq_counter_melo=seq_data[seq_select][seq_counter_master];
switch(seq_counter_melo){
case 0:
note_number=note_seq_0;
digitalWrite(led_0,HIGH);
digitalWrite(led_1,LOW);
digitalWrite(led_2,LOW);
digitalWrite(led_3,LOW);
break;
case 1:
note_number=note_seq_1;
digitalWrite(led_0,LOW);
digitalWrite(led_1,HIGH);
digitalWrite(led_2,LOW);
digitalWrite(led_3,LOW);
break;
case 2:
note_number=note_seq_2;
digitalWrite(led_0,LOW);
digitalWrite(led_1,LOW);
digitalWrite(led_2,HIGH);
digitalWrite(led_3,LOW);
break;
case 3:
note_number=note_seq_3;
digitalWrite(led_0,LOW);
digitalWrite(led_1,LOW);
digitalWrite(led_2,LOW);
digitalWrite(led_3,HIGH);
break;
}
oscil_1.setFreq( mtof(note_number) ) ;
oscil_2.setFreq( mtof(note_number) ) ;
envB1.setADLevels((byte)250, (byte)250); // bassのエンベロープレベル 0~255
envB1.setTimes(attackBa1, decayBa1,sustainBa1, releaseBa1); // bassのエンベロープタイム
envB1.noteOn();
envB2.setADLevels((byte)lf1, (byte)lf2); // bassのエンベロープレベル 0~255
envB2.setTimes(att_fil, dec_fil,sus_fil, rel_fil); // bassのエンベロープタイム
envB2.noteOn();
kTriggerDelay.start(tempo);
seq_counter_master+=1;
if(seq_counter_master>=seq_step[seq_select])seq_counter_master=0;
} // kTrigger if文終わり
// freq=filt.next();
svf.setResonance(200);
svf.setCentreFreq(filt_freq*14);
if(digitalRead(under_switch)){
note_on_1=false;
note_on_2=true;
}else{
note_on_1=true;
note_on_2=false;
}
} //void updateControl()終わり
int updateAudio(){
envB1.update();
envB2.update();
filt_freq=envB2.next();
int env2=envB1.next();
// return lpf.next((((( ((env2*triWarm1.next() )>>7))+ ( ((env2*triWarm2.next() )>>7))+ ( ((env2*triWarm3.next() )>>7))+( ((env2*triWarm4.next() )>>7)) )>>5)*gainF )>>7) ; // サイン波とノイズを足す ノイズはgainで256倍されているので8ビットシフト(=1/2^8倍)で音量を小さくする
// return svf.next(((( ((env2*(triWarm1.next()+triWarm2.next()+triWarm3.next()) )>>5))>>4 )*gainF )>>6) ;
// return svf.next((( (((env2*note_on_1*oscil_1.next())>>5)>>4)+ (((env2*note_on_2*oscil_2.next())>>5)>>4) ) )*gainF )>>5 ;
return svf.next((( (((env2*note_on_1*oscil_1.next())>>3)>>3)+ (((env2*note_on_2*oscil_2.next())>>3)>>3) ) ) )>>4 ;
}
void loop(){
audioHook();
}
ESP32とnanoでテンポ同期して演奏してみました。
テンポなどについて
mozziのスケッチでは
EventDelay kTriggerDelay;をつかって一定のタイミングでシーケンサを動かしています。
kTriggerDelay.ready()はkTriggerDelay.start(100)が実行されてから時間が経ったかどうか判別します。100なら100msごとにif文内の処理を実行します。
これを使って一定のタイミングで動作させています。
if( kTriggerDelay.ready() ){ // 100ms経ったかどうか判別
//この間に処理を書く
kTriggerDelay.start(100); // カウント開始
} // kTrigger 100msごとに繰り返す
テンポシンク機能などについて
ESP32側からパルス信号のようなものを出してnano側で読み取ってテンポを同期させています。
読み取りに関してはこんな感じで書いています
gate_clock_switch=digitalRead(upper_switch); //テンポシンクと内蔵テンポ切り替え用のトグルスイッチの読み取り
pulse=digitalRead(gate_jack); // パルス入力読み取り用
if(gate_clock_switch==1){ //トグルスイッチの切り替えの判断
trigger=kTriggerDelay.ready(); //内蔵のテンポでクロックする
}else{
if(pulse==0&&check==0){ //パルスが来て、かつチェックが0なら
trigger=true; //トリガーする
check=1; //チェックを1にして次はトリガーしないようにする
}else{
trigger=false; //トリガーしない
}
if(pulse==1){ //パルスが0ならチェックを0にして次にパルスが1になった時にトリガー出来るようにする.
check=0;
}
}
mozziのウェーブテーブル
作製したmozziのウェーブテーブルです。一応ここからダウンロードできます。
...........