~pbatch/patchwerk

5d5b944f3b7e10e4df9cfdaab7d023cb5bee314a — paul 10 months ago 9896a10
added oscmorph

FossilOrigin-Name: f9299b8180a157438d9266db0ef8145e78d6c0d8cb5996c1746c400b9cbfd9f0
5 files changed, 197 insertions(+), 0 deletions(-)

M dsp/config.mk
A dsp/oscmorph.c
A dsp/oscmorph.h
M dsp/ugen_list.h
A runt/nodes/r_oscmorph.c
M dsp/config.mk => dsp/config.mk +1 -0
@@ 83,6 83,7 @@ NODES=\
	mode.o\
	pdhalf.o\
	tabread.o\
	oscmorph.o\

# old list
#NODES=\

A dsp/oscmorph.c => dsp/oscmorph.c +67 -0
@@ 0,0 1,67 @@
#include <stdlib.h>
#include <soundpipe.h>
#include "patchwerk.h"
#include "oscmorph.h"
#include "ugen_enums.h"

static void destroy(pw_node *node)
{
    oscmorph_d *osc;
    osc = (oscmorph_d *) pw_node_get_data(node);
    sp_oscmorph_destroy(&osc->osc);
    pw_node_cables_free(node);
    free(osc);
}

static void compute(pw_node *node)
{
    int i;
    int blksize;
    oscmorph_d *osc;
    SPFLOAT out;

    osc = pw_node_get_data(node);
    blksize = pw_node_blksize(node);

    for(i = 0; i < blksize; i++) {
        osc->osc->freq = pw_cable_get(osc->freq, i);
        osc->osc->amp = pw_cable_get(osc->amp, i);
        osc->osc->wtpos = pw_cable_get(osc->wtpos, i);
        sp_oscmorph_compute(osc->sp, osc->osc, NULL, &out);
        pw_cable_set(osc->out, i, out);
    }
}

void node_oscmorph(pw_node *node,
                   sp_data *sp,
                   sp_ftbl **ft,
                   int nft,
                   SPFLOAT iphs)
{
    oscmorph_d *osc;

    osc = malloc(sizeof(oscmorph_d));
    osc->sp = sp;

    sp_oscmorph_create(&osc->osc);
    sp_oscmorph_init(sp, osc->osc, ft, nft, iphs);

    pw_node_cables_alloc(node, 4);

    pw_node_get_cable(node, 0, &osc->freq);
    pw_cable_set_constant(osc->freq, 440);

    pw_node_get_cable(node, 1, &osc->amp);
    pw_cable_set_constant(osc->amp, 0.2);

    pw_node_get_cable(node, 2, &osc->wtpos);
    pw_cable_set_constant(osc->wtpos, 0);

    pw_node_get_cable(node, 3, &osc->out);
    pw_node_set_block(node, 3);

    pw_node_set_type(node, TYPE_OSCMORPH);
    pw_node_set_compute(node, compute);
    pw_node_set_destroy(node, destroy);
    pw_node_set_data(node, osc);
}

A dsp/oscmorph.h => dsp/oscmorph.h +16 -0
@@ 0,0 1,16 @@
#ifndef OSCMORPH_H
#define OSCMORPH_H
typedef struct {
    sp_data *sp;
    sp_oscmorph *osc;
    pw_cable *freq;
    pw_cable *amp;
    pw_cable *wtpos;
    pw_cable *out;
} oscmorph_d;
void node_oscmorph(pw_node *node,
                   sp_data *sp,
                   sp_ftbl **ft,
                   int nft,
                   SPFLOAT iphs);
#endif

M dsp/ugen_list.h => dsp/ugen_list.h +1 -0
@@ 109,3 109,4 @@ UGEN(TYPE_WAVIN, wavin)
UGEN(TYPE_SLICE, slice)
/* UGEN(TYPE_SNDWARP, sndwarp) */
/* UGEN(TYPE_CONV, conv) */
UGEN(TYPE_OSCMORPH, oscmorph)

A runt/nodes/r_oscmorph.c => runt/nodes/r_oscmorph.c +112 -0
@@ 0,0 1,112 @@
#include <stdio.h>
#include <runt.h>
#include <soundpipe.h>
#include <math.h>

/* TODO: remove once pw_memory_alloc is used instead */
#include <stdlib.h>

#include "patchwerk.h"
#include "runt_patchwerk.h"
#include "runt_ftbl.h"
#include "oscmorph.h"

static void free_list(pw_pointer *p)
{
    sp_ftbl **ft;

    /* TODO: free with pw_memory_free */

    ft = pw_pointer_data(p);

    free(ft);
}

static int mk_ftlist(runt_vm *vm,
                     pw_patch *patch,
                     int nft,
                     sp_ftbl ***plist)
{
    sp_ftbl **list;
    int i;
    int rc;

    /* TODO: allocate with pw_memory_alloc */

    list = malloc(sizeof(sp_ftbl *) * nft);

    pw_patch_append_userdata(patch, free_list, list);

    for (i = 0; i < nft; i++) {
        sp_ftbl *ft;
        rc = rpw_get_ftable(vm, &ft);
        RUNT_ERROR_CHECK(rc);
        list[i] = ft;
    }

    *plist = list;
    return RUNT_OK;
}

static runt_int rproc_node_oscmorph(runt_vm *vm, runt_ptr p)
{
    runt_int rc;
    pw_node *node;
    pw_patch *patch;
    sp_data *sp;
    rpw_param freq;
    rpw_param amp;
    rpw_param wtpos;
    sp_ftbl **ft;
    SPFLOAT iphs;
    int nft;
    runt_stacklet *out;
    runt_stacklet *s;

    rc = runt_ppop(vm, &s);
    RUNT_ERROR_CHECK(rc);
    nft = floor(s->f);

    if (nft <= 0) {
        runt_print(vm, "Invalid # of ftables %d\n", nft);
        return RUNT_NOT_OK;
    }

    patch = rpw_get_patch(p);
    rc = mk_ftlist(vm, patch, nft, &ft);
    RUNT_ERROR_CHECK(rc);

    rc = runt_ppop(vm, &s);
    RUNT_ERROR_CHECK(rc);
    iphs = s->f;

    rc = rpw_get_param(vm, &wtpos);
    RUNT_ERROR_CHECK(rc);

    rc = rpw_get_param(vm, &amp);
    RUNT_ERROR_CHECK(rc);

    rc = rpw_get_param(vm, &freq);
    RUNT_ERROR_CHECK(rc);

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

    rc = pw_patch_new_node(patch, &node);
    PW_RUNT_ERROR_CHECK(rc);

    sp = pw_patch_data_get(patch);
    node_oscmorph(node, sp, ft, nft, iphs);

    rpw_set_param(vm, node, &freq, 0);
    rpw_set_param(vm, node, &amp, 1);
    rpw_set_param(vm, node, &wtpos, 2);
    rpw_push_output(vm, node, out, 3);
    return RUNT_OK;
}

runt_int rpw_node_oscmorph(runt_vm *vm, runt_ptr p)
{
    patchwerk_word_define(vm, p, "oscmorph", 8, rproc_node_oscmorph);
    return RUNT_OK;
}