9. tlseq

The tlseq node provides a sample sequencer node similar to tseq that takes in ftlist directly. This example is designed to showcase the sample accurate choosing capabilities.

9.1. Struct

<<tlseq_struct>>=
typedef struct {
    gf_cable *trig;
    gf_cable *out;
    sp_ftlist *ftl;
    GFFLT last;
    int pos;
} tlseq;

9.2. Node

<<tlseq_funcdefs>>=
int node_tlseq(gf_node *node, sp_ftlist *ftl);
<<tlseq_funcs>>=
int node_tlseq(gf_node *node, sp_ftlist *ftl)
{
    tlseq *seq;
    void *mem;
    gf_patch *patch;
    int rc;

    rc = gf_node_get_patch(node, &patch);

    if (rc != GF_OK) return rc;

    rc = gf_memory_alloc(patch, sizeof(tlseq), &mem);
    if (rc != GF_OK) return rc;

    seq = mem;

    seq->ftl = ftl;
    seq->pos = -1;
    seq->last = 0;
    gf_node_cables_alloc(node, 2);
    gf_node_set_block(node, 1);
    gf_node_get_cable(node, 0, &seq->trig);
    gf_node_get_cable(node, 1, &seq->out);

    gf_node_set_data(node, seq);
    gf_node_set_compute(node, compute);
    gf_node_set_destroy(node, destroy);
    return GF_OK;
}

The computation is reasonably straight forward. Read the trigger and position cables. Any time the trigger is non-zero, run sp_ftlist_choose.

<<tlseq_static_funcdefs>>=
static void compute(gf_node *node);
<<tlseq_funcs>>=
static void compute(gf_node *node)
{
    int blksize;
    tlseq *seq;
    int n;

    blksize = gf_node_blksize(node);
    seq = gf_node_get_data(node);

    for (n = 0; n < blksize; n++) {
        GFFLT t;

        t = gf_cable_get(seq->trig, n);

        if (t != 0) {
            sp_ftbl *ft;
            ft = sp_ftlist_target_sa(seq->ftl, n);
            seq->pos++;

            while (seq->pos >= ft->size) {
                seq->pos -= ft->size;
            }

            seq->last = ft->tbl[seq->pos];
        }

        gf_cable_set(seq->out, n, seq->last);
    }
}
<<tlseq_static_funcdefs>>=
static void destroy(gf_node *node);
<<tlseq_funcs>>=
static void destroy(gf_node *node)
{
    int rc;
    gf_patch *patch;
    void *mem;


    gf_node_cables_free(node);

    rc = gf_node_get_patch(node, &patch);
    if (rc != GF_OK) return;

    mem = gf_node_get_data(node);
    gf_memory_free(patch, &mem);
}

9.3. Runt Loader

tlseq is loaded as a runt word using the function load_tlseq.

<<tlseq_funcdefs>>=
int load_tlseq(runt_vm *vm, runt_ptr pw);
<<tlseq_funcs>>=
int load_tlseq(runt_vm *vm, runt_ptr pw)
{
    runt_cell *c;
    runt_keyword_define(vm, "tlseq", 5, rproc_tlseq, &c);
    runt_cell_data(vm, c, pw);
    return runt_is_alive(vm);
}

9.4. Runt Word

<<tlseq_static_funcdefs>>=
static runt_int rproc_tlseq(runt_vm *vm, runt_ptr p);
<<tlseq_funcdefs>>=
static runt_int rproc_tlseq(runt_vm *vm, runt_ptr p)
{
    runt_int rc;
    gf_patch *patch;
    rgf_param trig;
    sp_ftlist *ftlst;
    gf_node *node;
    runt_stacklet *out;

    rc = rgf_get_ftlist(vm, &ftlst);
    RUNT_ERROR_CHECK(rc);

    rc = rgf_get_param(vm, &trig);
    RUNT_ERROR_CHECK(rc);

    rc = runt_ppush(vm, &out);
    RUNT_ERROR_CHECK(rc);

    patch = rgf_get_patch(p);

    rc = gf_patch_new_node(patch, &node);
    GF_RUNT_ERROR_CHECK(rc);


    node_tlseq(node, ftlst);

    rgf_set_param(vm, node, &trig, 0);
    rgf_push_output(vm, node, out, 1);

    return RUNT_OK;
}



prev | home | next