Sigrid Solveig HaflínudóttirPlan 9 port (only the executable for now)41ce78a5 years agoHistory
1349 lines · 27.2 KB · Text
RawDownload
#+TITLE: Core* OverviewThis document describes and outlines a small API forsndkit. It is primarily designed to be a small layer on topof Patchwerk, a library used to build up directed audiographs. A large portion of the functionality is based onwhat is found in runt-patchwerk. Just simpler. In addition to maintaining an instance of patchwerk, thesndkit API provides a stack and a register system. Thestack is the primary means of sharing data between nodes.Registers are for more persitently used values.* Tangled files=core.h= and =core.c=. #+NAME: core.h#+BEGIN_SRC c :tangle core.h#ifndef SKPW_H#define SKPW_H #ifndef SKFLT#define SKFLT float#endif <<typedefs>>#ifdef SK_CORE_PRIV<<structs>><<core>>#endif<<macros>><<funcdefs>> #ifdef __plan9__#pragma incomplete sk_core#pragma incomplete sk_stack#pragma incomplete sk_regtbl#pragma incomplete sk_table#endif#endif#+END_SRC #+NAME: core.c#+BEGIN_SRC c :tangle core.c#include <stdlib.h>#include <math.h>#include <string.h>#include "patchwerk.h"#define SK_CORE_PRIV#include "core.h"<<enums>><<funcs>>#+END_SRC* Engine ManagementAll this behavior is defined in a struct called =sk_core=. Creating/freeing is done with =sk_core_new= and=sk_core_del=. #+NAME: funcdefs#+BEGIN_SRC csk_core * sk_core_new(int sr);void sk_core_del(sk_core *core);#+END_SRC #+NAME: funcs#+BEGIN_SRC csk_core * sk_core_new(int sr){    sk_core *core;    pw_patch *patch;     core = malloc(sizeof(sk_core));    core->patch = malloc(pw_patch_size());     patch = core->patch;    pw_patch_init(patch, 64);    pw_patch_alloc(patch, 8, 10);    pw_patch_srate_set(patch, sr);     sk_stack_init(&core->stack);    sk_regtbl_init(&core->regtbl);     sk_core_srand(core, 0);    return core;}#+END_SRC #+NAME: funcs#+BEGIN_SRC cvoid sk_core_del(sk_core *core){    if (core == NULL) return;     pw_patch_destroy(core->patch);    pw_patch_free_nodes(core->patch);    free(core->patch);     free(core);    core = NULL;}#+END_SRC #+NAME: typedefs#+BEGIN_SRC ctypedef struct sk_core sk_core;#+END_SRC #+NAME: core#+BEGIN_SRC cstruct sk_core {    pw_patch *patch;    sk_stack stack;    sk_regtbl regtbl;    unsigned long rng;};#+END_SRC A internal block of audio can be computed with=sk_core_compute=. Usually this size is 64 samples. #+NAME: funcdefs#+BEGIN_SRC cvoid sk_core_compute(sk_core *core);#+END_SRC #+NAME: funcs#+BEGIN_SRC cvoid sk_core_compute(sk_core *core){    pw_patch_compute(core->patch);}#+END_SRC =sk_core_computes= is like =sk_core_compute=, but computesan approximuate number of seconds of audio. This valuegets rounded to the nearest block. The number of blocksrendered gets rendered. #+NAME: funcdefs#+BEGIN_SRC csize_t sk_core_computes(sk_core *core, SKFLT secs);#+END_SRC #+NAME: funcs#+BEGIN_SRC csize_t sk_core_computes(sk_core *core, SKFLT secs){    size_t nblocks, n;    nblocks = sk_core_seconds_to_blocks(core, secs);     for (n = 0; n < nblocks; n++) {        sk_core_compute(core);    }     return nblocks;}#+END_SRC Building up nodes involves interacting with the patchwerkAPI. To get the top level struct of that opaquely, use=sk_core_patch=. #+NAME: funcdefs#+BEGIN_SRC cpw_patch * sk_core_patch(sk_core *core);#+END_SRC #+NAME: funcs#+BEGIN_SRC cpw_patch * sk_core_patch(sk_core *core){    return core->patch;}#+END_SRC The function =sk_core_seconds_to_blocks= convertsseconds to a number of render blocks. #+NAME: funcdefs#+BEGIN_SRC csize_t sk_core_seconds_to_blocks(sk_core *core, SKFLT secs);#+END_SRC #+NAME: funcs#+BEGIN_SRC csize_t sk_core_seconds_to_blocks(sk_core *core, SKFLT secs){    size_t nblocks;    int sr;     sr = pw_patch_srate_get(core->patch);    nblocks = floor((sr * secs) / 64) + 1;     return nblocks;}#+END_SRC* Stack** Core Data TypesAn item on a stack is contained in a thing known as a=stacklet=. A stacklet has integer for a type flag, afloating point number for numerical values, and a genericpointer for C structures. #+NAME: typedefs#+BEGIN_SRC ctypedef struct sk_stacklet sk_stacklet;#+END_SRC #+NAME: structs#+BEGIN_SRC cstruct sk_stacklet {    int type;    SKFLT f;    void *ptr;};<<stack_struct>>#+END_SRC A stacklet is initialized with the function=sk_stacklet_init=. #+NAME: funcdefs#+BEGIN_SRC cvoid sk_stacklet_init(sk_stacklet *s);#+END_SRC #+NAME: funcs#+BEGIN_SRC cvoid sk_stacklet_init(sk_stacklet *s){    s->type = SK_TYPE_NONE;    s->f = 0;    s->ptr = NULL;}#+END_SRC An array of stacklets forms the foundation of a =sk_stack=. #+NAME: typedefs#+BEGIN_SRC ctypedef struct sk_stack sk_stack;#+END_SRC The stack will be hard coded to be 16. An integer =pos= is used to keep track of position. #+NAME: stack_struct#+BEGIN_SRC c#define SK_STACKSIZE 16struct sk_stack {    sk_stacklet stack[SK_STACKSIZE];    int pos;};#+END_SRC A stack is initialized with =sk_stack_init=. #+NAME: funcdefs#+BEGIN_SRC cvoid sk_stack_init(sk_stack *s);#+END_SRC The position is set to be negative, indicating an emptystack. #+NAME: funcs#+BEGIN_SRC cvoid sk_stack_init(sk_stack *s){    int i;     for (i = 0; i < SK_STACKSIZE; i++) {        sk_stacklet_init(&s->stack[i]);    }     s->pos = -1;}#+END_SRC** TypesThe typeflag currently supports the following types: #+NAME: enums#+BEGIN_SRC cenum {   SK_TYPE_NONE,   SK_TYPE_CONSTANT,   SK_TYPE_CABLE,   SK_TYPE_TABLE,   SK_TYPE_GENERIC};#+END_SRC** Push/PopPush and pop are the core operations for the stack. Bothreturn non-zero values on error. =sk_stack_pop= will pop a value off the stack and save itto the stacklet variable =s=. =sk_stack_push= will push an initialized stacklet to thestack, and save that value to stacklet variable =s= tobe filled with some item. #+NAME: funcdefs#+BEGIN_SRC cint sk_stack_pop(sk_stack *stack, sk_stacklet **out);int sk_stack_push(sk_stack *stack, sk_stacklet **out);#+END_SRC #+NAME: funcs#+BEGIN_SRC cint sk_stack_pop(sk_stack *stack, sk_stacklet **out){    sk_stacklet *s;    /* no items on stack */    if (stack->pos < 0) return 1;     /* stack overflow */    if (stack->pos >= SK_STACKSIZE) return 2;     s = &stack->stack[stack->pos];    stack->pos--;     *out = s;    return 0;}#+END_SRC #+NAME: funcs#+BEGIN_SRC cint sk_stack_push(sk_stack *stack, sk_stacklet **out){    sk_stacklet *s;     if (stack->pos >= (SK_STACKSIZE - 1)) return 1;    stack->pos++;    s = &stack->stack[stack->pos];     sk_stacklet_init(s);    *out = s;    return 0;}#+END_SRC** PeakThe function =sk_stack_peak= will look at the last item onthe stack, but not pop it off the stack. #+NAME: funcdefs#+BEGIN_SRC cint sk_stack_peak(sk_stack *stack, sk_stacklet **out);#+END_SRC #+NAME: funcs#+BEGIN_SRC cint sk_stack_peak(sk_stack *stack, sk_stacklet **out){    sk_stacklet *s;    if (stack->pos < 0) return 1;    if (stack->pos >= SK_STACKSIZE) return 2;     s = &stack->stack[stack->pos];    *out = s;    return 0;}#+END_SRC** Dup=dup= is an operation that duplicates an item on the stack. The basic operation can be done with =sk_stack_dup=. Theoperation will store the duplicated stack item to =out= ifthe argument is not =NULL=. #+NAME: funcdefs#+BEGIN_SRC cint sk_stack_dup(sk_stack *stack, sk_stacklet **out);#+END_SRC #+NAME: funcs#+BEGIN_SRC cint sk_stack_dup(sk_stack *stack, sk_stacklet **out){    int rc;    sk_stacklet *a, *b;     rc = sk_stack_peak(stack, &a);    SK_ERROR_CHECK(rc);     rc = sk_stack_push(stack, &b);    SK_ERROR_CHECK(rc);     *b = *a;     if (out != NULL) *out = b;     return 0;}#+END_SRC  =sk_core_dup= will call =sk_stack_dup= on the internalstack, but also will call a dup operation on the patchwerkstack if the item is a patchwerk cable. #+NAME: funcdefs#+BEGIN_SRC cint sk_core_dup(sk_core *core);#+END_SRC #+NAME: funcs#+BEGIN_SRC cint sk_core_dup(sk_core *core){    sk_stacklet *s;    int rc;     rc = sk_stack_dup(&core->stack, &s);    SK_ERROR_CHECK(rc);     if (s->type == SK_TYPE_CABLE) {        pw_stack *stack;        stack = pw_patch_stack(core->patch);        pw_stack_dup(stack);    }     return 0;}#+END_SRC** Drop=drop= is an operation that drops an item on the stack. The basic operation is done with =sk_stack_drop=. The dropped value will be saved to =out= if =out= isnot =NULL=. #+NAME: funcdefs#+BEGIN_SRC cint sk_stack_drop(sk_stack *stack, sk_stacklet **out);#+END_SRC #+NAME: funcs#+BEGIN_SRC cint sk_stack_drop(sk_stack *stack, sk_stacklet **out){    int rc;    sk_stacklet *s;     rc = sk_stack_pop(stack, &s);     SK_ERROR_CHECK(rc);     if (out != NULL) *out = s;    return 0;}#+END_SRC The function =sk_core_drop= performs a drop on the stackin the core struct. If the item is a patchwerk cable, itwill also perform a drop on the patchwerk buffer stack. #+NAME: funcdefs#+BEGIN_SRC cint sk_core_drop(sk_core *core);#+END_SRC #+NAME: funcs#+BEGIN_SRC cint sk_core_drop(sk_core *core){    int rc;    sk_stacklet *s;    rc = sk_stack_drop(&core->stack, &s);     SK_ERROR_CHECK(rc);     if (s->type == SK_TYPE_CABLE) {        pw_stack *stack;        stack = pw_patch_stack(core->patch);        pw_stack_pop(stack, NULL);    }     return 0;}#+END_SRC** Swap=swap= will swap the positions of the last two items onthe stack. The basic operation is done with =sk_stack_swap=. #+NAME: funcdefs#+BEGIN_SRC cint sk_stack_swap(sk_stack *stack,                  sk_stacklet **s1,                  sk_stacklet **s2);#+END_SRC #+NAME: funcs#+BEGIN_SRC cint sk_stack_swap(sk_stack *stack,

Lines 1–500 of 1349.

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