Merge branch 'master' of https://github.com/tildearrow/furnace into es5506_alt
This commit is contained in:
commit
0a49d4bfd0
449 changed files with 36799 additions and 10388 deletions
|
|
@ -31,7 +31,9 @@ void DivEngine::nextOrder() {
|
|||
curRow=0;
|
||||
if (repeatPattern) return;
|
||||
if (++curOrder>=curSubSong->ordersLen) {
|
||||
logV("end of orders reached");
|
||||
endOfSong=true;
|
||||
memset(walked,0,8192);
|
||||
curOrder=0;
|
||||
}
|
||||
}
|
||||
|
|
@ -57,6 +59,16 @@ const char* cmdName[]={
|
|||
"PRE_PORTA",
|
||||
"PRE_NOTE",
|
||||
|
||||
"HINT_VIBRATO",
|
||||
"HINT_VIBRATO_RANGE",
|
||||
"HINT_VIBRATO_SHAPE",
|
||||
"HINT_PITCH",
|
||||
"HINT_ARPEGGIO",
|
||||
"HINT_VOLUME",
|
||||
"HINT_VOL_SLIDE",
|
||||
"HINT_PORTA",
|
||||
"HINT_LEGATO",
|
||||
|
||||
"SAMPLE_MODE",
|
||||
"SAMPLE_FREQ",
|
||||
"SAMPLE_BANK",
|
||||
|
|
@ -157,6 +169,7 @@ const char* cmdName[]={
|
|||
"X1_010_ENVELOPE_PERIOD",
|
||||
"X1_010_ENVELOPE_SLIDE",
|
||||
"X1_010_AUTO_ENVELOPE",
|
||||
"X1_010_SAMPLE_BANK_SLOT",
|
||||
|
||||
"WS_SWEEP_TIME",
|
||||
"WS_SWEEP_AMOUNT",
|
||||
|
|
@ -193,6 +206,8 @@ const char* cmdName[]={
|
|||
"DIV_CMD_SU_SYNC_PERIOD_LOW",
|
||||
"DIV_CMD_SU_SYNC_PERIOD_HIGH",
|
||||
|
||||
"ADPCMA_GLOBAL_VOLUME",
|
||||
|
||||
"ALWAYS_SET_VOLUME"
|
||||
};
|
||||
|
||||
|
|
@ -215,7 +230,27 @@ const char* formatNote(unsigned char note, unsigned char octave) {
|
|||
|
||||
int DivEngine::dispatchCmd(DivCommand c) {
|
||||
if (view==DIV_STATUS_COMMANDS) {
|
||||
printf("%8d | %d: %s(%d, %d)\n",totalTicksR,c.chan,cmdName[c.cmd],c.value,c.value2);
|
||||
if (!skipping) {
|
||||
switch (c.cmd) {
|
||||
// strip away hinted/useless commands
|
||||
case DIV_ALWAYS_SET_VOLUME:
|
||||
break;
|
||||
case DIV_CMD_GET_VOLUME:
|
||||
break;
|
||||
case DIV_CMD_VOLUME:
|
||||
break;
|
||||
case DIV_CMD_NOTE_PORTA:
|
||||
break;
|
||||
case DIV_CMD_LEGATO:
|
||||
break;
|
||||
case DIV_CMD_PITCH:
|
||||
break;
|
||||
case DIV_CMD_PRE_NOTE:
|
||||
break;
|
||||
default:
|
||||
printf("%8d | %d: %s(%d, %d)\n",totalTicksR,c.chan,cmdName[c.cmd],c.value,c.value2);
|
||||
}
|
||||
}
|
||||
}
|
||||
totalCmds++;
|
||||
if (cmdStreamEnabled && cmdStream.size()<2000) {
|
||||
|
|
@ -276,13 +311,39 @@ int DivEngine::dispatchCmd(DivCommand c) {
|
|||
}
|
||||
|
||||
bool DivEngine::perSystemEffect(int ch, unsigned char effect, unsigned char effectVal) {
|
||||
if (sysDefs[sysOfChan[ch]]==NULL) return false;
|
||||
return sysDefs[sysOfChan[ch]]->effectFunc(ch,effect,effectVal);
|
||||
DivSysDef* sysDef=sysDefs[sysOfChan[ch]];
|
||||
if (sysDef==NULL) return false;
|
||||
auto iter=sysDef->effectHandlers.find(effect);
|
||||
if (iter==sysDef->effectHandlers.end()) return false;
|
||||
EffectHandler handler=iter->second;
|
||||
int val=0;
|
||||
int val2=0;
|
||||
try {
|
||||
val=handler.val?handler.val(effect,effectVal):effectVal;
|
||||
val2=handler.val2?handler.val2(effect,effectVal):0;
|
||||
} catch (DivDoNotHandleEffect& e) {
|
||||
return false;
|
||||
}
|
||||
// wouldn't this cause problems if it were to return 0?
|
||||
return dispatchCmd(DivCommand(handler.dispatchCmd,ch,val,val2));
|
||||
}
|
||||
|
||||
bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char effectVal) {
|
||||
if (sysDefs[sysOfChan[ch]]==NULL) return false;
|
||||
return sysDefs[sysOfChan[ch]]->postEffectFunc(ch,effect,effectVal);
|
||||
DivSysDef* sysDef=sysDefs[sysOfChan[ch]];
|
||||
if (sysDef==NULL) return false;
|
||||
auto iter=sysDef->postEffectHandlers.find(effect);
|
||||
if (iter==sysDef->postEffectHandlers.end()) return false;
|
||||
EffectHandler handler=iter->second;
|
||||
int val=0;
|
||||
int val2=0;
|
||||
try {
|
||||
val=handler.val?handler.val(effect,effectVal):effectVal;
|
||||
val2=handler.val2?handler.val2(effect,effectVal):0;
|
||||
} catch (DivDoNotHandleEffect& e) {
|
||||
return true;
|
||||
}
|
||||
// wouldn't this cause problems if it were to return 0?
|
||||
return dispatchCmd(DivCommand(handler.dispatchCmd,ch,val,val2));
|
||||
}
|
||||
|
||||
void DivEngine::processRow(int i, bool afterDelay) {
|
||||
|
|
@ -306,20 +367,38 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
if (effectVal>0) speed2=effectVal;
|
||||
break;
|
||||
case 0x0b: // change order
|
||||
if (changeOrd==-1) {
|
||||
if (changeOrd==-1 || song.jumpTreatment==0) {
|
||||
changeOrd=effectVal;
|
||||
changePos=0;
|
||||
if (song.jumpTreatment==1 || song.jumpTreatment==2) {
|
||||
changePos=0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x0d: // next order
|
||||
if (changeOrd<0 && (curOrder<(curSubSong->ordersLen-1) || !song.ignoreJumpAtEnd)) {
|
||||
changeOrd=-2;
|
||||
changePos=effectVal;
|
||||
if (song.jumpTreatment==2) {
|
||||
if ((curOrder<(curSubSong->ordersLen-1) || !song.ignoreJumpAtEnd)) {
|
||||
changeOrd=-2;
|
||||
changePos=effectVal;
|
||||
}
|
||||
} else if (song.jumpTreatment==1) {
|
||||
if (changeOrd<0 && (curOrder<(curSubSong->ordersLen-1) || !song.ignoreJumpAtEnd)) {
|
||||
changeOrd=-2;
|
||||
changePos=effectVal;
|
||||
}
|
||||
} else {
|
||||
if (curOrder<(curSubSong->ordersLen-1) || !song.ignoreJumpAtEnd) {
|
||||
if (changeOrd<0) {
|
||||
changeOrd=-2;
|
||||
}
|
||||
changePos=effectVal;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xed: // delay
|
||||
if (effectVal!=0) {
|
||||
if (effectVal<=nextSpeed) {
|
||||
bool comparison=(song.delayBehavior==1)?(effectVal<=nextSpeed):(effectVal<(nextSpeed*(curSubSong->timeBase+1)));
|
||||
if (song.delayBehavior==2) comparison=true;
|
||||
if (comparison) {
|
||||
chan[i].rowDelay=effectVal+1;
|
||||
chan[i].delayOrder=whatOrder;
|
||||
chan[i].delayRow=whatRow;
|
||||
|
|
@ -330,6 +409,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
}
|
||||
returnAfterPre=true;
|
||||
} else {
|
||||
logV("higher than nextSpeed! %d>%d",effectVal,nextSpeed);
|
||||
chan[i].delayLocked=false;
|
||||
}
|
||||
}
|
||||
|
|
@ -337,6 +417,8 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
}
|
||||
}
|
||||
if (returnAfterPre) return;
|
||||
} else {
|
||||
logV("honoring delay at position %d",whatRow);
|
||||
}
|
||||
|
||||
if (chan[i].delayLocked) return;
|
||||
|
|
@ -344,10 +426,16 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
// instrument
|
||||
bool insChanged=false;
|
||||
if (pat->data[whatRow][2]!=-1) {
|
||||
dispatchCmd(DivCommand(DIV_CMD_INSTRUMENT,i,pat->data[whatRow][2]));
|
||||
if (chan[i].lastIns!=pat->data[whatRow][2]) {
|
||||
dispatchCmd(DivCommand(DIV_CMD_INSTRUMENT,i,pat->data[whatRow][2]));
|
||||
chan[i].lastIns=pat->data[whatRow][2];
|
||||
insChanged=true;
|
||||
if (song.legacyVolumeSlides && chan[i].volume==chan[i].volMax+1) {
|
||||
logV("forcing volume");
|
||||
chan[i].volume=chan[i].volMax;
|
||||
dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VOLUME,i,chan[i].volume>>8));
|
||||
}
|
||||
}
|
||||
}
|
||||
// note
|
||||
|
|
@ -359,11 +447,13 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
if (chan[i].stopOnOff) {
|
||||
chan[i].portaNote=-1;
|
||||
chan[i].portaSpeed=-1;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,chan[i].portaNote,chan[i].portaSpeed));
|
||||
chan[i].stopOnOff=false;
|
||||
}
|
||||
if (disCont[dispatchOfChan[i]].dispatch->keyOffAffectsPorta(dispatchChanOfChan[i])) {
|
||||
chan[i].portaNote=-1;
|
||||
chan[i].portaSpeed=-1;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,chan[i].portaNote,chan[i].portaSpeed));
|
||||
/*if (i==2 && sysOfChan[i]==DIV_SYSTEM_SMS) {
|
||||
chan[i+1].portaNote=-1;
|
||||
chan[i+1].portaSpeed=-1;
|
||||
|
|
@ -380,11 +470,13 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
if (chan[i].stopOnOff) {
|
||||
chan[i].portaNote=-1;
|
||||
chan[i].portaSpeed=-1;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,chan[i].portaNote,chan[i].portaSpeed));
|
||||
chan[i].stopOnOff=false;
|
||||
}
|
||||
if (disCont[dispatchOfChan[i]].dispatch->keyOffAffectsPorta(dispatchChanOfChan[i])) {
|
||||
chan[i].portaNote=-1;
|
||||
chan[i].portaSpeed=-1;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,chan[i].portaNote,chan[i].portaSpeed));
|
||||
/*if (i==2 && sysOfChan[i]==DIV_SYSTEM_SMS) {
|
||||
chan[i+1].portaNote=-1;
|
||||
chan[i+1].portaSpeed=-1;
|
||||
|
|
@ -401,6 +493,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
if (!chan[i].keyOn) {
|
||||
if (disCont[dispatchOfChan[i]].dispatch->keyOffAffectsArp(dispatchChanOfChan[i])) {
|
||||
chan[i].arp=0;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_ARPEGGIO,i,chan[i].arp));
|
||||
}
|
||||
}
|
||||
chan[i].doNote=true;
|
||||
|
|
@ -417,6 +510,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
}
|
||||
chan[i].volume=pat->data[whatRow][3]<<8;
|
||||
dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VOLUME,i,chan[i].volume>>8));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -461,11 +555,13 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
if (effectVal==0) {
|
||||
chan[i].portaNote=-1;
|
||||
chan[i].portaSpeed=-1;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,chan[i].portaNote,chan[i].portaSpeed));
|
||||
chan[i].inPorta=false;
|
||||
if (!song.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0));
|
||||
} else {
|
||||
chan[i].portaNote=song.limitSlides?0x60:255;
|
||||
chan[i].portaSpeed=effectVal;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,chan[i].portaNote,chan[i].portaSpeed));
|
||||
chan[i].portaStop=true;
|
||||
chan[i].nowYouCanStop=false;
|
||||
chan[i].stopOnOff=false;
|
||||
|
|
@ -481,11 +577,13 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
if (effectVal==0) {
|
||||
chan[i].portaNote=-1;
|
||||
chan[i].portaSpeed=-1;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,chan[i].portaNote,chan[i].portaSpeed));
|
||||
chan[i].inPorta=false;
|
||||
if (!song.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0));
|
||||
} else {
|
||||
chan[i].portaNote=song.limitSlides?disCont[dispatchOfChan[i]].dispatch->getPortaFloor(dispatchChanOfChan[i]):-60;
|
||||
chan[i].portaSpeed=effectVal;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,chan[i].portaNote,chan[i].portaSpeed));
|
||||
chan[i].portaStop=true;
|
||||
chan[i].nowYouCanStop=false;
|
||||
chan[i].stopOnOff=false;
|
||||
|
|
@ -499,6 +597,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
if (effectVal==0) {
|
||||
chan[i].portaNote=-1;
|
||||
chan[i].portaSpeed=-1;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,chan[i].portaNote,chan[i].portaSpeed));
|
||||
chan[i].inPorta=false;
|
||||
dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0));
|
||||
} else {
|
||||
|
|
@ -512,6 +611,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
chan[i].inPorta=true;
|
||||
chan[i].wasShorthandPorta=false;
|
||||
}
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,chan[i].portaNote,chan[i].portaSpeed));
|
||||
chan[i].portaStop=true;
|
||||
if (chan[i].keyOn) chan[i].doNote=false;
|
||||
chan[i].stopOnOff=song.stopPortaOnNoteOff; // what?!
|
||||
|
|
@ -523,6 +623,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
case 0x04: // vibrato
|
||||
chan[i].vibratoDepth=effectVal&15;
|
||||
chan[i].vibratoRate=effectVal>>4;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VIBRATO,i,chan[i].vibratoDepth,chan[i].vibratoRate));
|
||||
dispatchCmd(DivCommand(DIV_CMD_PITCH,i,chan[i].pitch+(((chan[i].vibratoDepth*vibTable[chan[i].vibratoPos]*chan[i].vibratoFine)>>4)/15)));
|
||||
break;
|
||||
case 0x07: // tremolo
|
||||
|
|
@ -546,12 +647,14 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
} else {
|
||||
chan[i].volSpeed=0;
|
||||
}
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VOL_SLIDE,i,chan[i].volSpeed));
|
||||
break;
|
||||
case 0x00: // arpeggio
|
||||
chan[i].arp=effectVal;
|
||||
if (chan[i].arp==0 && song.arp0Reset) {
|
||||
chan[i].resetArp=true;
|
||||
}
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_ARPEGGIO,i,chan[i].arp));
|
||||
break;
|
||||
case 0x0c: // retrigger
|
||||
if (effectVal!=0) {
|
||||
|
|
@ -567,14 +670,11 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
break;
|
||||
case 0xc0: case 0xc1: case 0xc2: case 0xc3: // set Hz
|
||||
divider=(double)(((effect&0x3)<<8)|effectVal);
|
||||
if (divider<10) divider=10;
|
||||
if (divider<1) divider=1;
|
||||
cycles=got.rate*pow(2,MASTER_CLOCK_PREC)/divider;
|
||||
clockDrift=0;
|
||||
subticks=0;
|
||||
break;
|
||||
case 0xdf: // set sample direction
|
||||
dispatchCmd(DivCommand(DIV_CMD_SAMPLE_DIR,i,effectVal));
|
||||
break;
|
||||
case 0xe0: // arp speed
|
||||
if (effectVal>0) {
|
||||
curSubSong->arpLen=effectVal;
|
||||
|
|
@ -583,6 +683,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
case 0xe1: // portamento up
|
||||
chan[i].portaNote=chan[i].note+(effectVal&15);
|
||||
chan[i].portaSpeed=(effectVal>>4)*4;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,chan[i].portaNote,chan[i].portaSpeed));
|
||||
chan[i].portaStop=true;
|
||||
chan[i].nowYouCanStop=false;
|
||||
chan[i].stopOnOff=song.stopPortaOnNoteOff; // what?!
|
||||
|
|
@ -601,6 +702,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
case 0xe2: // portamento down
|
||||
chan[i].portaNote=chan[i].note-(effectVal&15);
|
||||
chan[i].portaSpeed=(effectVal>>4)*4;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,chan[i].portaNote,chan[i].portaSpeed));
|
||||
chan[i].portaStop=true;
|
||||
chan[i].nowYouCanStop=false;
|
||||
chan[i].stopOnOff=song.stopPortaOnNoteOff; // what?!
|
||||
|
|
@ -618,9 +720,11 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
break;
|
||||
case 0xe3: // vibrato direction
|
||||
chan[i].vibratoDir=effectVal;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VIBRATO_SHAPE,i,chan[i].vibratoDir));
|
||||
break;
|
||||
case 0xe4: // vibrato fine
|
||||
chan[i].vibratoFine=effectVal;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VIBRATO_RANGE,i,chan[i].vibratoFine));
|
||||
break;
|
||||
case 0xe5: // pitch
|
||||
chan[i].pitch=effectVal-0x80;
|
||||
|
|
@ -631,6 +735,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
}
|
||||
//chan[i].pitch+=globalPitch;
|
||||
dispatchCmd(DivCommand(DIV_CMD_PITCH,i,chan[i].pitch+(((chan[i].vibratoDepth*vibTable[chan[i].vibratoPos]*chan[i].vibratoFine)>>4)/15)));
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PITCH,i,chan[i].pitch));
|
||||
break;
|
||||
case 0xea: // legato mode
|
||||
chan[i].legato=effectVal;
|
||||
|
|
@ -639,7 +744,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
dispatchCmd(DivCommand(DIV_CMD_SAMPLE_BANK,i,effectVal));
|
||||
break;
|
||||
case 0xec: // delayed note cut
|
||||
if (effectVal>0 && effectVal<nextSpeed) {
|
||||
if (effectVal>0 && (song.delayBehavior==2 || effectVal<nextSpeed)) {
|
||||
chan[i].cut=effectVal+1;
|
||||
}
|
||||
break;
|
||||
|
|
@ -653,7 +758,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
break;
|
||||
case 0xf0: // set Hz by tempo
|
||||
divider=(double)effectVal*2.0/5.0;
|
||||
if (divider<10) divider=10;
|
||||
if (divider<1) divider=1;
|
||||
cycles=got.rate*pow(2,MASTER_CLOCK_PREC)/divider;
|
||||
clockDrift=0;
|
||||
subticks=0;
|
||||
|
|
@ -680,17 +785,21 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
break;
|
||||
case 0xf3: // fine volume ramp up
|
||||
chan[i].volSpeed=effectVal;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VOL_SLIDE,i,chan[i].volSpeed));
|
||||
break;
|
||||
case 0xf4: // fine volume ramp down
|
||||
chan[i].volSpeed=-effectVal;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VOL_SLIDE,i,chan[i].volSpeed));
|
||||
break;
|
||||
case 0xf8: // single volume ramp up
|
||||
chan[i].volume=MIN(chan[i].volume+effectVal*256,chan[i].volMax);
|
||||
dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VOLUME,i,chan[i].volume>>8));
|
||||
break;
|
||||
case 0xf9: // single volume ramp down
|
||||
chan[i].volume=MAX(chan[i].volume-effectVal*256,0);
|
||||
dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VOLUME,i,chan[i].volume>>8));
|
||||
break;
|
||||
case 0xfa: // fast volume ramp
|
||||
if (effectVal!=0) {
|
||||
|
|
@ -702,6 +811,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
} else {
|
||||
chan[i].volSpeed=0;
|
||||
}
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VOL_SLIDE,i,chan[i].volSpeed));
|
||||
break;
|
||||
|
||||
case 0xff: // stop song
|
||||
|
|
@ -733,15 +843,18 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
dispatchCmd(DivCommand(DIV_CMD_PITCH,i,chan[i].pitch+(((chan[i].vibratoDepth*vibTable[chan[i].vibratoPos]*chan[i].vibratoFine)>>4)/15)));
|
||||
if (chan[i].legato) {
|
||||
dispatchCmd(DivCommand(DIV_CMD_LEGATO,i,chan[i].note));
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_LEGATO,i,chan[i].note));
|
||||
} else {
|
||||
if (chan[i].inPorta && chan[i].keyOn && !chan[i].shorthandPorta) {
|
||||
if (song.e1e2StopOnSameNote && chan[i].wasShorthandPorta) {
|
||||
chan[i].portaSpeed=-1;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,chan[i].portaNote,chan[i].portaSpeed));
|
||||
if (!song.brokenShortcutSlides) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0));
|
||||
chan[i].wasShorthandPorta=false;
|
||||
chan[i].inPorta=false;
|
||||
} else {
|
||||
chan[i].portaNote=chan[i].note;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,chan[i].portaNote,chan[i].portaSpeed));
|
||||
}
|
||||
} else if (!chan[i].noteOnInhibit) {
|
||||
dispatchCmd(DivCommand(DIV_CMD_NOTE_ON,i,chan[i].note,chan[i].volume>>8));
|
||||
|
|
@ -752,12 +865,14 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
if (!chan[i].keyOn && chan[i].scheduledSlideReset) {
|
||||
chan[i].portaNote=-1;
|
||||
chan[i].portaSpeed=-1;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,chan[i].portaNote,chan[i].portaSpeed));
|
||||
chan[i].scheduledSlideReset=false;
|
||||
chan[i].inPorta=false;
|
||||
}
|
||||
if (!chan[i].keyOn && chan[i].volume>chan[i].volMax) {
|
||||
chan[i].volume=chan[i].volMax;
|
||||
dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VOLUME,i,chan[i].volume>>8));
|
||||
}
|
||||
chan[i].keyOn=true;
|
||||
chan[i].keyOff=false;
|
||||
|
|
@ -781,7 +896,7 @@ void DivEngine::nextRow() {
|
|||
static char pb1[4096];
|
||||
static char pb2[4096];
|
||||
static char pb3[4096];
|
||||
if (view==DIV_STATUS_PATTERN) {
|
||||
if (view==DIV_STATUS_PATTERN && !skipping) {
|
||||
strcpy(pb1,"");
|
||||
strcpy(pb3,"");
|
||||
for (int i=0; i<chans; i++) {
|
||||
|
|
@ -826,22 +941,29 @@ void DivEngine::nextRow() {
|
|||
prevRow=curRow;
|
||||
|
||||
for (int i=0; i<chans; i++) {
|
||||
chan[i].rowDelay=0;
|
||||
if (song.delayBehavior!=2) {
|
||||
chan[i].rowDelay=0;
|
||||
}
|
||||
processRow(i,false);
|
||||
}
|
||||
|
||||
walked[((curOrder<<5)+(curRow>>3))&8191]|=1<<(curRow&7);
|
||||
|
||||
if (changeOrd!=-1) {
|
||||
if (repeatPattern) {
|
||||
curRow=0;
|
||||
changeOrd=-1;
|
||||
} else {
|
||||
curRow=changePos;
|
||||
changePos=0;
|
||||
if (changeOrd==-2) changeOrd=curOrder+1;
|
||||
if (changeOrd<=curOrder) endOfSong=true;
|
||||
// old loop detection routine
|
||||
//if (changeOrd<=curOrder) endOfSong=true;
|
||||
curOrder=changeOrd;
|
||||
if (curOrder>=curSubSong->ordersLen) {
|
||||
curOrder=0;
|
||||
endOfSong=true;
|
||||
memset(walked,0,8192);
|
||||
}
|
||||
changeOrd=-1;
|
||||
}
|
||||
|
|
@ -851,6 +973,13 @@ void DivEngine::nextRow() {
|
|||
if (haltOn==DIV_HALT_PATTERN) halted=true;
|
||||
}
|
||||
|
||||
// new loop detection routine
|
||||
if (!endOfSong && walked[((curOrder<<5)+(curRow>>3))&8191]&(1<<(curRow&7))) {
|
||||
logV("loop reached");
|
||||
endOfSong=true;
|
||||
memset(walked,0,8192);
|
||||
}
|
||||
|
||||
if (song.brokenSpeedSel) {
|
||||
if ((curSubSong->patLen&1) && curOrder&1) {
|
||||
ticks=((curRow&1)?speed2:speed1)*(curSubSong->timeBase+1);
|
||||
|
|
@ -876,7 +1005,9 @@ void DivEngine::nextRow() {
|
|||
if (!(pat->data[curRow][0]==0 && pat->data[curRow][1]==0)) {
|
||||
if (pat->data[curRow][0]!=100 && pat->data[curRow][0]!=101 && pat->data[curRow][0]!=102) {
|
||||
if (!chan[i].legato) {
|
||||
dispatchCmd(DivCommand(DIV_CMD_PRE_NOTE,i,ticks));
|
||||
if (disCont[dispatchOfChan[i]].dispatch!=NULL) {
|
||||
if (disCont[dispatchOfChan[i]].dispatch->getWantPreNote()) dispatchCmd(DivCommand(DIV_CMD_PRE_NOTE,i,ticks));
|
||||
}
|
||||
|
||||
if (song.oneTickCut) {
|
||||
bool doPrepareCut=true;
|
||||
|
|
@ -906,7 +1037,7 @@ void DivEngine::nextRow() {
|
|||
|
||||
bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
|
||||
bool ret=false;
|
||||
if (divider<10) divider=10;
|
||||
if (divider<1) divider=1;
|
||||
|
||||
if (lowLatency && !skipping && !inhibitLowLat) {
|
||||
tickMult=1000/divider;
|
||||
|
|
@ -924,13 +1055,30 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
|
|||
|
||||
// MIDI clock
|
||||
if (output) if (!skipping && output->midiOut!=NULL) {
|
||||
output->midiOut->send(TAMidiMessage(TA_MIDI_CLOCK,0,0));
|
||||
//output->midiOut->send(TAMidiMessage(TA_MIDI_CLOCK,0,0));
|
||||
}
|
||||
|
||||
if (!pendingNotes.empty()) {
|
||||
bool isOn[DIV_MAX_CHANS];
|
||||
memset(isOn,0,DIV_MAX_CHANS*sizeof(bool));
|
||||
|
||||
for (int i=pendingNotes.size()-1; i>=0; i--) {
|
||||
if (pendingNotes[i].channel<0 || pendingNotes[i].channel>=chans) continue;
|
||||
if (pendingNotes[i].on) {
|
||||
isOn[pendingNotes[i].channel]=true;
|
||||
} else {
|
||||
if (isOn[pendingNotes[i].channel]) {
|
||||
logV("erasing off -> on sequence in %d",pendingNotes[i].channel);
|
||||
pendingNotes.erase(pendingNotes.begin()+i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (!pendingNotes.empty()) {
|
||||
DivNoteEvent& note=pendingNotes.front();
|
||||
if (note.channel<0 || note.channel>=chans) {
|
||||
pendingNotes.pop();
|
||||
pendingNotes.pop_front();
|
||||
continue;
|
||||
}
|
||||
if (note.on) {
|
||||
|
|
@ -950,7 +1098,7 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
|
|||
dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF,note.channel));
|
||||
}
|
||||
}
|
||||
pendingNotes.pop();
|
||||
pendingNotes.pop_front();
|
||||
}
|
||||
|
||||
if (!freelance) {
|
||||
|
|
@ -995,15 +1143,19 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
|
|||
if (chan[i].volume>chan[i].volMax) {
|
||||
chan[i].volume=chan[i].volMax;
|
||||
chan[i].volSpeed=0;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VOLUME,i,chan[i].volume>>8));
|
||||
dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VOL_SLIDE,i,0));
|
||||
} else if (chan[i].volume<0) {
|
||||
chan[i].volSpeed=0;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VOL_SLIDE,i,0));
|
||||
if (song.legacyVolumeSlides) {
|
||||
chan[i].volume=chan[i].volMax+1;
|
||||
} else {
|
||||
chan[i].volume=0;
|
||||
}
|
||||
dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VOLUME,i,chan[i].volume>>8));
|
||||
} else {
|
||||
dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
|
||||
}
|
||||
|
|
@ -1032,10 +1184,12 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
|
|||
if ((chan[i].keyOn || chan[i].keyOff) && chan[i].portaSpeed>0) {
|
||||
if (dispatchCmd(DivCommand(DIV_CMD_NOTE_PORTA,i,chan[i].portaSpeed*(song.linearPitch==2?song.pitchSlideSpeed:1),chan[i].portaNote))==2 && chan[i].portaStop && song.targetResetsSlides) {
|
||||
chan[i].portaSpeed=0;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,chan[i].portaNote,chan[i].portaSpeed));
|
||||
chan[i].oldNote=chan[i].note;
|
||||
chan[i].note=chan[i].portaNote;
|
||||
chan[i].inPorta=false;
|
||||
dispatchCmd(DivCommand(DIV_CMD_LEGATO,i,chan[i].note));
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_LEGATO,i,chan[i].note));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1049,11 +1203,13 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
|
|||
if (chan[i].stopOnOff) {
|
||||
chan[i].portaNote=-1;
|
||||
chan[i].portaSpeed=-1;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,chan[i].portaNote,chan[i].portaSpeed));
|
||||
chan[i].stopOnOff=false;
|
||||
}
|
||||
if (disCont[dispatchOfChan[i]].dispatch->keyOffAffectsPorta(dispatchChanOfChan[i])) {
|
||||
chan[i].portaNote=-1;
|
||||
chan[i].portaSpeed=-1;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,chan[i].portaNote,chan[i].portaSpeed));
|
||||
/*if (i==2 && sysOfChan[i]==DIV_SYSTEM_SMS) {
|
||||
chan[i+1].portaNote=-1;
|
||||
chan[i+1].portaSpeed=-1;
|
||||
|
|
@ -1067,6 +1223,7 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
|
|||
}
|
||||
if (chan[i].resetArp) {
|
||||
dispatchCmd(DivCommand(DIV_CMD_LEGATO,i,chan[i].note));
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_LEGATO,i,chan[i].note));
|
||||
chan[i].resetArp=false;
|
||||
}
|
||||
if (song.rowResetsArpPos && firstTick) {
|
||||
|
|
@ -1115,7 +1272,7 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
|
|||
}
|
||||
}
|
||||
|
||||
if (consoleMode && subticks<=1) fprintf(stderr,"\x1b[2K> %d:%.2d:%.2d.%.2d %.2x/%.2x:%.3d/%.3d %4dcmd/s\x1b[G",totalSeconds/3600,(totalSeconds/60)%60,totalSeconds%60,totalTicks/10000,curOrder,curSubSong->ordersLen,curRow,curSubSong->patLen,cmdsPerSecond);
|
||||
if (consoleMode && subticks<=1 && !skipping) fprintf(stderr,"\x1b[2K> %d:%.2d:%.2d.%.2d %.2x/%.2x:%.3d/%.3d %4dcmd/s\x1b[G",totalSeconds/3600,(totalSeconds/60)%60,totalSeconds%60,totalTicks/10000,curOrder,curSubSong->ordersLen,curRow,curSubSong->patLen,cmdsPerSecond);
|
||||
}
|
||||
|
||||
if (haltOn==DIV_HALT_TICK) halted=true;
|
||||
|
|
@ -1153,7 +1310,7 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
case TA_MIDI_NOTE_OFF: {
|
||||
if (chan<0 || chan>=chans) break;
|
||||
if (midiIsDirect) {
|
||||
pendingNotes.push(DivNoteEvent(chan,-1,-1,-1,false));
|
||||
pendingNotes.push_back(DivNoteEvent(chan,-1,-1,-1,false));
|
||||
} else {
|
||||
autoNoteOff(msg.type&15,msg.data[0]-12,msg.data[1]);
|
||||
}
|
||||
|
|
@ -1168,13 +1325,13 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
if (chan<0 || chan>=chans) break;
|
||||
if (msg.data[1]==0) {
|
||||
if (midiIsDirect) {
|
||||
pendingNotes.push(DivNoteEvent(chan,-1,-1,-1,false));
|
||||
pendingNotes.push_back(DivNoteEvent(chan,-1,-1,-1,false));
|
||||
} else {
|
||||
autoNoteOff(msg.type&15,msg.data[0]-12,msg.data[1]);
|
||||
}
|
||||
} else {
|
||||
if (midiIsDirect) {
|
||||
pendingNotes.push(DivNoteEvent(chan,ins,msg.data[0]-12,msg.data[1],true));
|
||||
pendingNotes.push_back(DivNoteEvent(chan,ins,msg.data[0]-12,msg.data[1],true));
|
||||
} else {
|
||||
autoNoteOn(msg.type&15,ins,msg.data[0]-12,msg.data[1]);
|
||||
}
|
||||
|
|
@ -1210,7 +1367,7 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
const int loopStart=pBeginVaild?sPreview.pBegin:s->loopStart;
|
||||
const int loopEnd=pEndVaild?sPreview.pEnd:(int)s->loopEnd;
|
||||
for (size_t i=0; i<prevtotal; i++) {
|
||||
if (sPreview.pos>=s->samples || (sPreview.pEnd>=0 && (int)sPreview.pos>=sPreview.pEnd)) {
|
||||
if (sPreview.pos>=(int)s->samples || (sPreview.pEnd>=0 && sPreview.pos>=sPreview.pEnd)) {
|
||||
samp_temp=0;
|
||||
} else {
|
||||
samp_temp=s->data16[sPreview.pos];
|
||||
|
|
@ -1223,98 +1380,95 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
blip_add_delta(samp_bb,i,samp_temp-samp_prevSample);
|
||||
samp_prevSample=samp_temp;
|
||||
|
||||
if (sPreview.dir) {
|
||||
if (s->isLoopable() && ((int)sPreview.pos)<loopStart) {
|
||||
switch (s->loopMode) {
|
||||
case DIV_SAMPLE_LOOPMODE_FORWARD:
|
||||
sPreview.dir=false;
|
||||
sPreview.pos=loopStart+1;
|
||||
break;
|
||||
case DIV_SAMPLE_LOOPMODE_BACKWARD:
|
||||
sPreview.dir=true;
|
||||
sPreview.pos=loopEnd-1;
|
||||
break;
|
||||
case DIV_SAMPLE_LOOPMODE_PINGPONG:
|
||||
sPreview.dir=false;
|
||||
sPreview.pos=loopStart+1;
|
||||
break;
|
||||
case DIV_SAMPLE_LOOPMODE_ONESHOT:
|
||||
default:
|
||||
break;
|
||||
if (sPreview.dir) { // backward
|
||||
if (sPreview.pos<s->loopStart || (sPreview.pBegin>=0 && sPreview.pos<sPreview.pBegin)) {
|
||||
if (s->isLoopable() && sPreview.pos<s->loopEnd) {
|
||||
switch (s->loopMode) {
|
||||
case DivSampleLoopMode::DIV_SAMPLE_LOOP_FORWARD:
|
||||
sPreview.pos=s->loopStart;
|
||||
sPreview.dir=false;
|
||||
break;
|
||||
case DivSampleLoopMode::DIV_SAMPLE_LOOP_BACKWARD:
|
||||
sPreview.pos=s->loopEnd-1;
|
||||
sPreview.dir=true;
|
||||
break;
|
||||
case DivSampleLoopMode::DIV_SAMPLE_LOOP_PINGPONG:
|
||||
sPreview.pos=s->loopStart;
|
||||
sPreview.dir=false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (s->isLoopable() && ((int)sPreview.pos)>=loopEnd) {
|
||||
switch (s->loopMode) {
|
||||
case DIV_SAMPLE_LOOPMODE_FORWARD:
|
||||
sPreview.dir=false;
|
||||
sPreview.pos=loopStart;
|
||||
break;
|
||||
case DIV_SAMPLE_LOOPMODE_BACKWARD:
|
||||
sPreview.dir=true;
|
||||
sPreview.pos=loopEnd-1;
|
||||
break;
|
||||
case DIV_SAMPLE_LOOPMODE_PINGPONG:
|
||||
sPreview.dir=true;
|
||||
sPreview.pos=loopEnd-1;
|
||||
break;
|
||||
case DIV_SAMPLE_LOOPMODE_ONESHOT:
|
||||
default:
|
||||
break;
|
||||
} else { // forward
|
||||
if (sPreview.pos>=s->loopEnd || (sPreview.pEnd>=0 && sPreview.pos>=sPreview.pEnd)) {
|
||||
if (s->isLoopable() && sPreview.pos>=s->loopStart) {
|
||||
switch (s->loopMode) {
|
||||
case DivSampleLoopMode::DIV_SAMPLE_LOOP_FORWARD:
|
||||
sPreview.pos=s->loopStart;
|
||||
sPreview.dir=false;
|
||||
break;
|
||||
case DivSampleLoopMode::DIV_SAMPLE_LOOP_BACKWARD:
|
||||
sPreview.pos=s->loopEnd-1;
|
||||
sPreview.dir=true;
|
||||
break;
|
||||
case DivSampleLoopMode::DIV_SAMPLE_LOOP_PINGPONG:
|
||||
sPreview.pos=s->loopEnd-1;
|
||||
sPreview.dir=true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sPreview.dir) {
|
||||
if ((s->isLoopable() && sPreview.pos<s->loopEnd) && ((int)sPreview.pos)<loopStart) {
|
||||
switch (s->loopMode) {
|
||||
case DIV_SAMPLE_LOOPMODE_FORWARD:
|
||||
sPreview.dir=false;
|
||||
sPreview.pos=loopStart+1;
|
||||
break;
|
||||
case DIV_SAMPLE_LOOPMODE_BACKWARD:
|
||||
sPreview.dir=true;
|
||||
sPreview.pos=loopEnd-1;
|
||||
break;
|
||||
case DIV_SAMPLE_LOOPMODE_PINGPONG:
|
||||
sPreview.dir=false;
|
||||
sPreview.pos=loopStart+1;
|
||||
break;
|
||||
case DIV_SAMPLE_LOOPMODE_ONESHOT:
|
||||
default:
|
||||
if (((int)sPreview.pos)<0) {
|
||||
sPreview.sample=-1;
|
||||
}
|
||||
break;
|
||||
if (sPreview.dir) { // backward
|
||||
if (sPreview.pos<=s->loopStart || (sPreview.pBegin>=0 && sPreview.pos<=sPreview.pBegin)) {
|
||||
if (s->isLoopable() && sPreview.pos>=s->loopStart) {
|
||||
switch (s->loopMode) {
|
||||
case DivSampleLoopMode::DIV_SAMPLE_LOOP_FORWARD:
|
||||
sPreview.pos=s->loopStart;
|
||||
sPreview.dir=false;
|
||||
break;
|
||||
case DivSampleLoopMode::DIV_SAMPLE_LOOP_BACKWARD:
|
||||
sPreview.pos=s->loopEnd-1;
|
||||
sPreview.dir=true;
|
||||
break;
|
||||
case DivSampleLoopMode::DIV_SAMPLE_LOOP_PINGPONG:
|
||||
sPreview.pos=s->loopStart;
|
||||
sPreview.dir=false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (sPreview.pos<0) {
|
||||
sPreview.sample=-1;
|
||||
}
|
||||
} else if (((int)sPreview.pos)<0) {
|
||||
sPreview.sample=-1;
|
||||
}
|
||||
} else {
|
||||
if ((s->isLoopable() && (int)sPreview.pos>=s->loopStart) && ((int)sPreview.pos)>=loopEnd) {
|
||||
switch (s->loopMode) {
|
||||
case DIV_SAMPLE_LOOPMODE_FORWARD:
|
||||
sPreview.dir=false;
|
||||
sPreview.pos=loopStart;
|
||||
break;
|
||||
case DIV_SAMPLE_LOOPMODE_BACKWARD:
|
||||
sPreview.dir=true;
|
||||
sPreview.pos=loopEnd-1;
|
||||
break;
|
||||
case DIV_SAMPLE_LOOPMODE_PINGPONG:
|
||||
sPreview.dir=true;
|
||||
sPreview.pos=loopEnd-1;
|
||||
break;
|
||||
case DIV_SAMPLE_LOOPMODE_ONESHOT:
|
||||
default:
|
||||
if (sPreview.pos>=s->samples) {
|
||||
sPreview.sample=-1;
|
||||
}
|
||||
break;
|
||||
} else { // forward
|
||||
if (sPreview.pos>=s->loopEnd || (sPreview.pEnd>=0 && sPreview.pos>=sPreview.pEnd)) {
|
||||
if (s->isLoopable() && sPreview.pos>=s->loopStart) {
|
||||
switch (s->loopMode) {
|
||||
case DivSampleLoopMode::DIV_SAMPLE_LOOP_FORWARD:
|
||||
sPreview.pos=s->loopStart;
|
||||
sPreview.dir=false;
|
||||
break;
|
||||
case DivSampleLoopMode::DIV_SAMPLE_LOOP_BACKWARD:
|
||||
sPreview.pos=s->loopEnd-1;
|
||||
sPreview.dir=true;
|
||||
break;
|
||||
case DivSampleLoopMode::DIV_SAMPLE_LOOP_PINGPONG:
|
||||
sPreview.pos=s->loopEnd-1;
|
||||
sPreview.dir=true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (sPreview.pos>=(int)s->samples) {
|
||||
sPreview.sample=-1;
|
||||
}
|
||||
} else if (sPreview.pos>=s->samples) {
|
||||
sPreview.sample=-1;
|
||||
}
|
||||
}
|
||||
} else if (sPreview.wave>=0 && sPreview.wave<(int)song.wave.size()) {
|
||||
|
|
@ -1325,7 +1479,7 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
} else {
|
||||
samp_temp=((MIN(wave->data[sPreview.pos],wave->max)<<14)/wave->max)-8192;
|
||||
}
|
||||
if (++sPreview.pos>=(unsigned int)wave->len) {
|
||||
if (++sPreview.pos>=wave->len) {
|
||||
sPreview.pos=0;
|
||||
}
|
||||
blip_add_delta(samp_bb,i,samp_temp-samp_prevSample);
|
||||
|
|
@ -1355,25 +1509,22 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
}
|
||||
|
||||
// logic starts here
|
||||
size_t runtotal[32];
|
||||
size_t runLeft[32];
|
||||
size_t runPos[32];
|
||||
size_t lastAvail[32];
|
||||
for (int i=0; i<song.systemLen; i++) {
|
||||
lastAvail[i]=blip_samples_avail(disCont[i].bb[0]);
|
||||
if (lastAvail[i]>0) {
|
||||
disCont[i].flush(lastAvail[i]);
|
||||
disCont[i].lastAvail=blip_samples_avail(disCont[i].bb[0]);
|
||||
if (disCont[i].lastAvail>0) {
|
||||
disCont[i].flush(disCont[i].lastAvail);
|
||||
}
|
||||
runtotal[i]=blip_clocks_needed(disCont[i].bb[0],size-lastAvail[i]);
|
||||
if (runtotal[i]>disCont[i].bbInLen) {
|
||||
disCont[i].runtotal=blip_clocks_needed(disCont[i].bb[0],size-disCont[i].lastAvail);
|
||||
if (disCont[i].runtotal>disCont[i].bbInLen) {
|
||||
logV("growing dispatch %d bbIn to %d",i,disCont[i].runtotal+256);
|
||||
delete[] disCont[i].bbIn[0];
|
||||
delete[] disCont[i].bbIn[1];
|
||||
disCont[i].bbIn[0]=new short[runtotal[i]+256];
|
||||
disCont[i].bbIn[1]=new short[runtotal[i]+256];
|
||||
disCont[i].bbInLen=runtotal[i]+256;
|
||||
disCont[i].bbIn[0]=new short[disCont[i].runtotal+256];
|
||||
disCont[i].bbIn[1]=new short[disCont[i].runtotal+256];
|
||||
disCont[i].bbInLen=disCont[i].runtotal+256;
|
||||
}
|
||||
runLeft[i]=runtotal[i];
|
||||
runPos[i]=0;
|
||||
disCont[i].runLeft=disCont[i].runtotal;
|
||||
disCont[i].runPos=0;
|
||||
}
|
||||
|
||||
if (metroTickLen<size) {
|
||||
|
|
@ -1425,10 +1576,10 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
// 3. tick the clock and fill buffers as needed
|
||||
if (cycles<runLeftG) {
|
||||
for (int i=0; i<song.systemLen; i++) {
|
||||
int total=(cycles*runtotal[i])/(size<<MASTER_CLOCK_PREC);
|
||||
disCont[i].acquire(runPos[i],total);
|
||||
runLeft[i]-=total;
|
||||
runPos[i]+=total;
|
||||
int total=(cycles*disCont[i].runtotal)/(size<<MASTER_CLOCK_PREC);
|
||||
disCont[i].acquire(disCont[i].runPos,total);
|
||||
disCont[i].runLeft-=total;
|
||||
disCont[i].runPos+=total;
|
||||
}
|
||||
runLeftG-=cycles;
|
||||
cycles=0;
|
||||
|
|
@ -1436,8 +1587,8 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
cycles-=runLeftG;
|
||||
runLeftG=0;
|
||||
for (int i=0; i<song.systemLen; i++) {
|
||||
disCont[i].acquire(runPos[i],runLeft[i]);
|
||||
runLeft[i]=0;
|
||||
disCont[i].acquire(disCont[i].runPos,disCont[i].runLeft);
|
||||
disCont[i].runLeft=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1458,7 +1609,7 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
totalProcessed=size-(runLeftG>>MASTER_CLOCK_PREC);
|
||||
|
||||
for (int i=0; i<song.systemLen; i++) {
|
||||
disCont[i].fillBuf(runtotal[i],lastAvail[i],size-lastAvail[i]);
|
||||
disCont[i].fillBuf(disCont[i].runtotal,disCont[i].lastAvail,size-disCont[i].lastAvail);
|
||||
}
|
||||
|
||||
for (int i=0; i<song.systemLen; i++) {
|
||||
|
|
@ -1512,6 +1663,14 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
out[1][i]=out[0][i];
|
||||
}
|
||||
}
|
||||
if (clampSamples) {
|
||||
for (size_t i=0; i<size; i++) {
|
||||
if (out[0][i]<-1.0) out[0][i]=-1.0;
|
||||
if (out[0][i]>1.0) out[0][i]=1.0;
|
||||
if (out[1][i]<-1.0) out[1][i]=-1.0;
|
||||
if (out[1][i]>1.0) out[1][i]=1.0;
|
||||
}
|
||||
}
|
||||
isBusy.unlock();
|
||||
|
||||
std::chrono::steady_clock::time_point ts_processEnd=std::chrono::steady_clock::now();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue