Skip to content

Commit

Permalink
Drum ops (monome#298)
Browse files Browse the repository at this point in the history
* Adding drum helper ops

* Adding feedback improvements

Step now 0 indexed
Pseudo random bank now goes to 215, in line with the other banks

* Typo

* Final feedback. tidyup and help text

* Adding drum ops to whats new file

* PR feedback
  • Loading branch information
subvertnormality authored Jan 17, 2023
1 parent 0a450e1 commit fa0e402
Show file tree
Hide file tree
Showing 20 changed files with 1,520 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- **IMP**: fader ops now support up to four faderbanks
- **NEW**: new Disting EX ops: dual algorithms, `EX.M.N#`, `EX.M.NO#`, `EX.M.CC#`
- **FIX**: reset M timer when changing metro rate
- **NEW**: new Drum Ops: `DR.T`, `DR.V`, `DR.P`

## v4.0.0

Expand Down
2 changes: 1 addition & 1 deletion docs/ops/disting.toml
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ short = "send MIDI Note On message on channel `x` for note `y` (0..127) and velo
prototype = "EX.M.NO x"
short = "send MIDI Note off message for note `x` (0..127)"

["EX.M.NO"]
["EX.M.NO#"]
prototype = "EX.M.NO x y"
short = "send MIDI Note off message on channel `x` for note `y` (0..127)"

Expand Down
24 changes: 24 additions & 0 deletions docs/ops/maths.toml
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,30 @@ For further detail ["see the manual"][nr_manual].
[nr_manual]: https://static1.squarespace.com/static/58c709192e69cf2422026fa6/t/5e6041ad4cbc0979d6d793f2/1583366574430/NR_manual.pdf
"""

["DR.T"]
prototype = "DR.T b p q l s"
short = "Tresillo helper, `b` is the drum bank (`0-4`), `p` is first pattern (0-215), `q` is the second pattern (0-215), `l` is length (`1-64`), and step is the step number (0-length-1), returns `0` or `1`"
description = """
The Tresillo helper uses the preset drum patterns described in the drum pattern help function in a 3, 3, 2 rythmic formation. In the tresillo, pattern 1 will be repeated twice for a number of steps determined by the overall length of the pattern. A pattern of length 8 will play the first three steps of your selected pattern 1 twice, and
the first two steps of pattern 2 once. A pattern length of 16 will play the first six steps of selected pattern 1 twice, and the first four steps of pattern 2 once. And so on. The max length is 64. Length will be rounded down to the nearest multiple of 8. The step number wraps at the given length.
"""

["DR.P"]
prototype = "DR.P b p s"
short = "Drum pattern helper, `b` is the drum bank (`0-4`), `p` is the pattern (0-215) and step is the step number (0-15), returns `0` or `1`"
description = """
The drum helper uses preset drum patterns to give 16-step gate patterns. Gates wrap after step 16. Bank 0 is a set of pseudo random gates increasing in density at higher numbered patterns, where pattern 0 is empty,
and pattern 215 is 1s. Bank 1 is bass drum patterns. Bank 2 is snare drum patterns. Bank 3 is closed hi-hats. Bank 4 is open hi-hits and in some cases cymbals. Bank 1-4 patterns are related to each other (bank 1 pattern 1's bass drum pattern fits bank 2 pattern 1's snare drum pattern).
The patterns are from [Paul Wenzel's "Pocket Operations" book](https://shittyrecording.studio/).
"""

["DR.V"]
prototype = "DR.V p s"
short = "Velocity helper. `p` is the pattern (0-9). `s` is the step number (0-15)"
description = """
The velocity helper gives velocity values (0-16383) at each step. The values are intended to be used for drum hit velocities. There are 16 steps, which wrap around. Divide by 129 to convert to midi cc values.
"""

[BPM]
prototype = "BPM x"
short = "milliseconds per beat in BPM `x`"
Expand Down
1 change: 1 addition & 0 deletions docs/whats_new.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- **IMP**: fader ops now support up to four faderbanks
- **NEW**: new Disting EX ops: dual algorithms, `EX.M.N#`, `EX.M.NO#`, `EX.M.CC#`
- **FIX**: reset M timer when changing metro rate
- **NEW**: drum ops: `DR.P`, `DR.V`, `DR.TR`

## v4.0.0

Expand Down
1 change: 1 addition & 0 deletions module/config.mk
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ CSRCS = \
../src/command.c \
../src/every.c \
../src/helpers.c \
../src/drum_helpers.c \
../src/match_token.c \
../src/scanner.c \
../src/scale.c \
Expand Down
22 changes: 20 additions & 2 deletions module/help_mode.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ const char* help3[HELP3_LENGTH] = { "3/16 PARAMETERS",
"FB.C.R X",
" RESET FADER X CALIBRATION" };

#define HELP4_LENGTH 78
#define HELP4_LENGTH 95
const char* help4[HELP4_LENGTH] = { "4/16 DATA AND TABLES",
" ",
"ALL PARAMS HAVE 16B RANGE",
Expand Down Expand Up @@ -261,7 +261,25 @@ const char* help4[HELP4_LENGTH] = { "4/16 DATA AND TABLES",
" LYD = 0, 2, 1, 6, 0, 1, 1",
" LOC = 6, 0, 1, 1, 0, 2, 1",
" MYX = 2, 1, 6, 0, 1, 1, 0",
" RETURNS N TABLE VALUE" };
" RETURNS N TABLE VALUE",
" ",
"DRUM PATTERN OP - DR.P",
"DR.P B P S",
" B = BANK (0-5)",
" P = PATTERN (0-215)",
" S = STEP (0-15)",
"DRUM TRESILLO OP - DR.T",
"DR.T B P Q L S",
" B = BANK (0-5)",
" P = PATTERN 1 (0-215)",
" Q = PATTERN 2 (0-215)",
" L = LENGTH (8-64)",
" S = STEP (0- LENGTH-1)",
"DRUM VELOCITY OP - DR.V",
"DR.V P S",
" P = PATTERN (0-9)",
" S = STEP (0-15)"
};

#define HELP5_LENGTH 128
const char* help5[HELP5_LENGTH] = { "5/16 OPERATORS",
Expand Down
2 changes: 1 addition & 1 deletion simulator/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.PHONY: clean
CFLAGS=-std=c99 -g -Wall -fno-common -DSIM -I. -I../src -I../libavr32/src
DEPS =
OBJ = tt.o ../src/teletype.o ../src/command.o ../src/helpers.o \
OBJ = tt.o ../src/teletype.o ../src/command.o ../src/helpers.o ../src/drum_helpers.o \
../src/every.o ../src/match_token.o ../src/scanner.o \
../src/scale.o ../src/scene_serialization.o \
../src/state.o ../src/table.o ../src/turtle.o ../src/chaos.o \
Expand Down
112 changes: 112 additions & 0 deletions src/drum_helpers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#include "drum_helpers.h"

#include <stdio.h>

#include "table.h"

static int wrap(int const k, int const lower_bound, int const upper_bound) {
int range = upper_bound - lower_bound + 1;
int kx = ((k - lower_bound) % range);
if (kx < 0)
return upper_bound + 1 + kx;
else
return lower_bound + kx;
}


static char get_byte(const char* a, int n) {
return a[n >> 3];
}

static int get_bit(const char* a, int k) {
char byte = get_byte(a, k);
int bit_index = 7 - (k % 8);

return (byte & (1 << bit_index)) != 0;
}

int tresillo(int bank, int pattern1, int pattern2, int len, int step) {
if (bank < 0 || bank > 4) return 0;
if (len < 8) return 0;
if (step < 0) return 0;
if (pattern1 >= drum_ops_pattern_len || pattern2 >= drum_ops_pattern_len) return 0;

const char* table1;
const char* table2;

switch (bank) {
case 0:
table1 = table_t_r_e[pattern1];
table2 = table_t_r_e[pattern2];
break;
case 1:
table1 = table_dr_bd[pattern1];
table2 = table_dr_bd[pattern2];
break;
case 2:
table1 = table_dr_sd[pattern1];
table2 = table_dr_sd[pattern2];
break;
case 3:
table1 = table_dr_ch[pattern1];
table2 = table_dr_ch[pattern2];
break;
case 4:
table1 = table_dr_oh[pattern1];
table2 = table_dr_oh[pattern2];
break;
}


int multiplier = len / 8;

int three = 3 * multiplier;
int wrapped_step = wrap(step, 0, multiplier * 8 - 1);


if (wrapped_step <= three - 1) { return get_bit(table1, wrapped_step); }
else if (wrapped_step <= three * 2 - 1) {
return get_bit(table1, wrapped_step - three);
}

return get_bit(table2, wrapped_step - (three * 2));
}

int drum(int bank, int pattern, int step) {
if (bank < 0 || bank > 4) return 0;
if (step < 0) return 0;
if (pattern >= drum_ops_pattern_len) return 0;

const char* table;

switch (bank) {
case 0:
table = table_t_r_e[pattern];
break;
case 1:
table = table_dr_bd[pattern];
break;
case 2:
table = table_dr_sd[pattern];
break;
case 3:
table = table_dr_ch[pattern];
break;
case 4:
table = table_dr_oh[pattern];
break;
}

int wrapped_step = wrap(step, 0, 15);

return get_bit(table, wrapped_step);
}

int velocity(int pattern, int step) {
if (step < 0) return 0;
if (pattern < 0 || pattern > 9) return 0;

const uint16_t* table = table_vel_helper[pattern];
int wrapped_step = wrap(step, 0, 15);
return table[wrapped_step];
}
8 changes: 8 additions & 0 deletions src/drum_helpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef _DRUM_HELPERS_H_
#define _DRUM_HELPERS_H_

int tresillo(int bank, int pattern1, int pattern2, int len, int step);
int drum(int bank, int pattern, int step);
int velocity(int pattern, int step);

#endif
5 changes: 4 additions & 1 deletion src/match_token.rl
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@
"OUTR" => { MATCH_OP(E_OP_OUTR); };
"INRI" => { MATCH_OP(E_OP_INRI); };
"OUTRI" => { MATCH_OP(E_OP_OUTRI); };
"NZ" => { MATCH_OP(E_OP_NZ); };
"NZ" => { MATCH_OP(E_OP_NZ); };
"EZ" => { MATCH_OP(E_OP_EZ); };
"RSH" => { MATCH_OP(E_OP_RSH); };
"LSH" => { MATCH_OP(E_OP_LSH); };
Expand Down Expand Up @@ -255,6 +255,9 @@
"VV" => { MATCH_OP(E_OP_VV); };
"ER" => { MATCH_OP(E_OP_ER); };
"NR" => { MATCH_OP(E_OP_NR); };
"DR.T" => { MATCH_OP(E_OP_DR_T); };
"DR.P" => { MATCH_OP(E_OP_DR_P); };
"DR.V" => { MATCH_OP(E_OP_DR_V); };
"BPM" => { MATCH_OP(E_OP_BPM);; };
"|" => { MATCH_OP(E_OP_BIT_OR);; };
"&" => { MATCH_OP(E_OP_BIT_AND);; };
Expand Down
57 changes: 47 additions & 10 deletions src/ops/maths.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#include "ops/maths.h"

#include <stdlib.h> // abs
#include "random.h"

#include "chaos.h"
#include "drum_helpers.h"
#include "euclidean/euclidean.h"
#include "helpers.h"
#include "random.h"
#include "table.h"

static void op_ADD_get(const void *data, scene_state_t *ss, exec_state_t *es,
Expand Down Expand Up @@ -138,6 +139,12 @@ static void op_ER_get(const void *data, scene_state_t *ss, exec_state_t *es,
command_state_t *cs);
static void op_NR_get(const void *data, scene_state_t *ss, exec_state_t *es,
command_state_t *cs);
static void op_DR_T_get(const void *data, scene_state_t *ss, exec_state_t *es,
command_state_t *cs);
static void op_DR_P_get(const void *data, scene_state_t *ss, exec_state_t *es,
command_state_t *cs);
static void op_DR_V_get(const void *data, scene_state_t *ss, exec_state_t *es,
command_state_t *cs);
static void op_BPM_get(const void *data, scene_state_t *ss, exec_state_t *es,
command_state_t *cs);
static void op_BIT_OR_get(const void *data, scene_state_t *ss, exec_state_t *es,
Expand Down Expand Up @@ -238,6 +245,9 @@ const tele_op_t op_V = MAKE_GET_OP(V , op_V_get , 1, true);
const tele_op_t op_VV = MAKE_GET_OP(VV , op_VV_get , 1, true);
const tele_op_t op_ER = MAKE_GET_OP(ER , op_ER_get , 3, true);
const tele_op_t op_NR = MAKE_GET_OP(NR , op_NR_get , 4, true);
const tele_op_t op_DR_T = MAKE_GET_OP(DR.T , op_DR_T_get , 5, true);
const tele_op_t op_DR_P = MAKE_GET_OP(DR.P , op_DR_P_get , 3, true);
const tele_op_t op_DR_V = MAKE_GET_OP(DR.V , op_DR_V_get , 2, true);
const tele_op_t op_BPM = MAKE_GET_OP(BPM , op_BPM_get , 1, true);
const tele_op_t op_BIT_OR = MAKE_GET_OP(|, op_BIT_OR_get , 2, true);
const tele_op_t op_BIT_AND = MAKE_GET_OP(&, op_BIT_AND_get, 2, true);
Expand Down Expand Up @@ -406,17 +416,19 @@ static int16_t quantize_to_bitmask_scale(int16_t scale_bits, int16_t transpose,
// accepts 12-bit scale mask and a pitch voltage. transpose is voltage for
// scale offset. returns nearest pitch voltage in scale.
if (scale_bits == 0) { return v_in; } // no active scale bits
v_in = normalise_value(-table_n[127], table_n[127], 0, v_in);
int16_t sign_offset = (v_in < 0) ? 18022 : 0; //11 octaves
v_in = v_in + sign_offset;

v_in = normalise_value(-table_n[127], table_n[127], 0, v_in);

int16_t sign_offset = (v_in < 0) ? 18022 : 0; // 11 octaves
v_in = v_in + sign_offset;

int16_t octave_in = v_in / table_n[12];
if (v_in <= 18021 && v_in >= 18018) { octave_in = 10; } //fix precision error
if (v_in <= 18021 && v_in >= 18018) {
octave_in = 10;
} // fix precision error
int16_t semitones_in = v_in % table_n[12];
transpose = transpose % table_n[12];

int16_t dist_nearest = INT16_MAX;
int16_t note_nearest = INT16_MAX;
int16_t try_note, try_distance;
Expand All @@ -432,7 +444,7 @@ static int16_t quantize_to_bitmask_scale(int16_t scale_bits, int16_t transpose,
}
}
}

return (note_nearest + table_n[octave_in * 12]) - sign_offset;
}

Expand Down Expand Up @@ -1082,6 +1094,31 @@ static void op_NR_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss),
cs_push(cs, bit_status);
}

static void op_DR_T_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss),
exec_state_t *NOTUSED(es), command_state_t *cs) {
int16_t bank = cs_pop(cs);
int16_t pattern1 = cs_pop(cs);
int16_t pattern2 = cs_pop(cs);
int16_t len = cs_pop(cs);
int16_t step = cs_pop(cs);
cs_push(cs, tresillo(bank, pattern1, pattern2, len, step));
}

static void op_DR_P_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss),
exec_state_t *NOTUSED(es), command_state_t *cs) {
int16_t bank = cs_pop(cs);
int16_t pattern = cs_pop(cs);
int16_t step = cs_pop(cs);
cs_push(cs, drum(bank, pattern, step));
}

static void op_DR_V_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss),
exec_state_t *NOTUSED(es), command_state_t *cs) {
int16_t pattern = cs_pop(cs);
int16_t step = cs_pop(cs);
cs_push(cs, velocity(pattern, step));
}

static void op_N_S_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss),
exec_state_t *NOTUSED(es), command_state_t *cs) {
int16_t root = cs_pop(cs);
Expand Down
3 changes: 3 additions & 0 deletions src/ops/maths.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ extern const tele_op_t op_V;
extern const tele_op_t op_VV;
extern const tele_op_t op_ER;
extern const tele_op_t op_NR;
extern const tele_op_t op_DR_T;
extern const tele_op_t op_DR_P;
extern const tele_op_t op_DR_V;
extern const tele_op_t op_BPM;
extern const tele_op_t op_BIT_OR;
extern const tele_op_t op_BIT_AND;
Expand Down
3 changes: 2 additions & 1 deletion src/ops/op.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ const tele_op_t *tele_ops[E_OP__LENGTH] = {
&op_RROT, &op_EXP, &op_ABS, &op_SGN, &op_AND, &op_OR, &op_AND3, &op_OR3,
&op_AND4, &op_OR4, &op_JI, &op_SCALE, &op_SCL, &op_N, &op_VN, &op_HZ,
&op_N_S, &op_N_C, &op_N_CS, &op_N_B, &op_N_BX, &op_V, &op_VV, &op_ER,
&op_NR, &op_BPM, &op_BIT_OR, &op_BIT_AND, &op_BIT_NOT, &op_BIT_XOR,
&op_NR, &op_DR_T, &op_DR_P, &op_DR_V, &op_BPM, &op_BIT_OR,
&op_BIT_AND, &op_BIT_NOT, &op_BIT_XOR,
&op_BSET, &op_BGET, &op_BCLR, &op_BTOG, &op_BREV, &op_XOR, &op_CHAOS,
&op_CHAOS_R, &op_CHAOS_ALG, &op_SYM_PLUS, &op_SYM_DASH, &op_SYM_STAR,
&op_SYM_FORWARD_SLASH, &op_SYM_PERCENTAGE, &op_SYM_EQUAL_x2,
Expand Down
3 changes: 3 additions & 0 deletions src/ops/op_enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,9 @@ typedef enum {
E_OP_VV,
E_OP_ER,
E_OP_NR,
E_OP_DR_T,
E_OP_DR_P,
E_OP_DR_V,
E_OP_BPM,
E_OP_BIT_OR,
E_OP_BIT_AND,
Expand Down
Loading

0 comments on commit fa0e402

Please sign in to comment.