diff options
author | Carl Hetherington <carl@carlh.net> | 2009-09-15 16:49:15 +0000 |
---|---|---|
committer | Carl Hetherington <carl@carlh.net> | 2009-09-15 16:49:15 +0000 |
commit | 127b8a62b790c7515a27934b920e88b7de04b7fc (patch) | |
tree | d60be81f6393477eb7335fc1dc0549cfa7571dc3 /libs/midi++2/channel.cc | |
parent | 7b14a4230b37a3cdd3af4ed84027957b7da60849 (diff) |
Normalise names of .cc and .h files.
git-svn-id: svn://localhost/ardour2/branches/3.0@5664 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/midi++2/channel.cc')
-rw-r--r-- | libs/midi++2/channel.cc | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/libs/midi++2/channel.cc b/libs/midi++2/channel.cc new file mode 100644 index 0000000000..f19c913644 --- /dev/null +++ b/libs/midi++2/channel.cc @@ -0,0 +1,299 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include <cstring> +#include "midi++/types.h" +#include "midi++/port.h" +#include "midi++/channel.h" + +using namespace sigc; +using namespace MIDI; + +Channel::Channel (byte channelnum, Port &p) : _port (p) +{ + _channel_number = channelnum; + + reset (0, 1, false); +} + +void +Channel::connect_input_signals () + +{ + _port.input()->channel_pressure[_channel_number].connect + (mem_fun (*this, &Channel::process_chanpress)); + _port.input()->channel_note_on[_channel_number].connect + (mem_fun (*this, &Channel::process_note_on)); + _port.input()->channel_note_off[_channel_number].connect + (mem_fun (*this, &Channel::process_note_off)); + _port.input()->channel_poly_pressure[_channel_number].connect + (mem_fun (*this, &Channel::process_polypress)); + _port.input()->channel_program_change[_channel_number].connect + (mem_fun (*this, &Channel::process_program_change)); + _port.input()->channel_controller[_channel_number].connect + (mem_fun (*this, &Channel::process_controller)); + _port.input()->channel_pitchbend[_channel_number].connect + (mem_fun (*this, &Channel::process_pitchbend)); + _port.input()->reset.connect (mem_fun (*this, &Channel::process_reset)); +} + +void +Channel::connect_output_signals () + +{ + _port.output()->channel_pressure[_channel_number].connect + (mem_fun (*this, &Channel::process_chanpress)); + _port.output()->channel_note_on[_channel_number].connect + (mem_fun (*this, &Channel::process_note_on)); + _port.output()->channel_note_off[_channel_number].connect + (mem_fun (*this, &Channel::process_note_off)); + _port.output()->channel_poly_pressure[_channel_number].connect + (mem_fun (*this, &Channel::process_polypress)); + _port.output()->channel_program_change[_channel_number].connect + (mem_fun (*this, &Channel::process_program_change)); + _port.output()->channel_controller[_channel_number].connect + (mem_fun (*this, &Channel::process_controller)); + _port.output()->channel_pitchbend[_channel_number].connect + (mem_fun (*this, &Channel::process_pitchbend)); + _port.output()->reset.connect (mem_fun (*this, &Channel::process_reset)); +} + +void +Channel::reset (timestamp_t timestamp, nframes_t /*nframes*/, bool notes_off) +{ + _program_number = _channel_number; + _bank_number = 0; + _pitch_bend = 0; + + _last_note_on = 0; + _last_note_off = 0; + _last_on_velocity = 0; + _last_off_velocity = 0; + + if (notes_off) { + all_notes_off (timestamp); + } + + memset (_polypress, 0, sizeof (_polypress)); + memset (_controller_msb, 0, sizeof (_controller_msb)); + memset (_controller_lsb, 0, sizeof (_controller_lsb)); + + /* zero all controllers XXX not necessarily the right thing */ + + memset (_controller_val, 0, sizeof (_controller_val)); + + for (int n = 0; n < 128; n++) { + _controller_14bit[n] = false; + } + + _rpn_msb = 0; + _rpn_lsb = 0; + _nrpn_msb = 0; + _nrpn_lsb = 0; + + _omni = true; + _poly = false; + _mono = true; + _notes_on = 0; +} + +void +Channel::process_note_off (Parser & /*parser*/, EventTwoBytes *tb) +{ + _last_note_off = tb->note_number; + _last_off_velocity = tb->velocity; + + if (_notes_on) { + _notes_on--; + } +} + +void +Channel::process_note_on (Parser & /*parser*/, EventTwoBytes *tb) +{ + _last_note_on = tb->note_number; + _last_on_velocity = tb->velocity; + _notes_on++; +} + +void +Channel::process_controller (Parser & /*parser*/, EventTwoBytes *tb) +{ + unsigned short cv; + + /* XXX arguably need a lock here to protect non-atomic changes + to controller_val[...]. or rather, need to make sure that + all changes *are* atomic. + */ + + if (tb->controller_number <= 31) { /* unsigned: no test for >= 0 */ + + /* if this controller is already known to use 14 bits, + then treat this value as the MSB, and combine it + with the existing LSB. + + otherwise, just treat it as a 7 bit value, and set + it directly. + */ + + cv = (unsigned short) _controller_val[tb->controller_number]; + + if (_controller_14bit[tb->controller_number]) { + cv = ((tb->value << 7) | (cv & 0x7f)); + } else { + cv = tb->value; + } + + _controller_val[tb->controller_number] = (controller_value_t)cv; + + } else if ((tb->controller_number >= 32 && + tb->controller_number <= 63)) { + + cv = (unsigned short) _controller_val[tb->controller_number]; + + /* LSB for CC 0-31 arrived. + + If this is the first time (i.e. its currently + flagged as a 7 bit controller), mark the + controller as 14 bit, adjust the existing value + to be the MSB, and OR-in the new LSB value. + + otherwise, OR-in the new low 7bits with the old + high 7. + */ + + int cn = tb->controller_number - 32; + + if (_controller_14bit[cn] == false) { + _controller_14bit[cn] = true; + cv = (cv << 7) | (tb->value & 0x7f); + } else { + cv = (cv & 0x3f80) | (tb->value & 0x7f); + } + + _controller_val[tb->controller_number] = + (controller_value_t) cv; + } else { + + /* controller can only take 7 bit values */ + + _controller_val[tb->controller_number] = + (controller_value_t) tb->value; + } + + /* bank numbers are special, in that they have their own signal + */ + + if (tb->controller_number == 0) { + _bank_number = (unsigned short) _controller_val[0]; + if (_port.input()) { + _port.input()->bank_change (*_port.input(), _bank_number); + _port.input()->channel_bank_change[_channel_number] + (*_port.input(), _bank_number); + } + } + +} + +void +Channel::process_program_change (Parser & /*parser*/, byte val) +{ + _program_number = val; +} + +void +Channel::process_chanpress (Parser & /*parser*/, byte val) +{ + _chanpress = val; +} + +void +Channel::process_polypress (Parser & /*parser*/, EventTwoBytes *tb) +{ + _polypress[tb->note_number] = tb->value; +} + +void +Channel::process_pitchbend (Parser & /*parser*/, pitchbend_t val) +{ + _pitch_bend = val; +} + +void +Channel::process_reset (Parser & /*parser*/) +{ + reset (0, 1); +} + +/** Write a message to a channel. + * \return true if success + */ +bool +Channel::channel_msg (byte id, byte val1, byte val2, timestamp_t timestamp) +{ + unsigned char msg[3]; + int len = 0; + + msg[0] = id | (_channel_number & 0xf); + + switch (id) { + case off: + msg[1] = val1 & 0x7F; + msg[2] = val2 & 0x7F; + len = 3; + break; + + case on: + msg[1] = val1 & 0x7F; + msg[2] = val2 & 0x7F; + len = 3; + break; + + case MIDI::polypress: + msg[1] = val1 & 0x7F; + msg[2] = val2 & 0x7F; + len = 3; + break; + + case controller: + msg[1] = val1 & 0x7F; + msg[2] = val2 & 0x7F; + len = 3; + break; + + case MIDI::program: + msg[1] = val1 & 0x7F; + len = 2; + break; + + case MIDI::chanpress: + msg[1] = val1 & 0x7F; + len = 2; + break; + + case MIDI::pitchbend: + msg[1] = val1 & 0x7F; + msg[2] = val2 & 0x7F; + len = 3; + break; + } + + return _port.midimsg (msg, len, timestamp); +} |