From 66f5b2117fb1df254d8e96c8cef90866fe35d12c Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 28 Apr 2022 00:26:21 -0500 Subject: [PATCH] dev90 - linear pitch macro option --- papers/format.md | 8 +++++++- src/engine/engine.cpp | 19 +++++++++++++------ src/engine/engine.h | 6 +++--- src/engine/fileOps.cpp | 13 +++++++++++-- src/engine/platform/amiga.cpp | 2 +- src/engine/platform/ay.cpp | 2 +- src/engine/platform/ay8930.cpp | 2 +- src/engine/platform/c64.cpp | 2 +- src/engine/platform/fds.cpp | 2 +- src/engine/platform/gb.cpp | 2 +- src/engine/platform/genesis.cpp | 2 +- src/engine/platform/genesisext.cpp | 2 +- src/engine/platform/lynx.cpp | 2 +- src/engine/platform/mmc5.cpp | 2 +- src/engine/platform/n163.cpp | 2 +- src/engine/platform/nes.cpp | 2 +- src/engine/platform/opl.cpp | 2 +- src/engine/platform/opll.cpp | 2 +- src/engine/platform/pce.cpp | 2 +- src/engine/platform/pcspkr.cpp | 2 +- src/engine/platform/pet.cpp | 2 +- src/engine/platform/qsound.cpp | 2 +- src/engine/platform/saa.cpp | 2 +- src/engine/platform/sms.cpp | 4 ++-- src/engine/platform/su.cpp | 2 +- src/engine/platform/swan.cpp | 2 +- src/engine/platform/vera.cpp | 2 +- src/engine/platform/vic20.cpp | 2 +- src/engine/platform/vrc6.cpp | 4 ++-- src/engine/platform/x1_010.cpp | 2 +- src/engine/platform/ym2610.cpp | 2 +- src/engine/platform/ym2610b.cpp | 2 +- src/engine/song.h | 4 +++- src/gui/compatFlags.cpp | 4 ++++ 34 files changed, 71 insertions(+), 43 deletions(-) diff --git a/papers/format.md b/papers/format.md index 8d977e84c..feafbe603 100644 --- a/papers/format.md +++ b/papers/format.md @@ -29,6 +29,9 @@ furthermore, an `or reserved` indicates this field is always present, but is res the format versions are: +- 90: Furnace dev90 +- 89: Furnace dev89 +- 88: Furnace dev88 - 87: Furnace dev87 - 86: Furnace dev86 - 85: Furnace dev85 @@ -280,7 +283,8 @@ size | description 1 | new Sega PCM (with macros and proper vol/pan) (>=84) or reserved 1 | weird f-num/block-based chip pitch slides (>=85) or reserved 1 | SN duty macro always resets phase (>=86) or reserved - 20 | reserved + 1 | pitch macro is linear (>=90) or reserved + 19 | reserved ``` # instrument @@ -669,6 +673,8 @@ size | description 1 | parameter 2 1 | parameter 3 1 | parameter 4 + --- | **extra C64 data** (>=89) + 1 | don't test/gate before new note ``` # wavetable diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 3177432cf..b2c0257f6 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -914,21 +914,28 @@ unsigned short DivEngine::calcBaseFreqFNumBlock(double clock, double divider, in return bf|(block<4095) pitch=4095; - return period? - ((base*(reversePitchTable[pitch]))/whatTheFuck): - (((base*(pitchTable[pitch]))>>10)*whatTheFuck)/1024; + int ret=period? + ((base*(reversePitchTable[pitch]))/whatTheFuck): + (((base*(pitchTable[pitch]))>>10)*whatTheFuck)/1024; + if (!song.pitchMacroIsLinear) { + ret+=period?(-pitch2):pitch2; + } + return ret; } return period? - base-pitch: - base+((pitch*octave)>>1); + base-pitch-pitch2: + base+((pitch*octave)>>1)+pitch2; } void DivEngine::play() { diff --git a/src/engine/engine.h b/src/engine/engine.h index bab5dcd03..7aa94fc58 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -44,8 +44,8 @@ #define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock(); #define BUSY_END isBusy.unlock(); softLocked=false; -#define DIV_VERSION "dev89" -#define DIV_ENGINE_VERSION 89 +#define DIV_VERSION "dev90" +#define DIV_ENGINE_VERSION 90 // for imports #define DIV_VERSION_MOD 0xff01 @@ -468,7 +468,7 @@ class DivEngine { unsigned short calcBaseFreqFNumBlock(double clock, double divider, int note, int bits); // calculate frequency/period - int calcFreq(int base, int pitch, bool period=false, int octave=0); + int calcFreq(int base, int pitch, bool period=false, int octave=0, int pitch2=0); // find song loop position void walkSong(int& loopOrder, int& loopRow, int& loopEnd); diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index 16678c49b..cfd23e1fb 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -1011,6 +1011,9 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { if (ds.version<86) { ds.snDutyReset=true; } + if (ds.version<90) { + ds.pitchMacroIsLinear=false; + } ds.isDMF=false; reader.readS(); // reserved @@ -1372,7 +1375,12 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { } else { reader.readC(); } - for (int i=0; i<20; i++) { + if (ds.version>=90) { + ds.pitchMacroIsLinear=reader.readC(); + } else { + reader.readC(); + } + for (int i=0; i<19; i++) { reader.readC(); } } @@ -2317,7 +2325,8 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) { w->writeC(song.newSegaPCM); w->writeC(song.fbPortaPause); w->writeC(song.snDutyReset); - for (int i=0; i<20; i++) { + w->writeC(song.pitchMacroIsLinear); + for (int i=0; i<19; i++) { w->writeC(0); } diff --git a/src/engine/platform/amiga.cpp b/src/engine/platform/amiga.cpp index 1212b15d0..ac76e193a 100644 --- a/src/engine/platform/amiga.cpp +++ b/src/engine/platform/amiga.cpp @@ -207,7 +207,7 @@ void DivPlatformAmiga::tick(bool sysTick) { } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { //DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_AMIGA); - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); if (chan[i].freq>4095) chan[i].freq=4095; if (chan[i].freq<0) chan[i].freq=0; if (chan[i].keyOn) { diff --git a/src/engine/platform/ay.cpp b/src/engine/platform/ay.cpp index 4ba384832..fc2a36ab6 100644 --- a/src/engine/platform/ay.cpp +++ b/src/engine/platform/ay.cpp @@ -239,7 +239,7 @@ void DivPlatformAY8910::tick(bool sysTick) { if (!chan[i].std.ex3.will) chan[i].autoEnvNum=1; } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); if (chan[i].freq>4095) chan[i].freq=4095; if (chan[i].keyOn) { //rWrite(16+i*5+1,((chan[i].duty&3)<<6)|(63-(ins->gb.soundLen&63))); diff --git a/src/engine/platform/ay8930.cpp b/src/engine/platform/ay8930.cpp index 640b495b3..03e99961d 100644 --- a/src/engine/platform/ay8930.cpp +++ b/src/engine/platform/ay8930.cpp @@ -261,7 +261,7 @@ void DivPlatformAY8930::tick(bool sysTick) { immWrite(0x1a,ayNoiseOr); } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); if (chan[i].freq>65535) chan[i].freq=65535; if (chan[i].keyOn) { if (chan[i].insChanged) { diff --git a/src/engine/platform/c64.cpp b/src/engine/platform/c64.cpp index d893283fc..3515f0465 100644 --- a/src/engine/platform/c64.cpp +++ b/src/engine/platform/c64.cpp @@ -205,7 +205,7 @@ void DivPlatformC64::tick(bool sysTick) { } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,8)+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,8,chan[i].std.pitch.val); if (chan[i].freq>0xffff) chan[i].freq=0xffff; if (chan[i].keyOn) { rWrite(i*7+5,(chan[i].attack<<4)|(chan[i].decay)); diff --git a/src/engine/platform/fds.cpp b/src/engine/platform/fds.cpp index 2c3512137..845e72475 100644 --- a/src/engine/platform/fds.cpp +++ b/src/engine/platform/fds.cpp @@ -177,7 +177,7 @@ void DivPlatformFDS::tick(bool sysTick) { } } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false)+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].std.pitch.val); if (chan[i].freq>4095) chan[i].freq=4095; if (chan[i].freq<0) chan[i].freq=0; if (chan[i].keyOn) { diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index b9668d58a..ded7b493c 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -227,7 +227,7 @@ void DivPlatformGB::tick(bool sysTick) { if (ntPos>255) ntPos=255; chan[i].freq=noiseTable[ntPos]; } else { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); if (chan[i].freq>2047) chan[i].freq=2047; if (chan[i].freq<0) chan[i].freq=0; } diff --git a/src/engine/platform/genesis.cpp b/src/engine/platform/genesis.cpp index 72dc9c0fb..80c51d950 100644 --- a/src/engine/platform/genesis.cpp +++ b/src/engine/platform/genesis.cpp @@ -410,7 +410,7 @@ void DivPlatformGenesis::tick(bool sysTick) { for (int i=0; i<6; i++) { if (i==2 && extMode) continue; if (chan[i].freqChanged) { - int fNum=parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,false,4)+chan[i].std.pitch.val; + int fNum=parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,false,4,chan[i].std.pitch.val); int block=(chan[i].baseFreq&0xf800)>>11; if (fNum<0) fNum=0; if (fNum>2047) { diff --git a/src/engine/platform/genesisext.cpp b/src/engine/platform/genesisext.cpp index 59b77587b..d77857a66 100644 --- a/src/engine/platform/genesisext.cpp +++ b/src/engine/platform/genesisext.cpp @@ -307,7 +307,7 @@ void DivPlatformGenesisExt::tick(bool sysTick) { unsigned char writeMask=2; if (extMode) for (int i=0; i<4; i++) { if (opChan[i].freqChanged) { - int fNum=parent->calcFreq(opChan[i].baseFreq&0x7ff,opChan[i].pitch,false,4)+opChan[i].std.pitch.val; + int fNum=parent->calcFreq(opChan[i].baseFreq&0x7ff,opChan[i].pitch,false,4,opChan[i].std.pitch.val); int block=(opChan[i].baseFreq&0xf800)>>11; if (fNum<0) fNum=0; if (fNum>2047) { diff --git a/src/engine/platform/lynx.cpp b/src/engine/platform/lynx.cpp index 4c688103c..f70198b6e 100644 --- a/src/engine/platform/lynx.cpp +++ b/src/engine/platform/lynx.cpp @@ -195,7 +195,7 @@ void DivPlatformLynx::tick(bool sysTick) { WRITE_OTHER(i, ((chan[i].lfsr&0xf00)>>4)); chan[i].lfsr=-1; } - chan[i].fd=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val; + chan[i].fd=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); if (chan[i].std.duty.had) { chan[i].duty=chan[i].std.duty.val; WRITE_FEEDBACK(i, chan[i].duty.feedback); diff --git a/src/engine/platform/mmc5.cpp b/src/engine/platform/mmc5.cpp index cf1ea36d6..dc8c15063 100644 --- a/src/engine/platform/mmc5.cpp +++ b/src/engine/platform/mmc5.cpp @@ -133,7 +133,7 @@ void DivPlatformMMC5::tick(bool sysTick) { } } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)-1+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val)-1; if (chan[i].freq>2047) chan[i].freq=2047; if (chan[i].freq<0) chan[i].freq=0; if (chan[i].keyOn) { diff --git a/src/engine/platform/n163.cpp b/src/engine/platform/n163.cpp index a00d4d05d..34515305e 100644 --- a/src/engine/platform/n163.cpp +++ b/src/engine/platform/n163.cpp @@ -347,7 +347,7 @@ void DivPlatformN163::tick(bool sysTick) { chan[i].waveUpdated=false; } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { - chan[i].freq=parent->calcFreq((((chan[i].baseFreq*chan[i].waveLen)*(chanMax+1))/16),chan[i].pitch,false,0)+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq((((chan[i].baseFreq*chan[i].waveLen)*(chanMax+1))/16),chan[i].pitch,false,0,chan[i].std.pitch.val); if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq>0x3ffff) chan[i].freq=0x3ffff; if (chan[i].keyOn) { diff --git a/src/engine/platform/nes.cpp b/src/engine/platform/nes.cpp index cebd39e2d..c54127874 100644 --- a/src/engine/platform/nes.cpp +++ b/src/engine/platform/nes.cpp @@ -217,7 +217,7 @@ void DivPlatformNES::tick(bool sysTick) { if (ntPos>252) ntPos=252; chan[i].freq=(parent->song.properNoiseLayout)?(15-(chan[i].baseFreq&15)):(noiseTable[ntPos]); } else { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)-1+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val)-1; if (chan[i].freq>2047) chan[i].freq=2047; if (chan[i].freq<0) chan[i].freq=0; } diff --git a/src/engine/platform/opl.cpp b/src/engine/platform/opl.cpp index fac157da3..1e727fa66 100644 --- a/src/engine/platform/opl.cpp +++ b/src/engine/platform/opl.cpp @@ -417,7 +417,7 @@ void DivPlatformOPL::tick(bool sysTick) { bool updateDrums=false; for (int i=0; icalcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq)); + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq),chan[i].std.pitch.val); if (chan[i].freq>131071) chan[i].freq=131071; int freqt=toFreq(chan[i].freq)+chan[i].std.pitch.val; chan[i].freqH=freqt>>8; diff --git a/src/engine/platform/opll.cpp b/src/engine/platform/opll.cpp index a02bc8de2..c2e1342bd 100644 --- a/src/engine/platform/opll.cpp +++ b/src/engine/platform/opll.cpp @@ -261,7 +261,7 @@ void DivPlatformOPLL::tick(bool sysTick) { for (int i=0; i<11; i++) { if (chan[i].freqChanged) { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq)); + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq),chan[i].std.pitch.val); if (chan[i].freq>262143) chan[i].freq=262143; int freqt=toFreq(chan[i].freq)+chan[i].std.pitch.val; chan[i].freqL=freqt&0xff; diff --git a/src/engine/platform/pce.cpp b/src/engine/platform/pce.cpp index 016b3b3c4..5178cad36 100644 --- a/src/engine/platform/pce.cpp +++ b/src/engine/platform/pce.cpp @@ -217,7 +217,7 @@ void DivPlatformPCE::tick(bool sysTick) { } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { //DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_PCE); - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); if (chan[i].furnaceDac) { double off=1.0; if (chan[i].dacSample>=0 && chan[i].dacSamplesong.sampleLen) { diff --git a/src/engine/platform/pcspkr.cpp b/src/engine/platform/pcspkr.cpp index 8a00c5638..1a4b2ee06 100644 --- a/src/engine/platform/pcspkr.cpp +++ b/src/engine/platform/pcspkr.cpp @@ -193,7 +193,7 @@ void DivPlatformPCSpeaker::tick(bool sysTick) { chan[i].freqChanged=true; } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)-1+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val)-1; if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq>65535) chan[i].freq=65535; if (chan[i].keyOn) { diff --git a/src/engine/platform/pet.cpp b/src/engine/platform/pet.cpp index 0e83e9d21..eb954a6e1 100644 --- a/src/engine/platform/pet.cpp +++ b/src/engine/platform/pet.cpp @@ -116,7 +116,7 @@ void DivPlatformPET::tick(bool sysTick) { chan.freqChanged=true; } if (chan.freqChanged || chan.keyOn || chan.keyOff) { - chan.freq=parent->calcFreq(chan.baseFreq,chan.pitch,true)+chan.std.pitch.val; + chan.freq=parent->calcFreq(chan.baseFreq,chan.pitch,true,0,chan.std.pitch.val); if (chan.freq>257) chan.freq=257; if (chan.freq<2) chan.freq=2; rWrite(8,chan.freq-2); diff --git a/src/engine/platform/qsound.cpp b/src/engine/platform/qsound.cpp index b5d194ffc..fa31caa81 100644 --- a/src/engine/platform/qsound.cpp +++ b/src/engine/platform/qsound.cpp @@ -331,7 +331,7 @@ void DivPlatformQSound::tick(bool sysTick) { } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { //DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_AMIGA); - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false)+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].std.pitch.val); if (chan[i].freq>0xffff) chan[i].freq=0xffff; if (chan[i].keyOn) { rWrite(q1_reg_map[Q1V_BANK][i], qsound_bank); diff --git a/src/engine/platform/saa.cpp b/src/engine/platform/saa.cpp index f21c7d5b4..2d4986b58 100644 --- a/src/engine/platform/saa.cpp +++ b/src/engine/platform/saa.cpp @@ -194,7 +194,7 @@ void DivPlatformSAA1099::tick(bool sysTick) { rWrite(0x18+(i/3),saaEnv[i/3]); } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); if (chan[i].freq>65535) chan[i].freq=65535; if (chan[i].freq>=32768) { chan[i].freqH=7; diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index c32548b56..faf5ba7d6 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -106,7 +106,7 @@ void DivPlatformSMS::tick(bool sysTick) { } for (int i=0; i<3; i++) { if (chan[i].freqChanged) { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); if (chan[i].freq>1023) chan[i].freq=1023; if (chan[i].freq<8) chan[i].freq=1; //if (chan[i].actualNote>0x5d) chan[i].freq=0x01; @@ -121,7 +121,7 @@ void DivPlatformSMS::tick(bool sysTick) { } } if (chan[3].freqChanged || updateSNMode) { - chan[3].freq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch,true)+chan[3].std.pitch.val; + chan[3].freq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch,true,0,chan[3].std.pitch.val); if (chan[3].freq>1023) chan[3].freq=1023; if (chan[3].actualNote>0x5d) chan[3].freq=0x01; if (snNoiseMode&2) { // take period from channel 3 diff --git a/src/engine/platform/su.cpp b/src/engine/platform/su.cpp index 2dca4b3ca..1f47a1629 100644 --- a/src/engine/platform/su.cpp +++ b/src/engine/platform/su.cpp @@ -168,7 +168,7 @@ void DivPlatformSoundUnit::tick(bool sysTick) { } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { //DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SU); - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false)+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].std.pitch.val); chWrite(i,0x00,chan[i].freq&0xff); chWrite(i,0x01,chan[i].freq>>8); if (chan[i].freq>65535) chan[i].freq=65535; diff --git a/src/engine/platform/swan.cpp b/src/engine/platform/swan.cpp index 86ad9b109..96752bd5a 100644 --- a/src/engine/platform/swan.cpp +++ b/src/engine/platform/swan.cpp @@ -194,7 +194,7 @@ void DivPlatformSwan::tick(bool sysTick) { } } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); if (i==1 && pcm && furnaceDac) { double off=1.0; if (dacSample>=0 && dacSamplesong.sampleLen) { diff --git a/src/engine/platform/vera.cpp b/src/engine/platform/vera.cpp index 63415a0c1..7d4ea7d54 100644 --- a/src/engine/platform/vera.cpp +++ b/src/engine/platform/vera.cpp @@ -194,7 +194,7 @@ void DivPlatformVERA::tick(bool sysTick) { chan[i].freqChanged=true; } if (chan[i].freqChanged) { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,8)+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,8,chan[i].std.pitch.val); if (chan[i].freq>65535) chan[i].freq=65535; rWrite(i,0,chan[i].freq&0xff); rWrite(i,1,(chan[i].freq>>8)&0xff); diff --git a/src/engine/platform/vic20.cpp b/src/engine/platform/vic20.cpp index aa787672b..efeb0a206 100644 --- a/src/engine/platform/vic20.cpp +++ b/src/engine/platform/vic20.cpp @@ -123,7 +123,7 @@ void DivPlatformVIC20::tick(bool sysTick) { chan[i].freqChanged=true; } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val); if (i<3) { chan[i].freq>>=(2-i); } else { diff --git a/src/engine/platform/vrc6.cpp b/src/engine/platform/vrc6.cpp index 56e95948c..29fadd4c7 100644 --- a/src/engine/platform/vrc6.cpp +++ b/src/engine/platform/vrc6.cpp @@ -183,9 +183,9 @@ void DivPlatformVRC6::tick(bool sysTick) { } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (i==2) { // sawtooth - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)-1+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val)-1; } else { // pulse - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)-1+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].std.pitch.val)-1; if (chan[i].furnaceDac) { double off=1.0; if (chan[i].dacSample>=0 && chan[i].dacSamplesong.sampleLen) { diff --git a/src/engine/platform/x1_010.cpp b/src/engine/platform/x1_010.cpp index f1498709f..46db65622 100644 --- a/src/engine/platform/x1_010.cpp +++ b/src/engine/platform/x1_010.cpp @@ -476,7 +476,7 @@ void DivPlatformX1_010::tick(bool sysTick) { chan[i].envChanged=false; } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false)+chan[i].std.pitch.val; + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].std.pitch.val); if (chan[i].pcm) { if (chan[i].freq<1) chan[i].freq=1; if (chan[i].freq>255) chan[i].freq=255; diff --git a/src/engine/platform/ym2610.cpp b/src/engine/platform/ym2610.cpp index 04338d265..0af0840ab 100644 --- a/src/engine/platform/ym2610.cpp +++ b/src/engine/platform/ym2610.cpp @@ -572,7 +572,7 @@ void DivPlatformYM2610::tick(bool sysTick) { for (int i=0; i<4; i++) { if (i==1 && extMode) continue; if (chan[i].freqChanged) { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq)); + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq),chan[i].std.pitch.val); if (chan[i].freq>262143) chan[i].freq=262143; int freqt=toFreq(chan[i].freq)+chan[i].std.pitch.val; immWrite(chanOffs[i]+ADDR_FREQH,freqt>>8); diff --git a/src/engine/platform/ym2610b.cpp b/src/engine/platform/ym2610b.cpp index a250e04ce..b0e530db3 100644 --- a/src/engine/platform/ym2610b.cpp +++ b/src/engine/platform/ym2610b.cpp @@ -635,7 +635,7 @@ void DivPlatformYM2610B::tick(bool sysTick) { for (int i=0; i<6; i++) { if (i==2 && extMode) continue; if (chan[i].freqChanged) { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq)); + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq),chan[i].std.pitch.val); if (chan[i].freq>262143) chan[i].freq=262143; int freqt=toFreq(chan[i].freq)+chan[i].std.pitch.val; immWrite(chanOffs[i]+ADDR_FREQH,freqt>>8); diff --git a/src/engine/song.h b/src/engine/song.h index 317ffa9b0..087d8c7b0 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -336,6 +336,7 @@ struct DivSong { bool newSegaPCM; bool fbPortaPause; bool snDutyReset; + bool pitchMacroIsLinear; DivOrders orders; std::vector ins; @@ -441,7 +442,8 @@ struct DivSong { e1e2AlsoTakePriority(false), newSegaPCM(true), fbPortaPause(false), - snDutyReset(false) { + snDutyReset(false), + pitchMacroIsLinear(true) { for (int i=0; i<32; i++) { system[i]=DIV_SYSTEM_NULL; systemVol[i]=64; diff --git a/src/gui/compatFlags.cpp b/src/gui/compatFlags.cpp index ccaeeb3fe..52f465027 100644 --- a/src/gui/compatFlags.cpp +++ b/src/gui/compatFlags.cpp @@ -121,6 +121,10 @@ void FurnaceGUI::drawCompatFlags() { if (ImGui::IsItemHovered()) { ImGui::SetTooltip("when enabled, duty macro will always reset phase, even if its value hasn't changed."); } + ImGui::Checkbox("Pitch macro is linear",&e->song.pitchMacroIsLinear); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("when enabled, the pitch macro of an instrument is in linear space."); + } ImGui::Text("Loop modality:"); if (ImGui::RadioButton("Reset channels",e->song.loopModality==0)) {