shithub: neindaw

ref: 381cb51b021ee312f0fcb09f2f8ffbe70f5279b2
dir: /dsp/main.c/

View raw version
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
#include "uiglue.h"
typedef struct DSP DSP;
#include "dspf.h"
#include "common.h"
#include "fs.h"
#include "ui.h"

/* FIXME figure out how to get the buffering right */
enum {
	Inmax = 2048, /* float = 8192 bytes */
	Outmax = 2048, /* float = 8192 bytes */
};

struct Auxdsp {
	void *dsp;
	float **in, **out;
	int numin, numout;
	int inmax, outmax;
};

static int rate = 44100;
static DSPf *dspf;

static Auxdsp *
dspwrap(void *p)
{
	Auxdsp *dsp;
	int i;

	if ((dsp = calloc(1, sizeof(*dsp))) == nil)
		return nil;

	dsp->dsp = p;
	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 ((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);
	}

	return dsp;
}

static Auxdsp *
dspnew(int *numin, int *numout)
{
	Auxdsp *dsp;

	dsp = dspwrap(dspf->new());
	dspf->init(dsp->dsp, rate);
	dspf->build_ui(dsp->dsp, &uiglue);
	*numin = dspf->num_in(dsp->dsp);
	*numout = dspf->num_out(dsp->dsp);

	return dsp;
}

static Auxdsp *
dspclone(Auxdsp *dsp)
{
	Auxdsp *clone;
	int i;

	clone = dspwrap(dspf->clone(dsp->dsp));
	if (clone->in != nil) {
		/* copy input data */
		/* FIXME need to set the valid data size when the processing is in */
		for (i = 0; i < dsp->numin; i++)
			memmove(clone->in[i], dsp->in[i], sizeof(**dsp->in)*dsp->inmax);
	}

	return clone;
}

static void *
dspstate(Auxdsp *dsp, int *sz)
{
	return dspf->state(dsp->dsp, sz);
}

static void
dspfree(Auxdsp *dsp)
{
	int i;

	dspf->delete(dsp->dsp);
	for (i = 0; i < dsp->numin; i++)
		free(dsp->in[i]);
	free(dsp->in);
	for (i = 0; i < dsp->numout; i++)
		free(dsp->out[i]);
	free(dsp->out);
	free(dsp);
}

static void
dspreset(Auxdsp *dsp)
{
	dspf->reset_ui(dsp->dsp);
}

static int
dspread(Auxdsp *dsp, float *b, int n)
{
	int i, j, numframes;

	numframes = n / dsp->numout;
	dspf->compute(dsp->dsp, numframes, dsp->in, dsp->out);
	for (i = 0; i < numframes; i++) {
		for (j = 0; j < dsp->numout; j++)
			*b++ = dsp->out[j][i];
	}

	return n;
}

static void
usage(void)
{
	print("usage: %s [-s srv] [-m mtpt] [-r rate]\n", argv0);
	exits("usage");
}

static Fs fs = {
	.dsp = {
		.new = dspnew,
		.clone = dspclone,
		.state = dspstate,
		.free = dspfree,
		.reset = dspreset,
		.read = dspread,
	},
};

static void
addmeta(void *metaInterface, const char *k, const char *v)
{
	int klen, vlen;
	static int metalen;

	USED(metaInterface);

	if (strchr(k, '/') != nil) /* ignore library-specific meta */ 
		return;

	klen = strlen(k);
	vlen = strlen(v);
	fs.metadata = realloc(fs.metadata, metalen + klen + 1 + vlen + 2);
	strcpy(fs.metadata+metalen, k);
	metalen += klen;
	fs.metadata[metalen++] = '\t';
	strcpy(fs.metadata+metalen, v);
	metalen += vlen;
	fs.metadata[metalen++] = '\n';
	fs.metadata[metalen] = 0;
}

void
threadmain(int argc, char **argv)
{
	char *srv, *mtpt;
	MetaGlue mg;

	srv = nil;
	mtpt = nil;
	ARGBEGIN{
	case 'D':
		chatty9p++;
		break;
	case 's':
		srv = EARGF(usage());
		break;
	case 'm':
		mtpt = EARGF(usage());
		break;
	case 'r':
		rate = atoi(EARGF(usage()));
		break;
	default:
		usage();
	}ARGEND

	if (srv == nil && mtpt == nil)
		sysfatal("must specify -s or -m option");

	setfcr(FPPDBL|FPRNR);

	mg.declare = addmeta;
	dspf = class_init(rate);
	dspf->metadata(&mg);

	fsinit(&fs);
	threadpostmountsrv(&fs.srv, srv, mtpt, MREPL);
	threadexits(nil);
}