Sigrid Solveig Haflínudóttircompile stuff50243ce5 years agoHistory
579 lines · 12.1 KB · C
RawDownload
/* * Tinyprop * By Paul Batchelor * * A tiny C implementation of prop, a proportional rhythmic notation system * */ #include <stdlib.h>#include <math.h>#include "soundpipe.h" typedef struct {    uint32_t size;    prop_list **ar;} prop_slice; static int prop_create(prop_data **pd);static int prop_parse(prop_data *pd, const char *str);static prop_event prop_next(sp_data *sp, prop_data *pd);static float prop_time(prop_data *pd, prop_event evt);static int prop_destroy(prop_data **pd); static int prop_val_free(prop_val val);static int prop_list_init(prop_list *lst);static int prop_list_destroy(prop_list *lst);static int prop_list_append(prop_list *lst, prop_val val);static void prop_list_reset(prop_list *lst);static int prop_list_copy(prop_list *src, prop_list **dst); static void mode_insert_event(prop_data *pd, char type);static void mode_insert_slice(prop_data *pd);static void mode_list_start(prop_data *pd);static void mode_list_end(prop_data *pd);static void prop_slice_encap(prop_data *pd);static void prop_slice_append(prop_data *pd);static void reset(prop_data *pd);static void back_to_top(prop_data *pd); enum {PTYPE_SLICE,PTYPE_LIST,PTYPE_EVENT,PTYPE_OFF,PTYPE_ON,PTYPE_MAYBE,PMODE_INSERT,PMODE_SETDIV,PMODE_SETMUL,PMODE_UNSETMUL,PMODE_INIT,PSTATUS_NOTOK,PSTATUS_OK,PTYPE_NULL}; int sp_prop_create(sp_prop **p){    *p = malloc(sizeof(sp_prop));    return SP_OK;} int sp_prop_destroy(sp_prop **p){    sp_prop *pp = *p;    prop_destroy(&pp->prp);    free(*p);    return SP_OK;} int sp_prop_init(sp_data *sp, sp_prop *p, const char *str){    USED(sp);     p->count = 0;     prop_create(&p->prp);     if (prop_parse(p->prp, str) == PSTATUS_NOTOK) {        fprintf(stderr,"There was an error parsing the string.\n");        return SP_NOT_OK;    }     p->bpm = 60;    p->lbpm = 60;    return SP_OK;} int sp_prop_compute(sp_data *sp, sp_prop *p, SPFLOAT *in, SPFLOAT *out){    USED(in);     if (p->count == 0) {        if (p->bpm != p->lbpm) {            p->prp->scale = (SPFLOAT) 60.0 / p->bpm;            p->lbpm = p->bpm;        }         p->evt = prop_next(sp, p->prp);        p->count = prop_time(p->prp, p->evt) * sp->sr;         switch (p->evt.type) {            case PTYPE_ON:                *out = 1.0;                break;            case PTYPE_MAYBE:                if (((SPFLOAT) sp_rand(sp) / SP_RANDMAX) > 0.5) *out = 1.0;                else *out = 0.0;                break;            default:                *out = 0.0;                break;        }        return SP_OK;    }     *out = 0;    p->count--;     return SP_OK;} static int stack_push(prop_stack *ps, uint32_t val){    if (ps->pos++ < 16) {        ps->stack[ps->pos] = val;    }    return SP_OK;} static void stack_init(prop_stack *ps){    int n;    ps->pos = -1;    for (n = 0; n < 16; n++) ps->stack[n] = 1;} static uint32_t stack_pop(prop_stack *ps){    if (ps->pos >= 0) {        return ps->stack[ps->pos--];    }    return 1;} static void mode_insert_event(prop_data *pd, char type){    prop_val val;    prop_event *evt;#ifdef DEBUG_PROP    if (type == PTYPE_ON) {        printf("mode_insert: PTYPE_ON\n");    } else {        printf("mode_insert: PTYPE_OFF\n");    }    printf("\tval/mul = %d, pos = %d, cons = %d, div = %d\n",            pd->mul, pd->num, pd->cons_mul, pd->div);#endif     val.type = PTYPE_EVENT;    evt = malloc(sizeof(prop_event));    evt->type = type;    evt->val = pd->mul;    evt->cons = pd->cons_mul;    val.ud = evt;    prop_list_append(pd->main, val);} static void mode_setdiv(prop_data *pd, char n){    if (pd->tmp == 0 && n == 0) n = 1;    pd->tmp *= 10;    pd->tmp += n;} static void mode_setmul(prop_data *pd){    pd->mul *= pd->tmp;    pd->div = pd->tmp;    stack_push(&pd->mstack, pd->tmp);    pd->tmp = 0;} static void mode_unsetmul(prop_data *pd){    uint32_t div = stack_pop(&pd->mstack);#ifdef DEBUG_PROP    printf("mul / div = %d / %d\n", pd->mul, div);#endif    pd->mul /= div;} static void mode_setcons(prop_data *pd){    pd->cons_mul *= pd->tmp;    pd->cons_div = pd->tmp;    stack_push(&pd->cstack, pd->tmp);    pd->tmp = 0;} static void mode_unsetcons(prop_data *pd){    uint32_t div = stack_pop(&pd->cstack);#ifdef DEBUG_PROP    printf("mul / div = %d / %d\n", pd->cons_mul, div);#endif    pd->cons_mul /= div;} static int prop_create(prop_data **pd){    prop_data *pdp;    *pd = malloc(sizeof(prop_data));    pdp = *pd;     pdp->mul = 1;    pdp->div = 0;    pdp->scale = 1;    pdp->cons_mul = 1;    pdp->cons_div = 0;    pdp->mode = PMODE_INIT;    pdp->pos = 1;    pdp->main = &pdp->top;    pdp->main->lvl = 0;    pdp->tmp = 0;     stack_init(&pdp->mstack);    stack_init(&pdp->cstack);    prop_list_init(pdp->main);     return PSTATUS_OK;} static int prop_parse(prop_data *pd, const char *str){    char c;     while (*str != 0) {        c = str[0];         switch(c) {            case '+':                mode_insert_event(pd, PTYPE_ON);                break;            case '?':                mode_insert_event(pd, PTYPE_MAYBE);                break;            case '-':                mode_insert_event(pd, PTYPE_OFF);                break;             case '0':                mode_setdiv(pd, 0);                break;            case '1':                mode_setdiv(pd, 1);                break;            case '2':                mode_setdiv(pd, 2);                break;            case '3':                mode_setdiv(pd, 3);                break;            case '4':                mode_setdiv(pd, 4);                break;            case '5':                mode_setdiv(pd, 5);                break;            case '6':                mode_setdiv(pd, 6);                break;            case '7':                mode_setdiv(pd, 7);                break;            case '8':                mode_setdiv(pd, 8);                break;            case '9':                mode_setdiv(pd, 9);                break;            case '(':                mode_setmul(pd);                break;            case ')':                mode_unsetmul(pd);                break;            case '[':                mode_setcons(pd);                break;            case ']':                mode_unsetcons(pd);                break;            case '|':                mode_insert_slice(pd);                break;            case '{':                mode_list_start(pd);                break;            case '}':                mode_list_end(pd);                break;            case ' ': break;            case '\n': break;            case '\t': break;             default:                return PSTATUS_NOTOK;        }        pd->pos++;        str++;    }    prop_list_reset(&pd->top);    pd->main = &pd->top;    return PSTATUS_OK;} prop_val prop_list_iterate(prop_list *lst){    prop_val val;    if (lst->pos >= lst->size) {        prop_list_reset(lst);    }    val = lst->last->val;    lst->last = lst->last->next;    lst->pos++;    return val;} static void back_to_top(prop_data *pd){    prop_list *lst = pd->main;    prop_list_reset(lst);    pd->main = lst->top;    reset(pd);} static void reset(prop_data *pd){    prop_list *lst = pd->main;    if (lst->pos >= lst->size) {        back_to_top(pd);    }} static prop_event prop_next(sp_data *sp, prop_data *pd){/*    prop_list *lst = pd->main;     if(lst->pos >= lst->size) {        //prop_list_reset(lst);        pd->main = lst->top;    }*/    prop_list *lst;    prop_event *p;    prop_val val;     reset(pd);    lst = pd->main;    val = lst->last->val;     lst->last = lst->last->next;    lst->pos++;     switch (val.type) {        case PTYPE_SLICE: {            prop_slice *slice = (prop_slice *)val.ud;             uint32_t pos = floor(                ((SPFLOAT)sp_rand(sp) / SP_RANDMAX)                * slice->size);             pd->main = slice->ar[pos];            prop_list_reset(pd->main);            return prop_next(sp, pd);            break;        }        case PTYPE_LIST: {            prop_list *lst = (prop_list *)val.ud;            pd->main = lst;            prop_list_reset(pd->main);            return prop_next(sp, pd);            break;        }        default:            break;    }    p = (prop_event *)val.ud;    return *p;} static float prop_time(prop_data *pd, prop_event evt){    float val = evt.cons * (pd->scale / evt.val);    return val;} static int prop_destroy(prop_data **pd){    prop_data *pdp = *pd;     prop_list_destroy(&pdp->top);     free(*pd);    return PSTATUS_OK;} static int prop_list_init(prop_list *lst){    lst->last = &lst->root;    lst->size = 0;    lst->pos = 0;    lst->root.val.type = PTYPE_NULL;    lst->top = lst;    return PSTATUS_OK;} static int prop_list_append(prop_list *lst, prop_val val){    prop_entry *new;    new = malloc(sizeof(prop_entry));    new->val = val;    lst->last->next = new;    lst->last = new;    lst->size++;    return PSTATUS_OK;} static int prop_slice_free(prop_slice *slice){    uint32_t i;    for (i = 0; i < slice->size; i++) {        prop_list_destroy(slice->ar[i]);        free(slice->ar[i]);    }    free(slice->ar);    return PSTATUS_OK;} static int prop_val_free(prop_val val){    switch (val.type) {        case PTYPE_SLICE:            prop_slice_free((prop_slice *)val.ud);            free(val.ud);            break;        case PTYPE_LIST:            prop_list_destroy((prop_list *)val.ud);            free(val.ud);            break;        default:            free(val.ud);            break;    }    return PSTATUS_OK;} static int prop_list_destroy(prop_list *lst){    prop_entry *entry = lst->root.next;    prop_entry *next;    uint32_t i;     for (i = 0; i < lst->size; i++) {        next = entry->next;        prop_val_free(entry->val);        free(entry);        entry = next;    }    return PSTATUS_OK;} static void prop_list_reset(prop_list *lst){    lst->last = lst->root.next;    lst->pos = 0;} static void mode_insert_slice(prop_data *pd){    prop_entry *entry;     entry = pd->main->top->last;    if (entry->val.type != PTYPE_SLICE) {        prop_slice_encap(pd);    } else {        prop_slice_append(pd);    }} static void prop_slice_encap(prop_data *pd){    prop_val val;    prop_list *lst, *new;    prop_list *top;    prop_slice *slice;     top = pd->main->top;

Lines 1–500 of 579.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t