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;
|
||||
return;
|
||||
}
|
||||
if (!preserveDrift) {
|
||||
runMidiClock(cycles);
|
||||
runMidiTime(cycles);
|
||||
}
|
||||
}
|
||||
int oldOrder=curOrder;
|
||||
while (playing && (curRow<goalRow || ticks>1)) {
|
||||
|
@ -2215,6 +2219,10 @@ void DivEngine::playSub(bool preserveDrift, int goalRow) {
|
|||
skipping=false;
|
||||
return;
|
||||
}
|
||||
if (!preserveDrift) {
|
||||
runMidiClock(cycles);
|
||||
runMidiTime(cycles);
|
||||
}
|
||||
if (oldOrder!=curOrder) 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;
|
||||
midiTimeCycles=0;
|
||||
midiTimeDrift=0;
|
||||
if (curMidiTime>0) {
|
||||
curMidiTime--;
|
||||
}
|
||||
if (curMidiClock>0) {
|
||||
curMidiClock--;
|
||||
}
|
||||
curMidiTimePiece=0;
|
||||
}
|
||||
if (!preserveDrift) {
|
||||
ticks=1;
|
||||
|
@ -2448,7 +2463,7 @@ void DivEngine::play() {
|
|||
// drop
|
||||
drop=((actualTime/(30*60))-(actualTime/(30*600)))*2;
|
||||
actualTime+=drop;
|
||||
|
||||
|
||||
msgData[5]=(actualTime/(60*60*30))%24;
|
||||
msgData[6]=(actualTime/(60*30))%60;
|
||||
msgData[7]=(actualTime/30)%60;
|
||||
|
|
|
@ -475,6 +475,8 @@ class DivEngine {
|
|||
void recalcChans();
|
||||
void reset();
|
||||
void playSub(bool preserveDrift, int goalRow=0);
|
||||
void runMidiClock(int totalCycles=1);
|
||||
void runMidiTime(int totalCycles=1);
|
||||
|
||||
void testFunction();
|
||||
|
||||
|
|
|
@ -1546,6 +1546,147 @@ int DivEngine::getBufferPos() {
|
|||
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) {
|
||||
lastLoopPos=-1;
|
||||
|
||||
|
@ -1833,141 +1974,12 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
// 3. run MIDI clock
|
||||
int midiTotal=MIN(cycles,runLeftG);
|
||||
for (int i=0; i<midiTotal; i++) {
|
||||
if (--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++;
|
||||
}
|
||||
}
|
||||
runMidiClock();
|
||||
}
|
||||
|
||||
// 4. run MIDI timecode
|
||||
for (int i=0; i<midiTotal; i++) {
|
||||
if (--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++;
|
||||
}
|
||||
}
|
||||
runMidiTime();
|
||||
}
|
||||
|
||||
// 5. tick the clock and fill buffers as needed
|
||||
|
|
Loading…
Reference in New Issue