2020-09-14 20:25:03 (UTC-03:00)
Marcel Rodrigues <marcelgmr@gmail.com>
basic matrix plain-text load/save
diff --git a/seqt.c b/seqt.c new file mode 100644 index 0000000..0d4501d --- /dev/null +++ b/seqt.c @@ -0,0 +1,199 @@ +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <stdio.h> + +#define MAXTRACK 0x0010 +#define MAXVOICE 0x0008 +#define MAXINDEX 0x1000 + +#define RECSIZE 0x20 +#define MAPSIZE 0x20 + +#define MAXINPUTLINE 0x400 + +#define REST 0 +#define CONT 1 +#define END 2 + +int ntracks; +char map[MAPSIZE][RECSIZE]; +unsigned char matrix[MAXTRACK][MAXINDEX][MAXVOICE]; + +/* search key in map + * if key is found, return record index, otherwise return negative int: + * return the index of the first empty record, negated + * if map is full, return -MAPSIZE */ +int +map_find(const char *key) +{ + int i; + for (i = 0; i < MAPSIZE; i++) { + if (!*map[i]) + return -i; + if (!strcmp(map[i], key)) + return i; + } + return -i; +} + +/* put a key-value pair on the map + * if the key is already on the map, update its value + * return 0 on success, negative value on error: + * -1: key-value pair is too large to fit on a record + * -2: no record available on the map */ +int +map_put(const char *key, const char *val) +{ + int keylen = strlen(key); + int vallen = strlen(val); + int i; + if (keylen + vallen + 2 > RECSIZE) + return -1; + i = map_find(key); + if (i == -MAPSIZE) + return -2; + if (i < 0) { + i = -i; + strcpy(&map[i][0], key); + } + strcpy(&map[i][keylen+1], val); + return 0; +} + +/* get the value associated with the given key on the map + * returns a pointer to the value found or NULL if not found */ +char * +map_get(const char *key) +{ + int i = map_find(key); + if (i < 0) + return NULL; + return &map[i][strlen(key)+1]; +} + +typedef enum TxtStt {NTRK, MTDT, TKNM, EVNT} TxtStt; + +int +load_txt(FILE *fp) +{ + char line[MAXINPUTLINE]; + char track_key[] = "TRK0"; + char *track_dig = track_key + 3; + TxtStt state = NTRK; + char *sep, *nl, *cell; + int track, index, voice; + unsigned char pitch; + while (fgets(line, MAXINPUTLINE, fp)) { + if (line[0] == '\n') + continue; + switch (state) { + case NTRK: + if (strncmp(line, "ntracks:", 8)) + return -1; + ntracks = atoi(line + 8); + track = 0; + state = MTDT; + break; + case MTDT: + if ((sep = strchr(line, ':'))) { + nl = strchr(line, '\n'); + *sep = *nl = '\0'; + map_put(line, sep + 1); + break; + } else { + state = TKNM; + } + /* fall through */ + case TKNM: + state = EVNT; +track_name: + nl = strchr(line, '\n'); + *nl = '\0'; + map_put(track_key, line); + *track_dig = *track_dig == '9' ? 'A' : *track_dig + 1; + index = 0; + break; + case EVNT: + if (isdigit(line[0])) { + /* noteset */ + cell = &line[2]; + voice = 0; + while (*cell) { + switch (*cell) { + case '.': + /* matrix[track][index][voice] = REST; */ + break; + case '=': + matrix[track][index][voice] = CONT; + break; + default: + pitch = (cell[0] - '0') * 10 + cell[1] - '0'; + matrix[track][index][voice] = pitch | 0x80; + } + cell += 3; + voice++; + } + index++; + } else { + if (!strchr(line, ':')) { + matrix[track][index][0] = END; + track++; + goto track_name; + } + printf("ignoring metaevent: %s", line); + } + } + } + matrix[track][index][0] = END; + ntracks = track + 1; + return 0; +} + +int +save_txt(FILE *fp) +{ + int track, index, voice; + int last_voice; + unsigned char cell; + char track_key[] = "TRK0"; + char *track_dig = track_key + 3; + fprintf(fp, "ntracks:%d\n\n", ntracks); + /* TODO: write metadata */ + fprintf(fp, "foo:bar\n"); + for (track = 0; track < ntracks; track++) { + fprintf(fp, "\n%s\n\n", map_get(track_key)); + for (index = 0; index < MAXINDEX; index++) { + if (matrix[track][index][0] == END) + break; + for (voice = MAXVOICE-1; voice >= 0; voice--) + if (matrix[track][index][voice]) + break; + last_voice = voice; + for (voice = 0; voice <= last_voice; voice++) { + cell = matrix[track][index][voice]; + if (cell & 0x80) + fprintf(fp, " %2u", cell & 0x7F); + else if (cell == REST) + fprintf(fp, " .."); + else if (cell == CONT) + fprintf(fp, " =="); + else + fprintf(fp, " ??"); + } + fprintf(fp, "\n"); + } + *track_dig = *track_dig == '9' ? 'A' : *track_dig + 1; + } + return 0; +} + +int +main() +{ + if (load_txt(stdin) < 0) + return -1; + if (save_txt(stdout) < 0) + return -2; + return 0; +}