2 * Copyright (C) 2016 Robin Gareus <robin@gareus.org>
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, or (at your option)
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 Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #ifndef _ardour_surfaces_m2pad_h_
20 #define _ardour_surfaces_m2pad_h_
23 #include "pbd/signals.h"
25 namespace ArdourSurface {
31 virtual ~M2PadInterface () {}
34 PBD::Signal1<void, float> pressed;
35 PBD::Signal0<void> released;
36 PBD::Signal1<void, float> aftertouch;
37 PBD::Signal2<void, float, bool> event;
38 PBD::Signal1<void, float> changed;
40 virtual uint16_t value () const { return 0; }
41 virtual float pressure () const { return 0.f; }
42 virtual void set_color (uint32_t rgba) {}
44 /* internal API - called from device thread */
45 virtual void set_value (uint16_t v) {}
47 virtual void color (uint8_t& r, uint8_t& g, uint8_t& b) const {
52 class M2Pad : public M2PadInterface
63 for (int i = 0; i < 4; ++i) {
68 uint16_t value () const { return _raw; }
69 float pressure () const { return _pressure; }
71 void set_color (uint32_t rgba) { _rgba = rgba; }
73 void color (uint8_t& r, uint8_t& g, uint8_t& b) const
75 r = ((_rgba >> 24) & 0xff) >> 1;
76 g = ((_rgba >> 16) & 0xff) >> 1;
77 b = ((_rgba >> 8) & 0xff) >> 1;
80 void set_value (uint16_t v)
82 // bleed to neighboring pads...
83 static const uint16_t high = 159;
84 static const float low = 159 / 4095.f;
85 static const float mindelta = 32.f / 4096.f;
92 // some pads never return to "0", and there's
93 // TODO map pressure from a min..max range,
94 // even hard hits rarely exceed 3400 or thereabouts.
95 // -> "pad sensitivity" config or "calibrate pads"
98 _cnt = (_cnt + 1) & 3;
101 const float p = v / 4095.f;
102 _pressure += .1 * (p - _pressure);
103 if (_pressure < low) {
106 released (); /* EMIT SIGNAL */
107 event (_pressure, true); /* EMIT SIGNAL */
109 if (fabsf (_last - _pressure) > mindelta) {
111 aftertouch (_pressure); /* EMIT SIGNAL */
112 event (_pressure, false); /* EMIT SIGNAL */
116 bool above_thresh = true;
118 for (int i = 0; i < 4; ++i) {
119 if (hist[i] < high) {
120 above_thresh = false;
123 max = std::max (max, hist[i]);
127 _last = _pressure = max / 4095.f;
129 event (_pressure, true); /* EMIT SIGNAL */
145 #endif /* _ardour_surfaces_m2pad_h_ */