Add fixed octave for block+fnum systems

This isn't implemented in SAA1099, despite also being block+fnum system, as there are no benefits from it
This commit is contained in:
Natt Akuma 2024-09-18 14:48:10 +07:00
parent 6a58797669
commit cf3d08ca5a
25 changed files with 194 additions and 97 deletions

View file

@ -1433,11 +1433,16 @@ void DivPlatformOPL::tick(bool sysTick) {
}
} else {
if (chan[i].freqChanged) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,octave(chan[i].baseFreq)*2,chan[i].pitch2,chipClock,CHIP_FREQBASE);
int mul=2;
int fixedBlock=parent->getIns(chan[i].ins)->fm.block;
if (parent->song.linearPitch!=2) {
mul=octave(chan[i].baseFreq,fixedBlock)*2;
}
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,mul,chan[i].pitch2,chipClock,CHIP_FREQBASE);
if (chan[i].fixedFreq>0) chan[i].freq=chan[i].fixedFreq;
if (chan[i].freq<0) chan[i].freq=0;
if (chan[i].freq>131071) chan[i].freq=131071;
int freqt=toFreq(chan[i].freq);
int freqt=toFreq(chan[i].freq,fixedBlock);
chan[i].freqH=freqt>>8;
chan[i].freqL=freqt&0xff;
immWrite(chanMap[i]+ADDR_FREQ,chan[i].freqL);
@ -1501,16 +1506,26 @@ void DivPlatformOPL::tick(bool sysTick) {
#define OPLL_C_NUM 686
int DivPlatformOPL::octave(int freq) {
int DivPlatformOPL::octave(int freq, int fixedBlock) {
if (fixedBlock>0) {
return 1<<(fixedBlock-1);
}
freq/=OPLL_C_NUM;
if (freq==0) return 1;
return 1<<bsr(freq);
}
int DivPlatformOPL::toFreq(int freq) {
int block=freq/OPLL_C_NUM;
if (block>0) block=bsr(block);
return (block<<10)|((freq>>block)&0x3ff);
int DivPlatformOPL::toFreq(int freq, int fixedBlock) {
int block=0;
if (fixedBlock>0) {
block=fixedBlock-1;
} else {
block=freq/OPLL_C_NUM;
if (block>0) block=bsr(block);
}
freq>>=block;
if (freq>0x3ff) freq=0x3ff;
return (block<<10)|freq;
}
void DivPlatformOPL::muteChannel(int ch, bool mute) {
@ -2020,21 +2035,27 @@ int DivPlatformOPL::dispatch(DivCommand c) {
int destFreq=(c.chan==adpcmChan)?(NOTE_ADPCMB(c.value2)):(NOTE_FREQUENCY(c.value2));
int newFreq;
bool return2=false;
int mul=1;
int fixedBlock=0;
if (parent->song.linearPitch!=2) {
fixedBlock=parent->getIns(chan[c.chan].ins)->fm.block;
mul=octave(chan[c.chan].baseFreq,fixedBlock);
}
if (destFreq>chan[c.chan].baseFreq) {
newFreq=chan[c.chan].baseFreq+c.value*((parent->song.linearPitch==2)?1:octave(chan[c.chan].baseFreq));
newFreq=chan[c.chan].baseFreq+c.value*mul;
if (newFreq>=destFreq) {
newFreq=destFreq;
return2=true;
}
} else {
newFreq=chan[c.chan].baseFreq-c.value*((parent->song.linearPitch==2)?1:octave(chan[c.chan].baseFreq));
newFreq=chan[c.chan].baseFreq-c.value*mul;
if (newFreq<=destFreq) {
newFreq=destFreq;
return2=true;
}
}
if (!chan[c.chan].portaPause && parent->song.linearPitch!=2) {
if (octave(chan[c.chan].baseFreq)!=octave(newFreq)) {
if (mul!=octave(newFreq,fixedBlock)) {
chan[c.chan].portaPause=true;
break;
}