shithub: neindaw

Download patch

ref: b67a151aecb558eeee40f34a6838ebce68b618bf
parent: c37e00d440c299a357bf418493024d0d2495d16b
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Tue Dec 31 11:09:19 EST 2019

reword internal data structures, keep generated code in

--- a/README.md
+++ b/README.md
@@ -5,40 +5,48 @@
 
 ## Testing
 
-Since Faust isn't(?) ported to Plan 9 (yet?), first you need to
-generate some code on some other OS that supports it, by running
-`./gen.sh`.  As an alternative, do `9fs ftrv.se; ls /n/ftrv.se/faust9p`,
-there is a generated file ready.
-
 So far only one instrument provided, which is a kick drum.
 
 ```
-% ./6.out -m /n/kick
-% cd /n/kick
+mk
+./6.out -m /n/kick
+cd /n/kick
+```
 
-# allocate one instance
-% cd `{cat clone}
+Allocate one instance.
+```
+cd `{cat clone}
+cd K*
+```
 
-# check the A oscillator frequency
-# the order is: type value initial min max step
-# it's different for different UI elements
-% cat K*/a/frequency/ctl
+Check the A oscillator frequency, the order is `type value initial min max step`.
+It's different for different UI elements.
+```
+cat a/frequency/ctl
 vslider	100	100	10	200	5
+```
 
-# raise frequency to 160Hz
-% echo 160 > K*/a/f*/ctl
+Raise frequency to 160Hz.
+```
+echo 160 > a/f*/ctl
+```
 
-# pipe sound to /dev/audio in background
-% while() { for(i in 22050 22050 22050 44100 44100) { audio/pcmconv -i f32c1r44100 -l $i < data } } > /dev/audio &
-# the numbers ar how many bytes of the output should be read
+Pipe sound to /dev/audio in background.  The numbers are how many
+bytes of the output should be read.
+```
+while() { for(i in 22050 22050 22050 44100 44100) { audio/pcmconv -i f32c1r44100 -l $i < ../data } } > /dev/audio &
+```
 
-# gate = 1, should start kicking
-% echo 1 > K*/control/gate/ctl
+Set gate to 1, should start kicking.
+```
+echo 1 > control/gate/ctl
+```
 
-# set B oscillator parameters and enable it
-% echo 400 > K*/b/frequency/ctl
-% echo 0.001 > K*/b/attack/ctl
-% echo 1 > K*/control/b*/ctl
+Set B oscillator parameters and enable it.
+```
+echo 400 > b/frequency/ctl
+echo 0.001 > b/attack/ctl
+echo 1 > control/b*/ctl
 ```
 
 ## Description
--- a/aux.h
+++ b/aux.h
@@ -1,10 +1,18 @@
-enum {
+typedef enum {
+	Xclone,
 	Xctl,
 	Xmetadata,
-	Xclone,
+
 	Xdsp,
 	Xdspctl,
 	Xdspdata,
+
+	Xui,
+	Xuictl,
+	Xuimeta,
+}Auxtype;
+
+typedef enum {
 	UITGroup,
 	UIHGroup,
 	UIVGroup,
@@ -15,9 +23,7 @@
 	UINEntry,
 	UIHBarGraph,
 	UIVBarGraph,
-	Xuictl,
-	Xuimeta,
-};
+}UItype;
 
 typedef struct Aux Aux;
 typedef struct Auxdsp Auxdsp;
@@ -32,12 +38,13 @@
 };
 
 struct Aux {
-	int type;
+	Auxtype type;
 	int id;
-	Auxdsp dsp;
 	int ctl;
 	int data;
 	int metadata;
+
+	Auxdsp *dsp;
 	UI *ui;
 };
 
@@ -47,6 +54,7 @@
 };
 
 struct UI {
+	UItype type;
 	const char *label;
 	FAUSTFLOAT *zone;
 	FAUSTFLOAT init;
@@ -53,8 +61,8 @@
 	FAUSTFLOAT min;
 	FAUSTFLOAT max;
 	FAUSTFLOAT step;
-	char *(*readstr)(Aux *a, UI *ui, int type, char *s, int sz);
-	int (*write)(Aux *a, UI *ui, int type, char *s);
+	char *(*readstr)(UI *ui, int type, char *s, int sz);
+	int (*write)(UI *ui, int type, char *s);
 
 	Meta *meta;
 	int nummeta;
--- a/fs.c
+++ b/fs.c
@@ -50,11 +50,12 @@
 {
 	File *f;
 	Aux *o;
+	Auxdsp *dsp;
 	int i;
 
 	for (i = 0, o = nil; o == nil && i < nelem(objs); i++) {
 		if (objs[i] == nil){
-			o = objs[i] = calloc(1, sizeof(*o));
+			o = objs[i] = calloc(1, sizeof(*o)+sizeof(Auxdsp));
 			break;
 		}
 	}
@@ -65,29 +66,32 @@
 	o->type = Xdsp;
 	o->ctl = Xdspctl;
 	o->data = Xdspdata;
-	o->dsp.dsp = dspf->new();
-	sprint(name, "%d", o->id);
+	o->dsp = dsp = (Auxdsp*)(o+1);
+	dsp->dsp = dspf->new();
 
-	o->dsp.in = o->dsp.out = nil;
-	if ((o->dsp.numin = dspf->num_in(o->dsp.dsp)) > 0) {
-		o->dsp.in = malloc(sizeof(*o->dsp.in) * o->dsp.numin);
-		o->dsp.inmax = Inmax;
-		for (i = 0; i < o->dsp.numin; i++)
-			o->dsp.in[i] = malloc(sizeof(**o->dsp.in) * o->dsp.inmax);
+	dsp->in = dsp->out = nil;
+	if ((dsp->numin = dspf->num_in(dsp->dsp)) > 0) {
+		dsp->in = malloc(sizeof(*dsp->in) * dsp->numin);
+		dsp->inmax = Inmax;
+		for (i = 0; i < dsp->numin; i++)
+			dsp->in[i] = malloc(sizeof(**dsp->in) * dsp->inmax);
 	}
-	if ((o->dsp.numout = dspf->num_out(o->dsp.dsp)) > 0) {
-		o->dsp.out = malloc(sizeof(*o->dsp.out) * o->dsp.numout);
-		o->dsp.outmax = Outmax;
-		for (i = 0; i < o->dsp.numout; i++)
-			o->dsp.out[i] = malloc(sizeof(**o->dsp.out) * o->dsp.outmax);
+	if ((dsp->numout = dspf->num_out(dsp->dsp)) > 0) {
+		dsp->out = malloc(sizeof(*dsp->out) * dsp->numout);
+		dsp->outmax = Outmax;
+		for (i = 0; i < dsp->numout; i++)
+			dsp->out[i] = malloc(sizeof(**dsp->out) * dsp->outmax);
 	}
 
-	f = createfile(fs.tree->root, name, nil, DMDIR|0775, o);
-	createfile(f, "ctl", nil, 0664, &o->ctl);
-	createfile(f, "data", nil, 0664, &o->data);
-	dspf->init(o->dsp.dsp, rate);
-	uiglue.uiInterface = f;
-	dspf->build_ui(o->dsp.dsp, &uiglue);
+	sprint(name, "%d", o->id);
+	if ((f = createfile(fs.tree->root, name, nil, DMDIR|0775, o)) == nil)
+		return nil;
+	closefile(createfile(f, "ctl", nil, 0664, &o->ctl));
+	closefile(createfile(f, "data", nil, 0664, &o->data));
+	closefile(f);
+	dspf->init(dsp->dsp, rate);
+	uiglue.f = f;
+	dspf->build_ui(dsp->dsp, &uiglue);
 
 	return o;
 }
@@ -95,13 +99,22 @@
 static void
 freeobj(Aux *o)
 {
+	int i;
+
 	if (o == nil)
 		return;
 
-	objs[o->id] = nil;
-	dspf->delete(o->dsp.dsp);
-	free(o->dsp.in);
-	free(o->dsp.out);
+	if (o->type == Xdsp) {
+		objs[o->id] = nil;
+		dspf->delete(o->dsp->dsp);
+		for (i = 0; i < o->dsp->numin; i++)
+			free(o->dsp->in[i]);
+		free(o->dsp->in);
+		for (i = 0; i < o->dsp->numout; i++)
+			free(o->dsp->out[i]);
+		free(o->dsp->out);
+	}
+
 	free(o);
 }
 
@@ -137,6 +150,7 @@
 fsread(Req *r)
 {
 	Aux *a, *o;
+	Auxdsp *dsp;
 	char b[256];
 	FAUSTFLOAT *p;
 	int i, j, n, numframes, framesz;
@@ -155,7 +169,8 @@
 			if (newobj(b) != nil) {
 				readstr(r, b);
 			} else {
-				respond(r, "no free objects");
+				snprint(b, sizeof(b), "no free objects: %r");
+				respond(r, b);
 				break;
 			}
 		}
@@ -165,23 +180,24 @@
 	case Xuimeta:
 		o = auxtype2obj(&a->type);
 		if (o->ui->readstr != nil)
-			readstr(r, o->ui->readstr(o, o->ui, a->type, b, sizeof(b)));
+			readstr(r, o->ui->readstr(o->ui, a->type, b, sizeof(b)));
 		respond(r, nil);
 		break;
 	case Xdspdata:
 		o = auxtype2obj(&a->type);
+		dsp = o->dsp;
 		if (r->ifcall.offset == 0) /* clear every time the offset is reset */
-			dspf->clear(o->dsp.dsp);
-		framesz = o->dsp.numout * sizeof(*p);
+			dspf->clear(dsp->dsp);
+		framesz = dsp->numout * sizeof(*p);
 		n = r->ifcall.count;
 		for (p = (FAUSTFLOAT*)r->ofcall.data; n >= framesz;) {
 			numframes = n / framesz;
-			if (numframes > o->dsp.outmax)
-				numframes = o->dsp.outmax;
-			dspf->compute(o->dsp.dsp, numframes, o->dsp.in, o->dsp.out);
+			if (numframes > dsp->outmax)
+				numframes = dsp->outmax;
+			dspf->compute(dsp->dsp, numframes, dsp->in, dsp->out);
 			for (i = 0; i < numframes; i++) {
-				for (j = 0; j < o->dsp.numout; j++)
-					*p++ = o->dsp.out[j][i];
+				for (j = 0; j < dsp->numout; j++)
+					*p++ = dsp->out[j][i];
 			}
 			n -= numframes * framesz;
 		}
@@ -213,17 +229,17 @@
 	switch (a->type) {
 	case Xuictl:
 		o = auxtype2obj(&a->type);
-		st = o->ui->write != nil ? o->ui->write(o, o->ui, Xuictl, b) : -1;
+		st = o->ui->write != nil ? o->ui->write(o->ui, a->type, b) : -1;
 		respond(r, st == 0 ? nil : "write failed");
 		break;
 	case Xdspctl: /* FIXME changing sampling rate */
 		o = auxtype2obj(&a->type);
 		if (strncmp(b, "clear", 5) == 0)
-			dspf->clear(o->dsp.dsp);
+			dspf->clear(o->dsp->dsp);
 		else if (strncmp(b, "reset", 5) == 0)
-			dspf->reset_ui(o->dsp.dsp);
+			dspf->reset_ui(o->dsp->dsp);
 		else if (strncmp(b, "init", 4) == 0)
-			dspf->init(o->dsp.dsp, rate);
+			dspf->init(o->dsp->dsp, rate);
 		respond(r, nil);
 		break;
 	case Xmetadata: /* FIXME should be possible to add new key/value */
@@ -233,6 +249,22 @@
 	}
 }
 
+static void
+fsdestroyfile(File *f)
+{
+	Aux *a;
+
+	if ((a = f->aux) == nil)
+		return;
+	switch (a->type) {
+	case Xdsp:
+	case Xui:
+		freeobj(a);
+		f->aux = nil;
+		break;
+	}
+}
+
 Srv fs = {
 	.open = fsopen,
 	.read = fsread,
@@ -278,7 +310,7 @@
 	dspf = class_init(rate);
 	dspf->metadata(&mg);
 
-	fs.tree = alloctree(nil, nil, DMDIR|0775, nil);
+	fs.tree = alloctree(nil, nil, DMDIR|0775, fsdestroyfile);
 	closefile(createfile(fs.tree->root, "ctl", nil, 0666, &rootaux[Xctl]));
 	closefile(createfile(fs.tree->root, "metadata", nil, 0444, &rootaux[Xmetadata]));
 	closefile(createfile(fs.tree->root, "clone", nil, 0444, &rootaux[Xclone]));
--- a/gen.sh
+++ b/gen.sh
@@ -8,5 +8,5 @@
 	faust -lang c -a arch.c -cn $class $@ $i -o /dev/stdout \
 		| sed 's/new\([^(]*\)() /new\1(void) /' \
 		| sed 's/'$class'[A-Z0-9]*\* dsp.*{/&\n\tUSED(dsp);/g' \
-		| sed 's/ \(samplingFreq\|inputs\).*{/&\n\tUSED(\1);/g' > $i.c
+		| sed 's/ \(samplingFreq\|inputs\).*{/&\n\tUSED(\1);/g' > `echo $i | sed 's/dsp$/c/'`
 done
--- /dev/null
+++ b/kick_drum.c
@@ -1,0 +1,465 @@
+/* ------------------------------------------------------------
+name: "Kick Drum"
+Code generated with Faust 2.5.23 (https://faust.grame.fr)
+Compilation options: c, -scal -ftz 0
+------------------------------------------------------------ */
+
+#ifndef  __KickDrum_H__
+#define  __KickDrum_H__
+
+/* KickDrum Plan 9 C architecture for Faust. */
+
+#include <u.h>
+#include <libc.h>
+#include "uiglue.h"
+
+#define max(x,y) (((x) > (y)) ? (x) : (y))
+#define min(x,y) (((x) < (y)) ? (x) : (y))
+
+#ifndef FAUSTFLOAT
+#define FAUSTFLOAT float
+#endif 
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <math.h>
+#include <stdlib.h>
+
+
+typedef struct {
+	
+	int iRec0[2];
+	
+} KickDrumSIG0;
+
+static KickDrumSIG0* newKickDrumSIG0(void) { return (KickDrumSIG0*)malloc(sizeof(KickDrumSIG0)); }
+static void deleteKickDrumSIG0(KickDrumSIG0* dsp) {
+	USED(dsp); free(dsp); }
+
+int getNumInputsKickDrumSIG0(KickDrumSIG0* dsp) {
+	USED(dsp);
+	return 0;
+	
+}
+int getNumOutputsKickDrumSIG0(KickDrumSIG0* dsp) {
+	USED(dsp);
+	return 1;
+	
+}
+int getInputRateKickDrumSIG0(KickDrumSIG0* dsp, int channel) {
+	USED(dsp);
+	int rate;
+	switch (channel) {
+		default: {
+			rate = -1;
+			break;
+		}
+		
+	}
+	return rate;
+	
+}
+int getOutputRateKickDrumSIG0(KickDrumSIG0* dsp, int channel) {
+	USED(dsp);
+	int rate;
+	switch (channel) {
+		case 0: {
+			rate = 0;
+			break;
+		}
+		default: {
+			rate = -1;
+			break;
+		}
+		
+	}
+	return rate;
+	
+}
+
+static void instanceInitKickDrumSIG0(KickDrumSIG0* dsp, int samplingFreq) {
+	USED(samplingFreq);
+	USED(dsp);
+	/* C99 loop */
+	{
+		int l0;
+		for (l0 = 0; (l0 < 2); l0 = (l0 + 1)) {
+			dsp->iRec0[l0] = 0;
+			
+		}
+		
+	}
+	
+}
+
+static void fillKickDrumSIG0(KickDrumSIG0* dsp, int count, float* output) {
+	USED(dsp);
+	/* C99 loop */
+	{
+		int i;
+		for (i = 0; (i < count); i = (i + 1)) {
+			dsp->iRec0[0] = (dsp->iRec0[1] + 1);
+			output[i] = sinf((9.58738019e-05f * (float)(dsp->iRec0[0] + -1)));
+			dsp->iRec0[1] = dsp->iRec0[0];
+			
+		}
+		
+	}
+	
+};
+
+static float ftbl0KickDrumSIG0[65536];
+
+#ifndef FAUSTCLASS 
+#define FAUSTCLASS KickDrum
+#endif
+#ifdef __APPLE__ 
+#define exp10f __exp10f
+#define exp10 __exp10
+#endif
+
+typedef struct {
+	
+	int fSamplingFreq;
+	float fConst0;
+	float fConst1;
+	FAUSTFLOAT fVslider0;
+	FAUSTFLOAT fVslider1;
+	FAUSTFLOAT fCheckbox0;
+	FAUSTFLOAT fButton0;
+	float fVec0[2];
+	FAUSTFLOAT fVslider2;
+	FAUSTFLOAT fVslider3;
+	float fVec1[2];
+	float fRec2[2];
+	float fConst2;
+	float fRec1[2];
+	FAUSTFLOAT fVslider4;
+	float fRec3[2];
+	FAUSTFLOAT fVslider5;
+	FAUSTFLOAT fVslider6;
+	float fRec5[2];
+	float fRec4[2];
+	
+} KickDrum;
+
+KickDrum* newKickDrum(void) { 
+	KickDrum* dsp = (KickDrum*)malloc(sizeof(KickDrum));
+	return dsp;
+}
+
+void deleteKickDrum(KickDrum* dsp) {
+	USED(dsp); 
+	free(dsp);
+}
+
+void metadataKickDrum(MetaGlue* m) { 
+	m->declare(m->metaInterface, "basics.lib/name", "Faust Basic Element Library");
+	m->declare(m->metaInterface, "basics.lib/version", "0.0");
+	m->declare(m->metaInterface, "envelopes.lib/author", "GRAME");
+	m->declare(m->metaInterface, "envelopes.lib/copyright", "GRAME");
+	m->declare(m->metaInterface, "envelopes.lib/license", "LGPL with exception");
+	m->declare(m->metaInterface, "envelopes.lib/name", "Faust Envelope Library");
+	m->declare(m->metaInterface, "envelopes.lib/version", "0.0");
+	m->declare(m->metaInterface, "filename", "kick_drum");
+	m->declare(m->metaInterface, "group", "synthesis");
+	m->declare(m->metaInterface, "maths.lib/author", "GRAME");
+	m->declare(m->metaInterface, "maths.lib/copyright", "GRAME");
+	m->declare(m->metaInterface, "maths.lib/license", "LGPL with exception");
+	m->declare(m->metaInterface, "maths.lib/name", "Faust Math Library");
+	m->declare(m->metaInterface, "maths.lib/version", "2.1");
+	m->declare(m->metaInterface, "name", "Kick Drum");
+	m->declare(m->metaInterface, "oscillators.lib/name", "Faust Oscillator Library");
+	m->declare(m->metaInterface, "oscillators.lib/version", "0.0");
+}
+
+int getSampleRateKickDrum(KickDrum* dsp) {
+	USED(dsp); return dsp->fSamplingFreq; }
+
+int getNumInputsKickDrum(KickDrum* dsp) {
+	USED(dsp);
+	return 1;
+	
+}
+int getNumOutputsKickDrum(KickDrum* dsp) {
+	USED(dsp);
+	return 1;
+	
+}
+int getInputRateKickDrum(KickDrum* dsp, int channel) {
+	USED(dsp);
+	int rate;
+	switch (channel) {
+		case 0: {
+			rate = 1;
+			break;
+		}
+		default: {
+			rate = -1;
+			break;
+		}
+		
+	}
+	return rate;
+	
+}
+int getOutputRateKickDrum(KickDrum* dsp, int channel) {
+	USED(dsp);
+	int rate;
+	switch (channel) {
+		case 0: {
+			rate = 1;
+			break;
+		}
+		default: {
+			rate = -1;
+			break;
+		}
+		
+	}
+	return rate;
+	
+}
+
+void classInitKickDrum(int samplingFreq) {
+	USED(samplingFreq);
+	KickDrumSIG0* sig0 = newKickDrumSIG0();
+	instanceInitKickDrumSIG0(sig0, samplingFreq);
+	fillKickDrumSIG0(sig0, 65536, ftbl0KickDrumSIG0);
+	deleteKickDrumSIG0(sig0);
+	
+}
+
+void instanceResetUserInterfaceKickDrum(KickDrum* dsp) {
+	USED(dsp);
+	dsp->fVslider0 = (FAUSTFLOAT)100.0f;
+	dsp->fVslider1 = (FAUSTFLOAT)200.0f;
+	dsp->fCheckbox0 = (FAUSTFLOAT)0.0f;
+	dsp->fButton0 = (FAUSTFLOAT)0.0f;
+	dsp->fVslider2 = (FAUSTFLOAT)0.001f;
+	dsp->fVslider3 = (FAUSTFLOAT)0.001f;
+	dsp->fVslider4 = (FAUSTFLOAT)0.001f;
+	dsp->fVslider5 = (FAUSTFLOAT)0.001f;
+	dsp->fVslider6 = (FAUSTFLOAT)0.01f;
+	
+}
+
+void instanceClearKickDrum(KickDrum* dsp) {
+	USED(dsp);
+	/* C99 loop */
+	{
+		int l1;
+		for (l1 = 0; (l1 < 2); l1 = (l1 + 1)) {
+			dsp->fVec0[l1] = 0.0f;
+			
+		}
+		
+	}
+	/* C99 loop */
+	{
+		int l2;
+		for (l2 = 0; (l2 < 2); l2 = (l2 + 1)) {
+			dsp->fVec1[l2] = 0.0f;
+			
+		}
+		
+	}
+	/* C99 loop */
+	{
+		int l3;
+		for (l3 = 0; (l3 < 2); l3 = (l3 + 1)) {
+			dsp->fRec2[l3] = 0.0f;
+			
+		}
+		
+	}
+	/* C99 loop */
+	{
+		int l4;
+		for (l4 = 0; (l4 < 2); l4 = (l4 + 1)) {
+			dsp->fRec1[l4] = 0.0f;
+			
+		}
+		
+	}
+	/* C99 loop */
+	{
+		int l5;
+		for (l5 = 0; (l5 < 2); l5 = (l5 + 1)) {
+			dsp->fRec3[l5] = 0.0f;
+			
+		}
+		
+	}
+	/* C99 loop */
+	{
+		int l6;
+		for (l6 = 0; (l6 < 2); l6 = (l6 + 1)) {
+			dsp->fRec5[l6] = 0.0f;
+			
+		}
+		
+	}
+	/* C99 loop */
+	{
+		int l7;
+		for (l7 = 0; (l7 < 2); l7 = (l7 + 1)) {
+			dsp->fRec4[l7] = 0.0f;
+			
+		}
+		
+	}
+	
+}
+
+void instanceConstantsKickDrum(KickDrum* dsp, int samplingFreq) {
+	USED(samplingFreq);
+	USED(dsp);
+	dsp->fSamplingFreq = samplingFreq;
+	dsp->fConst0 = min(192000.0f, max(1.0f, (float)dsp->fSamplingFreq));
+	dsp->fConst1 = (1.0f / dsp->fConst0);
+	dsp->fConst2 = (1.0f / dsp->fConst0);
+	
+}
+
+void instanceInitKickDrum(KickDrum* dsp, int samplingFreq) {
+	USED(samplingFreq);
+	USED(dsp);
+	instanceConstantsKickDrum(dsp, samplingFreq);
+	instanceResetUserInterfaceKickDrum(dsp);
+	instanceClearKickDrum(dsp);
+}
+
+void initKickDrum(KickDrum* dsp, int samplingFreq) {
+	USED(samplingFreq);
+	USED(dsp);
+	classInitKickDrum(samplingFreq);
+	instanceInitKickDrum(dsp, samplingFreq);
+}
+
+void buildUserInterfaceKickDrum(KickDrum* dsp, UIGlue* ui_interface) {
+	USED(dsp);
+	ui_interface->openVerticalBox(ui_interface->uiInterface, "Kick Drum");
+	ui_interface->openHorizontalBox(ui_interface->uiInterface, "a");
+	ui_interface->declare(ui_interface->uiInterface, &dsp->fVslider0, "0", "");
+	ui_interface->declare(ui_interface->uiInterface, &dsp->fVslider0, "unit", "Hz");
+	ui_interface->addVerticalSlider(ui_interface->uiInterface, "frequency", &dsp->fVslider0, 100.0f, 10.0f, 400.0f, 5.0f);
+	ui_interface->declare(ui_interface->uiInterface, &dsp->fVslider5, "1", "");
+	ui_interface->declare(ui_interface->uiInterface, &dsp->fVslider5, "unit", "s");
+	ui_interface->addVerticalSlider(ui_interface->uiInterface, "attack", &dsp->fVslider5, 0.00100000005f, 9.99999975e-06f, 0.200000003f, 0.00100000005f);
+	ui_interface->declare(ui_interface->uiInterface, &dsp->fVslider6, "2", "");
+	ui_interface->declare(ui_interface->uiInterface, &dsp->fVslider6, "unit", "s");
+	ui_interface->addVerticalSlider(ui_interface->uiInterface, "delay", &dsp->fVslider6, 0.00999999978f, 9.99999975e-06f, 1.0f, 0.00100000005f);
+	ui_interface->declare(ui_interface->uiInterface, &dsp->fVslider4, "3", "");
+	ui_interface->declare(ui_interface->uiInterface, &dsp->fVslider4, "unit", "s");
+	ui_interface->addVerticalSlider(ui_interface->uiInterface, "release", &dsp->fVslider4, 0.00100000005f, 9.99999975e-06f, 1.0f, 0.00100000005f);
+	ui_interface->closeBox(ui_interface->uiInterface);
+	ui_interface->openHorizontalBox(ui_interface->uiInterface, "b");
+	ui_interface->declare(ui_interface->uiInterface, &dsp->fVslider2, "0", "");
+	ui_interface->declare(ui_interface->uiInterface, &dsp->fVslider2, "unit", "s");
+	ui_interface->addVerticalSlider(ui_interface->uiInterface, "attack", &dsp->fVslider2, 0.00100000005f, 9.99999975e-06f, 0.200000003f, 0.00100000005f);
+	ui_interface->declare(ui_interface->uiInterface, &dsp->fVslider1, "1", "");
+	ui_interface->addVerticalSlider(ui_interface->uiInterface, "frequency", &dsp->fVslider1, 200.0f, -400.0f, 400.0f, 5.0f);
+	ui_interface->declare(ui_interface->uiInterface, &dsp->fVslider3, "2", "");
+	ui_interface->declare(ui_interface->uiInterface, &dsp->fVslider3, "unit", "s");
+	ui_interface->addVerticalSlider(ui_interface->uiInterface, "release", &dsp->fVslider3, 0.00100000005f, 9.99999975e-06f, 1.0f, 0.00100000005f);
+	ui_interface->closeBox(ui_interface->uiInterface);
+	ui_interface->openHorizontalBox(ui_interface->uiInterface, "control");
+	ui_interface->declare(ui_interface->uiInterface, &dsp->fButton0, "0", "");
+	ui_interface->addButton(ui_interface->uiInterface, "gate", &dsp->fButton0);
+	ui_interface->declare(ui_interface->uiInterface, &dsp->fCheckbox0, "1", "");
+	ui_interface->addCheckButton(ui_interface->uiInterface, "b enable", &dsp->fCheckbox0);
+	ui_interface->closeBox(ui_interface->uiInterface);
+	ui_interface->closeBox(ui_interface->uiInterface);
+	
+}
+
+void computeKickDrum(KickDrum* dsp, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) {
+	USED(inputs);
+	USED(dsp);
+	FAUSTFLOAT* input0 = inputs[0];
+	FAUSTFLOAT* output0 = outputs[0];
+	float fSlow0 = (float)dsp->fVslider0;
+	float fSlow1 = ((float)dsp->fVslider1 * (float)dsp->fCheckbox0);
+	float fSlow2 = (float)dsp->fButton0;
+	float fSlow3 = (float)dsp->fVslider2;
+	float fSlow4 = (fSlow3 + (float)dsp->fVslider3);
+	float fSlow5 = (dsp->fConst0 * fSlow4);
+	float fSlow6 = (dsp->fConst0 * fSlow3);
+	float fSlow7 = (1.0f / (0.0f - (dsp->fConst0 * (fSlow3 - fSlow4))));
+	float fSlow8 = (dsp->fConst2 / fSlow3);
+	int iSlow9 = (fSlow2 > 0.0f);
+	int iSlow10 = (iSlow9 > 0);
+	float fSlow11 = (float)dsp->fVslider4;
+	float fSlow12 = (dsp->fConst0 * fSlow11);
+	int iSlow13 = ((fSlow2 == 0.0f) > 0);
+	float fSlow14 = (float)dsp->fVslider5;
+	float fSlow15 = (fSlow14 + (float)dsp->fVslider6);
+	float fSlow16 = (dsp->fConst0 * fSlow15);
+	float fSlow17 = (dsp->fConst0 * fSlow14);
+	float fSlow18 = (9.99999997e-07f * fSlow2);
+	float fSlow19 = ((fSlow18 + -1.0f) / (0.0f - (dsp->fConst0 * (fSlow14 - fSlow15))));
+	float fSlow20 = (dsp->fConst2 / fSlow14);
+	float fSlow21 = (dsp->fConst2 / fSlow11);
+	/* C99 loop */
+	{
+		int i;
+		for (i = 0; (i < count); i = (i + 1)) {
+			dsp->fVec0[0] = fSlow2;
+			dsp->fVec1[0] = fSlow4;
+			dsp->fRec2[0] = ((((fSlow2 - dsp->fVec0[1]) > 0.0f) > 0)?0.0f:min(fSlow5, ((dsp->fRec2[1] + (dsp->fConst0 * (fSlow4 - dsp->fVec1[1]))) + 1.0f)));
+			int iTemp0 = (dsp->fRec2[0] < fSlow6);
+			float fTemp1 = ((dsp->fRec1[1] * (float)(1 - ((float)input0[i] > 0.0f))) + (dsp->fConst1 * (fSlow0 + (fSlow1 * (iTemp0?((dsp->fRec2[0] < 0.0f)?0.0f:(iTemp0?(fSlow8 * dsp->fRec2[0]):1.0f)):((dsp->fRec2[0] < fSlow5)?((fSlow7 * (0.0f - (dsp->fRec2[0] - fSlow6))) + 1.0f):0.0f))))));
+			dsp->fRec1[0] = (fTemp1 - floorf(fTemp1));
+			dsp->fRec3[0] = (iSlow10?0.0f:min(fSlow12, (dsp->fRec3[1] + 1.0f)));
+			dsp->fRec5[0] = (iSlow13?0.0f:min(fSlow16, (dsp->fRec5[1] + 1.0f)));
+			int iTemp2 = (dsp->fRec5[0] < fSlow17);
+			dsp->fRec4[0] = (iSlow9?((float)iSlow9 * (iTemp2?((dsp->fRec5[0] < 0.0f)?0.0f:(iTemp2?(fSlow20 * dsp->fRec5[0]):1.0f)):((dsp->fRec5[0] < fSlow16)?((fSlow19 * (dsp->fRec5[0] - fSlow17)) + 1.0f):fSlow18))):dsp->fRec4[1]);
+			output0[i] = (FAUSTFLOAT)(ftbl0KickDrumSIG0[(int)(65536.0f * dsp->fRec1[0])] * ((dsp->fRec3[0] < 0.0f)?dsp->fRec4[0]:((dsp->fRec3[0] < fSlow12)?(dsp->fRec4[0] + (fSlow21 * (dsp->fRec3[0] * (0.0f - dsp->fRec4[0])))):0.0f)));
+			dsp->fVec0[1] = dsp->fVec0[0];
+			dsp->fVec1[1] = dsp->fVec1[0];
+			dsp->fRec2[1] = dsp->fRec2[0];
+			dsp->fRec1[1] = dsp->fRec1[0];
+			dsp->fRec3[1] = dsp->fRec3[0];
+			dsp->fRec5[1] = dsp->fRec5[0];
+			dsp->fRec4[1] = dsp->fRec4[0];
+			
+		}
+		
+	}
+	
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#define DSP KickDrum
+
+#include "dspf.h"
+
+static DSPf dspf = {
+	.new = newKickDrum,
+	.init = instanceInitKickDrum,
+	.delete = deleteKickDrum,
+	.metadata = metadataKickDrum,
+	.num_in = getNumInputsKickDrum,
+	.num_out = getNumOutputsKickDrum,
+	.clear = instanceClearKickDrum,
+	.reset_ui = instanceResetUserInterfaceKickDrum,
+	.build_ui = buildUserInterfaceKickDrum,
+	.compute = computeKickDrum,
+};
+
+void *
+class_init(int rate)
+{
+	classInitKickDrum(rate);
+	return &dspf;
+}
+
+#endif
--- a/mkfile
+++ b/mkfile
@@ -1,15 +1,19 @@
 </$objtype/mkfile
 
-TARG=kick_drum
-BIN=/$objtype/bin
+TARG=\
+	kick_drum\
+
+BIN=/$objtype/bin/daw
 OFILES=\
 	fs.$O\
-	kick_drum.dsp.$O\
 	uiglue.$O\
 
 default:V:	all
 
 CLEANFILES=\
-	kick_drum.dsp.c\
 
-</sys/src/cmd/mkone
+</sys/src/cmd/mkmany
+
+$BIN/%:	$O.%
+	mkdir -p $BIN
+	cp $O.$stem $BIN/$stem
--- a/uiglue.c
+++ b/uiglue.c
@@ -13,13 +13,13 @@
 }decl;
 
 static char *
-ui_readstr(Aux *a, UI *ui, int type, char *s, int sz)
+ui_readstr(UI *ui, int type, char *s, int sz)
 {
 	char *x;
 	int i;
 
 	if (type == Xuictl) {
-		switch (a->type) {
+		switch (ui->type) {
 		case UITGroup: snprint(s, sz, "tgroup\n"); return s;
 		case UIHGroup: snprint(s, sz, "hgroup\n"); return s;
 		case UIVGroup: snprint(s, sz, "vgroup\n"); return s;
@@ -30,7 +30,7 @@
 		case UINEntry: snprint(s, sz, "nentry\t%g\t%g\t%g\t%g\t%g\n", *ui->zone, ui->init, ui->min, ui->max, ui->step); return s;
 		case UIHBarGraph: snprint(s, sz, "hbargraph\t%g\t%g\t%g\n", *ui->zone, ui->min, ui->max); return s;
 		case UIVBarGraph: snprint(s, sz, "vbargraph\t%g\t%g\t%g\n", *ui->zone, ui->min, ui->max); return s;
-		default: sysfatal("unknown ui type %d", a->type);
+		default: sysfatal("unknown ui type %d", ui->type);
 		}
 	} else if (type == Xuimeta) {
 		x = s;
@@ -39,7 +39,7 @@
 			x = seprint(x, s+sz-1, "%s\t%s\n", ui->meta[i].k, ui->meta[i].v);
 		return s;
 	} else {
-		sysfatal("unknown ui file");
+		sysfatal("unknown ui file type %d", type);
 	}
 
 	return nil;
@@ -46,7 +46,7 @@
 }
 
 static int
-ui_write(Aux *a, UI *ui, int type, char *s)
+ui_write(UI *ui, int type, char *s)
 {
 	int failoor;
 	float v;
@@ -72,7 +72,7 @@
 	}
 
 	if (ui->zone != nil) {
-		if (a->type == UIButton || a->type == UICheckBox) {
+		if (ui->type == UIButton || ui->type == UICheckBox) {
 			v = !!v;
 		} else if (v < ui->min) {
 			if (failoor)
@@ -95,23 +95,27 @@
 	Aux *a;
 
 	a = calloc(1, sizeof(*a)+sizeof(UI) + sizeof(Meta)*decl.nummeta);
+	a->type = Xui;
 	a->ui = (UI*)(a+1);
+	a->ui->type = type;
 	a->ui->meta = (Meta*)(a->ui+1);
 	a->ui->nummeta = decl.nummeta;
 	memmove(a->ui->meta, decl.meta, sizeof(Meta)*decl.nummeta);
 	a->ctl = Xuictl;
 	a->metadata = Xuimeta;
-	a->type = type;
 	a->ui->zone = decl.zone;
 	a->ui->label = label;
 	a->ui->readstr = ui_readstr;
 	a->ui->write = ui_write;
-	if ((uiglue.uiInterface = createfile(f, label, nil, DMDIR|0775, a)) == nil)
+	if ((uiglue.f = createfile(f, label, nil, DMDIR|0775, a)) == nil)
 		sysfatal("failed to create ui: %r");
-	if (createfile(uiglue.uiInterface, "ctl", nil, 0664, &a->ctl) == nil)
+	if ((f = createfile(uiglue.f, "ctl", nil, 0664, &a->ctl)) == nil)
 		sysfatal("failed to create ui ctl: %r");
-	if (createfile(uiglue.uiInterface, "metadata", nil, 0664, &a->metadata) == nil)
+	closefile(f);
+	if ((f = createfile(uiglue.f, "metadata", nil, 0664, &a->metadata)) == nil)
 		sysfatal("failed to create ui metadata: %r");
+	closefile(f);
+	closefile(uiglue.f);
 
 	free(decl.meta);
 	decl.zone = nil;
@@ -145,7 +149,7 @@
 	File *f;
 
 	f = file;
-	uiglue.uiInterface = f->parent;
+	uiglue.f = f->parent;
 }
 
 static UI *
@@ -156,7 +160,7 @@
 	if (zone != decl.zone)
 		sysfatal("zone mismatch during definition");
 	ui = newui(f, label, type);
-	uiglue.uiInterface = f;
+	uiglue.f = f;
 
 	return ui;
 }
--- a/uiglue.h
+++ b/uiglue.h
@@ -5,8 +5,13 @@
 typedef struct UIGlue UIGlue;
 typedef struct MetaGlue MetaGlue;
 
+struct File;
+
 struct UIGlue {
-	void *uiInterface;
+	union {
+		void *uiInterface;
+		struct File *f;
+	};
 	void (*openTabBox)(void *uiInterface, const char *label);
 	void (*openHorizontalBox)(void *uiInterface, const char *label);
 	void (*openVerticalBox)(void *uiInterface, const char *label);