2 * Copyright (c) 2006,2007 Dmitry S. Baikov
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #ifndef __jack_midi_unpack_h__
20 #define __jack_midi_unpack_h__
23 MIDI_UNPACK_MAX_MSG
= 1024
29 unsigned char data
[MIDI_UNPACK_MAX_MSG
];
34 void midi_unpack_init(midi_unpack_t
*u
)
37 u
->size
= sizeof(u
->data
);
42 void midi_unpack_reset(midi_unpack_t
*u
)
48 static const unsigned char midi_voice_len
[] =
52 3, /*0xA0 Aftertouch*/
53 3, /*0xB0 Control Change*/
54 2, /*0xC0 Program Change*/
55 2, /*0xD0 Channel Pressure*/
56 3, /*0xE0 Pitch Wheel*/
60 static const unsigned char midi_system_len
[] =
62 0, /*0xF0 System Exclusive Start*/
63 2, /*0xF1 MTC Quarter Frame*/
64 3, /*0xF2 Song Position*/
65 2, /*0xF3 Song Select*/
68 1, /*0xF6 Tune Request*/
69 1 /*0xF7 System Exclusive End*/
73 int midi_unpack_buf(midi_unpack_t
*buf
, const unsigned char *data
, int len
, void *jack_port_buf
, jack_nframes_t time
)
76 for (i
= 0; i
< len
; ++i
) {
77 const unsigned char byte
= data
[i
];
78 if (byte
>= 0xF8) // system realtime
80 jack_midi_event_write(jack_port_buf
, time
, &data
[i
], 1);
81 //printf("midi_unpack: written system relatime event\n");
82 //midi_input_write(in, &data[i], 1);
83 } else if (byte
< 0x80) // data
85 assert (buf
->pos
< buf
->size
);
86 buf
->data
[buf
->pos
++] = byte
;
87 } else if (byte
< 0xF0) // voice
89 assert (byte
>= 0x80 && byte
< 0xF0);
90 //buf->need = ((byte|0x0F) == 0xCF || (byte|0x0F)==0xDF) ? 2 : 3;
91 buf
->need
= midi_voice_len
[(byte
-0x80)>>4];
94 } else if (byte
== 0xF7) // sysex end
96 assert (buf
->pos
< buf
->size
);
97 buf
->data
[buf
->pos
++] = byte
;
100 assert (byte
>= 0xF0 && byte
< 0xF8);
103 buf
->need
= midi_system_len
[byte
- 0xF0];
105 buf
->need
= buf
->size
;
107 if (buf
->pos
== buf
->need
) {
108 // TODO: deal with big sysex'es (they are silently dropped for now)
109 if (buf
->data
[0] >= 0x80 || (buf
->data
[0] == 0xF0 && buf
->data
[buf
->pos
-1] == 0xF7)) {
110 /* convert Note On with velocity 0 to Note Off */
111 if ((buf
->data
[0] & 0xF0) == 0x90 && buf
->data
[2] == 0) {
112 // we use temp array here to keep running status sync
113 jack_midi_data_t temp
[3] = { 0x80, 0, 0x40 };
114 temp
[0] |= buf
->data
[0] & 0x0F;
115 temp
[1] = buf
->data
[1];
116 jack_midi_event_write(jack_port_buf
, time
, temp
, 3);
118 jack_midi_event_write(jack_port_buf
, time
, &buf
->data
[0], buf
->pos
);
119 //printf("midi_unpack: written %d-byte event\n", buf->pos);
120 //midi_input_write(in, &buf->data[0], buf->pos);
122 /* keep running status */
123 if (buf
->data
[0] >= 0x80 && buf
->data
[0] < 0xF0)
127 buf
->need
= buf
->size
;
135 #endif /* __jack_midi_unpack_h__ */