shithub: prismriver

ref: beb274816e4ac1c0910e8c7297f2a38c29f8fe37
dir: /p-wavegen.c/

View raw version
#include <u.h>
#include <libc.h>

#include "prismriver.h"
#include "p-internal.h"

void
destroywavegen(Wavegen *gen)
{
	gen->destroy(gen);
}

Buffer*
buffermap(Buffer *buf, Wavegen *gen, double freq, ulong *pc, int d, ulong s, ulong sz)
{
	if(buf == nil)
		buf = createbuffer(s + sz);

	for(ulong c = s; c < sz; c++)
		buf->data[c] = gen->fn(gen, freq, c + (pc == nil ? 0 : *pc));

	if(d)
		destroywavegen(gen);

	if(pc != nil)
		*pc += sz;

	return buf;
}

/** Simple Waveforms **/

typedef struct
{
	Wavegen;
	double (*wavefn)(double);
	double amp, phase;
} Waveprops;

Stuple
waveformfn(Wavegen *w, double freq, ulong t)
{
	Waveprops *p = (Waveprops*)w;
	double v	= p->amp * p->wavefn(s2d(t) * freq + p->phase);
	sample val	= truncate(v);
	return (Stuple)
	{
		val, val
	};
}

Wavegen*
waveform(double (*fn)(double), double amp, double φ)
{
	Waveprops *p = emallocz(sizeof(Waveprops));
	p->fn		= waveformfn;
	p->destroy 	= (void(*)(Wavegen*))free;
	p->wavefn	= fn;
	p->amp		= amp;
	p->phase	= φ;
	return p;
}

double
sine(double num)
{
	return sin(2 * π * num);
}

double
saw(double num)
{
	return 2 * (num - (int)num) - 1;
}

double
pulse(double num, double threshold)
{
	return saw(num) < threshold ? -1.0 : 1.0;
}

double
square(double num)
{
	return pulse(num, 0);
}

double
triangle(double num)
{
	return 2 * fabs(saw(num)) - 1;
}

/** PCM-backed wave "generators" **/

typedef struct
{
	Wavegen;
	Buffer *buf;
} Pcmprops;

Stuple
pcmfn(Wavegen *w, double freq, ulong t)
{
	(void)freq;
	Pcmprops *p = (Pcmprops*)w;
	if(t < p->buf->size)
		return p->buf->data[t];
	return (Stuple) { 0, 0 };
}

void
pcmdestroy(Wavegen *w)
{
	Pcmprops *p = (Pcmprops*)w;
	destroybuffer(p->buf);
	free(p);
}

Wavegen*
pcm(Buffer *buf)
{
	Pcmprops *p = emallocz(sizeof(*p));
	p->fn		= pcmfn;
	p->destroy	= pcmdestroy;
	p->buf		= buf;
	return p;
}