import mjs.processing.mobile.msound.*; static final int tickCount = 16; static final int instrCount = 5; static final int midiChannel = 9; static final int pauseDuration = 50; int gridX = 40; int gridXX = 200; int gridY = 40; int gridYY = 240; int tickHeight = (gridYY - gridY) / tickCount; int instrWidth = (gridXX - gridX) / instrCount; boolean[][] cells; // kick, snare, hat1, hat2, cowbell boolean playing = false; int cursorRow = 0; int cursorCol = 0; int currentTick = 0; MMidi midi = new MMidi(); void setup() { cells = new boolean[instrCount][tickCount]; background(255, 255, 255); drawLabels(); } void keyPressed() { // key is a char switch (key) { // Cursor movement case '2': cursorRow--; if (cursorRow < 0) cursorRow = tickCount - 1; break; case '4': cursorCol--; if (cursorCol < 0) cursorCol = instrCount - 1; break; case '6': cursorCol++; if (cursorCol >= instrCount) cursorCol = 0; break; case '8': cursorRow++; if (cursorRow >= tickCount) cursorRow = 0; break; // Toggle cell case '5': cells[cursorCol][cursorRow] = !cells[cursorCol][cursorRow]; break; // Toggle playing case '1': playing = !playing; if (playing) currentTick = -1; break; } } void draw() { noStroke(); fill(255, 255, 255); rect(gridX, gridY, gridXX - gridX, gridYY - gridY); //background(255, 255, 255); drawCells(); drawSequencerGrid(playing ? currentTick : -1); drawCursor(); drawLabels(); if (playing) { pause(pauseDuration); currentTick = (currentTick >= tickCount - 1) ? 0 : currentTick + 1; playCurrentRow(); } } void pause(int duration) { try { Thread.sleep(duration); } catch (InterruptedException e) { } } void drawLabels() { int n = instrWidth / 2 + gridX; int ypos = 30; textFont(loadFont(FACE_SYSTEM, STYLE_BOLD, SIZE_LARGE)); fill(0, 0, 0); textAlign(CENTER); text("BD", n, ypos); text("SD", instrWidth + n, ypos); text("HH", instrWidth * 2 + n, ypos); text("HO", instrWidth * 3 + n, ypos); text("CB", instrWidth * 4 + n, ypos); } void drawSequencerGrid(int highlightTick) { // Grid is 240 x 256 pixels int n; // Draw rows noFill(); strokeWeight(1); stroke(160, 160, 160); for (int i = 0; i <= tickCount; i++) { n = gridY + tickHeight * i; line(gridX, n, gridXX, n); } if (playing) { stroke(255, 0, 0); strokeWeight(3); n = gridY + tickHeight * (highlightTick + 1); line(gridX, n, gridXX, n); } // Draw columns stroke(160, 160, 160); strokeWeight(1); for (int i = 0; i <= instrCount; i++) { n = gridX + instrWidth * i; line(n, gridY, n, gridY + tickHeight * tickCount); } } void drawCells() { noStroke(); fill(0, 0, 0); for (int i = 0; i < tickCount; i++) { int y1 = gridY + tickHeight * i; // Draw kick cells if (cells[0][i]) { rect(gridX, y1, instrWidth, tickHeight); } // Draw snare cells if (cells[1][i]) { rect(gridX + instrWidth, y1, instrWidth, tickHeight); } // Draw hat1 cells if (cells[2][i]) { rect(gridX + instrWidth * 2, y1, instrWidth, tickHeight); } // Draw hat2 cells if (cells[3][i]) { rect(gridX + instrWidth * 3, y1, instrWidth, tickHeight); } // Draw cowbell cells if (cells[4][i]) { rect(gridX + instrWidth * 4, y1, instrWidth, tickHeight); } } } void drawCursor() { noFill(); stroke(255, 0, 0); strokeWeight(2); rect(gridX + (instrWidth * cursorCol), gridY + (tickHeight * cursorRow), instrWidth, tickHeight); } void playCurrentRow() { // Play kick int kckVol = (cells[0][currentTick]) ? 127 : 0; int snrVol = (cells[1][currentTick]) ? 127 : 0; int ht1Vol = (cells[2][currentTick]) ? 127 : 0; int ht2Vol = (cells[3][currentTick]) ? 127 : 0; int cblVol = (cells[4][currentTick]) ? 127 : 0; midi.noteOn(midiChannel, 36, kckVol); midi.noteOn(midiChannel, 40, snrVol); midi.noteOn(midiChannel, 42, ht1Vol); midi.noteOn(midiChannel, 46, ht2Vol); midi.noteOn(midiChannel, 56, cblVol); }