diff options
Diffstat (limited to 'attic/muse2-oom/muse2/muse/sync.cpp')
-rw-r--r-- | attic/muse2-oom/muse2/muse/sync.cpp | 1395 |
1 files changed, 0 insertions, 1395 deletions
diff --git a/attic/muse2-oom/muse2/muse/sync.cpp b/attic/muse2-oom/muse2/muse/sync.cpp deleted file mode 100644 index 9fe5f4d3..00000000 --- a/attic/muse2-oom/muse2/muse/sync.cpp +++ /dev/null @@ -1,1395 +0,0 @@ -//========================================================= -// MusE -// Linux Music Editor -// $Id: sync.cpp,v 1.6.2.12 2009/06/20 22:20:41 terminator356 Exp $ -// -// (C) Copyright 2003 Werner Schweer (ws@seh.de) -//========================================================= - -#include <cmath> -#include "sync.h" -#include "song.h" -#include "utils.h" -#include "midiport.h" -#include "mididev.h" -#include "globals.h" -#include "midiseq.h" -#include "audio.h" -#include "audiodev.h" -//#include "driver/audiodev.h" // p4.0.2 -#include "gconfig.h" -#include "xml.h" -#include "midi.h" - -//int rxSyncPort = -1; // receive from all ports -//int txSyncPort = 1; -//int rxDeviceId = 0x7f; // any device -//int txDeviceId = 0x7f; // any device -//MidiSyncPort midiSyncPorts[MIDI_PORTS]; -int volatile curMidiSyncInPort = -1; - -bool debugSync = true; - -int mtcType = 1; -MTC mtcOffset; -BValue extSyncFlag(0, "extSync"); // false - MASTER, true - SLAVE -//bool genMTCSync = false; // output MTC Sync -//bool genMCSync = false; // output MidiClock Sync -//bool genMMC = false; // output Midi Machine Control -//bool acceptMTC = false; -//bool acceptMC = true; -//bool acceptMMC = true; -BValue useJackTransport(0,"useJackTransport"); -bool volatile jackTransportMaster = true; - -static MTC mtcCurTime; -static int mtcState; // 0-7 next expected quarter message -static bool mtcValid; -static int mtcLost; -static bool mtcSync; // receive complete mtc frame? - -// p3.3.28 -static bool playPendingFirstClock = false; -unsigned int syncSendFirstClockDelay = 1; // In milliseconds. -//static int lastStoppedBeat = 0; -static unsigned int curExtMidiSyncTick = 0; -unsigned int volatile lastExtMidiSyncTick = 0; -double volatile curExtMidiSyncTime = 0.0; -double volatile lastExtMidiSyncTime = 0.0; - -// Not used yet. -// static bool mcStart = false; -// static int mcStartTick; - -// p3.3.25 -// From the "Introduction to the Volatile Keyword" at Embedded dot com -/* A variable should be declared volatile whenever its value could change unexpectedly. - ... <such as> global variables within a multi-threaded application - ... So all shared global variables should be declared volatile */ -unsigned int volatile midiExtSyncTicks = 0; - -//--------------------------------------------------------- -// MidiSyncInfo -//--------------------------------------------------------- - -MidiSyncInfo::MidiSyncInfo() -{ - _port = -1; - _idOut = 127; - _idIn = 127; - _sendMC = false; - _sendMRT = false; - _sendMMC = false; - _sendMTC = false; - _recMC = false; - _recMRT = false; - _recMMC = false; - _recMTC = false; - - _lastClkTime = 0.0; - _lastTickTime = 0.0; - _lastMRTTime = 0.0; - _lastMMCTime = 0.0; - _lastMTCTime = 0.0; - _clockTrig = false; - _tickTrig = false; - _MRTTrig = false; - _MMCTrig = false; - _MTCTrig = false; - _clockDetect = false; - _tickDetect = false; - _MRTDetect = false; - _MMCDetect = false; - _MTCDetect = false; - _recMTCtype = 0; - _recRewOnStart = true; - //_sendContNotStart = false; - _actDetectBits = 0; - for(int i = 0; i < MIDI_CHANNELS; ++i) - { - _lastActTime[i] = 0.0; - _actTrig[i] = false; - _actDetect[i] = false; - } -} - -//--------------------------------------------------------- -// operator = -//--------------------------------------------------------- - -MidiSyncInfo& MidiSyncInfo::operator=(const MidiSyncInfo &sp) -{ - //_port = sp._port; - - copyParams(sp); - - _lastClkTime = sp._lastClkTime; - _lastTickTime = sp._lastTickTime; - _lastMRTTime = sp._lastMRTTime; - _lastMMCTime = sp._lastMMCTime; - _lastMTCTime = sp._lastMTCTime; - _clockTrig = sp._clockTrig; - _tickTrig = sp._tickTrig; - _MRTTrig = sp._MRTTrig; - _MMCTrig = sp._MMCTrig; - _MTCTrig = sp._MTCTrig; - _clockDetect = sp._clockDetect; - _tickDetect = sp._tickDetect; - _MRTDetect = sp._MRTDetect; - _MMCDetect = sp._MMCDetect; - _MTCDetect = sp._MTCDetect; - _recMTCtype = sp._recMTCtype; - for(int i = 0; i < MIDI_CHANNELS; ++i) - { - _lastActTime[i] = sp._lastActTime[i]; - _actTrig[i] = sp._actTrig[i]; - _actDetect[i] = sp._actDetect[i]; - } - return *this; -} - -//--------------------------------------------------------- -// copyParams -//--------------------------------------------------------- - -MidiSyncInfo& MidiSyncInfo::copyParams(const MidiSyncInfo &sp) -{ - //_port = sp._port; - - _idOut = sp._idOut; - _idIn = sp._idIn; - _sendMC = sp._sendMC; - _sendMRT = sp._sendMRT; - _sendMMC = sp._sendMMC; - _sendMTC = sp._sendMTC; - setMCIn(sp._recMC); - _recMRT = sp._recMRT; - _recMMC = sp._recMMC; - _recMTC = sp._recMTC; - _recRewOnStart = sp._recRewOnStart; - //_sendContNotStart = sp._sendContNotStart; - return *this; -} - -//--------------------------------------------------------- -// setTime -//--------------------------------------------------------- - -void MidiSyncInfo::setTime() -{ - // Note: CurTime() makes a system call to gettimeofday(), - // which apparently can be slow in some cases. So I avoid calling this function - // too frequently by calling it (at the heartbeat rate) in Song::beat(). T356 - double t = curTime(); - - if(_clockTrig) - { - _clockTrig = false; - _lastClkTime = t; - } - else - if(_clockDetect && (t - _lastClkTime >= 1.0)) // Set detect indicator timeout to about 1 second. - { - _clockDetect = false; - // Give up the current midi sync in port number if we took it... - if(curMidiSyncInPort == _port) - curMidiSyncInPort = -1; - } - - if(_tickTrig) - { - _tickTrig = false; - _lastTickTime = t; - } - else - if(_tickDetect && (t - _lastTickTime) >= 1.0) // Set detect indicator timeout to about 1 second. - _tickDetect = false; - - if(_MRTTrig) - { - _MRTTrig = false; - _lastMRTTime = t; - } - else - if(_MRTDetect && (t - _lastMRTTime) >= 1.0) // Set detect indicator timeout to about 1 second. - { - _MRTDetect = false; - // Give up the current midi sync in port number if we took it... - //if(curMidiSyncInPort == _port) - // curMidiSyncInPort = -1; - } - - if(_MMCTrig) - { - _MMCTrig = false; - _lastMMCTime = t; - } - else - if(_MMCDetect && (t - _lastMMCTime) >= 1.0) // Set detect indicator timeout to about 1 second. - { - _MMCDetect = false; - // Give up the current midi sync in port number if we took it... - //if(curMidiSyncInPort == _port) - // curMidiSyncInPort = -1; - } - - if(_MTCTrig) - { - _MTCTrig = false; - _lastMTCTime = t; - } - else - if(_MTCDetect && (t - _lastMTCTime) >= 1.0) // Set detect indicator timeout to about 1 second. - { - _MTCDetect = false; - // Give up the current midi sync in port number if we took it... - if(curMidiSyncInPort == _port) - curMidiSyncInPort = -1; - } - - for(int i = 0; i < MIDI_CHANNELS; i++) - { - if(_actTrig[i]) - { - _actTrig[i] = false; - _lastActTime[i] = t; - } - else - if(_actDetect[i] && (t - _lastActTime[i]) >= 1.0) // Set detect indicator timeout to about 1 second. - { - _actDetect[i] = false; - //_actDetectBits &= ~bitShiftLU[i]; - _actDetectBits &= ~(1 << i); - } - } -} - -//--------------------------------------------------------- -// setMCIn -//--------------------------------------------------------- - -void MidiSyncInfo::setMCIn(const bool v) -{ - _recMC = v; - // If sync receive was turned off, clear the current midi sync in port number so another port can grab it. - if(!_recMC && _port != -1 && curMidiSyncInPort == _port) - curMidiSyncInPort = -1; -} - -//--------------------------------------------------------- -// setMRTIn -//--------------------------------------------------------- - -void MidiSyncInfo::setMRTIn(const bool v) -{ - _recMRT = v; - // If sync receive was turned off, clear the current midi sync in port number so another port can grab it. - //if(!_recMRT && _port != -1 && curMidiSyncInPort == _port) - // curMidiSyncInPort = -1; -} - -//--------------------------------------------------------- -// setMMCIn -//--------------------------------------------------------- - -void MidiSyncInfo::setMMCIn(const bool v) -{ - _recMMC = v; - // If sync receive was turned off, clear the current midi sync in port number so another port can grab it. - //if(!_recMMC && _port != -1 && curMidiSyncInPort == _port) - // curMidiSyncInPort = -1; -} - -//--------------------------------------------------------- -// setMTCIn -//--------------------------------------------------------- - -void MidiSyncInfo::setMTCIn(const bool v) -{ - _recMTC = v; - // If sync receive was turned off, clear the current midi sync in port number so another port can grab it. - if(!_recMTC && _port != -1 && curMidiSyncInPort == _port) - curMidiSyncInPort = -1; -} - -//--------------------------------------------------------- -// trigMCSyncDetect -//--------------------------------------------------------- - -void MidiSyncInfo::trigMCSyncDetect() -{ - _clockDetect = true; - _clockTrig = true; - // Set the current midi sync in port number if it's not taken... - if(_recMC && curMidiSyncInPort == -1) - curMidiSyncInPort = _port; -} - -//--------------------------------------------------------- -// trigTickDetect -//--------------------------------------------------------- - -void MidiSyncInfo::trigTickDetect() -{ - _tickDetect = true; - _tickTrig = true; -} - -//--------------------------------------------------------- -// trigMRTDetect -//--------------------------------------------------------- - -void MidiSyncInfo::trigMRTDetect() -{ - _MRTDetect = true; - _MRTTrig = true; - // Set the current midi sync in port number if it's not taken... - //if(_recMRT && curMidiSyncInPort == -1) - // curMidiSyncInPort = _port; -} - -//--------------------------------------------------------- -// trigMMCDetect -//--------------------------------------------------------- - -void MidiSyncInfo::trigMMCDetect() -{ - _MMCDetect = true; - _MMCTrig = true; - // Set the current midi sync in port number if it's not taken... - //if(_recMMC && curMidiSyncInPort == -1) - // curMidiSyncInPort = _port; -} - -//--------------------------------------------------------- -// trigMTCDetect -//--------------------------------------------------------- - -void MidiSyncInfo::trigMTCDetect() -{ - _MTCDetect = true; - _MTCTrig = true; - // Set the current midi sync in port number if it's not taken... - if(_recMTC && curMidiSyncInPort == -1) - curMidiSyncInPort = _port; -} - -//--------------------------------------------------------- -// actDetect -//--------------------------------------------------------- - -bool MidiSyncInfo::actDetect(const int ch) const -{ - if(ch < 0 || ch >= MIDI_CHANNELS) - return false; - - return _actDetect[ch]; -} - -//--------------------------------------------------------- -// trigActDetect -//--------------------------------------------------------- - -void MidiSyncInfo::trigActDetect(const int ch) -{ - if(ch < 0 || ch >= MIDI_CHANNELS) - return; - - //_actDetectBits |= bitShiftLU[ch]; - _actDetectBits |= (1 << ch); - _actDetect[ch] = true; - _actTrig[ch] = true; -} - -//--------------------------------------------------------- -// isDefault -//--------------------------------------------------------- - -bool MidiSyncInfo::isDefault() const -{ - return(_idOut == 127 && _idIn == 127 && !_sendMC && !_sendMRT && !_sendMMC && !_sendMTC && - /* !_sendContNotStart && */ !_recMC && !_recMRT && !_recMMC && !_recMTC && _recRewOnStart); -} - -//--------------------------------------------------------- -// read -//--------------------------------------------------------- - -void MidiSyncInfo::read(Xml& xml) - { - for (;;) { - Xml::Token token(xml.parse()); - const QString& tag(xml.s1()); - switch (token) { - case Xml::Error: - case Xml::End: - return; - case Xml::TagStart: - if (tag == "idOut") - _idOut = xml.parseInt(); - else if (tag == "idIn") - _idIn = xml.parseInt(); - else if (tag == "sendMC") - _sendMC = xml.parseInt(); - else if (tag == "sendMRT") - _sendMRT = xml.parseInt(); - else if (tag == "sendMMC") - _sendMMC = xml.parseInt(); - else if (tag == "sendMTC") - _sendMTC = xml.parseInt(); - //else if (tag == "sendContNotStart") - // _sendContNotStart = xml.parseInt(); - else if (tag == "recMC") - _recMC = xml.parseInt(); - else if (tag == "recMRT") - _recMRT = xml.parseInt(); - else if (tag == "recMMC") - _recMMC = xml.parseInt(); - else if (tag == "recMTC") - _recMTC = xml.parseInt(); - else if (tag == "recRewStart") - _recRewOnStart = xml.parseInt(); - else - xml.unknown("midiSyncInfo"); - break; - case Xml::TagEnd: - if (tag == "midiSyncInfo") - return; - default: - break; - } - } - } - -//--------------------------------------------------------- -// write -//--------------------------------------------------------- - -//void MidiSyncInfo::write(int level, Xml& xml, MidiDevice* md) -void MidiSyncInfo::write(int level, Xml& xml) -{ - //if(!md) - // return; - - // All defaults? Nothing to write. - //if(_idOut == 127 && _idIn == 127 && !_sendMC && !_sendMRT && !_sendMMC && !_sendMTC && - // /* !_sendContNotStart && */ !_recMC && !_recMRT && !_recMMC && !_recMTC && _recRewOnStart) - // return; - if(isDefault()) - return; - - xml.tag(level++, "midiSyncInfo"); - //xml.intTag(level, "idx", idx); - //xml.intTag(level++, "midiSyncPort", idx); - //xml.tag(level++, "midiSyncInfo idx=\"%d\"", idx); - - //xml.strTag(level, "device", md->name()); - - if(_idOut != 127) - xml.intTag(level, "idOut", _idOut); - if(_idIn != 127) - xml.intTag(level, "idIn", _idIn); - - if(_sendMC) - xml.intTag(level, "sendMC", true); - if(_sendMRT) - xml.intTag(level, "sendMRT", true); - if(_sendMRT) - xml.intTag(level, "sendMMC", true); - if(_sendMTC) - xml.intTag(level, "sendMTC", true); - //if(_sendContNotStart) - // xml.intTag(level, "sendContNotStart", true); - - if(_recMC) - xml.intTag(level, "recMC", true); - if(_recMRT) - xml.intTag(level, "recMRT", true); - if(_recMMC) - xml.intTag(level, "recMMC", true); - if(_recMTC) - xml.intTag(level, "recMTC", true); - if(!_recRewOnStart) - xml.intTag(level, "recRewStart", false); - - xml.etag(level, "midiSyncInfo"); -} - -//--------------------------------------------------------- -// mmcInput -// Midi Machine Control Input received -//--------------------------------------------------------- - -//void MidiSeq::mmcInput(const unsigned char* p, int n) -void MidiSeq::mmcInput(int port, const unsigned char* p, int n) - { - if (debugSync) - printf("mmcInput: n:%d %02x %02x %02x %02x\n", - n, p[2], p[3], p[4], p[5]); - - MidiPort* mp = &midiPorts[port]; - MidiSyncInfo& msync = mp->syncInfo(); - // Trigger MMC detect in. - msync.trigMMCDetect(); - // MMC locate SMPTE time code may contain format type bits. Grab them. - if(p[3] == 0x44 && p[4] == 6 && p[5] == 1) - msync.setRecMTCtype((p[6] >> 5) & 3); - - // MMC in not turned on? Forget it. - if(!msync.MMCIn()) - return; - - //if (!(extSyncFlag.value() && acceptMMC)) - //if(!extSyncFlag.value()) - // return; - - switch(p[3]) { - case 1: - if (debugSync) - printf(" MMC: STOP\n"); - - playPendingFirstClock = false; - - //if ((state == PLAY || state == PRECOUNT)) - if (audio->isPlaying()) - audio->msgPlay(false); - playStateExt = false; - alignAllTicks(); - //stopPlay(); - break; - case 2: - if (debugSync) - printf(" MMC: PLAY\n"); - case 3: - if (debugSync) - printf(" MMC: DEFERRED PLAY\n"); - mtcState = 0; - mtcValid = false; - mtcLost = 0; - mtcSync = false; - //startPlay(); - alignAllTicks(); - audio->msgPlay(true); - playStateExt = true; - break; - - case 4: - printf("MMC: FF not implemented\n"); - playPendingFirstClock = false; - break; - case 5: - printf("MMC: REWIND not implemented\n"); - playPendingFirstClock = false; - break; - case 6: - printf("MMC: REC STROBE not implemented\n"); - playPendingFirstClock = false; - break; - case 7: - printf("MMC: REC EXIT not implemented\n"); - playPendingFirstClock = false; - break; - case 0xd: - printf("MMC: RESET not implemented\n"); - playPendingFirstClock = false; - break; - case 0x44: - if (p[5] == 0) { - printf("MMC: LOCATE IF not implemented\n"); - break; - } - else if (p[5] == 1) { - if (!checkAudioDevice()) return; - MTC mtc(p[6] & 0x1f, p[7], p[8], p[9], p[10]); - int type = (p[6] >> 5) & 3; - //int mmcPos = tempomap.frame2tick(lrint(mtc.time()*sampleRate)); - //int mmcPos = lrint(mtc.time()*sampleRate); - int mmcPos = lrint(mtc.time(type) * sampleRate); - - //Pos tp(mmcPos, true); - Pos tp(mmcPos, false); - //audioDevice->seekTransport(tp.frame()); - audioDevice->seekTransport(tp); - alignAllTicks(); - //seek(tp); - if (debugSync) { - //printf("MMC: %f %d seek ", mtc.time(), mmcPos); - printf("MMC: LOCATE mtc type:%d time:%lf frame:%d mtc: ", type, mtc.time(), mmcPos); - mtc.print(); - printf("\n"); - } - //write(sigFd, "G", 1); - break; - } - // fall through - default: - printf("MMC %x %x, unknown\n", p[3], p[4]); break; - } - } - -//--------------------------------------------------------- -// mtcInputQuarter -// process Quarter Frame Message -//--------------------------------------------------------- - -//void MidiSeq::mtcInputQuarter(int, unsigned char c) -void MidiSeq::mtcInputQuarter(int port, unsigned char c) - { - static int hour, min, sec, frame; - - // p3.3.28 - //printf("MidiSeq::mtcInputQuarter c:%h\n", c); - - int valL = c & 0xf; - int valH = valL << 4; - - int _state = (c & 0x70) >> 4; - if (mtcState != _state) - mtcLost += _state - mtcState; - mtcState = _state + 1; - - switch(_state) { - case 7: - hour = (hour & 0x0f) | valH; - break; - case 6: - hour = (hour & 0xf0) | valL; - break; - case 5: - min = (min & 0x0f) | valH; - break; - case 4: - min = (min & 0xf0) | valL; - break; - case 3: - sec = (sec & 0x0f) | valH; - break; - case 2: - sec = (sec & 0xf0) | valL; - break; - case 1: - frame = (frame & 0x0f) | valH; - break; - case 0: frame = (frame & 0xf0) | valL; - break; - } - frame &= 0x1f; // 0-29 - sec &= 0x3f; // 0-59 - min &= 0x3f; // 0-59 - int tmphour = hour; - int type = (hour >> 5) & 3; - hour &= 0x1f; - - if(mtcState == 8) - { - mtcValid = (mtcLost == 0); - mtcState = 0; - mtcLost = 0; - if(mtcValid) - { - mtcCurTime.set(hour, min, sec, frame); - if(port != -1) - { - MidiPort* mp = &midiPorts[port]; - MidiSyncInfo& msync = mp->syncInfo(); - msync.setRecMTCtype(type); - msync.trigMTCDetect(); - // Not for the current in port? External sync not turned on? MTC in not turned on? Forget it. - if(port == curMidiSyncInPort && extSyncFlag.value() && msync.MTCIn()) - { - if(debugSync) - printf("MidiSeq::mtcInputQuarter hour byte:%hx\n", tmphour); - mtcSyncMsg(mtcCurTime, type, !mtcSync); - } - } - mtcSync = true; - } - } - else if (mtcValid && (mtcLost == 0)) - { - //mtcCurTime.incQuarter(); - mtcCurTime.incQuarter(type); - //mtcSyncMsg(mtcCurTime, type, false); - } - } - -//--------------------------------------------------------- -// mtcInputFull -// process Frame Message -//--------------------------------------------------------- - -//void MidiSeq::mtcInputFull(const unsigned char* p, int n) -void MidiSeq::mtcInputFull(int port, const unsigned char* p, int n) - { - if (debugSync) - printf("mtcInputFull\n"); - //if (!extSyncFlag.value()) - // return; - - if (p[3] != 1) { - if (p[3] != 2) { // silently ignore user bits - printf("unknown mtc msg subtype 0x%02x\n", p[3]); - dump(p, n); - } - return; - } - int hour = p[4]; - int min = p[5]; - int sec = p[6]; - int frame = p[7]; - - frame &= 0x1f; // 0-29 - sec &= 0x3f; // 0-59 - min &= 0x3f; // 0-59 - int type = (hour >> 5) & 3; - hour &= 0x1f; - - mtcCurTime.set(hour, min, sec, frame); - mtcState = 0; - mtcValid = true; - mtcLost = 0; - - // Added by Tim. - if(debugSync) - printf("mtcInputFull: time:%lf stime:%lf hour byte (all bits):%hx\n", mtcCurTime.time(), mtcCurTime.time(type), p[4]); - if(port != -1) - { - MidiPort* mp = &midiPorts[port]; - MidiSyncInfo& msync = mp->syncInfo(); - msync.setRecMTCtype(type); - msync.trigMTCDetect(); - // MTC in not turned on? Forget it. - //if(extSyncFlag.value() && msync.MTCIn()) - if(msync.MTCIn()) - { - //Pos tp(lrint(mtcCurTime.time() * sampleRate), false); - Pos tp(lrint(mtcCurTime.time(type) * sampleRate), false); - audioDevice->seekTransport(tp); - alignAllTicks(); - } - } - } - -//--------------------------------------------------------- -// nonRealtimeSystemSysex -//--------------------------------------------------------- - -//void MidiSeq::nonRealtimeSystemSysex(const unsigned char* p, int n) -void MidiSeq::nonRealtimeSystemSysex(int /*port*/, const unsigned char* p, int n) - { -// int chan = p[2]; - switch(p[3]) { - case 4: - printf("NRT Setup\n"); - break; - default: - printf("unknown NRT Msg 0x%02x\n", p[3]); - dump(p, n); - break; - } - } - -//--------------------------------------------------------- -// setSongPosition -// MidiBeat is a 14 Bit value. Each MidiBeat spans -// 6 MIDI Clocks. Inother words, each MIDI Beat is a -// 16th note (since there are 24 MIDI Clocks in a -// quarter note). -//--------------------------------------------------------- - -void MidiSeq::setSongPosition(int port, int midiBeat) - { - if (midiInputTrace) - printf("set song position port:%d %d\n", port, midiBeat); - - //midiPorts[port].syncInfo().trigMCSyncDetect(); - midiPorts[port].syncInfo().trigMRTDetect(); - - //if (!extSyncFlag.value()) - // External sync not on? Clock in not turned on? - //if(!extSyncFlag.value() || !midiPorts[port].syncInfo().MCIn()) - if(!extSyncFlag.value() || !midiPorts[port].syncInfo().MRTIn()) - return; - - // Re-transmit song position to other devices if clock out turned on. - for(int p = 0; p < MIDI_PORTS; ++p) - //if(p != port && midiPorts[p].syncInfo().MCOut()) - if(p != port && midiPorts[p].syncInfo().MRTOut()) - midiPorts[p].sendSongpos(midiBeat); - - curExtMidiSyncTick = (config.division * midiBeat) / 4; - lastExtMidiSyncTick = curExtMidiSyncTick; - - //Pos pos((config.division * midiBeat) / 4, true); - Pos pos(curExtMidiSyncTick, true); - - if (!checkAudioDevice()) return; - - //audioDevice->seekTransport(pos.frame()); - audioDevice->seekTransport(pos); - alignAllTicks(pos.frame()); - if (debugSync) - printf("setSongPosition %d\n", pos.tick()); - } - - - -//--------------------------------------------------------- -// set all runtime variables to the "in sync" value -//--------------------------------------------------------- -void MidiSeq::alignAllTicks(int frameOverride) - { - //printf("alignAllTicks audioDriver->framePos=%d, audio->pos().frame()=%d\n", - // audioDevice->framePos(), audio->pos().frame()); - unsigned curFrame; - if (!frameOverride) - curFrame = audio->pos().frame(); - else - curFrame = frameOverride; - - int tempo = tempomap.tempo(0); - - // use the last old values to give start values for the tripple buffering - int recTickSpan = recTick1 - recTick2; - int songTickSpan = (int)(songtick1 - songtick2); //prevent compiler warning: casting double to int - storedtimediffs = 0; // pretend there is no sync history - - mclock2=mclock1=0.0; // set all clock values to "in sync" - - recTick = (int) ((double(curFrame)/double(sampleRate)) * - double(config.division * 1000000.0) / double(tempo) //prevent compiler warning: casting double to int - ); - songtick1 = recTick - songTickSpan; - if (songtick1 < 0) - songtick1 = 0; - songtick2 = songtick1 - songTickSpan; - if (songtick2 < 0) - songtick2 = 0; - recTick1 = recTick - recTickSpan; - if (recTick1 < 0) - recTick1 = 0; - recTick2 = recTick1 - recTickSpan; - if (recTick2 < 0) - recTick2 = 0; - if (debugSync) - printf("alignAllTicks curFrame=%d recTick=%d tempo=%.3f frameOverride=%d\n",curFrame,recTick,(float)((1000000.0 * 60.0)/tempo), frameOverride); - - } - -//--------------------------------------------------------- -// realtimeSystemInput -// real time message received -//--------------------------------------------------------- -void MidiSeq::realtimeSystemInput(int port, int c) - { - - if (midiInputTrace) - printf("realtimeSystemInput port:%d 0x%x\n", port+1, c); - - //if (midiInputTrace && (rxSyncPort != port) && rxSyncPort != -1) { - // if (debugSync) - // printf("rxSyncPort configured as %d; received sync from port %d\n", - // rxSyncPort, port); - // return; - // } - - MidiPort* mp = &midiPorts[port]; - - // Trigger on any tick, clock, or realtime command. - if(c == ME_TICK) // Tick - mp->syncInfo().trigTickDetect(); - else - if(c == ME_CLOCK) // Clock - mp->syncInfo().trigMCSyncDetect(); - else - mp->syncInfo().trigMRTDetect(); // Other - - // External sync not on? Clock in not turned on? Otherwise realtime in not turned on? - if(!extSyncFlag.value()) - return; - if(c == ME_CLOCK) - { - if(!mp->syncInfo().MCIn()) - return; - } - else - if(!mp->syncInfo().MRTIn()) - return; - - - switch(c) { - case ME_CLOCK: // midi clock (24 ticks / quarter note) - { - // Not for the current in port? Forget it. - if(port != curMidiSyncInPort) - break; - - // p3.3.31 - //printf("midi clock:%f\n", curTime()); - - // Re-transmit clock to other devices if clock out turned on. - // Must be careful not to allow more than one clock input at a time. - // Would re-transmit mixture of multiple clocks - confusing receivers. - // Solution: Added curMidiSyncInPort. - // Maybe in MidiSeq::processTimerTick(), call sendClock for the other devices, instead of here. - for(int p = 0; p < MIDI_PORTS; ++p) - if(p != port && midiPorts[p].syncInfo().MCOut()) - midiPorts[p].sendClock(); - - // p3.3.28 - if(playPendingFirstClock) - { - playPendingFirstClock = false; - // Hopefully the transport will be ready by now, the seek upon start should mean the - // audio prefetch has already finished or at least started... - // Must comfirm that play does not force a complete prefetch again, but don't think so... - if(!audio->isPlaying()) - audioDevice->startTransport(); - } - //else - // This part will be run on the second and subsequent clocks, after start. - // Can't check audio state, might not be playing yet, we might miss some increments. - //if(audio->isPlaying()) - if(playStateExt) - { - lastExtMidiSyncTime = curExtMidiSyncTime; - curExtMidiSyncTime = curTime(); - int div = config.division/24; - midiExtSyncTicks += div; - lastExtMidiSyncTick = curExtMidiSyncTick; - curExtMidiSyncTick += div; - } - -//BEGIN : Original code: - /* - double mclock0 = curTime(); - // Difference in time last 2 rounds: - double tdiff0 = mclock0 - mclock1; - double tdiff1 = mclock1 - mclock2; - double averagetimediff = 0.0; - - if (mclock1 != 0.0) { - if (storedtimediffs < 24) - { - timediff[storedtimediffs] = mclock0 - mclock1; - storedtimediffs++; - } - else { - for (int i=0; i<23; i++) { - timediff[i] = timediff[i+1]; - } - timediff[23] = mclock0 - mclock1; - } - // Calculate average timediff: - for (int i=0; i < storedtimediffs; i++) { - averagetimediff += timediff[i]/storedtimediffs; - } - } - - // Compare w audio if playing: - if (playStateExt == true ) { //audio->isPlaying() state == PLAY - //BEGIN standard setup: - recTick += config.division / 24; // The one we're syncing to - int tempo = tempomap.tempo(0); - unsigned curFrame = audio->pos().frame(); - double songtick = (double(curFrame)/double(sampleRate)) * - double(config.division * 1000000.0) / double(tempo); - - double scale = double(tdiff0/averagetimediff); - double tickdiff = songtick - ((double) recTick - 24 + scale*24.0); - - //END standard setup - if (debugSync) { - int m, b, t; - audio->pos().mbt(&m, &b, &t); - - int song_beat = b + m*4; // if the time-signature is different than 4/4, this will be wrong. - int sync_beat = recTick/config.division; - printf("pT=%.3f rT=%d diff=%.3f songB=%d syncB=%d scale=%.3f, curFrame=%d", - songtick, recTick, tickdiff, song_beat, sync_beat, scale, curFrame); - } - - //if ((mclock2 !=0.0) && (tdiff1 > 0.0) && fabs(tickdiff) > 0.5 && lastTempo != 0) { - if ((mclock2 !=0.0) && (tdiff1 > 0.0) && lastTempo != 0) { - // Interpolate: - double tickdiff1 = songtick1 - recTick1; - double tickdiff2 = songtick2 - recTick2; - double newtickdiff = (tickdiff1+tickdiff2)/250; - //tickdiff/5.0 + - tickdiff1/16.0 + - tickdiff2/24.0; //5 mins 30 secs on 116BPM, -p 512 jackd - - if (newtickdiff != 0.0) { - int newTempo = tempomap.tempo(0); - //newTempo += int(24.0 * newtickdiff * scale); - newTempo += int(24.0 * newtickdiff); - if (debugSync) - printf(" tdiff=%f ntd=%f lt=%d tmpo=%.3f", - tdiff0, newtickdiff, lastTempo, (float)((1000000.0 * 60.0)/newTempo)); - //syncTempo = newTempo; - tempomap.setTempo(0,newTempo); - } - if (debugSync) - printf("\n"); - } - else if (debugSync) - printf("\n"); - - //BEGIN post calc - lastTempo = tempo; - recTick2 = recTick1; - recTick1 = recTick; - mclock2 = mclock1; - mclock1 = mclock0; - songtick2 = songtick1; - songtick1 = songtick; - //END post calc - break; - } // END state play - // - // Pre-sync (when audio is not running) - // Calculate tempo depending on time per pulse - // - if (mclock1 == 0.0) { - mp->device()->discardInput(); - if (debugSync) - printf("Discarding input from port %d\n", port); - } - if ((mclock2 != 0.0) && (tdiff0 > 0.0)) { - int tempo0 = int(24000000.0 * tdiff0 + .5); - int tempo1 = int(24000000.0 * tdiff1 + .5); - int tempo = tempomap.tempo(0); - - int diff0 = tempo0 - tempo; - int diff1 = tempo1 - tempo0; - if (diff0) { - int newTempo = tempo + diff0/8 + diff1/16; - if (debugSync) - printf("setting new tempo %d = %f\n", newTempo, (float)((1000000.0 * 60.0)/newTempo)); - tempomap.setTempo(0, newTempo); - } - } - mclock2 = mclock1; - mclock1 = mclock0; - */ -//END : Original Code - -//BEGIN : Using external tempo map: - /* - double mclock0 = curTime(); - // Difference in time last 2 rounds: - double tdiff0 = mclock0 - mclock1; - double tdiff1 = mclock1 - mclock2; - double averagetimediff = 0.0; - - if (mclock1 != 0.0) { - if (storedtimediffs < 24) - { - timediff[storedtimediffs] = mclock0 - mclock1; - storedtimediffs++; - } - else { - for (int i=0; i<23; i++) { - timediff[i] = timediff[i+1]; - } - timediff[23] = mclock0 - mclock1; - } - // Calculate average timediff: - for (int i=0; i < storedtimediffs; i++) { - averagetimediff += timediff[i]/storedtimediffs; - } - } - - // Compare w audio if playing: - //if (playStateExt == true ) { //audio->isPlaying() state == PLAY - if (0) { - //BEGIN standard setup: - recTick += config.division / 24; // The one we're syncing to - int tempo = tempomap.tempo(0); - //unsigned curFrame = audio->pos().frame(); - //double songtick = (double(curFrame)/double(sampleRate)) * - // double(config.division * 1000000.0) / double(tempo); - double songtick = tempomap.curTickExt(mclock0); - - double scale = double(tdiff0/averagetimediff); - double tickdiff = songtick - ((double) recTick - 24 + scale*24.0); - - //END standard setup - if (debugSync) { - int m, b, t; - audio->pos().mbt(&m, &b, &t); - - int song_beat = b + m*4; // if the time-signature is different than 4/4, this will be wrong. - int sync_beat = recTick/config.division; - printf("pT=%.3f rT=%d diff=%.3f songB=%d syncB=%d scale=%.3f, curFrame=%d averagetimediff:%.3lf", - songtick, recTick, tickdiff, song_beat, sync_beat, scale, audio->pos().frame(), averagetimediff); - } - - //if ((mclock2 !=0.0) && (tdiff1 > 0.0) && fabs(tickdiff) > 0.5 && lastTempo != 0) { - if ((mclock2 !=0.0) && (tdiff1 > 0.0) && lastTempo != 0) { - // Interpolate: - double tickdiff1 = songtick1 - recTick1; - double tickdiff2 = songtick2 - recTick2; - double newtickdiff = (tickdiff1+tickdiff2)/250; - ////double newtickdiff = (tickdiff1+tickdiff2) / 10.0; - //double newtickdiff = tickdiff/5.0 + - // tickdiff1/16.0 + - // tickdiff2/24.0; //5 mins 30 secs on 116BPM, -p 512 jackd - - if (newtickdiff != 0.0) { - //int newTempo = tempomap.tempo(0); - int newTempo = tempo; - //newTempo += int(24.0 * newtickdiff * scale); - newTempo += int(24.0 * newtickdiff); - if (debugSync) - printf(" tdiff=%f ntd=%f lt=%d tmpo=%.3f", - tdiff0, newtickdiff, lastTempo, (float)((1000000.0 * 60.0)/newTempo)); - //syncTempo = newTempo; - //tempomap.setTempo(0,newTempo); - // Don't set the last stable tempo. - //tempomap.setTempo(0, newTempo, false); - tempomap.setExtTempo(newTempo); - } - if (debugSync) - printf("\n"); - } - else if (debugSync) - printf("\n"); - - //BEGIN post calc - lastTempo = tempo; - recTick2 = recTick1; - recTick1 = recTick; - mclock2 = mclock1; - mclock1 = mclock0; - songtick2 = songtick1; - songtick1 = songtick; - //END post calc - break; - } // END state play - // - // Pre-sync (when audio is not running) - // Calculate tempo depending on time per pulse - // - if (mclock1 == 0.0) { - mp->device()->discardInput(); - if (debugSync) - printf("Discarding input from port %d\n", port); - } - if ((mclock2 != 0.0) && (tdiff0 > 0.0)) { - - //int tempo0 = int(24000000.0 * tdiff0 + .5); - //int tempo1 = int(24000000.0 * tdiff1 + .5); - //int tempo = tempomap.tempo(0); - //int diff0 = tempo0 - tempo; - //int diff1 = tempo1 - tempo0; - - //if (diff0) { - // int newTempo = tempo + diff0/8 + diff1/16; - // if (debugSync) - // printf("setting new tempo %d = %f\n", newTempo, (float)((1000000.0 * 60.0)/newTempo)); - //tempomap.setTempo(0, newTempo); - // Don't set the last stable tempo. - //tempomap.setTempo(0, newTempo, false); - // tempomap.setExtTempo(newTempo); - // } - - //double tempo0 = 24000000.0 * tdiff0; - //double tempo1 = 24000000.0 * tdiff1; - //int newTempo = int((tempo0 + tempo1) / 2.0); - int newTempo = int(averagetimediff * 24000000.0); - if(debugSync) - printf("setting new tempo %d = %f\n", newTempo, (float)((1000000.0 * 60.0)/newTempo)); - tempomap.setExtTempo(newTempo); - } - - mclock2 = mclock1; - mclock1 = mclock0; - */ -//END : Using external tempo map - - } - break; - case ME_TICK: // midi tick (every 10 msec) - // FIXME: Unfinished? mcStartTick is uninitialized and Song::setPos doesn't set it either. Dangerous to allow this. - //if (mcStart) { - // song->setPos(0, mcStartTick); - // mcStart = false; - // return; - // } - break; - case ME_START: // start - // Re-transmit start to other devices if clock out turned on. - for(int p = 0; p < MIDI_PORTS; ++p) - //if(p != port && midiPorts[p].syncInfo().MCOut()) - if(p != port && midiPorts[p].syncInfo().MRTOut()) - { - // p3.3.31 - // If we aren't rewinding on start, there's no point in re-sending start. - // Re-send continue instead, for consistency. - if(midiPorts[port].syncInfo().recRewOnStart()) - midiPorts[p].sendStart(); - else - midiPorts[p].sendContinue(); - } - if (debugSync) - printf(" start\n"); - - // p3.3.31 - //printf("midi start:%f\n", curTime()); - - if (1 /* !audio->isPlaying()*/ /*state == IDLE*/) { - if (!checkAudioDevice()) return; - - // p3.3.31 - // Rew on start option. - if(midiPorts[port].syncInfo().recRewOnStart()) - { - curExtMidiSyncTick = 0; - lastExtMidiSyncTick = curExtMidiSyncTick; - //audioDevice->seekTransport(0); - audioDevice->seekTransport(Pos(0, false)); - } - - //unsigned curFrame = audio->curFrame(); - //if (debugSync) - // printf(" curFrame=%d\n", curFrame); - - alignAllTicks(); - //if (debugSync) - // printf(" curFrame: %d curTick: %d tempo: %d\n", curFrame, recTick, tempomap.tempo(0)); - - storedtimediffs = 0; - for (int i=0; i<24; i++) - timediff[i] = 0.0; - - // p3.3.26 1/23/10 - // Changed because msgPlay calls audioDevice->seekTransport(song->cPos()) - // and song->cPos() may not be changed to 0 yet, causing tranport not to go to 0. - //audio->msgPlay(true); - //audioDevice->startTransport(); - // p3.3.28 - playPendingFirstClock = true; - - midiExtSyncTicks = 0; - playStateExt = true; - } - break; - case ME_CONTINUE: // continue - // Re-transmit continue to other devices if clock out turned on. - for(int p = 0; p < MIDI_PORTS; ++p) - //if(p != port && midiPorts[p].syncInfo().MCOut()) - if(p != port && midiPorts[p].syncInfo().MRTOut()) - midiPorts[p].sendContinue(); - - if (debugSync) - printf("realtimeSystemInput continue\n"); - - // p3.3.31 - //printf("continue:%f\n", curTime()); - - if (1 /* !audio->isPlaying() */ /*state == IDLE */) { - //unsigned curFrame = audio->curFrame(); - //recTick = tempomap.frame2tick(curFrame); // don't think this will work... (ml) - //alignAllTicks(); - - // p3.3.28 - //audio->msgPlay(true); - // p3.3.31 - // Begin incrementing immediately upon first clock reception. - playPendingFirstClock = true; - - playStateExt = true; - } - break; - case ME_STOP: // stop - { - // p3.3.35 - // Stop the increment right away. - midiExtSyncTicks = 0; - playStateExt = false; - playPendingFirstClock = false; - - // Re-transmit stop to other devices if clock out turned on. - for(int p = 0; p < MIDI_PORTS; ++p) - //if(p != port && midiPorts[p].syncInfo().MCOut()) - if(p != port && midiPorts[p].syncInfo().MRTOut()) - midiPorts[p].sendStop(); - - //playPendingFirstClock = false; - - //lastStoppedBeat = (audio->tickPos() * 4) / config.division; - //curExtMidiSyncTick = (config.division * lastStoppedBeat) / 4; - - // p3.3.31 - //printf("stop:%f\n", curTime()); - - if (audio->isPlaying() /*state == PLAY*/) { - audio->msgPlay(false); - //playStateExt = false; - } - - if (debugSync) - printf("realtimeSystemInput stop\n"); - - // Just in case the process still runs a cycle or two and causes the - // audio tick position to increment, reset the incrementer and force - // the transport position to what the hardware thinks is the current position. - //midiExtSyncTicks = 0; - //Pos pos((config.division * lastStoppedBeat) / 4, true); - //Pos pos(curExtMidiSyncTick, true); - //audioDevice->seekTransport(pos); - } - - break; - //case 0xfd: // unknown - //case ME_SENSE: // active sensing - //case ME_META: // system reset (reset is 0xff same enumeration as file meta event) - default: - break; - } - - } - -//--------------------------------------------------------- -// mtcSyncMsg -// process received mtc Sync -// seekFlag - first complete mtc frame received after -// start -//--------------------------------------------------------- - -void MidiSeq::mtcSyncMsg(const MTC& mtc, int type, bool seekFlag) - { - double time = mtc.time(); - double stime = mtc.time(type); - if (debugSync) - printf("MidiSeq::mtcSyncMsg time:%lf stime:%lf seekFlag:%d\n", time, stime, seekFlag); - - if (seekFlag && audio->isRunning() /*state == START_PLAY*/) { -// int tick = tempomap.time2tick(time); - //state = PLAY; - //write(sigFd, "1", 1); // say PLAY to gui - if (!checkAudioDevice()) return; - if (debugSync) - printf("MidiSeq::mtcSyncMsg starting transport.\n"); - audioDevice->startTransport(); - return; - } - - /*if (tempoSN != tempomap.tempoSN()) { - double cpos = tempomap.tick2time(_midiTick, 0); - samplePosStart = samplePos - lrint(cpos * sampleRate); - rtcTickStart = rtcTick - lrint(cpos * realRtcTicks); - tempoSN = tempomap.tempoSN(); - }*/ - - // - // diff is the time in sec MusE is out of sync - // - /*double diff = time - (double(samplePosStart)/double(sampleRate)); - if (debugSync) - printf(" state %d diff %f\n", mtcState, diff); - */ - } - - |