![見出し画像](https://assets.st-note.com/production/uploads/images/59885086/rectangle_large_type_2_d77bfe70efa84ac48601783896a9bb16.jpg?width=1200)
ESP32とmozziで作る電子楽器_メモ_備忘録1
一応、個人の備忘録ですので記事内容等、現在は変更されている場合があります。参考までに。
fendoap - Passing Scenery : buffer zone records
初めに
Mozziはarduinoの音響ライブラリー。それを用いるとシンセサイザーなどが作れる。制作のメモなどをまとめています。その2は以下↓
下は以前にarduino unoで制作したシンセサイザー楽器。
https://sensorium.github.io/Mozzi/
MozziはESP32をサポートしてるのでarduino IDEで書けばESP32でmozziが使える。今回はESP32-WROOM-32Eを試してみることに。
https://akizukidenshi.com/catalog/g/gM-15673/
Mozzi使用時のESP32-WROOM-32Eのピンについて
注意! 現在とピン状況変わっている場合がありますので参考までに:
mozziを使用させながらESP32のピンについて動作を確認。
デジタル出力は15,2,4,16,17,5,18,19,21,22,23,13,12,14,27,33,32が使えた。
デジタル入力は15,2,4,16,17,5,18,19,21,22,23,13,12,14,27,33,32,35,34,39が使えた。なぜか36が使えなかった。
アナログ入力は36,39,34,35,32,33,27,14,12,13,4,2,15が使えた。23,22,21,19,18,5,17,16は使えなかった。
以下のようなOLEDモジュールなどのI2C通信を使う場合22pinをSCLに21pinをSDAに接続するため22,21pinは入出力には使えない。
OLEDのライブラリについて
上記のKeeYees OLEDディスプレイについてはAdafruit_SSD1306.hライブラリが使えた。初めスケッチ例のssd1306_128x64_i2cが動かなかったが
#define SCREEN_ADDRESS 0x3D の部分の0x3Dを
#define SCREEN_ADDRESS 0x3C のように 0x3Cとすると動いた。
がAdafruit_SSD1306.hライブラリをmozziと並行して使おうとするとうまくいかなかった。描画しているときは音が止まってうまく動かない。
そこでu8g2ライブラリを試してみた。
U8g2の描画モードについて
U8g2にはfull bufferモード page bufferモード u8x8 characterモードがあり、それぞれ
full bufferモード
・速い ・多くのRAMを使う
page bufferモード
・遅い ・RAMの消費は少ない
u8x8 characterモード
・速い ・RAMの消費は少ない ・グラフィックの表示ができない
という違いがある。
full bufferモードにするときには例えば
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
のNONAME_1の部分を
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
のようにNONAME_Fのようにする。
full bufferモードの時は
u8g2.clearBuffer(); // 描画の記述をclearBuffer()とsendBuffer()で挟む
u8g2.drawStr(2,30,s); //間に描画の記述を書く
u8g2.sendBuffer();
page bufferモードの時は
u8g2.firstPage();
do {
u8g2.drawStr(2,30,s); //do_while文の間に描画の記述を書く
} while ( u8g2.nextPage() );
のように書く。
I2CのOLEDとmozziの併用時の遅延について
初めI2CとSPIの違いが判らずI2CのOLEDを入手した。
がmozziとI2CのOLEDを併用して試してみると音の遅延があった。調べてみるとSPIのほうが速度が速いらしくSPIのOLEDを選択するのが良いかもしれない。なんとかI2Cでも音の遅延を少なくしたいと思いあれこれしてみたところ一応音の遅延は減った。以下にいくつか試したこと。
void setup(){
u8g2.setBusClock(40000000); //これを数字を大きくして設定する。
}
u8g2.setBusClock(40000000)で多分信号を送るスピードを設定できるらしい。これを大きくしてsetup()に書き込むと遅延が少なくなった。数字は適当に大きくてもエラーにはならなかった。
それからmozziのupdateControl()内で描画を記述する場合
#define CONTROL_RATE 1024 //
#define CONTROL_RATE を大きくしたらいいかもしれない。
I2CでのOLEDのテストも兼ねて試した動画_1。
音と映像はI2Cと併用でこんな感じくらいまでは動くみたい。
試しで作って変数名とかは適当でいろいろ実験で試した途中に使ったコードも散らかってますがコードは一応以下に載せてます。
#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
//U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ 16, /* data=*/ 17);
//U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
//U8G2_SSD1306_128X64_ALT0_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); // same as the NONAME variant, but may solve the "every 2nd line skipped" problem
//U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* reset=*/ 8);
//U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE); // All Boards without Reset of the Display
//U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ 16, /* data=*/ 17, /* reset=*/ U8X8_PIN_NONE); // ESP32 Thing, pure SW emulated I2C
//U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ 1, /* data=*/ 1); // ESP32 Thing, HW I2C with pin remapping
//U8G2_SSD1306_128X64_NONAME_1_6800 u8g2(U8G2_R0, 13, 11, 2, 3, 4, 5, 6, A4, /*enable=*/ 7, /*cs=*/ 10, /*dc=*/ 9, /*reset=*/ 8);
//U8G2_SSD1306_128X64_NONAME_1_8080 u8g2(U8G2_R0, 13, 11, 2, 3, 4, 5, 6, A4, /*enable=*/ 7, /*cs=*/ 10, /*dc=*/ 9, /*reset=*/ 8);
//U8G2_SSD1306_128X64_VCOMH0_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8); // same as the NONAME variant, but maximizes setContrast() range
//U8G2_SSD1306_128X64_ALT0_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8); // same as the NONAME variant, but may solve the "every 2nd line skipped" problem
#define SECONDS 4;
int A=0;
int B=1;
int C=2;
bool Ab1,Bb1,Cb1;
bool Ab2,Bb2,Cb2;
bool Ab3,Bb3,Cb3;
bool Ab4,Bb4,Cb4;
int red[]={21,22,23,24,25,26,27,28};
int green[]={1,2,3,4,35,36,37,38};
int i=0;
int timedata=0;
int timebase=0;
int row[]={52,53,42,43, 14,15,17,19};
boolean matrixc[8][8];
boolean matrix[8][8] = {
{ 0, 0, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 1, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 0, 1, 0, 0, 0 },
{ 1, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 1, 0, 0, 0, 0, 1 },
{ 0, 0, 0, 0, 1, 0, 0, 0 }
};
boolean matrix1[8][8] = {
{ 0, 0, 1, 0, 0, 0, 1, 0 },
{ 1, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 0, 1 },
{ 1, 0, 1, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 1, 1, 1, 0 },
{ 0, 1, 1, 0, 0, 0, 0, 1 },
{ 1, 0, 1, 0, 1, 0, 0, 0 }
};
boolean matrix2[8][8] = {
{ 0, 0, 1, 0, 1, 1, 0, 0 },
{ 1, 1, 0, 1, 1, 0, 0, 0 },
{ 0, 1, 0, 0, 1, 1, 0, 1 },
{ 1, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 1, 0, 1 },
{ 0, 1, 0, 0, 1, 0, 0, 1 },
{ 0, 1, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 1, 1, 1, 0, 1 }
};
#include <MozziGuts.h> // Mozziの基本ヘッダファイル
#include <Oscil.h> // オシレータのテンプレート
#include <mozzi_rand.h>
#include <ADSR.h> //エンベロープ
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;
ADSR <AUDIO_RATE, AUDIO_RATE> envB8;
#include <mozzi_midi.h>
#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> triWarm1(TRIANGLE_DIST_CUBED_2048_DATA);
//Oscil <TRIANGLE_WARM8192_NUM_CELLS, AUDIO_RATE> triWarm2(TRIANGLE_WARM8192_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;
EventDelay sttdelay;
#include <StateVariable.h>
StateVariable <LOWPASS> svf;
// スムースに値を変化させるためのヘッダ
int count=0;
int kleady=0;
int sttutter=0;
int cul_A=0;
int cul_B=0;
byte pin5;
byte pulse;
int tempo;
int tempo1=0;
bool trigger;
byte check; //パルスの立ち上がりの判定用
int trigA=0;
bool seqsn1[]={0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,1, 0,0,1,0, 0,0,1,0, 0,0,0,0, 0,1,0,0};
bool seqsn2[]={0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0};
bool seqk[]={1,0,0,1, 0,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0, 0,1,0,0};
bool seqh1[]={0,0,1,0, 0,0,1,0, 0,0,1,0, 0,0,1,0, 0,0,1,0, 0,0,1,0, 0,0,1,0, 0,0,1,0};
bool seqh2[]={1,0,1,0, 0,1,1,0, 1,0,1,0, 1,0,1,0, 1,0,1,0, 1,0,1,0, 0,0,1,0, 0,0,1,0};
bool seqc[]={0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,1,0, 0,0,0,1, 0,0,1,0, 1,0,0,0, 0,1,0,0};
bool seqsnap[]={1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1};
bool seqt[]={0,0,0,1, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,1,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0};
float seqf1[]={3,3,3,3, 4,4,4,4, 3.75,3.75,3.75,3.75, 2.812,2.812,2.812,2.812, 2.25,2.25,2.25,2.25, 2.7,2.7,2.7,2.7, 3,3,3,3, 4,4,4,4};
bool seqm[]={0,0,40,0, 40,0,40,0, 0,40,0,40, 0,40,0,0};
bool seqtt[]={0,0,0,0, 1,0,0,1, 0,0,0,0, 1,0,0,0};
//int melo[]={63,65,67,70,72,65,70,67, 70,65,70,65,63,65,67,63};
int melo[]={63,65,67,70,72,65,70,67,70,65,70,65,63,65,67,63, 70,72,70,72,74,75,72,70,77,70,72,75,70,75,72,77, 82,77,79,75,79,75,79,74,75,72,75,77,79,74,82,75 ,79,84,82,77,67,65,67,70,75,72,77,79,82,86,84,87, 77,79,75,79,82,74,70,72, 74,75,79,72,67,72,77,79, 70,86,91,77,82,84,87,79, 82,82,74,77,72,75,72,74, 82,77,79,74,87,84,77,91, 75,72,86,74,79,84,82,89, 91,86,94,82,87,77,75,91, 75,86,82,79,82,87,84,79};
int ser=0;
int sertime=10;
int rseqs,rseqk,rseqh,rseqc,rmel1;
int pseq1,pseq2,pseq3,pseq4,pseq5,pseq6,pseq7,pseq8,pseq9,pseq10;
int add=1;
int dellaa=0;
int delch=0;
int countB=0;
int note2c=0;
int note3c=0;
int trigB=0;
int trigC=0;
int trigD=0;
int trigE=0;
int trigF=0;
int trigBcount=0;
int trigCcount=0;
int trigDcount=0;
int trigEcount=0;
int trigFcount=0;
//Oscil <SQUARE_NO_ALIAS_2048_NUM_CELLS, AUDIO_RATE> triWarm2(SQUARE_NO_ALIAS_2048_DATA);
// コントロールレートをあらかじめ定義
#define CONTROL_RATE 1024
void setup(){
u8g2.begin();
pinMode(8,INPUT_PULLUP);
u8g2.setBusClock(40000000);
startMozzi(CONTROL_RATE);
kTriggerDelay.start(100);// トリガーのタイミング指定(100ms)
set_freq();
u8g2.setFontMode(1);
u8g2.enableUTF8Print();
u8g2.setFont(u8g2_font_b10_t_japanese1);
u8g2.setFontDirection(0);
}
void updateControl(){
int check1=mozziAnalogRead(A0);
if(kTriggerDelay.ready()&&countB<=1024){
A=random(100);
B=random(40);
int c=random(100);
int d=random(30);
int ee=random(100);
int ff=random(30);
int gg=random(100);
int hh=random(30);
u8g2.clearBuffer();
u8g2.setFontDirection(0);
// u8g2.setFont(u8g2_font_b10_t_japanese1);
u8g2.setFont(u8g2_font_5x7_tf);
u8g2.drawStr(10, 50, "fendoap");
u8g2.drawCircle(40,50,random(20));
u8g2.drawFrame(40,50,random(30),random(20));
if(countB>=128&&countB<=640||countB>=768){
if(seqsn1[count]) { snare4.start();
u8g2.setCursor(90, 20);
u8g2.print( "snare");
}
if(seqsn2[count]) {
snare3.start();
u8g2.setCursor(90, 20);
u8g2.print( "snare");
}
if(seqt[count]) {
u8g2.setCursor(90, 30);
u8g2.print( "water");
water1.start(); }
if(seqk[count]) { kick9.start();
u8g2.setCursor(90, 40);
u8g2.print( "kick");
}
if(countB>=384){
if(seqh1[count]) { hihat1.start();
test2.start();
u8g2.setCursor(90, 50);
u8g2.print( "hihat");
}
if(seqh2[count]) {
u8g2.setCursor(90, 50);
u8g2.print( "hihat");
hihat2.start();}
}
if(seqc[count]) {
u8g2.setCursor(90, 60);
u8g2.print( "clap");
clap.start();}
}
u8g2.drawFrame(count*4,0,20,10);
u8g2.setCursor(5+count*4,10);
u8g2.print(count);
countB+=1;
count +=1;
if(count==32){
count=0;
}
u8g2.setCursor(10,20);
u8g2.print("note1:");
u8g2.setCursor(40,20);
u8g2.print(melo[count+32]+12);
if(trigA==0){
triWarm1.setFreq( mtof(melo[count+23]+12) ) ;
envB1.setADLevels((byte)100, (byte)50); // bassのエンベロープレベル 0~255
envB1.setTimes(10,random(100),100,200); // bassのエンベロープタイム
envB1.noteOn();
}
trigB=random(3);
if(trigB==0&&countB>=256){
triWarm2.setFreq( mtof(melo[count+55]-12) ) ;
envB2.setADLevels((byte)170, (byte)50); // bassのエンベロープレベル 0~255
envB2.setTimes(4,random(100),100,random(150)); // bassのエンベロープタイム
envB2.noteOn();
note2c=melo[count+64]-24;
}
if(trigC==0||trigE==0){
triWarm3.setFreq( mtof(melo[count+17]) ) ;
envB3.setADLevels((byte)130, (byte)80); // bassのエンベロープレベル 0~255
envB3.setTimes(5,random(200),100,random(500)); // bassのエンベロープタイム
envB3.noteOn();
note3c=melo[count+12];
trigCcount+=1;
}
if(trigD==0&&countB>=512){
triWarm6.setFreq( mtof(melo[trigDcount]-12) ) ;
triWarm5.setFreq( mtof(melo[trigDcount+37]-36) ) ;
triWarm7.setFreq( mtof(melo[trigDcount+48]-12) ) ;
triWarm4.setFreq( mtof(melo[trigDcount+7]) ) ;
envB4.setADLevels((byte)100, (byte)100); // bassのエンベロープレベル 0~255
envB4.setTimes(200,100,3000,random(1500)); // bassのエンベロープタイム
envB4.noteOn();
// bassのエンベロープレベル 0~255
// bassのエンベロープレベル 0~255
trigDcount+=1;
}
if(countB>=768&&countB<=896){
triWarm8.setFreq( mtof(melo[count+70]) ) ;
envB5.setADLevels((byte)170, (byte)100); // bassのエンベロープレベル 0~255
envB5.setTimes(10,100,100,200); // bassのエンベロープタイム
envB5.noteOn();
}else{
}
if(countB>=256){
u8g2.setCursor(10,30);
u8g2.print("note2:");
u8g2.setCursor(40,30);
u8g2.print(note2c);
}
if(countB>=256){
u8g2.setCursor(10,40);
u8g2.print("note3:");
u8g2.setCursor(40,40);
u8g2.print(note3c);
}
dellaa=1;
trigA+=1;
trigC+=1;
trigD+=1;
trigE+=1;
trigF+=1;
if(trigA==1)trigA=0;
if(trigC==3)trigC=0;
if(trigD==8)trigD=0;
if(trigE==7)trigE=0;
if(trigF==2)trigF=0;
if(trigCcount==32)trigC==0;
u8g2.sendBuffer();
kTriggerDelay.start(100);
} // kTrigger if文終わり
} //void updateControl()終わり
int updateAudio(){
envB1.update();
envB2.update();
envB3.update();
envB4.update();
envB5.update();
// int low=(svf.next((envB2.next()*(triWarm2.next()>>4))>>3));
int code=envB4.next()*((triWarm4.next()>>8)+(triWarm5.next()>>8)+(triWarm6.next()>>8)+(triWarm7.next()>>8));
return ( (code>>1)+ (envB5.next()*triWarm8.next()>>8)+ (envB3.next()*triWarm3.next()>>7)+(envB2.next()*triWarm2.next()>>7)+((envB1.next()*triWarm1.next())>>7)+(test2.next()>>2)+snare3.next()+snare4.next() +kick9.next()+(hihat1.next())+(hihat2.next()) +clap.next() +water1.next() )>>3;
}
void loop(){
audioHook();
}
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( 4*(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 );
}
ESP32の電池駆動について
ESP32は3.3v以下でも動作するらしく電池などを昇圧回路で昇圧しなくても使えるらしいとのことで試した。
試してみるとmozziを併用しながら単4ニッケル水素充電池二本でも動作することがわかった。ただ持続時間については分からないのとOLEDなどを併用して使う場合昇圧回路と一緒に使った方が良いかもしれない。
昇圧回路については
https://akizukidenshi.com/catalog/g/gK-16116/
を試した。
半田付けすると写真のような感じ
逆に半田付けしてしまった。IGOの文字が見えるように半田付けすると使いやすい。Iに電池の+側、Gにマイナス側を接続してOから3.3v前後が出力された。試しにOLEDにつないでみるとOLEDも動作させることができた。
ESP32の5Vピンについて
写真の5Vについて、USBにつないでいるときは5Vが出力されるけど、電池から電源を取ると5Vは出力されない。試しに測ってみると電池の電圧より少し低い電圧が出力されていた。
テストも兼ねて試したサウンド2。
リアルタイムではないですがlive coding的にmozziを使ってコードで音楽を奏でられます。処理能力的にはまだ余裕がある感じがします。ESP32の可能性を感じます。
事前にプログラムして再生する音楽と違いシンセサイザーやシーケンサーなどを積んだデバイスの場合インターフェース上で楽曲を制作していくことになると思います。CPUの性能上は曲を作れたとしてもインターフェース上で作れるかどうかはまた別の問題だと感じました。
試しで作って変数名とかは適当でいろいろ実験で試した途中に使ったコードも散らかってますがコードは一応以下に載せてます。
#include <Arduino.h>
#include <U8g2lib.h>
#define CONTROL_RATE 1024
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
//U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ 16, /* data=*/ 17);
//U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
//U8G2_SSD1306_128X64_ALT0_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); // same as the NONAME variant, but may solve the "every 2nd line skipped" problem
//U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* reset=*/ 8);
//U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE); // All Boards without Reset of the Display
//U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ 16, /* data=*/ 17, /* reset=*/ U8X8_PIN_NONE); // ESP32 Thing, pure SW emulated I2C
//U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ 1, /* data=*/ 1); // ESP32 Thing, HW I2C with pin remapping
//U8G2_SSD1306_128X64_NONAME_1_6800 u8g2(U8G2_R0, 13, 11, 2, 3, 4, 5, 6, A4, /*enable=*/ 7, /*cs=*/ 10, /*dc=*/ 9, /*reset=*/ 8);
//U8G2_SSD1306_128X64_NONAME_1_8080 u8g2(U8G2_R0, 13, 11, 2, 3, 4, 5, 6, A4, /*enable=*/ 7, /*cs=*/ 10, /*dc=*/ 9, /*reset=*/ 8);
//U8G2_SSD1306_128X64_VCOMH0_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8); // same as the NONAME variant, but maximizes setContrast() range
//U8G2_SSD1306_128X64_ALT0_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8); // same as the NONAME variant, but may solve the "every 2nd line skipped" problem
#define SECONDS 4;
int A=0;
int B=1;
int C=2;
bool Ab1,Bb1,Cb1;
bool Ab2,Bb2,Cb2;
bool Ab3,Bb3,Cb3;
bool Ab4,Bb4,Cb4;
int red[]={21,22,23,24,25,26,27,28};
int green[]={1,2,3,4,35,36,37,38};
int i=0;
int timedata=0;
int timebase=0;
int row[]={52,53,42,43, 14,15,17,19};
boolean matrixc[8][8];
boolean matrix[8][8] = {
{ 0, 0, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 1, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 0, 1, 0, 0, 0 },
{ 1, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 1, 0, 0, 0, 0, 1 },
{ 0, 0, 0, 0, 1, 0, 0, 0 }
};
boolean matrix1[8][8] = {
{ 0, 0, 1, 0, 0, 0, 1, 0 },
{ 1, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 0, 1 },
{ 1, 0, 1, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 1, 1, 1, 0 },
{ 0, 1, 1, 0, 0, 0, 0, 1 },
{ 1, 0, 1, 0, 1, 0, 0, 0 }
};
boolean matrix2[8][8] = {
{ 0, 0, 1, 0, 1, 1, 0, 0 },
{ 1, 1, 0, 1, 1, 0, 0, 0 },
{ 0, 1, 0, 0, 1, 1, 0, 1 },
{ 1, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 1, 0, 1 },
{ 0, 1, 0, 0, 1, 0, 0, 1 },
{ 0, 1, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 1, 1, 1, 0, 1 }
};
#include <MozziGuts.h> // Mozziの基本ヘッダファイル
#include <Oscil.h> // オシレータのテンプレート
#include <mozzi_rand.h>
#include <ADSR.h> //エンベロープ
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;
ADSR <AUDIO_RATE, AUDIO_RATE> envB8;
#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> triWarm1(TRIANGLE_DIST_CUBED_2048_DATA);
//Oscil <TRIANGLE_WARM8192_NUM_CELLS, AUDIO_RATE> triWarm2(TRIANGLE_WARM8192_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;
EventDelay sttdelay;
#include <StateVariable.h>
StateVariable <LOWPASS> svf;
// スムースに値を変化させるためのヘッダ
int count=0;
int kleady=0;
int sttutter=0;
int cul_A=0;
int cul_B=0;
byte pin5;
byte pulse;
int tempo;
int tempo1=0;
bool trigger;
byte check; //パルスの立ち上がりの判定用
bool seqsn1[]={0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,1, 0,0,1,0, 0,0,1,0, 0,0,0,0, 0,1,0,0};
bool seqsn2[]={0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0};
bool seqk[]={1,0,0,1, 0,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0, 0,1,0,0};
bool seqh1[]={0,0,1,0, 0,0,1,0, 0,0,1,0, 0,0,1,0, 0,0,1,0, 0,0,1,0, 0,0,1,0, 0,0,1,0};
bool seqh2[]={1,0,1,0, 0,1,1,0, 1,0,1,0, 1,0,1,0, 1,0,1,0, 1,0,1,0, 0,0,1,0, 0,0,1,0};
bool seqc[]={0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,1,0, 0,0,0,1, 0,0,1,0, 1,0,0,0, 0,1,0,0};
bool seqsnap[]={1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1};
bool seqt[]={0,0,0,1, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,1,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0};
float seqf1[]={3,3,3,3, 4,4,4,4, 3.75,3.75,3.75,3.75, 2.812,2.812,2.812,2.812, 2.25,2.25,2.25,2.25, 2.7,2.7,2.7,2.7, 3,3,3,3, 4,4,4,4};
bool seqm[]={0,0,40,0, 40,0,40,0, 0,40,0,40, 0,40,0,0};
bool seqtt[]={0,0,0,0, 1,0,0,1, 0,0,0,0, 1,0,0,0};
//int melo[]={63,65,67,70,72,65,70,67, 70,65,70,65,63,65,67,63};
int melo[]={60,60,60,62, 71,64,67,64, 67,67,67,67, 69,69,69,67, 72,72,72,72, 72,72,72,72, 60,60,60,60, 60,60,60,60, 67,67,67,67, 64,64,64,64, 69,69,64,64, 62,62,62,60, 60,62,69,76, 76,79,76,79, 68,68,64,64, 63,63,55,55, 55};
int melo1[]={62,62,62,62, 67,67,67,67, 69,69,72,72, 69,69,69,62, 55,55,57,57, 57,57,57,57, 62,62,62,62, 64,64,64,60, 67,67,67,67, 64,64,64,64, 69,69,64,64, 62,62,62,67, 64,62,69,76, 76,81,76,81, 68,68,64,64, 63,63,55,55, 55};
int melo2[]={64,64,72,69, 79,79,81,81, 69,69,72,72, 76,69,76,62, 62,55,52,55, 60,62,57,64, 64,67,64,62, 64,60,64,64, 67,67,69,67, 64,64,64,64, 72,69,64,64, 62,62,62,60, 60,62,69,76, 76,79,76,79, 68,68,64,64, 63,63,55,55, 55};
int melo_code[5][20]= {
{ 64,64, 62,62, 67,67, 65, 65, 65, 65, 64,64, 62,62, 67,67, 68, 67, 66, 65},
{ 60,60, 59,59, 64,64, 62, 62, 62, 62, 60,60, 59,59, 64,64, 65, 64, 63, 62},
{ 57,57, 56,56, 60,60, 58, 58, 58, 58, 57,57, 56,56, 60,60, 61, 60, 59, 58},
{ 53,57, 52,52, 57,57, 55, 55, 55, 55, 53,57, 52,52, 57,57, 58, 57, 56, 55},
{ 29,29, 28,28, 33,33, 31, 31, 31, 31, 29,29, 28,28, 33,33, 34, 33, 32, 31}
};
bool melo_code_trig[]={1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,0,1,0,1,0,1,0};
int melo_code_num[]={0,0,0,0,1,1,1,1, 2,2,2,2,3,3,3,3, 4,4,4,4,5,5,5,5, 6,6,7,7,8,8,9,9, 10,10,10,10,11,11,11,11, 12,12,12,12,13,13,13,13, 14,14,14,14,15,15,15,15, 16,0,17,0,18,0,19,0};
int ser=0;
int sertime=10;
int rseqs,rseqk,rseqh,rseqc,rmel1;
int pseq1,pseq2,pseq3,pseq4,pseq5,pseq6,pseq7,pseq8,pseq9,pseq10;
int add=1;
int dellaa=0;
int delch=0;
int countB=0;
int note2c=0;
int note3c=0;
int trigA=0;
int trigB=0;
int trigC=0;
int trigD=0;
int trigE=0;
int trigF=0;
int trigAcount=0;
int trigBcount=0;
int trigCcount=0;
int trigDcount=0;
int trigEcount=0;
int trigFcount=0;
//Oscil <SQUARE_NO_ALIAS_2048_NUM_CELLS, AUDIO_RATE> triWarm2(SQUARE_NO_ALIAS_2048_DATA);
// コントロールレートをあらかじめ定義
void setup(){
u8g2.begin();
pinMode(8,INPUT_PULLUP);
u8g2.setBusClock(40000000);
Wire.setClock(3400000);
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);
}
void updateControl(){
int check1=mozziAnalogRead(A0);
if(kTriggerDelay.ready()&&countB<=1024){
A=random(100);
B=random(40);
int c=random(100);
int d=random(30);
int ee=random(100);
int ff=random(30);
int gg=random(100);
int hh=random(30);
u8g2.clearBuffer();
u8g2.setFontDirection(0);
// u8g2.setFont(u8g2_font_b10_t_japanese1);
u8g2.setFont(u8g2_font_5x7_tf);
u8g2.drawStr(10, 50, "fendoap");
u8g2.drawCircle(40,50,random(20));
u8g2.drawFrame(40,50,random(30),random(20));
if(countB>=128&&countB<=640||countB>=768){
if(seqsn1[count]) { snare4.start();
u8g2.setCursor(90, 20);
u8g2.print( "snare");
}
if(seqsn2[count]) {
snare3.start();
u8g2.setCursor(90, 20);
u8g2.print( "snare");
}
if(seqt[count]) {
u8g2.setCursor(90, 30);
u8g2.print( "water");
water1.start(); }
if(seqk[count]) { kick9.start();
u8g2.setCursor(90, 40);
u8g2.print( "kick");
}
if(countB>=384){
if(seqh1[count]) { hihat1.start();
test2.start();
u8g2.setCursor(90, 50);
u8g2.print( "hihat");
}
if(seqh2[count]) {
u8g2.setCursor(90, 50);
u8g2.print( "hihat");
hihat2.start();}
}
if(seqc[count]) {
u8g2.setCursor(90, 60);
u8g2.print( "clap");
clap.start();}
}
u8g2.drawFrame(count*4,0,20,10);
u8g2.setCursor(5+count*4,10);
u8g2.print(count);
countB+=1;
count +=1;
if(count==32){
count=0;
}
u8g2.setCursor(10,20);
u8g2.print("note1:");
u8g2.setCursor(40,20);
u8g2.print(melo[count+32]+12);
if(trigA==0){
gliss_start = triWarm1.phaseIncFromFreq(mtof(melo[trigAcount]+12));
gliss_end = triWarm1.phaseIncFromFreq(mtof(melo[trigAcount+1]+12));
aGliss.set(gliss_start,gliss_end, 1000);
if(countB>=0&&countB<256){
freq1=mtof(melo[trigAcount]+12);
}else if(countB>=256&&countB<512){
freq1=mtof(melo1[trigAcount]+12);
}else if(countB>=512&&countB<768){
freq1=mtof(melo2[trigAcount]+12);
}else{
freq1=mtof(melo[trigAcount]+12);
}
// aPortamentoA.start(Q16n16 mtof(melo[trigAcount]));
// triWarm1.setFreq(aPortamentoA.next() );
// triWarm1.setFreq( mtof(melo[trigAcount]) );
envB1.setADLevels((byte)180, (byte)80); // bassのエンベロープレベル 0~255
envB1.setTimes(5,150,50,200); // bassのエンベロープタイム
envB1.noteOn();
trigAcount+=1;
}
if(trigC==0||trigE==0){
triWarm2.setFreq( mtof(melo2[count]) ) ;
envB2.setADLevels((byte)180, (byte)80); // bassのエンベロープレベル 0~255
envB2.setTimes(5,200,100,400); // bassのエンベロープタイム
envB2.noteOn();
note2c=melo2[count+12];
trigCcount+=1;
}
if(trigA==0&&melo_code_trig[trigD]){
triWarm6.setFreq( mtof(melo_code[0][melo_code_num[trigD]]) ) ;
triWarm5.setFreq( mtof(melo_code[1][melo_code_num[trigD]]) ) ;
triWarm7.setFreq( mtof(melo_code[2][melo_code_num[trigD]]) ) ;
triWarm4.setFreq( mtof(melo_code[3][melo_code_num[trigD]]) ) ;
triWarm3.setFreq( mtof(melo_code[4][melo_code_num[trigD]]) ) ;
envB4.setADLevels((byte)180, (byte)100); // bassのエンベロープレベル 0~255
envB4.setTimes(50,100,400,random(100)); // bassのエンベロープタイム
envB4.noteOn();
// bassのエンベロープレベル 0~255
// bassのエンベロープレベル 0~255
}
if(countB>=512&&countB<=767){
triWarm8.setFreq( mtof(melo[count]+int(random(3)*12)) ) ;
envB5.setADLevels((byte)170, (byte)100); // bassのエンベロープレベル 0~255
envB5.setTimes(10,100,100,200); // bassのエンベロープタイム
envB5.noteOn();
}else if(countB>=768&&countB<=896){
triWarm8.setFreq( mtof(melo1[count]+int(random(3)*12)) ) ;
envB5.setADLevels((byte)170, (byte)100); // bassのエンベロープレベル 0~255
envB5.setTimes(10,100,100,200); // bassのエンベロープタイム
envB5.noteOn();
}
if(countB>=256){
u8g2.setCursor(10,30);
u8g2.print("note2:");
u8g2.setCursor(40,30);
u8g2.print(note2c);
}
if(countB>=256){
u8g2.setCursor(10,40);
u8g2.print("note3:");
u8g2.setCursor(40,40);
u8g2.print(note3c);
}
dellaa=1;
trigA+=1;
trigC+=1;
trigE+=1;
trigF+=1;
if(trigA==1){
trigA=0;
trigD+=1;
}
if(trigC==3)trigC=0;
if(trigD==64){
trigD=0;
trigDcount+=1;
}
if(trigE==7)trigE=0;
if(trigF==2)trigF=0;
if(trigAcount==64)trigAcount=0;
if(trigCcount==32)trigCcount=0;
if(trigDcount==20)trigDcount=0;
u8g2.sendBuffer();
kTriggerDelay.start(100);
} // kTrigger if文終わり
} //void updateControl()終わり
int updateAudio(){
envB1.update();
envB2.update();
envB3.update();
envB4.update();
envB5.update();
//triWarm1.setPhaseInc(aGliss.next());
int smoothedFreq = aSmooth.next(freq1);
triWarm1.setFreq(smoothedFreq);
// int low=(svf.next((envB2.next()*(triWarm2.next()>>4))>>3));
int code=envB4.next()*((triWarm3.next()>>8)+(triWarm4.next()>>8)+(triWarm5.next()>>8)+(triWarm6.next()>>8)+(triWarm7.next()>>8));
return ( (code>>1)+ (envB5.next()*triWarm8.next()>>8)+(envB2.next()*triWarm2.next()>>7)+((envB1.next()*triWarm1.next())>>7)+(test2.next()>>2)+snare3.next()+snare4.next() +kick9.next()+(hihat1.next())+(hihat2.next()) +clap.next() +water1.next() )>>3;
}
void loop(){
audioHook();
}
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 );
}
可変抵抗について
基板取付用の可変抵抗を試しに入手してみた。
https://akizukidenshi.com/catalog/g/gP-14827/
があまりこれは今回の用途には適していないかも。一つはノブの長さがやや長く見た目のバランスの相性があまりよくない。もう一つはセンタークリックがあること。センタークリックとは可変抵抗の真ん中の位置がわかるようにそこでクリック感のような若干引っ掛かりがあるような仕様の事。
ちなみにAカーブ、Bカーブについては
が参考になります。
パラメータが1対一に結びついていなくて可変的ならロータリーエンコーダなどもよさそうだと思うので試してみたいです。
イヤホンジャックについて
イヤホンジャックについては
先端がL、真ん中がR、付け根がGです。
SPI通信のOLEDについて
SPI通信のOLEDについては
U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
のコメントアウトを外すことで動きました。
/* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
の数字はピンの番号で任意のピンの番号を指定してOLEDとつなぎます。
OLEDによってはリセットが無かったり、
などはピンの名前が若干異なる。自分の場合は
U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 14, /* data=*/ 13, /* cs=*/ 15, /* dc=*/ 16, /* reset=*/ 17);
と設定した。
実際に制作してみた
制作してみました。
可変抵抗は左から39 34 35 32 33 27pin
タクトスイッチは←23 ↑13 →18 ↓19 5 17 16 4pin
OLEDはCLK22 MOSI 21 CS15 D/C 2 pin
CV/GATE上14 下12pinです。
読み取った可変抵抗の値をOLEDに表示する
#define A1 39
#define A2 34
#define A3 35
#define A4 32
#define A5 33
#define A6 27
#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);
void setup() {
u8g2.begin();
u8g2.setFontMode(1);
u8g2.setFont(u8g2_font_5x7_tf);
}
void loop() {
String knob_value_1="knob1:";
int potention_meter_1=analogRead(A1);
knob_value_1 += (String) potention_meter_1;
String knob_value_2="knob2:";
int potention_meter_2=analogRead(A2);
knob_value_2 += (String) potention_meter_2;
String knob_value_3="knob3:";
int potention_meter_3=analogRead(A3);
knob_value_3 += (String) potention_meter_3;
String knob_value_4="knob4:";
int potention_meter_4=analogRead(A4);
knob_value_4 += (String) potention_meter_4;
String knob_value_5="knob5:";
int potention_meter_5=analogRead(A5);
knob_value_5 += (String) potention_meter_5;
String knob_value_6="knob6:";
int potention_meter_6=analogRead(A6);
knob_value_6 += (String) potention_meter_6;
u8g2.clearBuffer();
u8g2.setCursor(0, 15);
u8g2.print(knob_value_1);
u8g2.setCursor(0, 30);
u8g2.print(knob_value_2);
u8g2.setCursor(0, 45);
u8g2.print(knob_value_3);
u8g2.setCursor(60, 15);
u8g2.print(knob_value_4);
u8g2.setCursor(60, 30);
u8g2.print(knob_value_5);
u8g2.setCursor(60, 45);
u8g2.print(knob_value_6);
u8g2.sendBuffer();
}
.......
いいなと思ったら応援しよう!
![fendoap](https://assets.st-note.com/production/uploads/images/168565235/profile_3098b5927308a0f9396df6408d985ac2.jpg?width=600&crop=1:1,smart)