shithub: dumb

ref: cbff5cf07f67b6a20c1718b10fece652a62bdaa0
dir: /examples/moddec.c/

View raw version
#include <dumb.h>

#pragma lib "./libdumb.a$O"

#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)<(b)?(a):(b))
#define SRATE 44100.0f

enum {
	Nsamp = 4096,
};

static uchar b[Nsamp*2*2];

static void
usage(void)
{
	fprint(2, "usage: %s [FILE]\n", argv0);
	exits("usage");
}

void
main(int argc, char **argv)
{
	DUMB_IT_SIGRENDERER *itren;
	DUH_SIGRENDERER *ren;
	sample_t **samp;
	char *data, *t;
	int n, sz, r;
	double pos;
	long nsamp;
	DUH *f;

	setfcr(getfcr() & ~(FPINVAL|FPOVFL));

	pos = 0.0;
	ARGBEGIN{
	case 's':
		pos = atof(EARGF(usage()));
		break;
	default:
		usage();
	}ARGEND;

	if(argc != 0)
		usage();

	sz = 32768;
	data = nil;
	for(n = 0;; n += r){
		if(sz-n < 65536){
			sz *= 2;
			if((data = realloc(data, sz)) == nil)
				sysfatal("memory");
		}
		if((r = read(0, data+n, sz-n)) < 0)
			sysfatal("%r");
		if(r == 0)
			break;
	}

	if((f = dumb_read_any(dumbfile_open_memory(data, sz), 1, 0)) == nil)
		sysfatal("unknown/invalid mod");
	if((t = (char*)duh_get_tag(f, "TITLE")) != nil && *t)
		fprint(2, "%s\n", t);
	ren = duh_start_sigrenderer(f, 0, 2, 0);
	itren = duh_get_it_sigrenderer(ren);
	dumb_it_set_loop_callback(itren, dumb_it_callback_terminate, nil);
	dumb_it_set_xm_speed_zero_callback(itren, dumb_it_callback_terminate, nil);
	dumb_it_set_resampling_quality(itren, DUMB_RQ_CUBIC);
	if(pos > 0.0)
		fprint(2, "time: %g\n", pos);

	n = 0;
	for(;;){
		if(pos > 0.0){
			pos -= (double)n / SRATE;
			n = MIN(pos*SRATE, Nsamp);
			if(n < 1)
				pos = 0.0;
		}
		memset(b, 0, sizeof(b));
		n = duh_render_int(ren, &samp, &nsamp, 16, 0, 1.0, 65536.0f/SRATE, MAX(n, Nsamp), b);
		if(n <= 0)
			break;
		if(pos <= 0.0 && write(1, b, n*2*2) != n*2*2)
			break;
	}

	exits(nil);
}