1 //=========================================================
2 //  MusE
3 //  Linux Music Editor
4 //  $Id: sync.h,v 1.1.1.1.2.2 2009/04/01 01:37:11 terminator356 Exp $
5 //
6 //  (C) Copyright 2003 Werner Schweer (ws@seh.de)
7 //  (C) Copyright 2016 Tim E. Real (terminator356 on sourceforge.net)
8 //
9 //  This program is free software; you can redistribute it and/or
10 //  modify it under the terms of the GNU General Public License
11 //  as published by the Free Software Foundation; version 2 of
12 //  the License, or (at your option) any later version.
13 //
14 //  This program is distributed in the hope that it will be useful,
15 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 //  GNU General Public License for more details.
18 //
19 //  You should have received a copy of the GNU General Public License
20 //  along with this program; if not, write to the Free Software
21 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22 //
23 //=========================================================
24 
25 #ifndef __SYNC_H__
26 #define __SYNC_H__
27 
28 #include "mtc.h"
29 #include "globaldefs.h"
30 
31 #include <stdint.h>
32 
33 namespace MusECore {
34 
35 class Xml;
36 
37 class MidiSyncInfo
38 {
39   public:
40     enum SyncRecFilterPresetType { NONE=0, TINY, SMALL, MEDIUM, LARGE, LARGE_WITH_PRE_DETECT, TYPE_END };
41 
42   private:
43     int _port;
44 
45     int _idOut;
46     int _idIn;
47 
48     bool _sendMC;
49     bool _sendMRT;
50     bool _sendMMC;
51     bool _sendMTC;
52     bool _recMC;
53     bool _recMRT;
54     bool _recMMC;
55     bool _recMTC;
56 
57     int _recMTCtype;
58 
59     bool _recRewOnStart;
60 
61     uint64_t _lastClkTime;
62     uint64_t _lastTickTime;
63     uint64_t _lastMRTTime;
64     uint64_t _lastMMCTime;
65     uint64_t _lastMTCTime;
66     uint64_t _lastActTime[MusECore::MUSE_MIDI_CHANNELS];
67 
68     bool     _clockTrig;
69     bool     _tickTrig;
70     bool     _MRTTrig;
71     bool     _MMCTrig;
72     bool     _MTCTrig;
73     bool     _actTrig[MusECore::MUSE_MIDI_CHANNELS];
74     bool     _clockDetect;
75     bool     _tickDetect;
76     bool     _MRTDetect;
77     bool     _MMCDetect;
78     bool     _MTCDetect;
79     bool     _actDetect[MusECore::MUSE_MIDI_CHANNELS];
80     int      _actDetectBits;
81 
82   public:
83     MidiSyncInfo();
84     MidiSyncInfo& operator= (const MidiSyncInfo &sp);
85     MidiSyncInfo& copyParams(const MidiSyncInfo &sp);
86 
port()87     int port() const              { return _port; }
setPort(const int p)88     void setPort(const int p)     { _port = p; }
89 
idOut()90     int idOut() const             { return _idOut; }
idIn()91     int idIn() const              { return _idIn; }
setIdOut(const int v)92     void setIdOut(const int v)    { _idOut = v; }
setIdIn(const int v)93     void setIdIn(const int v)     { _idIn = v; }
94 
MCOut()95     bool MCOut() const            { return _sendMC; }
MRTOut()96     bool MRTOut() const           { return _sendMRT; }
MMCOut()97     bool MMCOut() const           { return _sendMMC; }
MTCOut()98     bool MTCOut() const           { return _sendMTC; }
99 
MCIn()100     bool MCIn() const             { return _recMC; }
MRTIn()101     bool MRTIn() const            { return _recMRT; }
MMCIn()102     bool MMCIn() const            { return _recMMC; }
MTCIn()103     bool MTCIn() const            { return _recMTC; }
104 
setMCOut(const bool v)105     void setMCOut(const bool v)   { _sendMC = v; }
setMRTOut(const bool v)106     void setMRTOut(const bool v)  { _sendMRT = v; }
setMMCOut(const bool v)107     void setMMCOut(const bool v)  { _sendMMC = v; }
setMTCOut(const bool v)108     void setMTCOut(const bool v)  { _sendMTC = v; }
109 
110     void setMCIn(const bool v);
111     void setMRTIn(const bool v);
112     void setMMCIn(const bool v);
113     void setMTCIn(const bool v);
114 
115     void setTime();
116 
recRewOnStart()117     bool recRewOnStart() const            { return _recRewOnStart; }
setRecRewOnStart(const bool v)118     void setRecRewOnStart(const bool v)   { _recRewOnStart = v; }
119 
MCSyncDetect()120     bool MCSyncDetect() const             { return _clockDetect; }
121     void trigMCSyncDetect();
122 
tickDetect()123     bool tickDetect() const       { return _tickDetect; }
124     void trigTickDetect();
125 
MTCDetect()126     bool MTCDetect() const       { return _MTCDetect; }
127     void trigMTCDetect();
recMTCtype()128     int recMTCtype() const       { return _recMTCtype; }
setRecMTCtype(int t)129     void setRecMTCtype(int t)    { _recMTCtype = t; }
130 
MRTDetect()131     bool MRTDetect() const       { return _MRTDetect; }
132     void trigMRTDetect();
133 
MMCDetect()134     bool MMCDetect() const       { return _MMCDetect; }
135     void trigMMCDetect();
136 
actDetectBits()137     int  actDetectBits() const    { return _actDetectBits; }
138     bool actDetect(const int ch) const;
139     void trigActDetect(const int ch);
140 
141     bool isDefault() const;
142     void read(Xml& xml);
143     void write(int level, Xml& xml);
144 };
145 
146 
147 //---------------------------------------------------------
148 //   ExtMidiClock
149 //   Holds the frame of each external clock,
150 //    and play state at that time.
151 //---------------------------------------------------------
152 
153 class ExtMidiClock
154 {
155   public:
156     enum ExternState { ExternStopped = 0, ExternStarting, ExternContinuing, ExternStarted, ExternContinued };
157 
158   private:
159     // The frame at which this clock arrived.
160     unsigned int _frame;
161     // The play state of the external device when this clock arrived.
162     ExternState _externState;
163     // Whether this clock is the first clock after a start or continue.
164     bool _isFirstClock;
165     // Whether this is a valid structure.
166     bool _isValid;
167 
168   public:
ExtMidiClock()169     ExtMidiClock() : _frame(0), _externState(ExternStopped), _isFirstClock(false), _isValid(false) { };
ExtMidiClock(unsigned int frame,ExternState extState,bool firstClock)170     ExtMidiClock(unsigned int frame, ExternState extState, bool firstClock) :
171                  _frame(frame), _externState(extState), _isFirstClock(firstClock), _isValid(true) { };
172 
173     // The frame at which this clock arrived.
frame()174     unsigned int frame() const { return _frame; }
175     // The play state of the external device when this clock arrived.
externState()176     ExternState externState() const { return _externState; }
177     // Whether this clock is the first clock after a start or continue.
isFirstClock()178     bool isFirstClock() const { return _isFirstClock; }
179     // Whether this is a valid structure.
isValid()180     bool isValid() const { return _isValid; }
isPlaying()181     bool isPlaying() const
182     {
183       switch(_externState)
184       {
185         case ExternStopped:
186         case ExternStarting:
187         case ExternContinuing:
188           return false;
189         break;
190 
191         case ExternStarted:
192         case ExternContinued:
193           return true;
194         break;
195       };
196       return false;
197     }
isRunning()198     bool isRunning() const
199     {
200       switch(_externState)
201       {
202         case ExternStopped:
203           return false;
204         break;
205 
206         case ExternStarting:
207         case ExternContinuing:
208         case ExternStarted:
209         case ExternContinued:
210           return true;
211         break;
212       };
213       return false;
214     }
215 };
216 
217 //---------------------------------------------------------
218 //   MidiSyncContainer
219 //---------------------------------------------------------
220 
221 class MidiSyncContainer {
222   private:
223 // REMOVE Tim. clock. Removed.
224       unsigned int _midiClock; // Accumulator for clock output.
225 
226 /* Testing */
227       ExtMidiClock::ExternState playStateExt;   // used for keeping play state in sync functions
228       int recTick;            // ext sync tick position
229       double mclock1, mclock2;
230       double songtick1, songtick2;
231       int recTick1, recTick2;
232       int lastTempo;
233       double timediff[16][48];
234       int storedtimediffs;
235       int    _avgClkDiffCounter[16];
236       double _lastRealTempo;
237       bool _averagerFull[16];
238       int _clockAveragerPoles;
239       int* _clockAveragerStages;
240       bool _preDetect;
241       double _tempoQuantizeAmount;
242       MidiSyncInfo::SyncRecFilterPresetType _syncRecFilterPreset;
243 
244       void setSyncRecFilterPresetArrays();
245       void alignAllTicks(int frameOverride = 0);
246 /* Testing */
247 
248       void mtcSyncMsg(const MTC&, int, bool);
249 
250    public:
251       MidiSyncContainer();
252       virtual ~MidiSyncContainer();
253 
254 // REMOVE Tim. clock. Removed.
midiClock()255       unsigned int midiClock() const { return _midiClock; }
setMidiClock(unsigned int val)256       void setMidiClock(unsigned int val) { _midiClock = val; }
externalPlayState()257       ExtMidiClock::ExternState externalPlayState() const { return playStateExt; }
setExternalPlayState(ExtMidiClock::ExternState v)258       void setExternalPlayState(ExtMidiClock::ExternState v) { playStateExt = v; }
isPlaying()259       bool isPlaying() const
260       {
261         switch(playStateExt)
262         {
263           case ExtMidiClock::ExternStopped:
264           case ExtMidiClock::ExternStarting:
265           case ExtMidiClock::ExternContinuing:
266             return false;
267           break;
268 
269           case ExtMidiClock::ExternStarted:
270           case ExtMidiClock::ExternContinued:
271             return true;
272           break;
273         };
274         return false;
275       }
isRunning()276       bool isRunning() const
277       {
278         switch(playStateExt)
279         {
280           case ExtMidiClock::ExternStopped:
281             return false;
282           break;
283 
284           case ExtMidiClock::ExternStarting:
285           case ExtMidiClock::ExternContinuing:
286           case ExtMidiClock::ExternStarted:
287           case ExtMidiClock::ExternContinued:
288             return true;
289           break;
290         };
291         return false;
292       }
293       void realtimeSystemInput(int port, int type);
294       // Starts transport if necessary. Adds clock to tempo list.
295       // Returns a clock structure including frame, state, and whether the clock was a
296       //  'first clock' after a start or continue message.
297       ExtMidiClock midiClockInput(int port, unsigned int frame);
298       void mtcInputQuarter(int, unsigned char);
299       void setSongPosition(int, int);
300       void mmcInput(int, const unsigned char*, int);
301       void mtcInputFull(int, const unsigned char*, int);
302       void nonRealtimeSystemSysex(int, const unsigned char*, int);
303 
syncRecFilterPreset()304       MidiSyncInfo::SyncRecFilterPresetType syncRecFilterPreset() const { return _syncRecFilterPreset; }
305       void setSyncRecFilterPreset(MidiSyncInfo::SyncRecFilterPresetType type);
recTempoValQuant()306       double recTempoValQuant() const { return _tempoQuantizeAmount; }
setRecTempoValQuant(double q)307       void setRecTempoValQuant(double q) { _tempoQuantizeAmount = q; }
308 };
309 
310 } // namespace MusECore
311 
312 namespace MusEGlobal {
313 
314 extern bool debugSync;
315 
316 extern int mtcType;
317 extern MusECore::MTC mtcOffset;
318 extern bool extSyncFlag;
319 extern bool timebaseMasterState;
320 extern bool timebaseMasterForceFlag;
321 extern unsigned int syncSendFirstClockDelay; // In milliseconds.
322 extern unsigned int volatile lastExtMidiSyncTick;
323 extern unsigned int volatile curExtMidiSyncTick;
324 extern MusECore::MidiSyncInfo::SyncRecFilterPresetType syncRecFilterPreset;
325 extern double syncRecTempoValQuant;
326 
327 extern MusECore::MidiSyncContainer midiSyncContainer;
328 
329 } // namespace MusEGlobal
330 
331 #endif
332 
333