usynth

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

midi.c (1765B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <stdint.h>
      4 #include <sndio.h>
      5 #include <assert.h>
      6 #include "midi.h"
      7 
      8 uint8_t mmessage[4];
      9 uint8_t mlen;
     10 uint8_t mi;
     11 struct mio_hdl *mh;
     12 uint8_t mbuf[32];
     13 Mvector m_vector;
     14 
     15 enum {
     16 	NOTE_OFF = 0x80,
     17 	NOTE_ON = 0x90,
     18 	KEY_PRESSURE = 0xa0,
     19 	CTL_CHANGE = 0xb0,
     20 	PROG_CHANGE = 0xc0,
     21 	CHAN_PRESSURE = 0xd0,
     22 	PITCH_WHEEL = 0xe0,
     23 	SYS_MESSAGE = 0xf0,
     24 };
     25 
     26 void m_exec(void);
     27 void m_fillmess(uint8_t);
     28 
     29 void
     30 m_fillmess(uint8_t b)
     31 {
     32 	if (b >= 0x80){ /* status byte */
     33 		mmessage[0] = b & 0xf0;
     34 		mmessage[1] = b & 0x0f;
     35 		mlen = 0;
     36 		switch (mmessage[0]){
     37 		case NOTE_OFF:
     38 		case NOTE_ON:
     39 		case KEY_PRESSURE:
     40 		case CTL_CHANGE:
     41 		case PITCH_WHEEL:
     42 			mlen = 4;
     43 			break;
     44 		case PROG_CHANGE:
     45 		case CHAN_PRESSURE:
     46 			mlen = 3;
     47 			break;
     48 		case SYS_MESSAGE:
     49 			mlen = 2;
     50 			break;
     51 		}
     52 		mi = 2;
     53 	} else if (mi < mlen){
     54 		mmessage[mi] = b;
     55 		mi++;
     56 	} 
     57 	if (mi == mlen) m_exec();
     58 }
     59 
     60 void
     61 m_exec(void)
     62 {
     63 	void (*f)(uint8_t*);
     64 	switch(mmessage[0]&0xf0){
     65 	case NOTE_OFF:
     66 		f = m_vector.note_off;
     67 		break;
     68 	case NOTE_ON:
     69 		f = m_vector.note_on;
     70 		assert(f != NULL);
     71 		break;
     72 	case KEY_PRESSURE:
     73 		f = m_vector.key_pressure;
     74 		break;
     75 	case CTL_CHANGE:
     76 		f = m_vector.ctl_change;
     77 		break;
     78 	case PROG_CHANGE:
     79 		f = m_vector.prog_change;
     80 		break;
     81 	case CHAN_PRESSURE:
     82 		f = m_vector.chan_pressure;
     83 		break;
     84 	case PITCH_WHEEL:
     85 		f = m_vector.pitch_wheel;
     86 		break;
     87 	case SYS_MESSAGE:
     88 		f = m_vector.sys_message;
     89 		break;
     90 	}
     91 	if (f != NULL) f(mmessage);
     92 }
     93 
     94 void
     95 m_init(char *mdev)
     96 {
     97 	mh = mio_open(mdev, MIO_IN, 1);
     98 	if (mh == 0){
     99 		fprintf(stderr, "error: couldn't open midi device %s\n", mdev);
    100 		exit(-1);
    101 	}
    102 	mlen = 0;
    103 	mi = 0;
    104 }
    105 
    106 void
    107 m_read(void)
    108 {
    109 	size_t i, n;
    110 	n = mio_read(mh, mbuf, 32);
    111 	for (i=0; i<n; i++) m_fillmess(mbuf[i]);
    112 }