midi_unpack.h

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         int pos, need, size;
00028         unsigned char data[MIDI_UNPACK_MAX_MSG];
00029 } midi_unpack_t;
00030 
00031 static inline
00032 void midi_unpack_init(midi_unpack_t *u)
00033 {
00034         u->pos = 0;
00035         u->size = sizeof(u->data);
00036         u->need = u->size;
00037 }
00038 
00039 static inline
00040 void midi_unpack_reset(midi_unpack_t *u)
00041 {
00042         u->pos = 0;
00043         u->need = u->size;
00044 }
00045 
00046 static const unsigned char midi_voice_len[] = {
00047         3, /*0x80 Note Off*/
00048         3, /*0x90 Note On*/
00049         3, /*0xA0 Aftertouch*/
00050         3, /*0xB0 Control Change*/
00051         2, /*0xC0 Program Change*/
00052         2, /*0xD0 Channel Pressure*/
00053         3, /*0xE0 Pitch Wheel*/
00054         1  /*0xF0 System*/
00055 };
00056 
00057 static const unsigned char midi_system_len[] = {
00058         0, /*0xF0 System Exclusive Start*/
00059         2, /*0xF1 MTC Quarter Frame*/
00060         3, /*0xF2 Song Postion*/
00061         2, /*0xF3 Song Select*/
00062         0, /*0xF4 undefined*/
00063         0, /*0xF5 undefined*/
00064         1, /*0xF6 Tune Request*/
00065         1  /*0xF7 System Exlusive End*/
00066 };
00067 
00068 static
00069 int midi_unpack_buf(midi_unpack_t *buf, const unsigned char *data, int len, void *jack_port_buf, jack_nframes_t time)
00070 {
00071         int i;
00072         for (i=0; i<len; ++i)
00073         {
00074                 const unsigned char byte = data[i];
00075                 if (byte >= 0xF8) // system realtime
00076                 {
00077                         jack_midi_event_write(jack_port_buf, time, &data[i], 1);
00078                         //printf("midi_unpack: written system relatime event\n");
00079                         //midi_input_write(in, &data[i], 1);
00080                 }
00081                 else if (byte < 0x80) // data
00082                 {
00083                         assert (buf->pos < buf->size);
00084                         buf->data[buf->pos++] = byte;
00085                 }
00086                 else if (byte < 0xF0) // voice
00087                 {
00088                         assert (byte >= 0x80 && byte < 0xF0);
00089                         //buf->need = ((byte|0x0F) == 0xCF || (byte|0x0F)==0xDF) ? 2 : 3;
00090                         buf->need = midi_voice_len[(byte-0x80)>>4];
00091                         buf->data[0] = byte;
00092                         buf->pos = 1;
00093                 }
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                 }
00100                 else
00101                 {
00102                         assert (byte >= 0xF0 && byte < 0xF8);
00103                         buf->pos = 1;
00104                         buf->data[0] = byte;
00105                         buf->need = midi_system_len[byte - 0xF0];
00106                         if (!buf->need)
00107                                 buf->need = buf->size;
00108                 }
00109                 if (buf->pos == buf->need)
00110                 {
00111                         // TODO: deal with big sysex'es (they are silently dropped for now)
00112                         if (buf->data[0] >= 0x80 || (buf->data[0]==0xF0 && buf->data[buf->pos-1] == 0xF7)) {
00113                                 /* convert Note On with velocity 0 to Note Off */
00114                                 if ((buf->data[0] & 0xF0) == 0x90 && buf->data[2] == 0) {
00115                                         // we use temp array here to keep running status sync
00116                                         jack_midi_data_t temp[3] = { 0x80, 0, 0x40 };
00117                                         temp[0] |= buf->data[0] & 0x0F;
00118                                         temp[1] = buf->data[1];
00119                                         jack_midi_event_write(jack_port_buf, time, temp, 3);
00120                                 } else
00121                                         jack_midi_event_write(jack_port_buf, time, &buf->data[0], buf->pos);
00122                                 //printf("midi_unpack: written %d-byte event\n", buf->pos);
00123                                 //midi_input_write(in, &buf->data[0], buf->pos);
00124                         }
00125                         /* keep running status */
00126                         if (buf->data[0] >= 0x80 && buf->data[0] < 0xF0)
00127                                 buf->pos = 1;
00128                         else
00129                         {
00130                                 buf->pos = 0;
00131                                 buf->need = buf->size;
00132                         }
00133                 }
00134         }
00135         assert (i==len);
00136         return i;
00137 }
00138 
00139 #endif /* __jack_midi_unpack_h__ */

Generated on Thu Feb 14 11:16:02 2008 for Jackdmp by  doxygen 1.5.1