ardour
midi_channel_filter.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2006-2015 Paul Davis
3  Author: David Robillard
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 
20 #include "ardour/buffer_set.h"
21 #include "ardour/midi_buffer.h"
23 #include "pbd/ffs.h"
24 
25 namespace ARDOUR {
26 
28  : _mode_mask(0x0000FFFF)
29 {}
30 
31 void
33 {
34  ChannelMode mode;
35  uint16_t mask;
36  get_mode_and_mask(&mode, &mask);
37 
38  if (mode == AllChannels) {
39  return;
40  }
41 
42  MidiBuffer& buf = bufs.get_midi(0);
43 
44  for (MidiBuffer::iterator e = buf.begin(); e != buf.end(); ) {
45  Evoral::MIDIEvent<framepos_t> ev(*e, false);
46 
47  if (ev.is_channel_event()) {
48  switch (mode) {
49  case FilterChannels:
50  if (0 == ((1 << ev.channel()) & mask)) {
51  e = buf.erase (e);
52  } else {
53  ++e;
54  }
55  break;
56  case ForceChannel:
57  ev.set_channel(PBD::ffs(mask) - 1);
58  ++e;
59  break;
60  case AllChannels:
61  /* handled by the opening if() */
62  ++e;
63  break;
64  }
65  } else {
66  ++e;
67  }
68  }
69 }
70 
71 bool
72 MidiChannelFilter::filter(uint8_t* buf, uint32_t len)
73 {
74  ChannelMode mode;
75  uint16_t mask;
76  get_mode_and_mask(&mode, &mask);
77 
78  const uint8_t type = buf[0] & 0xF0;
79  const bool is_channel_event = (0x80 <= type) && (type <= 0xE0);
80  if (!is_channel_event) {
81  return false;
82  }
83 
84  const uint8_t channel = buf[0] & 0x0F;
85  switch (mode) {
86  case AllChannels:
87  return false;
88  case FilterChannels:
89  return !((1 << channel) & mask);
90  case ForceChannel:
91  buf[0] = (0xF0 & buf[0]) | (0x0F & (PBD::ffs(mask) - 1));
92  return false;
93  }
94 
95  return false;
96 }
97 
101 static inline uint16_t
102 force_mask(const ChannelMode mode, const uint16_t mask)
103 {
104  return ((mode == ForceChannel)
105  ? (mask ? (1 << (PBD::ffs(mask) - 1)) : 1)
106  : mask);
107 }
108 
109 bool
111 {
112  ChannelMode old_mode;
113  uint16_t old_mask;
114  get_mode_and_mask(&old_mode, &old_mask);
115 
116  if (old_mode != mode || old_mask != mask) {
117  mask = force_mask(mode, mask);
118  g_atomic_int_set(&_mode_mask, (uint32_t(mode) << 16) | uint32_t(mask));
120  return true;
121  }
122 
123  return false;
124 }
125 
126 bool
128 {
129  ChannelMode mode;
130  uint16_t old_mask;
131  get_mode_and_mask(&mode, &old_mask);
132 
133  if (old_mask != mask) {
134  mask = force_mask(mode, mask);
135  g_atomic_int_set(&_mode_mask, (uint32_t(mode) << 16) | uint32_t(mask));
137  return true;
138  }
139 
140  return false;
141 }
142 
143 } /* namespace ARDOUR */
Force all events to a certain channel.
Definition: types.h:212
MidiBuffer & get_midi(size_t i)
Definition: buffer_set.h:107
PBD::Signal0< void > ChannelModeChanged
int ffs(int x)
Definition: ffs.cc:28
void get_mode_and_mask(ChannelMode *mode, uint16_t *mask) const
uint8_t channel() const
Definition: MIDIEvent.hpp:64
bool is_channel_event() const
Definition: MIDIEvent.hpp:97
static uint16_t force_mask(const ChannelMode mode, const uint16_t mask)
uint32_t _mode_mask
16 bits mode, 16 bits mask
ChannelMode
Definition: types.h:209
void set_channel(uint8_t channel)
Definition: MIDIEvent.hpp:65
PBD::Signal0< void > ChannelMaskChanged
Definition: amp.h:29
iterator erase(const iterator &i)
Definition: midi_buffer.h:133
void filter(BufferSet &bufs)
bool set_channel_mask(uint16_t mask)
Pass through all channel information unmodified.
Definition: types.h:210
iterator begin()
Definition: midi_buffer.h:127
bool set_channel_mode(ChannelMode mode, uint16_t mask)
Ignore events on certain channels.
Definition: types.h:211