【Arduino MIDIドラムシーケンサ④】スイッチでリズムパターン切り替え
前回作成したドラムシーケンサでは1パターンのリズムしか演奏できませんでした。今回はタクトスイッチを使ってチャンネル1~4まで切り替えることで4種類のリズムパターンを演奏できるようにしてみました。
jakejake.hatenablog.com
配線
デジタルピンの3, 4, 5, 8にタクトスイッチを接続しました。タクトスイッチを押すとGNDにつながる(LOWになる)ようにします。
コード
主な追加個所はbyte Getchannelとboolean GetRTMの部分です。byte Getchannelはタクトスイッチの押下を監視し、boolean GetRTMはチャンネル、拍、楽器ごとのドラムパターンを出力します。
// Arduino MIDI Drum sequencer // Sending MIDI messages to the host PC. // DAW: Waveform Free // // Author: Tara-chang // // Revision History: // Date | Author | Change // --------------------------------------------------- // 2021-05-09 | Tara-chang | Initial Release // 2021-05-09 | Tara-chang | Added LCD and Trimpot to tempo control // 2021-05-16 | Tara-chang | Added BUTTONS to change channel #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); #include <MIDI.h> MIDI_CREATE_DEFAULT_INSTANCE(); #define CRUSH 49 //C#3 #define KICK 36 //C2 #define CLAP 39 //D#2 #define SNARE 38 //D2 #define RIDE 51 //D#3 #define HITOM 50 //D3 #define MIDTOM 48 //C3 #define LOWTOM 45 //A2 #define OPHIHAT 46 //A#2 #define CLHIHAT 42//F#2 int DRUM[] = {SNARE, KICK, CLHIHAT, CRUSH}; const byte NUM_DRUM = sizeof(DRUM)/sizeof(DRUM[0]); const byte NUM_BEAT = 8; boolean RTM[NUM_DRUM][NUM_BEAT] = { {0,0,1,0,0,0,1,0},//SNARE {1,1,0,0,1,1,0,0},//KICK {1,1,1,1,1,1,1,1},//CLHIHAT {1,0,0,0,1,0,0,0}//RIDE }; boolean RTM2[NUM_DRUM][NUM_BEAT] = { {0,1,0,1,0,1,0,1},//SNARE {1,0,0,0,1,1,1,0},//KICK {1,0,1,0,1,0,1,0},//CLHIHAT {1,0,0,0,1,0,0,0}//RIDE }; boolean RTM3[NUM_DRUM][NUM_BEAT] = { {0,0,0,0,1,0,0,0},//SNARE {1,1,1,1,1,1,1,1},//KICK {0,0,0,0,0,0,0,0},//CLHIHAT {1,0,0,0,1,0,0,0}//RIDE }; boolean RTM4[NUM_DRUM][NUM_BEAT] = { {1,1,1,1,1,1,1,1},//SNARE {1,0,1,0,1,0,1,0},//KICK {0,0,0,0,0,0,0,0},//CLHIHAT {1,0,1,0,1,0,1,0}//RIDE }; boolean RTM5[NUM_DRUM][NUM_BEAT] = { {1,1,1,1,1,1,1,1},//SNARE {1,0,1,0,1,0,1,0},//KICK {0,0,0,0,0,0,0,0},//CLHIHAT {1,0,1,0,1,0,1,0}//RIDE }; byte nt = 0; byte in = 0; byte i = 0; int BPM = 0; //X beats/60sec = 60/X sec/beat int interval = 295;//60/double(BPM)*(NUM_BEAT/4)*1000; // boolean changed = 1; int trimpot = 300; int now_trimpot = 300; #define INT_MIN 200 #define INT_MAX 1000 #define TRM_MIN 0 #define TRM_MAX 1023 byte LEDPIN[] = {11, 12, 13, 10}; byte BUTPIN[] = {3, 4, 5, 8}; byte NUM_BUTPIN = sizeof(BUTPIN)/sizeof(BUTPIN[0]); byte NUM_LEDPIN = sizeof(LEDPIN)/sizeof(LEDPIN[0]); byte CHANNELS[] = {1,2,3,4}; byte NUM_CHANNELS = sizeof(CHANNELS)/sizeof(CHANNELS[0]); byte NOW_CHANNEL = 1; byte CHANNEL = 1; byte nowchannel; void setup() { for (i=0;i<NUM_BUTPIN;i++){ pinMode(BUTPIN[i], INPUT); digitalWrite(BUTPIN[i], HIGH); } for (i=0;i<NUM_LEDPIN;i++){ pinMode(LEDPIN[i], OUTPUT); digitalWrite(LEDPIN[i], LOW); } Serial.begin(115200); MIDI.begin(4); // lcd.init(); lcd.backlight(); lcd.clear(); } void loop(){ NOW_CHANNEL = Getchannel(CHANNEL); for (nt = 0; nt < NUM_BEAT; nt++){ for (in = 0; in < NUM_DRUM; in++){ //String text = "(in,nt)=("+String(in)+","+String(nt)+")"+String(RTM[in][nt]); if (GetRTM(CHANNEL, in, nt)){ MIDI.sendNoteOn(DRUM[in],127,1); // (pitch, velocity, channel) MIDI.sendNoteOff(DRUM[in],0,1); // } } delay(now_trimpot*(4/double(NUM_BEAT))); } now_trimpot = map(analogRead(0), TRM_MAX, TRM_MIN, INT_MAX, INT_MIN); if ((now_trimpot!= trimpot)||(CHANNEL!=NOW_CHANNEL)){ trimpot = now_trimpot; CHANNEL = NOW_CHANNEL; changed = 1; } else{ //Serial.println("trimpot changed"); } if(changed){ BPM = 1/double(trimpot)*60*1000; lcd.clear(); lcd.setCursor(0, 0); lcd.print(BPM); lcd.setCursor(0, 1); lcd.print(CHANNEL); changed=0; } // OLD_CHANNEL = NOW_CHANNEL; } byte Getchannel(byte oldchannel){ nowchannel = oldchannel; for (i=0;i<NUM_BUTPIN;i++){ if ((digitalRead(BUTPIN[i])==LOW)){ nowchannel = CHANNELS[i]; } else{ //nowchannel = oldchannel; } } return nowchannel; } boolean GetRTM(byte nowchannel, byte in, byte nt){ if(nowchannel==1){ return RTM[in][nt]; } else if(nowchannel==2){ return RTM2[in][nt]; } else if(nowchannel==3){ return RTM3[in][nt]; } else if(nowchannel==4){ return RTM4[in][nt]; } else{ return RTM[in][nt]; } }