From 8db53faf720800d769fcbddbb564a24d33e34ccd Mon Sep 17 00:00:00 2001 From: tildearrow Date: Fri, 22 Apr 2022 04:23:52 -0500 Subject: [PATCH] new FM frequency calculation experiments --- src/engine/dispatch.h | 1 + src/engine/platform/genesis.cpp | 78 +++++++++--------------------- src/engine/platform/genesis.h | 3 -- src/engine/platform/genesisext.cpp | 66 +++++++++++-------------- 4 files changed, 51 insertions(+), 97 deletions(-) diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index c35ff919..b358c464 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -426,6 +426,7 @@ class DivDispatch { #define NOTE_PERIODIC(x) round(parent->calcBaseFreq(chipClock,CHIP_DIVIDER,x,true)) #define NOTE_PERIODIC_NOROUND(x) parent->calcBaseFreq(chipClock,CHIP_DIVIDER,x,true) #define NOTE_FREQUENCY(x) parent->calcBaseFreq(chipClock,CHIP_FREQBASE,x,false) +#define NOTE_FNUM_BLOCK(x,bits) ((((int)parent->calcBaseFreq(chipClock,CHIP_FREQBASE,(x)%12,false))&((1<calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq)); - if (chan[i].freq>262143) chan[i].freq=262143; - int freqt=toFreq(chan[i].freq)+chan[i].std.pitch.val; + chan[i].freq=((chan[i].baseFreq&0xf800)|parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,false))+chan[i].std.pitch.val; + if (chan[i].freq>65535) chan[i].freq=65535; + int freqt=chan[i].freq; immWrite(chanOffs[i]+ADDR_FREQH,freqt>>8); immWrite(chanOffs[i]+ADDR_FREQ,freqt&0xff); if (chan[i].furnaceDac && dacMode) { @@ -422,47 +422,6 @@ void DivPlatformGenesis::tick(bool sysTick) { } } -int DivPlatformGenesis::octave(int freq) { - if (freq>=82432) { - return 128; - } else if (freq>=41216) { - return 64; - } else if (freq>=20608) { - return 32; - } else if (freq>=10304) { - return 16; - } else if (freq>=5152) { - return 8; - } else if (freq>=2576) { - return 4; - } else if (freq>=1288) { - return 2; - } else { - return 1; - } - return 1; -} - -int DivPlatformGenesis::toFreq(int freq) { - if (freq>=82432) { - return 0x3800|((freq>>7)&0x7ff); - } else if (freq>=41216) { - return 0x3000|((freq>>6)&0x7ff); - } else if (freq>=20608) { - return 0x2800|((freq>>5)&0x7ff); - } else if (freq>=10304) { - return 0x2000|((freq>>4)&0x7ff); - } else if (freq>=5152) { - return 0x1800|((freq>>3)&0x7ff); - } else if (freq>=2576) { - return 0x1000|((freq>>2)&0x7ff); - } else if (freq>=1288) { - return 0x800|((freq>>1)&0x7ff); - } else { - return freq&0x7ff; - } -} - void DivPlatformGenesis::muteChannel(int ch, bool mute) { isMuted[ch]=mute; for (int j=0; j<4; j++) { @@ -509,7 +468,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) { dacPos=0; dacPeriod=0; if (c.value!=DIV_NOTE_NULL) { - chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value); + chan[c.chan].baseFreq=NOTE_FNUM_BLOCK(c.value,11); chan[c.chan].freqChanged=true; } chan[c.chan].furnaceDac=true; @@ -576,7 +535,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) { chan[c.chan].insChanged=false; if (c.value!=DIV_NOTE_NULL) { - chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value); + chan[c.chan].baseFreq=NOTE_FNUM_BLOCK(c.value,11); chan[c.chan].portaPause=false; chan[c.chan].note=c.value; chan[c.chan].freqChanged=true; @@ -656,26 +615,33 @@ int DivPlatformGenesis::dispatch(DivCommand c) { break; } case DIV_CMD_NOTE_PORTA: { - int destFreq=NOTE_FREQUENCY(c.value2); + int destFreq=NOTE_FNUM_BLOCK(c.value2,11); int newFreq; bool return2=false; if (destFreq>chan[c.chan].baseFreq) { - newFreq=chan[c.chan].baseFreq+c.value*octave(chan[c.chan].baseFreq); + newFreq=chan[c.chan].baseFreq+c.value; if (newFreq>=destFreq) { newFreq=destFreq; return2=true; } } else { - newFreq=chan[c.chan].baseFreq-c.value*octave(chan[c.chan].baseFreq); + newFreq=chan[c.chan].baseFreq-c.value; if (newFreq<=destFreq) { newFreq=destFreq; return2=true; } } + // check for octave boundary if (!chan[c.chan].portaPause) { - if (octave(chan[c.chan].baseFreq)!=octave(newFreq)) { - chan[c.chan].portaPause=true; - break; + if ((newFreq&0x7ff)>1288) { + newFreq=((newFreq&0x7ff)>>1)|((newFreq+0x800)&0xf800); + /*chan[c.chan].portaPause=true; + break;*/ + } + if ((newFreq&0x7ff)<644) { + newFreq=(newFreq&0x7ff)<<1|((newFreq-0x800)&0xf800); + /*chan[c.chan].portaPause=true; + break;*/ } } chan[c.chan].baseFreq=newFreq; @@ -699,7 +665,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) { } break; case DIV_CMD_LEGATO: { - chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value); + chan[c.chan].baseFreq=NOTE_FNUM_BLOCK(c.value,11); chan[c.chan].note=c.value; chan[c.chan].freqChanged=true; break; diff --git a/src/engine/platform/genesis.h b/src/engine/platform/genesis.h index 34db5a25..ce52c6df 100644 --- a/src/engine/platform/genesis.h +++ b/src/engine/platform/genesis.h @@ -93,9 +93,6 @@ class DivPlatformGenesis: public DivDispatch { short oldWrites[512]; short pendingWrites[512]; - int octave(int freq); - int toFreq(int freq); - friend void putDispatchChan(void*,int,int); void acquire_nuked(short* bufL, short* bufR, size_t start, size_t len); diff --git a/src/engine/platform/genesisext.cpp b/src/engine/platform/genesisext.cpp index f0369370..db51f5ea 100644 --- a/src/engine/platform/genesisext.cpp +++ b/src/engine/platform/genesisext.cpp @@ -72,7 +72,7 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { opChan[ch].insChanged=false; if (c.value!=DIV_NOTE_NULL) { - opChan[ch].baseFreq=NOTE_FREQUENCY(c.value); + opChan[ch].baseFreq=NOTE_FNUM_BLOCK(c.value,11); opChan[ch].portaPause=false; opChan[ch].freqChanged=true; } @@ -127,31 +127,46 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { break; } case DIV_CMD_NOTE_PORTA: { - int destFreq=NOTE_FREQUENCY(c.value2); + int destFreq=NOTE_FNUM_BLOCK(c.value2,11); int newFreq; bool return2=false; if (destFreq>opChan[ch].baseFreq) { - newFreq=opChan[ch].baseFreq+c.value*octave(opChan[ch].baseFreq); + newFreq=opChan[ch].baseFreq+c.value; if (newFreq>=destFreq) { newFreq=destFreq; return2=true; } } else { - newFreq=opChan[ch].baseFreq-c.value*octave(opChan[ch].baseFreq); + newFreq=opChan[ch].baseFreq-c.value; if (newFreq<=destFreq) { newFreq=destFreq; return2=true; } } if (!opChan[ch].portaPause) { - if (octave(opChan[ch].baseFreq)!=octave(newFreq)) { + opChan[ch].freqChanged=true; + if ((newFreq&0x7ff)>1288) { + newFreq=((newFreq&0x7ff)>>1)|((newFreq+0x800)&0xf800); opChan[ch].portaPause=true; - break; + opChan[ch].freqChanged=false; + return2=false; + if (ch==3) printf("%d: upper bound\n",ch); + //break; } + if ((newFreq&0x7ff)<644) { + newFreq=(newFreq&0x7ff)<<1|((newFreq-0x800)&0xf800); + opChan[ch].portaPause=true; + opChan[ch].freqChanged=false; + return2=false; + if (ch==3) printf("%d: lower bound\n",ch); + //break; + } + } else { + opChan[ch].portaPause=false; + opChan[ch].freqChanged=true; } + if (ch==3) printf("%d: writing %.4x to freq\n",ch,newFreq); opChan[ch].baseFreq=newFreq; - opChan[ch].portaPause=false; - opChan[ch].freqChanged=true; if (return2) return 2; break; } @@ -172,7 +187,7 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { } break; case DIV_CMD_LEGATO: { - opChan[ch].baseFreq=NOTE_FREQUENCY(c.value); + opChan[ch].baseFreq=NOTE_FNUM_BLOCK(c.value,11); opChan[ch].freqChanged=true; break; } @@ -289,35 +304,10 @@ void DivPlatformGenesisExt::tick(bool sysTick) { unsigned char writeMask=2; if (extMode) for (int i=0; i<4; i++) { if (opChan[i].freqChanged) { - opChan[i].freq=parent->calcFreq(opChan[i].baseFreq,opChan[i].pitch); - if (opChan[i].freq>262143) opChan[i].freq=262143; - if (opChan[i].freq>=82432) { - opChan[i].freqH=((opChan[i].freq>>15)&7)|0x38; - opChan[i].freqL=(opChan[i].freq>>7)&0xff; - } else if (opChan[i].freq>=41216) { - opChan[i].freqH=((opChan[i].freq>>14)&7)|0x30; - opChan[i].freqL=(opChan[i].freq>>6)&0xff; - } else if (opChan[i].freq>=20608) { - opChan[i].freqH=((opChan[i].freq>>13)&7)|0x28; - opChan[i].freqL=(opChan[i].freq>>5)&0xff; - } else if (opChan[i].freq>=10304) { - opChan[i].freqH=((opChan[i].freq>>12)&7)|0x20; - opChan[i].freqL=(opChan[i].freq>>4)&0xff; - } else if (opChan[i].freq>=5152) { - opChan[i].freqH=((opChan[i].freq>>11)&7)|0x18; - opChan[i].freqL=(opChan[i].freq>>3)&0xff; - } else if (opChan[i].freq>=2576) { - opChan[i].freqH=((opChan[i].freq>>10)&7)|0x10; - opChan[i].freqL=(opChan[i].freq>>2)&0xff; - } else if (opChan[i].freq>=1288) { - opChan[i].freqH=((opChan[i].freq>>9)&7)|0x08; - opChan[i].freqL=(opChan[i].freq>>1)&0xff; - } else { - opChan[i].freqH=(opChan[i].freq>>8)&7; - opChan[i].freqL=opChan[i].freq&0xff; - } - immWrite(opChanOffsH[i],opChan[i].freqH); - immWrite(opChanOffsL[i],opChan[i].freqL); + opChan[i].freq=(opChan[i].baseFreq&0xf800)|parent->calcFreq(opChan[i].baseFreq&0x7ff,opChan[i].pitch); + if (chan[i].freq>65535) chan[i].freq=65535; + immWrite(opChanOffsH[i],opChan[i].freq>>8); + immWrite(opChanOffsL[i],opChan[i].freq&0xff); } writeMask|=opChan[i].active<<(4+i); if (opChan[i].keyOn) {