-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapcKey25.h
More file actions
129 lines (106 loc) · 3.41 KB
/
apcKey25.h
File metadata and controls
129 lines (106 loc) · 3.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#ifndef _apcKey25_h_
#define _apcKey25_h_
#include "commonDefines.h"
#include "Looper.h"
// APC Key 25 pad grid: 5 rows x 8 cols, note = row*8 + col, row 0 = bottom
#define APC_ROWS 5
#define APC_COLS 8
#define APC_BTN_STOP_ALL 0x51
#define APC_BTN_PLAY 0x5B
#define APC_BTN_RECORD 0x5D
#define APC_BTN_FORMAT 0x54
#define APC_BTN_SHIFT 0x62
#define APC_CH_NOTE_ON 0x90
#define APC_CH_NOTE_OFF 0x80
#define APC_VEL_LED_OFF 0
#define APC_VEL_LED_GREEN 1
#define APC_VEL_LED_RED 3
#define APC_VEL_LED_YELLOW 5
#define APC_HOLD_ERASE_MS 1000
#define APC_LED_BOOT_DELAY_MS 2000
// We map looper tracks to APC rows from bottom: track 0 = row 0 (bottom row)
// Col 0 = rec/play/stop track button
// Col 1 = track presence (tap to erase, hold to erase)
struct ApcCmd {
enum Type { NONE, TRACK, ERASE_TRACK, STOP_TRACK, LOOPER } type;
int arg;
};
class apcKey25
{
public:
apcKey25();
void handleMidi(u8 status, u8 data1, u8 data2);
void handleFilterCC(u8 cc, u8 data2);
void handleEffectsCC(u8 cc, u8 data2);
void update();
void invalidateLedCache();
struct DebugState {
bool transposeLocked;
int transposePitch;
float pitchWheelOffset;
float driftTarget;
float computedRatio;
bool liveEngaged;
float livePitchSemitones;
};
struct EffectsState {
float filterHP;
float filterLP;
float filterRes;
float reverbAmount;
float delayAmount;
float time;
float formant;
};
DebugState getDebugState() const;
EffectsState getEffectsState() const;
private:
bool m_shift;
volatile bool m_cmdReady;
volatile ApcCmd::Type m_cmdType;
volatile int m_cmdArg;
// Hold tracking for col1 (mute/erase)
unsigned long m_col1HoldStart[LOOPER_NUM_TRACKS];
bool m_col1Held[LOOPER_NUM_TRACKS];
bool m_col1EraseTriggered[LOOPER_NUM_TRACKS];
// Hold tracking for layer pads (cols 2-5): tap=stop/play toggle, hold=clear layer
unsigned long m_layerHoldStart[LOOPER_NUM_TRACKS][LOOPER_NUM_LAYERS];
bool m_layerHeld[LOOPER_NUM_TRACKS][LOOPER_NUM_LAYERS];
bool m_layerClearTriggered[LOOPER_NUM_TRACKS][LOOPER_NUM_LAYERS];
unsigned long m_nowMs;
unsigned long m_bootMs;
unsigned long m_lastLedMs;
bool m_transposeLocked;
int m_transposePitch;
int m_pitchWheelOffset;
float m_driftTarget;
unsigned long m_lastDriftMs;
float m_computedRatio;
bool m_liveEngaged;
float m_livePitchSemitones;
volatile bool m_liveLedDirty;
float m_filterHP;
float m_filterLP;
float m_filterRes;
float m_reverbAmount;
float m_delayAmount;
float m_time;
float m_formant;
void _applyLivePitch();
void _applyFilters();
void _applyEffects();
void _applyFormant();
void _queueCmd(ApcCmd::Type type, int arg);
void _onPadPress(int row, int col);
void _onPadRelease(int row, int col);
void _onButton(u8 note);
void _sendLed(u8 note, u8 velocity);
void _updateComputedRatio();
void _updateDrift();
void _updateGridLeds();
u8 _trackLedColor(int track);
u8 _muteLedColor(int track);
u8 _padNote(int row, int col);
};
extern apcKey25 *pTheAPC;
#endif