HAGIWO MOD1用にプログラミングしたスネア&ハイハット・シーケンサーです。
サンプラーのスネア・クローズハイハット&オープンハイハットの組み合わせに適したセッティングです。
何度か類似のプログラミングを投稿していますが、こちらがひとまずの完成版になります。
2025年7月20日に渋谷CIRCUS TOKYOで開催された「Patching for Modular」のライブで使ったシーケンサーです。
1つ目のシーケンサー、2つ目のシーケンサーとも、ライブ演奏で使いやすいスネア・ハットパターンをプログラミングしております。
1つ目のシーケンサーはスネアに特化しており、POT1でリズムパターンを設定します。ノブを回すごとにトリガー回数が増え、最大値で16ステップ全てのトリガーが鳴ります。ステップはシフトレジストしており、1周目は5ステップ目から有効になります。主にスネア音源との相性が良いシーケンサーです。
2つ目のシーケンサーも16ステップで固定されており、POT2でトリガー回数を設定します。また、POT3はランダムコイントスで、POT2で設定したパターンを、さらに確率的に2つの出力に振り分けます。こちらは1ステップ目から有効です。主にクローズハイハット、オープンハイハット音源の組み合わせと相性が良いシーケンサーです。
プログラミング内の {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},の箇所が16ステップシーケンスの書き込み部分にあたります。「0」がトリガーなしで「1」がトリガー発生です。数字を書き換えることで、お好みのリズムパターンに変更できます。
※機能を一部修正しました。リセットインが加わり、不規則なパフォーマンスにも対応するようになりました。
注意事項1:chatGPTで作成したプロンプトです。プログラミング知識は一切ないため、動作の安定性は保証はできません。趣味用途でお使いください
[機能紹介]
※入力したクロックをもとに、リズムパターンを生成するモジュールです。
※トリガー長は5msで設定しています。トリガー長は delayMicroseconds(5000); の箇所で変更可能です。(5ms=5000)
POT1:出力1のリズムパターンを設定します。
POT2:出力2のリズムパターンを設定します。
POT3:リズムパターンのループ回数を設定します。デフォルトは16ステップですが、ツマミを回していくと、14ループ→12ループとループ数が短くなります。デフォルト位置に届くと、クロックに同期した16ステップのリズムパターンに戻ります。
F1:トリガーIN
F2:リセットIN
F3:出力1のトリガー出力
F4:出力1のトリガー出力
P4:???
LED:F1に連動する
[プログラム](ArduinoでMOD1にプログラミングしてください)
▼次の行からコピーペースト▼
// ===== Robust 2-output trigger sequencer =====
const int numSteps = 16;
// pins
const int trigInPin = 17;
const int resetPin = 9;
const int out1Pin = 10;
const int out2Pin = 11;
const int ledPin = 3;
const int pot1Pin = A0;
const int pot2Pin = A1;
const int loopPotPin= A2;
const unsigned long trigLen = 5000UL;
// — fixed patterns —
const bool fixedPatterns1[16][numSteps] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0},
{0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,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,0,0,0,1,0,0,0,0},
{0,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0},
{0,0,0,1,0,0,1,0,1,0,0,0,0,1,0,0},
{0,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0},
{0,0,0,1,0,0,1,0,1,0,1,1,0,0,1,0},
{1,0,0,1,0,0,1,0,1,0,0,0,0,1,0,0},
{0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,1},
{0,1,0,1,0,1,1,0,1,0,1,1,0,1,1,1},
{1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,1},
{1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
};
const bool fixedPatterns2[16][numSteps] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0},
{0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
{0,1,0,0,1,0,0,0,0,0,0,1,0,0,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,0,0,1,0,0},
{0,1,0,0,0,1,0,0,0,1,0,0,1,1,0,0},
{0,1,0,0,0,1,0,0,1,1,0,1,1,0,0,0},
{0,1,0,1,0,0,1,1,0,1,0,0,0,1,0,0},
{0,1,0,1,0,0,1,1,0,1,0,0,0,1,0,1},
{0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1},
{0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1},
{0,1,0,1,1,1,1,0,0,1,0,1,0,0,1,0},
{1,1,1,1,1,0,1,1,0,1,1,0,1,1,1,1},
{1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
};
// — state —
int step = 0;
bool lastTrig = LOW;
bool lastReset = LOW;
unsigned long t1 = 0, t2 = 0;
// — helpers —
int readPatternIndex(int pin) {
int v = analogRead(pin);
if (v >= 1018) return 15;
return v / 64;
}
int getLoopLength() {
static const int table[9] = {16,8,7,6,5,4,3,2,1};
int pos = map(analogRead(loopPotPin),0,1023,0,8);
return table[pos];
}
// — setup —
void setup() {
pinMode(trigInPin, INPUT);
pinMode(resetPin, INPUT);
pinMode(out1Pin, OUTPUT);
pinMode(out2Pin, OUTPUT);
pinMode(ledPin, OUTPUT);
}
// — loop —
void loop() {
bool trig = digitalRead(trigInPin);
bool reset = digitalRead(resetPin);
if (reset && !lastReset) step = 0;
if (trig && !lastTrig) {
int loopLen = getLoopLength();
int s = step % loopLen;
int p1 = readPatternIndex(pot1Pin);
int p2 = readPatternIndex(pot2Pin);
if (fixedPatterns1[p1][s]) {
digitalWrite(out1Pin, HIGH);
digitalWrite(ledPin, HIGH);
t1 = micros();
}
if (fixedPatterns2[p2][s]) {
digitalWrite(out2Pin, HIGH);
t2 = micros();
}
step = (step + 1) % numSteps;
}
unsigned long now = micros();
if (digitalRead(out1Pin) && now – t1 >= trigLen) {
digitalWrite(out1Pin, LOW);
digitalWrite(ledPin, LOW);
}
if (digitalRead(out2Pin) && now – t2 >= trigLen) {
digitalWrite(out2Pin, LOW);
}
lastTrig = trig;
lastReset = reset;
}