Compare commits
4 Commits
comparator
...
rhythm
| Author | SHA1 | Date | |
|---|---|---|---|
| 8b4b96e65a | |||
| 26f65eed10 | |||
| 9be88be1f4 | |||
| 7c06da08b4 |
@ -18,7 +18,7 @@
|
||||
// Define the constants for the current firmware.
|
||||
const char StateManager::SKETCH_NAME[] = "ALT EUCLIDEAN";
|
||||
const char StateManager::SEMANTIC_VERSION[] =
|
||||
"V2.0.1BETA1"; // NOTE: This should match the version in the
|
||||
"V2.0.1"; // NOTE: This should match the version in the
|
||||
// library.properties file.
|
||||
|
||||
// Number of available save slots.
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
// Define the constants for the current firmware.
|
||||
const char StateManager::SKETCH_NAME[] = "ALT GRAVITY";
|
||||
const char StateManager::SEMANTIC_VERSION[] =
|
||||
"V2.0.1BETA1"; // NOTE: This should match the version in the
|
||||
"V2.0.1"; // NOTE: This should match the version in the
|
||||
// library.properties file.
|
||||
|
||||
// Number of available save slots.
|
||||
|
||||
371
firmware/Rhythm/Rhythm.ino
Normal file
371
firmware/Rhythm/Rhythm.ino
Normal file
@ -0,0 +1,371 @@
|
||||
#include "maps.h"
|
||||
#include <EEPROM.h>
|
||||
#include <Wire.h>
|
||||
#include <libGravity.h>
|
||||
|
||||
// Configuration
|
||||
const int MAX_DENSITY = 255;
|
||||
const int MAP_RESOLUTION = 255;
|
||||
const int MAX_CHAOS = 255;
|
||||
|
||||
// EEPROM addrs
|
||||
const int EEPROM_INIT_ADDR = 0;
|
||||
const int EEPROM_DENS_K = 1;
|
||||
const int EEPROM_DENS_S = 3;
|
||||
const int EEPROM_DENS_H = 5;
|
||||
const int EEPROM_MAP_X = 7;
|
||||
const int EEPROM_MAP_Y = 9;
|
||||
const int EEPROM_CHAOS = 11;
|
||||
const byte EEPROM_INIT_FLAG = 0xAC; // Update flag to re-init
|
||||
|
||||
// EEPROM Delay Save
|
||||
const unsigned long SAVE_DELAY_MS = 5000;
|
||||
bool eeprom_needs_save = false;
|
||||
unsigned long last_param_change = 0;
|
||||
|
||||
// UI & Navigation
|
||||
enum SelectedParam {
|
||||
PARAM_KICK_DENS = 0,
|
||||
PARAM_SNARE_DENS = 1,
|
||||
PARAM_HIHAT_DENS = 2,
|
||||
PARAM_CHAOS = 3,
|
||||
PARAM_MAP_X = 4,
|
||||
PARAM_MAP_Y = 5,
|
||||
PARAM_LAST = 6
|
||||
};
|
||||
|
||||
SelectedParam current_param = PARAM_KICK_DENS;
|
||||
bool editing_param = false;
|
||||
bool needs_redraw = true;
|
||||
unsigned long last_redraw = 0;
|
||||
const unsigned long REDRAW_DELAY_MS = 30; // ~33fps limit
|
||||
|
||||
// Sequencer State
|
||||
int current_step = 0;
|
||||
bool is_playing = false;
|
||||
|
||||
// Engine Parameters (0-255)
|
||||
int inst_density[3] = {128, 128,
|
||||
128}; // Default 50% density for kick, snare, hihat
|
||||
int map_x = 0; // 0 to 255 (0 = House, 127 = Breakbeat, 255 = Hiphop)
|
||||
int map_y = 127; // 0 to 255 (0 = Sparse, 127 = Standard, 255 = Busy)
|
||||
int chaos_amount = 0; // 0 to 255
|
||||
|
||||
volatile int cv1_val = 0;
|
||||
volatile int cv2_val = 0;
|
||||
|
||||
// LFSR State for Chaos
|
||||
uint16_t lfsr = 0xACE1;
|
||||
|
||||
// Math Helper: 1D Linear Interpolation between two bytes
|
||||
uint8_t lerp(uint8_t a, uint8_t b, uint8_t t) {
|
||||
// t is 0-255. returns a if t=0, b if t=255
|
||||
return a + (((b - a) * t) >> 8);
|
||||
}
|
||||
|
||||
// Math Helper: Get threshold from 2D map via interpolation
|
||||
uint8_t GetThreshold(int inst, int step, int x_pos, int y_pos) {
|
||||
// x_pos is 0-255 mapped across 4 nodes (0, 1, 2, 3). Distance is 85 (255 / 3)
|
||||
// y_pos is 0-255 mapped across 4 nodes (0, 1, 2, 3). Distance is 85 (255 / 3)
|
||||
|
||||
int x_idx = x_pos / 85;
|
||||
int y_idx = y_pos / 85;
|
||||
|
||||
uint8_t x_frac = (x_pos % 85) * 3; // scale remainder 0-84 up to 0-255
|
||||
uint8_t y_frac = (y_pos % 85) * 3;
|
||||
|
||||
// Guard against out of bounds if exactly 255
|
||||
if (x_idx >= 3) {
|
||||
x_idx = 2;
|
||||
x_frac = 255;
|
||||
}
|
||||
if (y_idx >= 3) {
|
||||
y_idx = 2;
|
||||
y_frac = 255;
|
||||
}
|
||||
|
||||
// Read 4 corners from PROGMEM
|
||||
uint8_t p00 = pgm_read_byte(&PATTERN_MAPS[x_idx][y_idx][inst][step]);
|
||||
uint8_t p10 = pgm_read_byte(&PATTERN_MAPS[x_idx + 1][y_idx][inst][step]);
|
||||
uint8_t p01 = pgm_read_byte(&PATTERN_MAPS[x_idx][y_idx + 1][inst][step]);
|
||||
uint8_t p11 = pgm_read_byte(&PATTERN_MAPS[x_idx + 1][y_idx + 1][inst][step]);
|
||||
|
||||
// Bilinear interpolation
|
||||
uint8_t lerp_top = lerp(p00, p10, x_frac);
|
||||
uint8_t lerp_bottom = lerp(p01, p11, x_frac);
|
||||
return lerp(lerp_top, lerp_bottom, y_frac);
|
||||
}
|
||||
|
||||
void LoadState() {
|
||||
if (EEPROM.read(EEPROM_INIT_ADDR) == EEPROM_INIT_FLAG) {
|
||||
EEPROM.get(EEPROM_DENS_K, inst_density[0]);
|
||||
EEPROM.get(EEPROM_DENS_S, inst_density[1]);
|
||||
EEPROM.get(EEPROM_DENS_H, inst_density[2]);
|
||||
EEPROM.get(EEPROM_MAP_X, map_x);
|
||||
EEPROM.get(EEPROM_MAP_Y, map_y);
|
||||
EEPROM.get(EEPROM_CHAOS, chaos_amount);
|
||||
}
|
||||
}
|
||||
|
||||
void SaveState() {
|
||||
EEPROM.update(EEPROM_INIT_ADDR, EEPROM_INIT_FLAG);
|
||||
EEPROM.put(EEPROM_DENS_K, inst_density[0]);
|
||||
EEPROM.put(EEPROM_DENS_S, inst_density[1]);
|
||||
EEPROM.put(EEPROM_DENS_H, inst_density[2]);
|
||||
EEPROM.put(EEPROM_MAP_X, map_x);
|
||||
EEPROM.put(EEPROM_MAP_Y, map_y);
|
||||
EEPROM.put(EEPROM_CHAOS, chaos_amount);
|
||||
}
|
||||
|
||||
// LFSR random bit generator (returns 0 or 1, fast)
|
||||
uint8_t GetRandomBit() {
|
||||
uint8_t bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5)) & 1;
|
||||
lfsr = (lfsr >> 1) | (bit << 15);
|
||||
return bit;
|
||||
}
|
||||
|
||||
// Get 8-bit pseudo-random number
|
||||
uint8_t GetRandomByte() {
|
||||
uint8_t r = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
r = (r << 1) | GetRandomBit();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void ProcessSequencerTick(uint32_t tick) {
|
||||
// Assuming 96 PPQN clock. We want 16th notes.
|
||||
// 96 pulses per quarter note / 4 = 24 pulses per 16th note.
|
||||
const int PULSES_PER_16TH = 24;
|
||||
|
||||
// Pulse logic outputs low halfway through the 16th note (12 pulses)
|
||||
if (tick % PULSES_PER_16TH == 12) {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
gravity.outputs[i].Low();
|
||||
}
|
||||
}
|
||||
|
||||
// Handle new 16th note step
|
||||
if (tick % PULSES_PER_16TH == 0) {
|
||||
|
||||
int mod_map_x = constrain(map_x + (cv1_val / 2), 0, 255);
|
||||
int active_chaos = constrain(chaos_amount + (cv2_val / 2), 0, 255);
|
||||
|
||||
// Evaluate hits for Kick, Snare, HiHats
|
||||
for (int inst = 0; inst < 3; inst++) {
|
||||
uint8_t threshold = GetThreshold(inst, current_step, mod_map_x, map_y);
|
||||
int active_density = inst_density[inst];
|
||||
|
||||
// Inject chaos
|
||||
if (active_chaos > 0) {
|
||||
// Chaos randomly adds or subtracts from density.
|
||||
int r = GetRandomByte();
|
||||
int chaos_variance = map(active_chaos, 0, 255, 0, 128);
|
||||
if (GetRandomBit()) {
|
||||
active_density += map(r, 0, 255, 0, chaos_variance);
|
||||
} else {
|
||||
active_density -= map(r, 0, 255, 0, chaos_variance);
|
||||
}
|
||||
active_density = constrain(active_density, 0, 255);
|
||||
}
|
||||
|
||||
// Fire Trigger?
|
||||
if (active_density > threshold) {
|
||||
// Output 1-3
|
||||
gravity.outputs[inst].High();
|
||||
|
||||
// Fire Accent Trigger? (If density greatly exceeds threshold)
|
||||
if (active_density > threshold + 60) {
|
||||
// Output 4-6
|
||||
gravity.outputs[inst + 3].High();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
current_step = (current_step + 1) % 16;
|
||||
}
|
||||
}
|
||||
|
||||
void OnPlayPress() {
|
||||
if (is_playing) {
|
||||
gravity.clock.Stop();
|
||||
for (int i = 0; i < 6; i++)
|
||||
gravity.outputs[i].Low();
|
||||
} else {
|
||||
gravity.clock.Start();
|
||||
}
|
||||
is_playing = !is_playing;
|
||||
needs_redraw = true;
|
||||
}
|
||||
|
||||
void OnEncoderPress() {
|
||||
editing_param = !editing_param;
|
||||
needs_redraw = true;
|
||||
}
|
||||
|
||||
void OnEncoderRotate(int val) {
|
||||
if (!editing_param) {
|
||||
// Navigate menu (clamp to edges, do not wrap)
|
||||
int next_param = (int)current_param + val;
|
||||
next_param = constrain(next_param, 0, PARAM_LAST - 1);
|
||||
current_param = (SelectedParam)next_param;
|
||||
} else {
|
||||
// Edit parameter
|
||||
int amt = val * 8; // Adjust by 8 values at a time for speed mapping
|
||||
|
||||
switch (current_param) {
|
||||
case PARAM_KICK_DENS:
|
||||
inst_density[0] = constrain(inst_density[0] + amt, 0, 255);
|
||||
break;
|
||||
case PARAM_SNARE_DENS:
|
||||
inst_density[1] = constrain(inst_density[1] + amt, 0, 255);
|
||||
break;
|
||||
case PARAM_HIHAT_DENS:
|
||||
inst_density[2] = constrain(inst_density[2] + amt, 0, 255);
|
||||
break;
|
||||
case PARAM_CHAOS:
|
||||
chaos_amount = constrain(chaos_amount + amt, 0, 255);
|
||||
break;
|
||||
case PARAM_MAP_X:
|
||||
map_x = constrain(map_x + amt, 0, 255);
|
||||
break;
|
||||
case PARAM_MAP_Y:
|
||||
map_y = constrain(map_y + amt, 0, 255);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
eeprom_needs_save = true;
|
||||
last_param_change = millis();
|
||||
}
|
||||
needs_redraw = true;
|
||||
}
|
||||
|
||||
void DrawBarGraph(int y, const char *label, int value, bool is_selected) {
|
||||
// Reset draw color to default foreground
|
||||
gravity.display.setDrawColor(1);
|
||||
gravity.display.setCursor(0, y);
|
||||
|
||||
if (is_selected) {
|
||||
gravity.display.print(">");
|
||||
if (editing_param) {
|
||||
// Draw solid white box behind the label
|
||||
gravity.display.drawBox(6, y - 8, 26, 10);
|
||||
// Switch to black text to 'cut out' the label from the box
|
||||
gravity.display.setDrawColor(0);
|
||||
}
|
||||
} else {
|
||||
gravity.display.print(" ");
|
||||
}
|
||||
|
||||
gravity.display.setCursor(6, y);
|
||||
gravity.display.print(label);
|
||||
|
||||
// Restore draw color to white for the bar and text
|
||||
gravity.display.setDrawColor(1);
|
||||
|
||||
// Draw Bar
|
||||
int barLen = map(value, 0, 255, 0, 60);
|
||||
gravity.display.drawFrame(34, y - 8, 60, 8);
|
||||
gravity.display.drawBox(34, y - 8, barLen, 8);
|
||||
|
||||
// Draw value percentage
|
||||
gravity.display.setCursor(98, y);
|
||||
int pct = map(value, 0, 255, 0, 100);
|
||||
gravity.display.print(pct);
|
||||
gravity.display.print("%");
|
||||
}
|
||||
|
||||
void UpdateDisplay() {
|
||||
gravity.display.setFontMode(1);
|
||||
gravity.display.setDrawColor(1);
|
||||
gravity.display.setFont(u8g2_font_5x7_tf);
|
||||
|
||||
// Header
|
||||
gravity.display.setCursor(0, 7);
|
||||
if (is_playing)
|
||||
gravity.display.print("[>] PLAY");
|
||||
else
|
||||
gravity.display.print("[||] PAUS");
|
||||
|
||||
gravity.display.setCursor(55, 7);
|
||||
gravity.display.print("BPM:");
|
||||
gravity.display.print(gravity.clock.Tempo());
|
||||
|
||||
gravity.display.drawHLine(0, 10, 128);
|
||||
|
||||
// Parameters List (Scrollable window of 5 items)
|
||||
int y_start = 20;
|
||||
int y_spacing = 9;
|
||||
|
||||
// Calculate window start index
|
||||
int window_start = max(0, min((int)current_param - 2, PARAM_LAST - 5));
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
int param_idx = window_start + i;
|
||||
int y_pos = y_start + (y_spacing * i);
|
||||
bool is_sel = (current_param == param_idx);
|
||||
|
||||
switch (param_idx) {
|
||||
case PARAM_KICK_DENS:
|
||||
DrawBarGraph(y_pos, "KICK", inst_density[0], is_sel);
|
||||
break;
|
||||
case PARAM_SNARE_DENS:
|
||||
DrawBarGraph(y_pos, "SNAR", inst_density[1], is_sel);
|
||||
break;
|
||||
case PARAM_HIHAT_DENS:
|
||||
DrawBarGraph(y_pos, "HHAT", inst_density[2], is_sel);
|
||||
break;
|
||||
case PARAM_CHAOS:
|
||||
DrawBarGraph(y_pos, "CHAO", chaos_amount, is_sel);
|
||||
break;
|
||||
case PARAM_MAP_X:
|
||||
DrawBarGraph(y_pos, "MAPX", map_x, is_sel);
|
||||
break;
|
||||
case PARAM_MAP_Y:
|
||||
DrawBarGraph(y_pos, "MAPY", map_y, is_sel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
gravity.Init();
|
||||
LoadState();
|
||||
|
||||
gravity.play_button.AttachPressHandler(OnPlayPress);
|
||||
gravity.encoder.AttachPressHandler(OnEncoderPress);
|
||||
gravity.encoder.AttachRotateHandler(OnEncoderRotate);
|
||||
|
||||
gravity.clock.AttachIntHandler(ProcessSequencerTick);
|
||||
// Default to 120 BPM internal
|
||||
gravity.clock.SetTempo(120);
|
||||
gravity.clock.SetSource(Clock::SOURCE_INTERNAL);
|
||||
|
||||
// Speed up I2C for faster OLED refreshing
|
||||
Wire.setClock(400000);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
gravity.Process();
|
||||
|
||||
// Apply CV modulation
|
||||
// CV1 modulates Map X, CV2 modulates Chaos
|
||||
cv1_val = gravity.cv1.Read(); // -512 to 512
|
||||
cv2_val = gravity.cv2.Read();
|
||||
|
||||
if (eeprom_needs_save && (millis() - last_param_change > SAVE_DELAY_MS)) {
|
||||
SaveState();
|
||||
eeprom_needs_save = false;
|
||||
}
|
||||
|
||||
if (needs_redraw && (millis() - last_redraw > REDRAW_DELAY_MS)) {
|
||||
needs_redraw = false;
|
||||
last_redraw = millis();
|
||||
gravity.display.firstPage();
|
||||
do {
|
||||
UpdateDisplay();
|
||||
} while (gravity.display.nextPage());
|
||||
}
|
||||
}
|
||||
136
firmware/Rhythm/maps.h
Normal file
136
firmware/Rhythm/maps.h
Normal file
@ -0,0 +1,136 @@
|
||||
#ifndef MAPS_H
|
||||
#define MAPS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
// 4x4 Grid of Patterns (X = Genre, Y = Variation)
|
||||
// X=0: House/Techno (4 on floor)
|
||||
// X=1: Breakbeat/Drum&Bass (Syncopated)
|
||||
// X=2: HipHop/Trap (Half-time feel)
|
||||
// X=3: Dem Bow / Reggaeton (Tresillo rhythm)
|
||||
// Y=0: Sparse/Basic
|
||||
// Y=1: Standard
|
||||
// Y=2: Syncopated/Groove
|
||||
// Y=3: Busy/Fills
|
||||
|
||||
// 3 Instruments (Kick=0, Snare=1, HiHat=2)
|
||||
// 16 Steps per pattern.
|
||||
// Values are "Thresholds" (0-255). A step fires if the channel's Density setting > Threshold.
|
||||
// A Threshold of 255 means it NEVER fires. 0 means it ALWAYS fires (even at minimum density).
|
||||
|
||||
const uint8_t PATTERN_MAPS[4][4][3][16] PROGMEM = {
|
||||
// X = 0 (House)
|
||||
{
|
||||
// Y = 0 (Sparse)
|
||||
{
|
||||
{ 20, 255, 255, 255, 20, 255, 255, 255, 20, 255, 255, 255, 20, 255, 255, 255 }, // Kick
|
||||
{ 255, 255, 255, 255, 50, 255, 255, 255, 255, 255, 255, 255, 50, 255, 255, 255 }, // Snare
|
||||
{ 255, 255, 60, 255, 255, 255, 60, 255, 255, 255, 60, 255, 255, 255, 60, 255 } // HiHat (Offbeats)
|
||||
},
|
||||
// Y = 1 (Standard)
|
||||
{
|
||||
{ 10, 255, 200, 255, 10, 255, 200, 255, 10, 255, 200, 255, 10, 255, 200, 255 }, // Kick
|
||||
{ 255, 255, 255, 255, 30, 255, 255, 200, 255, 255, 255, 255, 30, 255, 255, 200 }, // Snare
|
||||
{ 150, 80, 40, 80, 150, 80, 40, 80, 150, 80, 40, 80, 150, 80, 40, 80 } // HiHat
|
||||
},
|
||||
// Y = 2 (Syncopated Break/Groove)
|
||||
{
|
||||
{ 10, 255, 180, 255, 255, 180, 150, 255, 10, 255, 180, 200, 255, 180, 150, 255 }, // Kick (pushing beats)
|
||||
{ 255, 200, 255, 200, 20, 200, 255, 150, 255, 200, 255, 200, 20, 200, 255, 150 }, // Snare (ghost notes)
|
||||
{ 60, 150, 20, 150, 80, 150, 20, 150, 60, 150, 20, 150, 80, 150, 20, 150 } // HiHat (dynamic 16ths)
|
||||
},
|
||||
// Y = 3 (Busy / Driving)
|
||||
{
|
||||
{ 5, 180, 150, 200, 5, 180, 150, 200, 5, 180, 150, 200, 5, 180, 150, 200 }, // Kick
|
||||
{ 255, 200, 200, 255, 20, 200, 200, 180, 255, 200, 200, 255, 20, 200, 200, 180 }, // Snare
|
||||
{ 20, 60, 10, 60, 20, 60, 10, 60, 20, 60, 10, 60, 20, 60, 10, 60 } // HiHat (accented 16ths)
|
||||
}
|
||||
},
|
||||
|
||||
// X = 1 (Breakbeat)
|
||||
{
|
||||
// Y = 0 (Sparse)
|
||||
{
|
||||
{ 20, 255, 255, 255, 255, 255, 100, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, // Kick (1, 3& half)
|
||||
{ 255, 255, 255, 255, 50, 255, 255, 255, 255, 255, 255, 255, 50, 255, 255, 255 }, // Snare (2, 4)
|
||||
{ 60, 255, 150, 255, 60, 255, 150, 255, 60, 255, 150, 255, 60, 255, 150, 255 } // HiHat (8ths)
|
||||
},
|
||||
// Y = 1 (Standard)
|
||||
{
|
||||
{ 10, 255, 150, 255, 255, 180, 80, 200, 255, 150, 255, 200, 255, 255, 150, 255 }, // Kick
|
||||
{ 255, 255, 200, 255, 30, 255, 255, 150, 255, 255, 180, 255, 30, 255, 200, 180 }, // Snare (syncopated ghosts)
|
||||
{ 40, 120, 80, 120, 40, 120, 80, 120, 40, 120, 80, 120, 40, 120, 80, 120 } // HiHat
|
||||
},
|
||||
// Y = 2 (Jungle / Fast Syncopation)
|
||||
{
|
||||
{ 10, 200, 255, 150, 255, 200, 80, 255, 10, 200, 255, 150, 255, 200, 80, 200 }, // Kick
|
||||
{ 255, 150, 200, 180, 20, 200, 150, 100, 255, 150, 200, 180, 20, 200, 150, 100 }, // Snare (heavy ghosts & rolls)
|
||||
{ 50, 150, 150, 100, 50, 150, 150, 100, 50, 150, 150, 100, 50, 150, 150, 100 } // HiHat (dynamic 16ths)
|
||||
},
|
||||
// Y = 3 (Busy Breakcore)
|
||||
{
|
||||
{ 5, 150, 120, 150, 180, 100, 50, 120, 150, 80, 150, 100, 200, 80, 100, 150 }, // Kick
|
||||
{ 200, 180, 150, 200, 20, 150, 180, 100, 180, 120, 100, 150, 20, 100, 120, 80 }, // Snare
|
||||
{ 20, 50, 40, 50, 20, 50, 40, 50, 20, 50, 40, 50, 20, 50, 40, 50 } // HiHat (16ths + dynamic)
|
||||
}
|
||||
},
|
||||
|
||||
// X = 2 (HipHop)
|
||||
{
|
||||
// Y = 0 (Sparse)
|
||||
{
|
||||
{ 20, 255, 255, 255, 255, 255, 255, 255, 100, 255, 255, 255, 255, 255, 255, 255 }, // Kick (1, 3)
|
||||
{ 255, 255, 255, 255, 60, 255, 255, 255, 255, 255, 255, 255, 60, 255, 255, 255 }, // Snare (2, 4)
|
||||
{ 80, 255, 255, 255, 80, 255, 255, 255, 80, 255, 255, 255, 80, 255, 255, 255 } // HiHat (Quarters)
|
||||
},
|
||||
// Y = 1 (Standard)
|
||||
{
|
||||
{ 10, 255, 255, 150, 255, 255, 255, 200, 80, 255, 150, 255, 255, 255, 255, 200 }, // Kick
|
||||
{ 255, 255, 255, 255, 40, 255, 255, 255, 255, 255, 255, 255, 40, 255, 200, 255 }, // Snare
|
||||
{ 50, 150, 50, 150, 50, 150, 50, 150, 50, 150, 50, 150, 50, 150, 50, 150 } // HiHat (8ths)
|
||||
},
|
||||
// Y = 2 (Boom Bap / Swing)
|
||||
{
|
||||
{ 10, 255, 150, 200, 255, 255, 150, 200, 50, 255, 100, 255, 255, 200, 150, 255 }, // Kick (Swung 16ths)
|
||||
{ 255, 255, 200, 255, 30, 255, 200, 150, 255, 255, 200, 255, 30, 200, 255, 150 }, // Snare (Ghost notes)
|
||||
{ 30, 200, 80, 150, 30, 200, 80, 150, 30, 200, 80, 150, 30, 200, 80, 150 } // HiHat (Heavy swing feel)
|
||||
},
|
||||
// Y = 3 (Busy / Trap)
|
||||
{
|
||||
{ 5, 200, 150, 80, 200, 180, 150, 120, 40, 150, 80, 200, 150, 180, 120, 100 }, // Kick
|
||||
{ 255, 255, 200, 255, 20, 200, 255, 150, 255, 255, 180, 255, 20, 150, 180, 100 }, // Snare (with trap rolls)
|
||||
{ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 } // HiHat (rapid 16ths)
|
||||
}
|
||||
},
|
||||
|
||||
// X = 3 (Dem Bow / Reggaeton - Tresillo Rhythm)
|
||||
{
|
||||
// Y = 0 (Sparse)
|
||||
{
|
||||
{ 20, 255, 255, 255, 20, 255, 255, 255, 20, 255, 255, 255, 20, 255, 255, 255 }, // Kick (4 on floor)
|
||||
{ 255, 255, 255, 60, 255, 255, 60, 255, 255, 255, 255, 60, 255, 255, 60, 255 }, // Snare (Tresillo off-beats)
|
||||
{ 255, 255, 150, 255, 255, 255, 150, 255, 255, 255, 150, 255, 255, 255, 150, 255 } // HiHat (basic offbeats)
|
||||
},
|
||||
// Y = 1 (Standard)
|
||||
{
|
||||
{ 10, 255, 200, 255, 10, 255, 200, 255, 10, 255, 200, 255, 10, 255, 200, 255 }, // Kick
|
||||
{ 255, 255, 255, 30, 255, 255, 30, 200, 255, 255, 255, 30, 255, 255, 30, 200 }, // Snare (Strong Tresillo + syncopation)
|
||||
{ 100, 200, 50, 200, 100, 200, 50, 200, 100, 200, 50, 200, 100, 200, 50, 200 } // HiHat (8th note swing)
|
||||
},
|
||||
// Y = 2 (Syncopated Tresillo)
|
||||
{
|
||||
{ 10, 255, 150, 200, 10, 255, 150, 200, 10, 255, 150, 200, 10, 255, 150, 200 }, // Kick (Driving but syncopated)
|
||||
{ 255, 200, 255, 20, 200, 255, 20, 150, 255, 200, 255, 20, 200, 255, 20, 150 }, // Snare (Pushing the backbeat)
|
||||
{ 50, 150, 100, 150, 50, 150, 100, 150, 50, 150, 100, 150, 50, 150, 100, 150 } // HiHat (Syncopated ride)
|
||||
},
|
||||
// Y = 3 (Busy / Rolls)
|
||||
{
|
||||
{ 5, 200, 150, 120, 5, 200, 150, 120, 5, 200, 150, 120, 5, 200, 150, 120 }, // Kick (driving)
|
||||
{ 255, 180, 200, 20, 180, 200, 20, 120, 255, 180, 200, 20, 180, 200, 20, 80 }, // Snare (Dem Bow rolls)
|
||||
{ 30, 80, 40, 80, 30, 80, 40, 80, 30, 80, 40, 80, 30, 80, 40, 80 } // HiHat (16ths riding on the tresillo)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,4 +1,4 @@
|
||||
version=2.0.1beta1
|
||||
version=2.0.1
|
||||
author=Adam Wonak
|
||||
maintainer=awonak <github.com/awonak>
|
||||
sentence=Hardware abstraction library for Sitka Instruments Gravity eurorack module
|
||||
|
||||
Reference in New Issue
Block a user