-
Notifications
You must be signed in to change notification settings - Fork 6
/
midi_mc_fader_pickup.h
128 lines (119 loc) · 6.14 KB
/
midi_mc_fader_pickup.h
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
/*
* The MIT License (MIT)
*
* Copyright (c) 2022 rppicomidi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
/**
* @file midi_mc_fader_pickup.h
*
* This file contains functions and data that implement fader "pickup" synchronization
* between a DAW that expects to be connected to a Mackie Control control surface that
* has motorized faders and a Mackie Control compatible control surface that has
* non-motorized faders. The Mackie control fader move message is the MIDI pitch
* bend message; pitch bend MIDI channels 1-8 correspond to fader channels 1-8;
* pitch bend MIDI channel 9 corresponds to the main fader. Each fader value is a 14-bit
* unsigned value encoded in the pitch bend position, 7 bit data, LSB first.
*
* The DAW will send the current expected fader values to the control surface on
* startup, fader bank change, mode change, etc. The faders on a control surface with
* motorized faders will move to match the target fader values from the DAW. Non-motorized
* faders cannot move to match target values all by themselves. This code provides data structures
* that allow higher level code to filter out fader move messages to the DAW for an individual fader
* until the user moves the fader up to or past the last target fader value the DAW sent for that fader.
*
* To use this code:
* 1. Create as many mc_fader_pickup_t structures as you have hardware faders on your control surface
* 2. Call mc_fader_pickup_init() to initialize each structure
* 3. For each Mackie Control fader move message (MIDI pitch bend) you receive, extract the fader value
* by calling mc_fader_extract_value().
* 4a. If the fader move message was from the DAW, update the structure by calling mc_fader_pickup_set_daw_fader_value().
* Do not send the message to the control surface (it can't do anything with it anyway)
* 4b. If the fader move message was from the hardware control surface, update the structure by calling
* mc_fader_pickup_set_hw_fader_value() and note the return value. If the return value value was true, send
* the fader move message to the DAW because the fader is in sync with the value the DAW thinks it should have.
* Otherwise, do not send the fader move message to the DAW.
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
MC_FADER_PICKUP_RESET, //!< Fader state and the fader target value is unknown
MC_FADER_PICKUP_HW_UNKNOWN, //!< Hardware Fader value is unknown but the DAW value is known
MC_FADER_PICKUP_DAW_UNKNOWN, //!< Hardware Fader value is known but the DAW value is unknown
MC_FADER_PICKUP_TOO_HIGH, //!< Fader is too high; need to reduce it down to or less than the fader target value
MC_FADER_PICKUP_TOO_LOW, //!< Fader is too low; need to increase it up to or greater than the fader target value
MC_FADER_PICKUP_SYNCED
} mc_fader_pickup_state_t;
typedef struct {
mc_fader_pickup_state_t state; // the current pickup state of the fader
uint16_t daw; // the last fader value the DAW sent (14-bits, unsigned)
uint16_t fader; // the last fader value the control surface sent (14-bits, unsigned)
uint16_t sync_delta; // the minimum difference between the fader values before they are considered "equal" (14-bits, unsigned)
} mc_fader_pickup_t;
/**
* @brief initialize a mc_fader_pickup structure
*
* @param pickup is a pointer to the structure to initialize
* @param sync_delta is the unsigned 14-bit absolute fader value difference
* that is close enough to call the fader in sync with the DAW
*/
void mc_fader_pickup_init(mc_fader_pickup_t* pickup, uint16_t sync_delta);
/**
* @brief get the 14-bit unsigned fader value from the pitch bend USB MIDI packet
*
* @param packet a standard 4-byte USB MIDI pitch bend message
* @return uint16_t the 14-bit unsigned fader value
*
* @note this function ignores the first two bytes of the packet
*/
uint16_t mc_fader_extract_value(uint8_t packet[4]);
/**
* @brief encode the 14-bit unsigned fader value to the pitch bend USB MIDI packet
*
* @param fader_value the 14-bit fader value to encode in the pitch bend message
* @param packet the standard USB MIDI pitch bend message with the fader value enocded
*
* @note this function does not set the the first two bytes of the packet
*/
void mc_fader_encode_value(uint16_t fader_value, uint8_t packet[4]);
/**
* @brief write a new DAW fader value to the pickup structure
*
* @param pickup a pointer to a mc_fader_pickupt_t structure
* @param daw_fader_value the 14-bit unsigned DAW fader value
* @return true if setting the DAW fader causes the hardware fader and DAW fader to be in sync
*/
bool mc_fader_pickup_set_daw_fader_value(mc_fader_pickup_t* pickup, uint16_t daw_fader_value);
/**
* @brief write a new hardare fader value to the pickup structure
*
* @param pickup a pointer to a mc_fader_pickupt_t structure
* @param hw_fader_value the 14-bit unsigned hardware fader value
* @return true if setting the hardware fader causes the hardware fader and DAW fader to be in sync
*/
bool mc_fader_pickup_set_hw_fader_value(mc_fader_pickup_t* pickup, uint16_t hw_fader_value);
#ifdef __cplusplus
}
#endif