YM2610(B): implement full linear pitch (part 4)

This commit is contained in:
tildearrow 2022-05-11 00:04:36 -05:00
parent a7e6323db9
commit f4652e6582
4 changed files with 116 additions and 44 deletions

View File

@ -461,8 +461,8 @@ double DivPlatformYM2610::NOTE_OPNB(int ch, int note) {
double DivPlatformYM2610::NOTE_ADPCMB(int note) { double DivPlatformYM2610::NOTE_ADPCMB(int note) {
if (chan[13].sample>=0 && chan[13].sample<parent->song.sampleLen) { if (chan[13].sample>=0 && chan[13].sample<parent->song.sampleLen) {
double off=(double)(parent->getSample(chan[13].sample)->centerRate)/8363.0; double off=65535.0*(double)(parent->getSample(chan[13].sample)->centerRate)/8363.0;
return off*parent->calcBaseFreq((double)chipClock/144,65535,note,false); return parent->calcBaseFreq((double)chipClock/144,off,note,false);
} }
return 0; return 0;
} }
@ -726,7 +726,12 @@ void DivPlatformYM2610::tick(bool sysTick) {
} }
} }
if (chan[13].freqChanged) { if (chan[13].freqChanged) {
chan[13].freq=parent->calcFreq(chan[13].baseFreq,chan[13].pitch,false,4); if (chan[13].sample>=0 && chan[13].sample<parent->song.sampleLen) {
double off=65535.0*(double)(parent->getSample(chan[13].sample)->centerRate)/8363.0;
chan[13].freq=parent->calcFreq(chan[13].baseFreq,chan[13].pitch,false,4,chan[13].pitch2,(double)chipClock/144,off);
} else {
chan[13].freq=0;
}
immWrite(0x19,chan[13].freq&0xff); immWrite(0x19,chan[13].freq&0xff);
immWrite(0x1a,(chan[13].freq>>8)&0xff); immWrite(0x1a,(chan[13].freq>>8)&0xff);
chan[13].freqChanged=false; chan[13].freqChanged=false;
@ -742,17 +747,21 @@ void DivPlatformYM2610::tick(bool sysTick) {
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
if (i==1 && extMode) continue; if (i==1 && extMode) continue;
if (chan[i].freqChanged) { if (chan[i].freqChanged) {
int fNum=parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,false,4,chan[i].pitch2); if (parent->song.linearPitch==2) {
int block=(chan[i].baseFreq&0xf800)>>11; chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,4,chan[i].pitch2,chipClock,CHIP_FREQBASE,11);
if (fNum<0) fNum=0; } else {
if (fNum>2047) { int fNum=parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,false,4,chan[i].pitch2,chipClock,CHIP_FREQBASE,11);
while (block<7) { int block=(chan[i].baseFreq&0xf800)>>11;
fNum>>=1; if (fNum<0) fNum=0;
block++; if (fNum>2047) {
while (block<7) {
fNum>>=1;
block++;
}
if (fNum>2047) fNum=2047;
} }
if (fNum>2047) fNum=2047; chan[i].freq=(block<<11)|fNum;
} }
chan[i].freq=(block<<11)|fNum;
if (chan[i].freq>0x3fff) chan[i].freq=0x3fff; if (chan[i].freq>0x3fff) chan[i].freq=0x3fff;
immWrite(chanOffs[i]+ADDR_FREQH,chan[i].freq>>8); immWrite(chanOffs[i]+ADDR_FREQH,chan[i].freq>>8);
immWrite(chanOffs[i]+ADDR_FREQ,chan[i].freq&0xff); immWrite(chanOffs[i]+ADDR_FREQ,chan[i].freq&0xff);
@ -993,7 +1002,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_NOTE_PORTA: { case DIV_CMD_NOTE_PORTA: {
if (c.chan>3) { // PSG, ADPCM-B if (c.chan>3 || parent->song.linearPitch==2) { // PSG, ADPCM-B
int destFreq=NOTE_OPNB(c.chan,c.value2); int destFreq=NOTE_OPNB(c.chan,c.value2);
bool return2=false; bool return2=false;
if (destFreq>chan[c.chan].baseFreq) { if (destFreq>chan[c.chan].baseFreq) {

View File

@ -441,8 +441,8 @@ double DivPlatformYM2610B::NOTE_OPNB(int ch, int note) {
double DivPlatformYM2610B::NOTE_ADPCMB(int note) { double DivPlatformYM2610B::NOTE_ADPCMB(int note) {
if (chan[15].sample>=0 && chan[15].sample<parent->song.sampleLen) { if (chan[15].sample>=0 && chan[15].sample<parent->song.sampleLen) {
double off=(double)(parent->getSample(chan[15].sample)->centerRate)/8363.0; double off=65535.0*(double)(parent->getSample(chan[15].sample)->centerRate)/8363.0;
return off*parent->calcBaseFreq((double)chipClock/144,65535,note,false); return parent->calcBaseFreq((double)chipClock/144,off,note,false);
} }
return 0; return 0;
} }
@ -704,7 +704,12 @@ void DivPlatformYM2610B::tick(bool sysTick) {
} }
} }
if (chan[15].freqChanged) { if (chan[15].freqChanged) {
chan[15].freq=parent->calcFreq(chan[15].baseFreq,chan[15].pitch,false,4); if (chan[15].sample>=0 && chan[15].sample<parent->song.sampleLen) {
double off=65535.0*(double)(parent->getSample(chan[15].sample)->centerRate)/8363.0;
chan[15].freq=parent->calcFreq(chan[15].baseFreq,chan[15].pitch,false,4,chan[15].pitch2,(double)chipClock/144,off);
} else {
chan[15].freq=0;
}
immWrite(0x19,chan[15].freq&0xff); immWrite(0x19,chan[15].freq&0xff);
immWrite(0x1a,(chan[15].freq>>8)&0xff); immWrite(0x1a,(chan[15].freq>>8)&0xff);
chan[15].freqChanged=false; chan[15].freqChanged=false;
@ -720,17 +725,21 @@ void DivPlatformYM2610B::tick(bool sysTick) {
for (int i=0; i<6; i++) { for (int i=0; i<6; i++) {
if (i==2 && extMode) continue; if (i==2 && extMode) continue;
if (chan[i].freqChanged) { if (chan[i].freqChanged) {
int fNum=parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,false,4,chan[i].pitch2); if (parent->song.linearPitch==2) {
int block=(chan[i].baseFreq&0xf800)>>11; chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,4,chan[i].pitch2,chipClock,CHIP_FREQBASE,11);
if (fNum<0) fNum=0; } else {
if (fNum>2047) { int fNum=parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,false,4,chan[i].pitch2);
while (block<7) { int block=(chan[i].baseFreq&0xf800)>>11;
fNum>>=1; if (fNum<0) fNum=0;
block++; if (fNum>2047) {
while (block<7) {
fNum>>=1;
block++;
}
if (fNum>2047) fNum=2047;
} }
if (fNum>2047) fNum=2047; chan[i].freq=(block<<11)|fNum;
} }
chan[i].freq=(block<<11)|fNum;
if (chan[i].freq>0x3fff) chan[i].freq=0x3fff; if (chan[i].freq>0x3fff) chan[i].freq=0x3fff;
immWrite(chanOffs[i]+ADDR_FREQH,chan[i].freq>>8); immWrite(chanOffs[i]+ADDR_FREQH,chan[i].freq>>8);
immWrite(chanOffs[i]+ADDR_FREQ,chan[i].freq&0xff); immWrite(chanOffs[i]+ADDR_FREQ,chan[i].freq&0xff);
@ -971,7 +980,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_NOTE_PORTA: { case DIV_CMD_NOTE_PORTA: {
if (c.chan>5) { // PSG, ADPCM-B if (c.chan>5 || parent->song.linearPitch==2) { // PSG, ADPCM-B
int destFreq=NOTE_OPNB(c.chan,c.value2); int destFreq=NOTE_OPNB(c.chan,c.value2);
bool return2=false; bool return2=false;
if (destFreq>chan[c.chan].baseFreq) { if (destFreq>chan[c.chan].baseFreq) {

View File

@ -120,6 +120,29 @@ int DivPlatformYM2610BExt::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_NOTE_PORTA: { case DIV_CMD_NOTE_PORTA: {
if (parent->song.linearPitch==2) {
int destFreq=NOTE_FREQUENCY(c.value2);
bool return2=false;
if (destFreq>opChan[ch].baseFreq) {
opChan[ch].baseFreq+=c.value;
if (opChan[ch].baseFreq>=destFreq) {
opChan[ch].baseFreq=destFreq;
return2=true;
}
} else {
opChan[ch].baseFreq-=c.value;
if (opChan[ch].baseFreq<=destFreq) {
opChan[ch].baseFreq=destFreq;
return2=true;
}
}
opChan[ch].freqChanged=true;
if (return2) {
//opChan[ch].inPorta=false;
return 2;
}
break;
}
int boundaryBottom=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,0,false); int boundaryBottom=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,0,false);
int boundaryTop=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,12,false); int boundaryTop=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,12,false);
int destFreq=NOTE_FNUM_BLOCK(c.value2,11); int destFreq=NOTE_FNUM_BLOCK(c.value2,11);
@ -384,17 +407,21 @@ void DivPlatformYM2610BExt::tick(bool sysTick) {
unsigned char writeMask=2; unsigned char writeMask=2;
if (extMode) for (int i=0; i<4; i++) { if (extMode) for (int i=0; i<4; i++) {
if (opChan[i].freqChanged) { if (opChan[i].freqChanged) {
int fNum=parent->calcFreq(opChan[i].baseFreq&0x7ff,opChan[i].pitch,false,4,opChan[i].pitch2); if (parent->song.linearPitch==2) {
int block=(opChan[i].baseFreq&0xf800)>>11; opChan[i].freq=parent->calcFreq(opChan[i].baseFreq,opChan[i].pitch,false,4,opChan[i].pitch2,chipClock,CHIP_FREQBASE,11);
if (fNum<0) fNum=0; } else {
if (fNum>2047) { int fNum=parent->calcFreq(opChan[i].baseFreq&0x7ff,opChan[i].pitch,false,4,opChan[i].pitch2);
while (block<7) { int block=(opChan[i].baseFreq&0xf800)>>11;
fNum>>=1; if (fNum<0) fNum=0;
block++; if (fNum>2047) {
while (block<7) {
fNum>>=1;
block++;
}
if (fNum>2047) fNum=2047;
} }
if (fNum>2047) fNum=2047; opChan[i].freq=(block<<11)|fNum;
} }
opChan[i].freq=(block<<11)|fNum;
if (opChan[i].freq>0x3fff) opChan[i].freq=0x3fff; if (opChan[i].freq>0x3fff) opChan[i].freq=0x3fff;
immWrite(opChanOffsH[i],opChan[i].freq>>8); immWrite(opChanOffsH[i],opChan[i].freq>>8);
immWrite(opChanOffsL[i],opChan[i].freq&0xff); immWrite(opChanOffsL[i],opChan[i].freq&0xff);

View File

@ -120,6 +120,29 @@ int DivPlatformYM2610Ext::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_NOTE_PORTA: { case DIV_CMD_NOTE_PORTA: {
if (parent->song.linearPitch==2) {
int destFreq=NOTE_FREQUENCY(c.value2);
bool return2=false;
if (destFreq>opChan[ch].baseFreq) {
opChan[ch].baseFreq+=c.value;
if (opChan[ch].baseFreq>=destFreq) {
opChan[ch].baseFreq=destFreq;
return2=true;
}
} else {
opChan[ch].baseFreq-=c.value;
if (opChan[ch].baseFreq<=destFreq) {
opChan[ch].baseFreq=destFreq;
return2=true;
}
}
opChan[ch].freqChanged=true;
if (return2) {
//opChan[ch].inPorta=false;
return 2;
}
break;
}
int boundaryBottom=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,0,false); int boundaryBottom=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,0,false);
int boundaryTop=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,12,false); int boundaryTop=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,12,false);
int destFreq=NOTE_FNUM_BLOCK(c.value2,11); int destFreq=NOTE_FNUM_BLOCK(c.value2,11);
@ -384,17 +407,21 @@ void DivPlatformYM2610Ext::tick(bool sysTick) {
unsigned char writeMask=2; unsigned char writeMask=2;
if (extMode) for (int i=0; i<4; i++) { if (extMode) for (int i=0; i<4; i++) {
if (opChan[i].freqChanged) { if (opChan[i].freqChanged) {
int fNum=parent->calcFreq(opChan[i].baseFreq&0x7ff,opChan[i].pitch,false,4,opChan[i].pitch2); if (parent->song.linearPitch==2) {
int block=(opChan[i].baseFreq&0xf800)>>11; opChan[i].freq=parent->calcFreq(opChan[i].baseFreq,opChan[i].pitch,false,4,opChan[i].pitch2,chipClock,CHIP_FREQBASE,11);
if (fNum<0) fNum=0; } else {
if (fNum>2047) { int fNum=parent->calcFreq(opChan[i].baseFreq&0x7ff,opChan[i].pitch,false,4,opChan[i].pitch2);
while (block<7) { int block=(opChan[i].baseFreq&0xf800)>>11;
fNum>>=1; if (fNum<0) fNum=0;
block++; if (fNum>2047) {
while (block<7) {
fNum>>=1;
block++;
}
if (fNum>2047) fNum=2047;
} }
if (fNum>2047) fNum=2047; opChan[i].freq=(block<<11)|fNum;
} }
opChan[i].freq=(block<<11)|fNum;
if (opChan[i].freq>0x3fff) opChan[i].freq=0x3fff; if (opChan[i].freq>0x3fff) opChan[i].freq=0x3fff;
immWrite(opChanOffsH[i],opChan[i].freq>>8); immWrite(opChanOffsH[i],opChan[i].freq>>8);
immWrite(opChanOffsL[i],opChan[i].freq&0xff); immWrite(opChanOffsL[i],opChan[i].freq&0xff);