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 }