diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 0ec3a295b..c6486f26b 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -384,7 +384,8 @@ class DivDispatch { virtual ~DivDispatch(); }; -#define NOTE_PERIODIC(x) parent->calcBaseFreq(chipClock,CHIP_DIVIDER,x,true) +#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 COLOR_NTSC (315000000.0/88.0) diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index e0c149752..48f88bfa1 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -815,11 +815,19 @@ void DivEngine::playSub(bool preserveDrift, int goalRow) { cmdStream.clear(); } +/* int DivEngine::calcBaseFreq(double clock, double divider, int note, bool period) { double base=(period?(song.tuning*0.0625):song.tuning)*pow(2.0,(float)(note+3)/12.0); return period? round((clock/base)/divider): base*(divider/clock); +}*/ + +double DivEngine::calcBaseFreq(double clock, double divider, int note, bool period) { + double base=(period?(song.tuning*0.0625):song.tuning)*pow(2.0,(float)(note+3)/12.0); + return period? + (clock/base)/divider: + base*(divider/clock); } int DivEngine::calcFreq(int base, int pitch, bool period, int octave) { diff --git a/src/engine/engine.h b/src/engine/engine.h index 1aa2b0c53..1eca56123 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -326,7 +326,7 @@ class DivEngine { void setConf(String key, String value); // calculate base frequency/period - int calcBaseFreq(double clock, double divider, int note, bool period); + double calcBaseFreq(double clock, double divider, int note, bool period); // calculate frequency/period int calcFreq(int base, int pitch, bool period=false, int octave=0); diff --git a/src/engine/platform/amiga.cpp b/src/engine/platform/amiga.cpp index d160d1125..13cb9604c 100644 --- a/src/engine/platform/amiga.cpp +++ b/src/engine/platform/amiga.cpp @@ -131,15 +131,15 @@ void DivPlatformAmiga::tick() { if (chan[i].std.hadArp) { if (!chan[i].inPorta) { if (chan[i].std.arpMode) { - chan[i].baseFreq=off*NOTE_PERIODIC(chan[i].std.arp); + chan[i].baseFreq=round(off*NOTE_PERIODIC_NOROUND(chan[i].std.arp)); } else { - chan[i].baseFreq=off*NOTE_PERIODIC(chan[i].note+chan[i].std.arp); + chan[i].baseFreq=round(off*NOTE_PERIODIC_NOROUND(chan[i].note+chan[i].std.arp)); } } chan[i].freqChanged=true; } else { if (chan[i].std.arpMode && chan[i].std.finishedArp) { - chan[i].baseFreq=off*NOTE_PERIODIC(chan[i].note); + chan[i].baseFreq=round(off*NOTE_PERIODIC_NOROUND(chan[i].note)); chan[i].freqChanged=true; } } @@ -183,7 +183,7 @@ int DivPlatformAmiga::dispatch(DivCommand c) { } } if (c.value!=DIV_NOTE_NULL) { - chan[c.chan].baseFreq=off*NOTE_PERIODIC(c.value); + chan[c.chan].baseFreq=round(off*NOTE_PERIODIC_NOROUND(c.value)); } if (chan[c.chan].sample<0 || chan[c.chan].sample>=parent->song.sampleLen) { chan[c.chan].sample=-1; @@ -241,7 +241,18 @@ int DivPlatformAmiga::dispatch(DivCommand c) { chan[c.chan].keyOn=true; break; case DIV_CMD_NOTE_PORTA: { - int destFreq=NOTE_PERIODIC(c.value2); + DivInstrument* ins=parent->getIns(chan[c.chan].ins); + chan[c.chan].sample=ins->amiga.initSample; + double off=1.0; + if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { + DivSample* s=parent->getSample(chan[c.chan].sample); + if (s->centerRate<1) { + off=1.0; + } else { + off=8363.0/(double)s->centerRate; + } + } + int destFreq=round(off*NOTE_PERIODIC_NOROUND(c.value2)); bool return2=false; if (destFreq>chan[c.chan].baseFreq) { chan[c.chan].baseFreq+=c.value; @@ -273,7 +284,7 @@ int DivPlatformAmiga::dispatch(DivCommand c) { off=8363.0/(double)s->centerRate; } } - chan[c.chan].baseFreq=off*NOTE_PERIODIC(c.value+((chan[c.chan].std.willArp && !chan[c.chan].std.arpMode)?(chan[c.chan].std.arp-12):(0))); + chan[c.chan].baseFreq=round(off*NOTE_PERIODIC_NOROUND(c.value+((chan[c.chan].std.willArp && !chan[c.chan].std.arpMode)?(chan[c.chan].std.arp-12):(0)))); chan[c.chan].freqChanged=true; chan[c.chan].note=c.value; break; diff --git a/src/engine/platform/segapcm.cpp b/src/engine/platform/segapcm.cpp index c0366a18a..361cef63c 100644 --- a/src/engine/platform/segapcm.cpp +++ b/src/engine/platform/segapcm.cpp @@ -87,15 +87,15 @@ void DivPlatformSegaPCM::tick() { if (chan[i].std.hadArp) { if (!chan[i].inPorta) { if (chan[i].std.arpMode) { - chan[i].baseFreq=(chan[i].std.arp<<6)+baseFreqOff; + chan[i].baseFreq=(chan[i].std.arp<<6); } else { - chan[i].baseFreq=((chan[i].note+(signed char)chan[i].std.arp)<<6)+baseFreqOff; + chan[i].baseFreq=((chan[i].note+(signed char)chan[i].std.arp)<<6); } } chan[i].freqChanged=true; } else { if (chan[i].std.arpMode && chan[i].std.finishedArp) { - chan[i].baseFreq=(chan[i].note<<6)+baseFreqOff; + chan[i].baseFreq=(chan[i].note<<6); chan[i].freqChanged=true; } } @@ -113,7 +113,7 @@ void DivPlatformSegaPCM::tick() { DivSample* s=parent->getSample(chan[i].pcm.sample); off=(double)s->centerRate/8363.0; } - chan[i].pcm.freq=MIN(255,((off*parent->song.tuning*pow(2.0,double(chan[i].freq+256)/(64.0*12.0)))*255)/31250); + chan[i].pcm.freq=MIN(255,(15625+(off*parent->song.tuning*pow(2.0,double(chan[i].freq+256)/(64.0*12.0)))*255)/31250); if (dumpWrites && i>=8) { addWrite(0x10007+((i-8)<<3),chan[i].pcm.freq); } @@ -250,17 +250,17 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) { break; } case DIV_CMD_NOTE_PORTA: { - int destFreq=(c.value2<<6)+baseFreqOff; + int destFreq=(c.value2<<6); int newFreq; bool return2=false; if (destFreq>chan[c.chan].baseFreq) { - newFreq=chan[c.chan].baseFreq+c.value; + newFreq=chan[c.chan].baseFreq+c.value*4; if (newFreq>=destFreq) { newFreq=destFreq; return2=true; } } else { - newFreq=chan[c.chan].baseFreq-c.value; + newFreq=chan[c.chan].baseFreq-c.value*4; if (newFreq<=destFreq) { newFreq=destFreq; return2=true; @@ -275,7 +275,7 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) { break; } case DIV_CMD_LEGATO: { - chan[c.chan].baseFreq=(c.value<<6)+baseFreqOff; + chan[c.chan].baseFreq=(c.value<<6); chan[c.chan].freqChanged=true; break; }