fix MTC/MIDI clock on playSub
This commit is contained in:
parent
826538e41b
commit
29688d1cc5
|
@ -2208,6 +2208,10 @@ void DivEngine::playSub(bool preserveDrift, int goalRow) {
|
||||||
skipping=false;
|
skipping=false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!preserveDrift) {
|
||||||
|
runMidiClock(cycles);
|
||||||
|
runMidiTime(cycles);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
int oldOrder=curOrder;
|
int oldOrder=curOrder;
|
||||||
while (playing && (curRow<goalRow || ticks>1)) {
|
while (playing && (curRow<goalRow || ticks>1)) {
|
||||||
|
@ -2215,6 +2219,10 @@ void DivEngine::playSub(bool preserveDrift, int goalRow) {
|
||||||
skipping=false;
|
skipping=false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!preserveDrift) {
|
||||||
|
runMidiClock(cycles);
|
||||||
|
runMidiTime(cycles);
|
||||||
|
}
|
||||||
if (oldOrder!=curOrder) break;
|
if (oldOrder!=curOrder) break;
|
||||||
if (ticks-((tempoAccum+curSubSong->virtualTempoN)/MAX(1,curSubSong->virtualTempoD))<1 && curRow>=goalRow) break;
|
if (ticks-((tempoAccum+curSubSong->virtualTempoN)/MAX(1,curSubSong->virtualTempoD))<1 && curRow>=goalRow) break;
|
||||||
}
|
}
|
||||||
|
@ -2237,6 +2245,13 @@ void DivEngine::playSub(bool preserveDrift, int goalRow) {
|
||||||
midiClockDrift=0;
|
midiClockDrift=0;
|
||||||
midiTimeCycles=0;
|
midiTimeCycles=0;
|
||||||
midiTimeDrift=0;
|
midiTimeDrift=0;
|
||||||
|
if (curMidiTime>0) {
|
||||||
|
curMidiTime--;
|
||||||
|
}
|
||||||
|
if (curMidiClock>0) {
|
||||||
|
curMidiClock--;
|
||||||
|
}
|
||||||
|
curMidiTimePiece=0;
|
||||||
}
|
}
|
||||||
if (!preserveDrift) {
|
if (!preserveDrift) {
|
||||||
ticks=1;
|
ticks=1;
|
||||||
|
@ -2448,7 +2463,7 @@ void DivEngine::play() {
|
||||||
// drop
|
// drop
|
||||||
drop=((actualTime/(30*60))-(actualTime/(30*600)))*2;
|
drop=((actualTime/(30*60))-(actualTime/(30*600)))*2;
|
||||||
actualTime+=drop;
|
actualTime+=drop;
|
||||||
|
|
||||||
msgData[5]=(actualTime/(60*60*30))%24;
|
msgData[5]=(actualTime/(60*60*30))%24;
|
||||||
msgData[6]=(actualTime/(60*30))%60;
|
msgData[6]=(actualTime/(60*30))%60;
|
||||||
msgData[7]=(actualTime/30)%60;
|
msgData[7]=(actualTime/30)%60;
|
||||||
|
|
|
@ -475,6 +475,8 @@ class DivEngine {
|
||||||
void recalcChans();
|
void recalcChans();
|
||||||
void reset();
|
void reset();
|
||||||
void playSub(bool preserveDrift, int goalRow=0);
|
void playSub(bool preserveDrift, int goalRow=0);
|
||||||
|
void runMidiClock(int totalCycles=1);
|
||||||
|
void runMidiTime(int totalCycles=1);
|
||||||
|
|
||||||
void testFunction();
|
void testFunction();
|
||||||
|
|
||||||
|
|
|
@ -1546,6 +1546,147 @@ int DivEngine::getBufferPos() {
|
||||||
return bufferPos>>MASTER_CLOCK_PREC;
|
return bufferPos>>MASTER_CLOCK_PREC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivEngine::runMidiClock(int totalCycles) {
|
||||||
|
if (freelance) return;
|
||||||
|
midiClockCycles-=totalCycles;
|
||||||
|
while (midiClockCycles<=0) {
|
||||||
|
curMidiClock++;
|
||||||
|
if (output) if (!skipping && output->midiOut!=NULL && midiOutClock) {
|
||||||
|
output->midiOut->send(TAMidiMessage(TA_MIDI_CLOCK,0,0));
|
||||||
|
}
|
||||||
|
|
||||||
|
double hl=curSubSong->hilightA;
|
||||||
|
if (hl<=0.0) hl=4.0;
|
||||||
|
double timeBase=curSubSong->timeBase+1;
|
||||||
|
double speedSum=0;
|
||||||
|
double vD=curSubSong->virtualTempoD;
|
||||||
|
for (int i=0; i<MIN(16,speeds.len); i++) {
|
||||||
|
speedSum+=speeds.val[i];
|
||||||
|
}
|
||||||
|
speedSum/=MAX(1,speeds.len);
|
||||||
|
if (timeBase<1.0) timeBase=1.0;
|
||||||
|
if (speedSum<1.0) speedSum=1.0;
|
||||||
|
if (vD<1) vD=1;
|
||||||
|
double bpm=((24.0*divider)/(timeBase*hl*speedSum))*(double)curSubSong->virtualTempoN/vD;
|
||||||
|
|
||||||
|
midiClockCycles+=got.rate*pow(2,MASTER_CLOCK_PREC)/(bpm);
|
||||||
|
midiClockDrift+=fmod(got.rate*pow(2,MASTER_CLOCK_PREC),(double)(bpm));
|
||||||
|
if (midiClockDrift>=(bpm)) {
|
||||||
|
midiClockDrift-=(bpm);
|
||||||
|
midiClockCycles++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivEngine::runMidiTime(int totalCycles) {
|
||||||
|
if (freelance) return;
|
||||||
|
midiTimeCycles-=totalCycles;
|
||||||
|
while (midiTimeCycles<=0) {
|
||||||
|
if (curMidiTimePiece==0) {
|
||||||
|
curMidiTimeCode=curMidiTime;
|
||||||
|
}
|
||||||
|
if (!(curMidiTimePiece&3)) curMidiTime++;
|
||||||
|
|
||||||
|
double frameRate=96.0;
|
||||||
|
int timeRate=midiOutTimeRate;
|
||||||
|
if (timeRate<1 || timeRate>4) {
|
||||||
|
if (curSubSong->hz>=47.98 && curSubSong->hz<=48.02) {
|
||||||
|
timeRate=1;
|
||||||
|
} else if (curSubSong->hz>=49.98 && curSubSong->hz<=50.02) {
|
||||||
|
timeRate=2;
|
||||||
|
} else if (curSubSong->hz>=59.9 && curSubSong->hz<=60.11) {
|
||||||
|
timeRate=4;
|
||||||
|
} else {
|
||||||
|
timeRate=4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int hour=0;
|
||||||
|
int minute=0;
|
||||||
|
int second=0;
|
||||||
|
int frame=0;
|
||||||
|
int drop=0;
|
||||||
|
int actualTime=curMidiTimeCode;
|
||||||
|
|
||||||
|
switch (timeRate) {
|
||||||
|
case 1: // 24
|
||||||
|
frameRate=96.0;
|
||||||
|
hour=(actualTime/(60*60*24))%24;
|
||||||
|
minute=(actualTime/(60*24))%60;
|
||||||
|
second=(actualTime/24)%60;
|
||||||
|
frame=actualTime%24;
|
||||||
|
break;
|
||||||
|
case 2: // 25
|
||||||
|
frameRate=100.0;
|
||||||
|
hour=(actualTime/(60*60*25))%24;
|
||||||
|
minute=(actualTime/(60*25))%60;
|
||||||
|
second=(actualTime/25)%60;
|
||||||
|
frame=actualTime%25;
|
||||||
|
break;
|
||||||
|
case 3: // 29.97 (NTSC drop)
|
||||||
|
frameRate=120.0*(1000.0/1001.0);
|
||||||
|
|
||||||
|
// drop
|
||||||
|
drop=((actualTime/(30*60))-(actualTime/(30*600)))*2;
|
||||||
|
actualTime+=drop;
|
||||||
|
|
||||||
|
hour=(actualTime/(60*60*30))%24;
|
||||||
|
minute=(actualTime/(60*30))%60;
|
||||||
|
second=(actualTime/30)%60;
|
||||||
|
frame=actualTime%30;
|
||||||
|
break;
|
||||||
|
case 4: // 30 (NTSC non-drop)
|
||||||
|
default:
|
||||||
|
frameRate=120.0;
|
||||||
|
hour=(actualTime/(60*60*30))%24;
|
||||||
|
minute=(actualTime/(60*30))%60;
|
||||||
|
second=(actualTime/30)%60;
|
||||||
|
frame=actualTime%30;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output) if (!skipping && output->midiOut!=NULL && midiOutTime) {
|
||||||
|
unsigned char val=0;
|
||||||
|
switch (curMidiTimePiece) {
|
||||||
|
case 0:
|
||||||
|
val=frame&15;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
val=frame>>4;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
val=second&15;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
val=second>>4;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
val=minute&15;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
val=minute>>4;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
val=hour&15;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
val=(hour>>4)|((timeRate-1)<<1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
val|=curMidiTimePiece<<4;
|
||||||
|
output->midiOut->send(TAMidiMessage(TA_MIDI_MTC_FRAME,val,0));
|
||||||
|
}
|
||||||
|
curMidiTimePiece=(curMidiTimePiece+1)&7;
|
||||||
|
|
||||||
|
midiTimeCycles+=got.rate*pow(2,MASTER_CLOCK_PREC)/(frameRate);
|
||||||
|
midiTimeDrift+=fmod(got.rate*pow(2,MASTER_CLOCK_PREC),(double)(frameRate));
|
||||||
|
if (midiTimeDrift>=(frameRate)) {
|
||||||
|
midiTimeDrift-=(frameRate);
|
||||||
|
midiTimeCycles++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size) {
|
void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size) {
|
||||||
lastLoopPos=-1;
|
lastLoopPos=-1;
|
||||||
|
|
||||||
|
@ -1833,141 +1974,12 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
||||||
// 3. run MIDI clock
|
// 3. run MIDI clock
|
||||||
int midiTotal=MIN(cycles,runLeftG);
|
int midiTotal=MIN(cycles,runLeftG);
|
||||||
for (int i=0; i<midiTotal; i++) {
|
for (int i=0; i<midiTotal; i++) {
|
||||||
if (--midiClockCycles<=0) {
|
runMidiClock();
|
||||||
curMidiClock++;
|
|
||||||
if (output) if (!skipping && output->midiOut!=NULL && midiOutClock) {
|
|
||||||
output->midiOut->send(TAMidiMessage(TA_MIDI_CLOCK,0,0));
|
|
||||||
}
|
|
||||||
|
|
||||||
double hl=curSubSong->hilightA;
|
|
||||||
if (hl<=0.0) hl=4.0;
|
|
||||||
double timeBase=curSubSong->timeBase+1;
|
|
||||||
double speedSum=0;
|
|
||||||
double vD=curSubSong->virtualTempoD;
|
|
||||||
for (int i=0; i<MIN(16,speeds.len); i++) {
|
|
||||||
speedSum+=speeds.val[i];
|
|
||||||
}
|
|
||||||
speedSum/=MAX(1,speeds.len);
|
|
||||||
if (timeBase<1.0) timeBase=1.0;
|
|
||||||
if (speedSum<1.0) speedSum=1.0;
|
|
||||||
if (vD<1) vD=1;
|
|
||||||
double bpm=((24.0*divider)/(timeBase*hl*speedSum))*(double)curSubSong->virtualTempoN/vD;
|
|
||||||
|
|
||||||
midiClockCycles=got.rate*pow(2,MASTER_CLOCK_PREC)/(bpm);
|
|
||||||
midiClockDrift+=fmod(got.rate*pow(2,MASTER_CLOCK_PREC),(double)(bpm));
|
|
||||||
if (midiClockDrift>=(bpm)) {
|
|
||||||
midiClockDrift-=(bpm);
|
|
||||||
midiClockCycles++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. run MIDI timecode
|
// 4. run MIDI timecode
|
||||||
for (int i=0; i<midiTotal; i++) {
|
for (int i=0; i<midiTotal; i++) {
|
||||||
if (--midiTimeCycles<=0) {
|
runMidiTime();
|
||||||
if (curMidiTimePiece==0) {
|
|
||||||
curMidiTimeCode=curMidiTime;
|
|
||||||
}
|
|
||||||
if (!(curMidiTimePiece&3)) curMidiTime++;
|
|
||||||
|
|
||||||
double frameRate=96.0;
|
|
||||||
int timeRate=midiOutTimeRate;
|
|
||||||
if (timeRate<1 || timeRate>4) {
|
|
||||||
if (curSubSong->hz>=47.98 && curSubSong->hz<=48.02) {
|
|
||||||
timeRate=1;
|
|
||||||
} else if (curSubSong->hz>=49.98 && curSubSong->hz<=50.02) {
|
|
||||||
timeRate=2;
|
|
||||||
} else if (curSubSong->hz>=59.9 && curSubSong->hz<=60.11) {
|
|
||||||
timeRate=4;
|
|
||||||
} else {
|
|
||||||
timeRate=4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int hour=0;
|
|
||||||
int minute=0;
|
|
||||||
int second=0;
|
|
||||||
int frame=0;
|
|
||||||
int drop=0;
|
|
||||||
int actualTime=curMidiTimeCode;
|
|
||||||
|
|
||||||
switch (timeRate) {
|
|
||||||
case 1: // 24
|
|
||||||
frameRate=96.0;
|
|
||||||
hour=(actualTime/(60*60*24))%24;
|
|
||||||
minute=(actualTime/(60*24))%60;
|
|
||||||
second=(actualTime/24)%60;
|
|
||||||
frame=actualTime%24;
|
|
||||||
break;
|
|
||||||
case 2: // 25
|
|
||||||
frameRate=100.0;
|
|
||||||
hour=(actualTime/(60*60*25))%24;
|
|
||||||
minute=(actualTime/(60*25))%60;
|
|
||||||
second=(actualTime/25)%60;
|
|
||||||
frame=actualTime%25;
|
|
||||||
break;
|
|
||||||
case 3: // 29.97 (NTSC drop)
|
|
||||||
frameRate=120.0*(1000.0/1001.0);
|
|
||||||
|
|
||||||
// drop
|
|
||||||
drop=((actualTime/(30*60))-(actualTime/(30*600)))*2;
|
|
||||||
actualTime+=drop;
|
|
||||||
|
|
||||||
hour=(actualTime/(60*60*30))%24;
|
|
||||||
minute=(actualTime/(60*30))%60;
|
|
||||||
second=(actualTime/30)%60;
|
|
||||||
frame=actualTime%30;
|
|
||||||
break;
|
|
||||||
case 4: // 30 (NTSC non-drop)
|
|
||||||
default:
|
|
||||||
frameRate=120.0;
|
|
||||||
hour=(actualTime/(60*60*30))%24;
|
|
||||||
minute=(actualTime/(60*30))%60;
|
|
||||||
second=(actualTime/30)%60;
|
|
||||||
frame=actualTime%30;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output) if (!skipping && output->midiOut!=NULL && midiOutTime) {
|
|
||||||
unsigned char val=0;
|
|
||||||
switch (curMidiTimePiece) {
|
|
||||||
case 0:
|
|
||||||
val=frame&15;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
val=frame>>4;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
val=second&15;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
val=second>>4;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
val=minute&15;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
val=minute>>4;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
val=hour&15;
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
val=(hour>>4)|((timeRate-1)<<1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
val|=curMidiTimePiece<<4;
|
|
||||||
output->midiOut->send(TAMidiMessage(TA_MIDI_MTC_FRAME,val,0));
|
|
||||||
}
|
|
||||||
curMidiTimePiece=(curMidiTimePiece+1)&7;
|
|
||||||
|
|
||||||
midiTimeCycles=got.rate*pow(2,MASTER_CLOCK_PREC)/(frameRate);
|
|
||||||
midiTimeDrift+=fmod(got.rate*pow(2,MASTER_CLOCK_PREC),(double)(frameRate));
|
|
||||||
if (midiTimeDrift>=(frameRate)) {
|
|
||||||
midiTimeDrift-=(frameRate);
|
|
||||||
midiTimeCycles++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. tick the clock and fill buffers as needed
|
// 5. tick the clock and fill buffers as needed
|
||||||
|
|
Loading…
Reference in a new issue