2020-12-19 00:29:37 (UTC-03:00)
Marcel Rodrigues <marcelgmr@gmail.com>
edit: add edit stack and basic operations
diff --git a/edit.c b/edit.c new file mode 100644 index 0000000..0a5553a --- /dev/null +++ b/edit.c @@ -0,0 +1,145 @@ +#include "seqt.h" + +#define NOPS 0x2000 +#define M1 (NOPS - 1) +#define M2 ((NOPS << 1) - 1) + +typedef enum OpCode {DUR, PIT, INS, DEL} OpCode; + +static uint32_t stack[NOPS]; +static int p, q, r; + +static uint32_t +track_index(unsigned track, unsigned index) +{ + return (track << 16) | (index << 4); +} + +uint32_t +op_dur(unsigned track, unsigned index, unsigned delta) +{ + uint32_t op = track_index(track, index) | DUR; + return op | (delta << 20); +} + +uint32_t +op_pit(unsigned track, unsigned index, unsigned voice, unsigned delta) +{ + uint32_t op = track_index(track, index) | PIT; + return op | (voice << 28) | (delta << 20); +} + +uint32_t +op_ins(unsigned track, unsigned index, unsigned nrows) +{ + uint32_t op = track_index(track, index) | INS; + return op | (nrows << 20); +} + +uint32_t +op_del(unsigned track, unsigned index, unsigned nrows) +{ + uint32_t op = track_index(track, index) | DEL; + return op | (nrows << 20); +} + +#define inc(i) (((i) + 1) & M2) +#define dec(i) (((i) - 1) & M2) +#define isempty (p == q) +#define isfull (p == (q ^ NOPS)) + +static void +push(uint32_t op) +{ + r = 0; + stack[q & M1] = op; + q = inc(q); +} + +static uint32_t +pop() +{ + r++; + q = dec(q); + return stack[q & M1]; +} + +static uint32_t +unpop() +{ + r--; + q = inc(q); + return stack[q & M1]; +} + +static void +apply(Matrix matrix, uint32_t op, int reverse) +{ + unsigned int track, index, delta, voice, nrows; + unsigned int args = op >> 20; + unsigned char duration, cell; + track = (op >> 16) & 0xF; + index = (op >> 4) & 0xFFF; + switch ((OpCode) (op & 3)) { + case DUR: + delta = args; + duration = matrix[index][0][track >> 1]; + duration = track & 1 ? duration & 0x0F : duration >> 4; + if (reverse) + duration = (duration - delta) & 0x0F; + else + duration = (duration + delta) & 0x0F; + matrix[index][0][track >> 1] |= duration << ((~track & 1) << 2); + break; + case PIT: + voice = args >> 8; + delta = args & 0xFF; + cell = matrix[index][track][voice]; + if (reverse) + cell = (cell - delta) & 0xFF; + else + cell = (cell + delta) & 0xFF; + matrix[index][track][voice] = cell; + break; + case INS: + /* TODO */ + (void) nrows; + break; + case DEL: + /* TODO */ + (void) nrows; + } +} + +void +doop(Matrix matrix, uint32_t op, int mark) +{ + apply(matrix, op, 0); + push(op | (((unsigned) mark) << 2)); +} + +void +undo(Matrix matrix) +{ + uint32_t op; + while (!isempty) { + op = pop(); + apply(matrix, op, 1); + if (op & 4) + break; + } +} + +void +redo(Matrix matrix) +{ + uint32_t op; + while (!isfull) { + op = unpop(); + if (op & 4) { + (void) pop(); + break; + } + apply(matrix, op, 0); + } +} diff --git a/seqt.c b/seqt.c index 9a75de7..93b8faf 100644 --- a/seqt.c +++ b/seqt.c @@ -5,7 +5,7 @@ int ntracks; char map[MAPSIZE][RECSIZE]; -unsigned char matrix[MAXINDEX][MAXTRACK][MAXVOICE]; +Matrix matrix; void print_blank() diff --git a/seqt.h b/seqt.h index 21d21e8..ff332d8 100644 --- a/seqt.h +++ b/seqt.h @@ -3,6 +3,7 @@ #define _POSIX_C_SOURCE 200809L +#include <stdint.h> #include <stdio.h> #include <fcntl.h> #include <sys/ioctl.h> @@ -13,11 +14,23 @@ #define MAXINDEX 0x1000 #define MAXTRACK 0x0010 #define MAXVOICE 0x0008 -extern unsigned char matrix[MAXINDEX][MAXTRACK][MAXVOICE]; +typedef unsigned char Matrix[MAXINDEX][MAXTRACK][MAXVOICE]; +extern Matrix matrix; #define REST 0 #define CONT 1 +/* ============================== Edit ============================== */ + +uint32_t op_dur(unsigned track, unsigned index, unsigned delta); +uint32_t op_pit(unsigned track, unsigned index, unsigned voice, unsigned delta); +uint32_t op_ins(unsigned track, unsigned index, unsigned nrows); +uint32_t op_del(unsigned track, unsigned index, unsigned nrows); + +void doop(Matrix matrix, uint32_t op, int mark); +void undo(Matrix matrix); +void redo(Matrix matrix); + /* =============================== Map ============================== */ #define RECSIZE 0x20