usynth

simple midi synth for sndio
git clone git://nsmpr.xyz/usynth.git
Log | Files | Refs

usynth.c (2333B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <unistd.h>
      4 #include <stdint.h>
      5 #include <sndio.h>
      6 #include <string.h>
      7 #include <assert.h>
      8 
      9 #include "arg.h"
     10 #include "util.h"
     11 #include "midi.h"
     12 #include "wavetable.h"
     13 #include "machine.h"
     14 #include "build.h"
     15 
     16 char *argv0;
     17 
     18 struct sio_hdl *sh;
     19 size_t bs;
     20 int16_t *sbuf;
     21 int16_t* vm;
     22 int keystack[32], kp;
     23 
     24 void note_on(uint8_t*);
     25 void note_off(uint8_t*);
     26 void fillbuf(int16_t*, size_t);
     27 
     28 void
     29 s_init(char *sdev)
     30 {
     31 	struct sio_par par;
     32 	sh = sio_open(sdev, SIO_PLAY, 0);
     33 	sio_initpar(&par);
     34 	par.pchan = 2;
     35 	par.sig = 1;
     36 	par.bits = 16;
     37 	par.le = 1;
     38 	par.rate = 44100;
     39 	par.xrun = SIO_SYNC;
     40 	par.appbufsz = 1024;
     41 	sio_setpar(sh, &par);
     42 	sio_getpar(sh, &par);
     43 	bs = par.round;
     44 	sbuf = malloc(bs * 2 * sizeof(int16_t));
     45 	sio_start(sh);
     46 }
     47 
     48 void
     49 usage(void)
     50 {
     51 	fprintf(stderr, "usage: %s [-f rsnd/0] [-q rmidi/0] [-o record.pcm]  program\n", argv0); 
     52 	exit(0);
     53 }
     54 
     55 int
     56 main(int argc, char *argv[])
     57 {
     58 	FILE *fp, *op;
     59 	char *mdev, *sdev, *fout;
     60 
     61 	mdev = "midithru/0";
     62 	sdev = "default";
     63 	fout = NULL;
     64 	op = NULL;
     65 	
     66 	ARGBEGIN {
     67 	case 'q':
     68 		mdev = EARGF(usage());
     69 		break;
     70 	case 'f':
     71 		sdev = EARGF(usage());
     72 	case 'o':
     73 		fout = EARGF(usage());
     74 		if (fout[0] == '-') op = stdout;
     75 		else op = fopen(fout, "w");
     76 		break;
     77 	default:
     78 		usage();
     79 	} ARGEND
     80 
     81 	fp = stdin;
     82 	if (argc == 1) {
     83 		fp = fopen(argv[0], "r");
     84 		if (fp == NULL) {
     85 			fprintf(stderr, "failed to open file %s\n", argv[1]);
     86 			exit(-1);
     87 		}
     88 	}
     89 
     90 	s_init(sdev);
     91 	wt_init();
     92 	m_init(mdev);
     93 	m_vector.note_on = note_on;
     94 	m_vector.note_off = note_off;
     95 
     96 	vm = malloc(VM_MEM_END);
     97 	vm[VM_ACTIVE] = 0;
     98 	buildfile(fp, vm);
     99 
    100 	while (1){
    101 		size_t n;
    102 		m_read();
    103 		fillbuf(sbuf, bs * 2);
    104 		n = sio_write(sh, sbuf, bs * 2 * sizeof(int16_t));
    105 		if (op != NULL)
    106 			fwrite(sbuf, bs * 2 * sizeof(int16_t), 1,
    107 			  op);
    108 	}
    109 }
    110 
    111 void
    112 note_on(uint8_t *m)
    113 {
    114 	keystack[kp] = m[2];
    115 	kp++;
    116 	if (kp > 31) kp = 31;
    117 	vm[VM_ACTIVE] = 1;
    118 	vm[VM_KEY] = m[2];
    119 	vm[VM_KEY_ON] = 1;
    120 }
    121 
    122 void
    123 note_off(uint8_t *m)
    124 {
    125 	int i;
    126 	for (i = 0; i < kp; i++) {
    127 		if (keystack[i] == m[2]) {
    128 			memcpy(keystack+i, keystack+i+1, kp - i);
    129 			kp--;
    130 		}
    131 	}
    132 	if (kp <= 0) {
    133 		vm[VM_KEY_ON] = 0;
    134 		// temporary:
    135 		vm[VM_ACTIVE] = 0;
    136 	} else vm[VM_KEY] = keystack[kp-1];
    137 }
    138 
    139 void
    140 fillbuf(int16_t* buf, size_t n)
    141 {
    142 	size_t i;
    143 	for (i=0; i < n; i+=2) {
    144 		buf[i] = buf[i+1] = vm_run(vm);
    145 	}
    146 }