Ardour  9.0-pre0-582-g084a23a80d
m2_pad.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2016 Robin Gareus <robin@gareus.org>
3  *
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.
8  *
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.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #ifndef _ardour_surfaces_m2pad_h_
20 #define _ardour_surfaces_m2pad_h_
21 
22 #include <stdint.h>
23 #include "pbd/signals.h"
24 
25 #include <cmath>
26 
27 namespace ArdourSurface {
28 
30 {
31  public:
33  virtual ~M2PadInterface () {}
34 
35  /* user API */
36  PBD::Signal<void(float)> pressed;
38  PBD::Signal<void(float)> aftertouch;
39  PBD::Signal<void(float, bool)> event;
40  PBD::Signal<void(float)> changed;
41 
42  virtual uint16_t value () const { return 0; }
43  virtual float pressure () const { return 0.f; }
44  virtual void set_color (uint32_t rgba) {}
45 
46  /* internal API - called from device thread */
47  virtual void set_value (uint16_t v) {}
48 
49  virtual void color (uint8_t& r, uint8_t& g, uint8_t& b) const {
50  r = g = b = 0;
51  }
52 };
53 
54 class M2Pad : public M2PadInterface
55 {
56  public:
57  M2Pad ()
58  : M2PadInterface ()
59  , _pressed (false)
60  , _pressure (0)
61  , _last (0)
62  , _cnt (0)
63  , _rgba (0)
64  {
65  for (int i = 0; i < 4; ++i) {
66  hist[i] = 0;
67  }
68  }
69 
70  uint16_t value () const { return _raw; }
71  float pressure () const { return _pressure; }
72 
73  void set_color (uint32_t rgba) { _rgba = rgba; }
74 
75  void color (uint8_t& r, uint8_t& g, uint8_t& b) const
76  {
77  r = ((_rgba >> 24) & 0xff) >> 1;
78  g = ((_rgba >> 16) & 0xff) >> 1;
79  b = ((_rgba >> 8) & 0xff) >> 1;
80  }
81 
82  void set_value (uint16_t v)
83  {
84  // bleed to neighboring pads...
85  static const uint16_t high = 159;
86  static const float low = 159 / 4095.f;
87  static const float mindelta = 32.f / 4096.f;
88 
89  if (_raw != v) {
90  changed (v / 4095.f);
91  _raw = v;
92  }
93 
94  // some pads never return to "0", and there's
95  // TODO map pressure from a min..max range,
96  // even hard hits rarely exceed 3400 or thereabouts.
97  // -> "pad sensitivity" config or "calibrate pads"
98 
99  hist[_cnt] = v;
100  _cnt = (_cnt + 1) & 3;
101 
102  if (_pressed) {
103  const float p = v / 4095.f;
104  _pressure += .1 * (p - _pressure);
105  if (_pressure < low) {
106  _pressure = 0;
107  _pressed = false;
108  released (); /* EMIT SIGNAL */
109  event (_pressure, true); /* EMIT SIGNAL */
110  } else {
111  if (std::fabsf (_last - _pressure) > mindelta) {
112  _last = _pressure;
113  aftertouch (_pressure); /* EMIT SIGNAL */
114  event (_pressure, false); /* EMIT SIGNAL */
115  }
116  }
117  } else {
118  bool above_thresh = true;
119  uint16_t max = 0;
120  for (int i = 0; i < 4; ++i) {
121  if (hist[i] < high) {
122  above_thresh = false;
123  break;
124  }
125  max = std::max (max, hist[i]);
126  }
127  if (above_thresh) {
128  _pressed = true;
129  _last = _pressure = max / 4095.f;
130  pressed (_pressure);
131  event (_pressure, true); /* EMIT SIGNAL */
132  }
133  }
134  }
135 
136  protected:
137  bool _pressed;
138  float _pressure;
139  uint16_t _raw;
140  float _last;
141  uint16_t hist[4];
142  unsigned int _cnt;
143  uint32_t _rgba;
144 };
145 
146 } /* namespace */
147 #endif /* _ardour_surfaces_m2pad_h_ */
148 
149 
150 
virtual void color(uint8_t &r, uint8_t &g, uint8_t &b) const
Definition: m2_pad.h:49
PBD::Signal< void(float)> pressed
Definition: m2_pad.h:36
virtual float pressure() const
Definition: m2_pad.h:43
virtual void set_color(uint32_t rgba)
Definition: m2_pad.h:44
PBD::Signal< void(float)> aftertouch
Definition: m2_pad.h:38
PBD::Signal< void(float, bool)> event
Definition: m2_pad.h:39
PBD::Signal< void()> released
Definition: m2_pad.h:37
virtual void set_value(uint16_t v)
Definition: m2_pad.h:47
PBD::Signal< void(float)> changed
Definition: m2_pad.h:40
virtual uint16_t value() const
Definition: m2_pad.h:42
void set_value(uint16_t v)
Definition: m2_pad.h:82
void set_color(uint32_t rgba)
Definition: m2_pad.h:73
unsigned int _cnt
Definition: m2_pad.h:142
uint32_t _rgba
Definition: m2_pad.h:143
float pressure() const
Definition: m2_pad.h:71
void color(uint8_t &r, uint8_t &g, uint8_t &b) const
Definition: m2_pad.h:75
uint16_t value() const
Definition: m2_pad.h:70
uint16_t hist[4]
Definition: m2_pad.h:141