Jack2 1.9.6
|
00001 /* 00002 * Copyright (c) 2006,2007 Dmitry S. Baikov 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 */ 00018 00019 #ifndef __jack_midi_unpack_h__ 00020 #define __jack_midi_unpack_h__ 00021 00022 enum { 00023 MIDI_UNPACK_MAX_MSG = 1024 00024 }; 00025 00026 typedef struct 00027 { 00028 int pos, need, size; 00029 unsigned char data[MIDI_UNPACK_MAX_MSG]; 00030 } 00031 midi_unpack_t; 00032 00033 static inline 00034 void midi_unpack_init(midi_unpack_t *u) 00035 { 00036 u->pos = 0; 00037 u->size = sizeof(u->data); 00038 u->need = u->size; 00039 } 00040 00041 static inline 00042 void midi_unpack_reset(midi_unpack_t *u) 00043 { 00044 u->pos = 0; 00045 u->need = u->size; 00046 } 00047 00048 static const unsigned char midi_voice_len[] = 00049 { 00050 3, /*0x80 Note Off*/ 00051 3, /*0x90 Note On*/ 00052 3, /*0xA0 Aftertouch*/ 00053 3, /*0xB0 Control Change*/ 00054 2, /*0xC0 Program Change*/ 00055 2, /*0xD0 Channel Pressure*/ 00056 3, /*0xE0 Pitch Wheel*/ 00057 1 /*0xF0 System*/ 00058 }; 00059 00060 static const unsigned char midi_system_len[] = 00061 { 00062 0, /*0xF0 System Exclusive Start*/ 00063 2, /*0xF1 MTC Quarter Frame*/ 00064 3, /*0xF2 Song Postion*/ 00065 2, /*0xF3 Song Select*/ 00066 0, /*0xF4 undefined*/ 00067 0, /*0xF5 undefined*/ 00068 1, /*0xF6 Tune Request*/ 00069 1 /*0xF7 System Exlusive End*/ 00070 }; 00071 00072 static 00073 int midi_unpack_buf(midi_unpack_t *buf, const unsigned char *data, int len, void *jack_port_buf, jack_nframes_t time) 00074 { 00075 int i; 00076 for (i = 0; i < len; ++i) { 00077 const unsigned char byte = data[i]; 00078 if (byte >= 0xF8) // system realtime 00079 { 00080 jack_midi_event_write(jack_port_buf, time, &data[i], 1); 00081 //printf("midi_unpack: written system relatime event\n"); 00082 //midi_input_write(in, &data[i], 1); 00083 } else if (byte < 0x80) // data 00084 { 00085 assert (buf->pos < buf->size); 00086 buf->data[buf->pos++] = byte; 00087 } else if (byte < 0xF0) // voice 00088 { 00089 assert (byte >= 0x80 && byte < 0xF0); 00090 //buf->need = ((byte|0x0F) == 0xCF || (byte|0x0F)==0xDF) ? 2 : 3; 00091 buf->need = midi_voice_len[(byte-0x80)>>4]; 00092 buf->data[0] = byte; 00093 buf->pos = 1; 00094 } else if (byte == 0xF7) // sysex end 00095 { 00096 assert (buf->pos < buf->size); 00097 buf->data[buf->pos++] = byte; 00098 buf->need = buf->pos; 00099 } else { 00100 assert (byte >= 0xF0 && byte < 0xF8); 00101 buf->pos = 1; 00102 buf->data[0] = byte; 00103 buf->need = midi_system_len[byte - 0xF0]; 00104 if (!buf->need) 00105 buf->need = buf->size; 00106 } 00107 if (buf->pos == buf->need) { 00108 // TODO: deal with big sysex'es (they are silently dropped for now) 00109 if (buf->data[0] >= 0x80 || (buf->data[0] == 0xF0 && buf->data[buf->pos-1] == 0xF7)) { 00110 /* convert Note On with velocity 0 to Note Off */ 00111 if ((buf->data[0] & 0xF0) == 0x90 && buf->data[2] == 0) { 00112 // we use temp array here to keep running status sync 00113 jack_midi_data_t temp[3] = { 0x80, 0, 0x40 }; 00114 temp[0] |= buf->data[0] & 0x0F; 00115 temp[1] = buf->data[1]; 00116 jack_midi_event_write(jack_port_buf, time, temp, 3); 00117 } else 00118 jack_midi_event_write(jack_port_buf, time, &buf->data[0], buf->pos); 00119 //printf("midi_unpack: written %d-byte event\n", buf->pos); 00120 //midi_input_write(in, &buf->data[0], buf->pos); 00121 } 00122 /* keep running status */ 00123 if (buf->data[0] >= 0x80 && buf->data[0] < 0xF0) 00124 buf->pos = 1; 00125 else { 00126 buf->pos = 0; 00127 buf->need = buf->size; 00128 } 00129 } 00130 } 00131 assert (i == len); 00132 return i; 00133 } 00134 00135 #endif /* __jack_midi_unpack_h__ */