2 Copyright (C) 1998-99 Paul Barton-Davis
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., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <midi++/types.h>
22 #include <midi++/port.h>
23 #include <midi++/channel.h>
28 Channel::Channel (byte channelnum, Port &p) : port (p)
30 channel_number = channelnum;
36 Channel::connect_input_signals ()
39 port.input()->channel_pressure[channel_number].connect
40 (mem_fun (*this, &Channel::process_chanpress));
41 port.input()->channel_note_on[channel_number].connect
42 (mem_fun (*this, &Channel::process_note_on));
43 port.input()->channel_note_off[channel_number].connect
44 (mem_fun (*this, &Channel::process_note_off));
45 port.input()->channel_poly_pressure[channel_number].connect
46 (mem_fun (*this, &Channel::process_polypress));
47 port.input()->channel_program_change[channel_number].connect
48 (mem_fun (*this, &Channel::process_program_change));
49 port.input()->channel_controller[channel_number].connect
50 (mem_fun (*this, &Channel::process_controller));
51 port.input()->channel_pitchbend[channel_number].connect
52 (mem_fun (*this, &Channel::process_pitchbend));
53 port.input()->reset.connect (mem_fun (*this, &Channel::process_reset));
57 Channel::connect_output_signals ()
60 port.output()->channel_pressure[channel_number].connect
61 (mem_fun (*this, &Channel::process_chanpress));
62 port.output()->channel_note_on[channel_number].connect
63 (mem_fun (*this, &Channel::process_note_on));
64 port.output()->channel_note_off[channel_number].connect
65 (mem_fun (*this, &Channel::process_note_off));
66 port.output()->channel_poly_pressure[channel_number].connect
67 (mem_fun (*this, &Channel::process_polypress));
68 port.output()->channel_program_change[channel_number].connect
69 (mem_fun (*this, &Channel::process_program_change));
70 port.output()->channel_controller[channel_number].connect
71 (mem_fun (*this, &Channel::process_controller));
72 port.output()->channel_pitchbend[channel_number].connect
73 (mem_fun (*this, &Channel::process_pitchbend));
74 port.output()->reset.connect (mem_fun (*this, &Channel::process_reset));
78 Channel::reset (bool notes_off)
80 program_number = channel_number;
86 _last_on_velocity = 0;
87 _last_off_velocity = 0;
93 memset (polypress, 0, sizeof (polypress));
94 memset (controller_msb, 0, sizeof (controller_msb));
95 memset (controller_lsb, 0, sizeof (controller_lsb));
97 /* zero all controllers XXX not necessarily the right thing */
99 memset (controller_val, 0, sizeof (controller_val));
101 for (int n = 0; n < 128; n++) {
102 controller_14bit[n] = false;
117 Channel::process_note_off (Parser &parser, EventTwoBytes *tb)
120 _last_note_off = tb->note_number;
121 _last_off_velocity = tb->velocity;
129 Channel::process_note_on (Parser &parser, EventTwoBytes *tb)
132 _last_note_on = tb->note_number;
133 _last_on_velocity = tb->velocity;
138 Channel::process_controller (Parser &parser, EventTwoBytes *tb)
143 /* XXX arguably need a lock here to protect non-atomic changes
144 to controller_val[...]. or rather, need to make sure that
145 all changes *are* atomic.
148 if (tb->controller_number <= 31) { /* unsigned: no test for >= 0 */
150 /* if this controller is already known to use 14 bits,
151 then treat this value as the MSB, and combine it
152 with the existing LSB.
154 otherwise, just treat it as a 7 bit value, and set
158 cv = (unsigned short) controller_val[tb->controller_number];
160 if (controller_14bit[tb->controller_number]) {
161 cv = ((tb->value << 7) | (cv & 0x7f));
166 controller_val[tb->controller_number] = (controller_value_t)cv;
168 } else if ((tb->controller_number >= 32 &&
169 tb->controller_number <= 63)) {
171 cv = (unsigned short) controller_val[tb->controller_number];
173 /* LSB for CC 0-31 arrived.
175 If this is the first time (i.e. its currently
176 flagged as a 7 bit controller), mark the
177 controller as 14 bit, adjust the existing value
178 to be the MSB, and OR-in the new LSB value.
180 otherwise, OR-in the new low 7bits with the old
184 int cn = tb->controller_number - 32;
186 if (controller_14bit[cn] == false) {
187 controller_14bit[cn] = true;
188 cv = (cv << 7) | (tb->value & 0x7f);
190 cv = (cv & 0x3f80) | (tb->value & 0x7f);
193 controller_val[tb->controller_number] =
194 (controller_value_t) cv;
197 /* controller can only take 7 bit values */
199 controller_val[tb->controller_number] =
200 (controller_value_t) tb->value;
203 /* bank numbers are special, in that they have their own signal
206 if (tb->controller_number == 0) {
207 bank_number = (unsigned short) controller_val[0];
209 port.input()->bank_change (*port.input(), bank_number);
210 port.input()->channel_bank_change[channel_number]
211 (*port.input(), bank_number);
218 Channel::process_program_change (Parser &parser, byte val)
221 program_number = val;
225 Channel::process_chanpress (Parser &parser, byte val)
232 Channel::process_polypress (Parser &parser, EventTwoBytes *tb)
235 polypress[tb->note_number] = tb->value;
239 Channel::process_pitchbend (Parser &parser, pitchbend_t val)
246 Channel::process_reset (Parser &parser)
253 Channel::channel_msg (byte id, byte val1, byte val2)
256 unsigned char msg[3];
259 msg[0] = id | (channel_number & 0xf);
263 msg[1] = val1 & 0x7F;
264 msg[2] = val2 & 0x7F;
269 msg[1] = val1 & 0x7F;
270 msg[2] = val2 & 0x7F;
274 case MIDI::polypress:
275 msg[1] = val1 & 0x7F;
276 msg[2] = val2 & 0x7F;
281 msg[1] = val1 & 0x7F;
282 msg[2] = val2 & 0x7F;
287 msg[1] = val1 & 0x7F;
291 case MIDI::chanpress:
292 msg[1] = val1 & 0x7F;
296 case MIDI::pitchbend:
297 msg[1] = val1 & 0x7F;
298 msg[2] = val2 & 0x7F;
303 return port.midimsg (msg, len);