diff --git a/src/engine/bsr.h b/src/engine/bsr.h index dcc865112..566125383 100644 --- a/src/engine/bsr.h +++ b/src/engine/bsr.h @@ -44,7 +44,7 @@ static inline int bsr32(unsigned int v) { static inline int bsr(unsigned short v) { if (v) { - return 32 - __builtin_clz(v); + return 32-__builtin_clz(v); } else { return -1; } @@ -52,7 +52,7 @@ static inline int bsr(unsigned short v) { static inline int bsr32(unsigned int v) { if (v) { - return 32 - __builtin_clz(v); + return 32-__builtin_clz(v); } else { return -1; } @@ -61,25 +61,52 @@ static inline int bsr32(unsigned int v) { #else static inline int bsr(unsigned short v) { - unsigned short mask = 0x8000; - for (int i = 16; i >= 0; --i) { - if (v&mask) - return i; - mask>>=1; + if (v==0) return -1; + if (v&0x8000) return 16; + int o=16; + if (!(v&0xff00)) { + o-=8; + v<<=8; + if (v&0x8000) return o; } - - return -1; + if (!(v&0xf000)) { + o-=4; + v<<=4; + if (v&0x8000) return o; + } + if (!(v&0xc000)) { + o-=2; + v<<=2; + if (v&0x8000) return o; + } + return (v&0x8000) ? o : o-1; } static inline int bsr32(unsigned int v) { - unsigned int mask = 0x80000000; - for (int i = 32; i >= 0; --i) { - if (v&mask) - return i; - mask>>=1; + if (v==0) return -1; + if (v&0x80000000) return 32; + int o=32; + if (!(v&0xffff0000)) { + o-=16; + v<<=16; + if (v&0x80000000) return o; } - - return -1; + if (!(v&0xff000000)) { + o-=8; + v<<=8; + if (v&0x80000000) return o; + } + if (!(v&0xf0000000)) { + o-=4; + v<<=4; + if (v&0x80000000) return o; + } + if (!(v&0xc0000000)) { + o-=2; + v<<=2; + if (v&0x80000000) return o; + } + return (v&0x80000000) ? o : o-1; } #endif diff --git a/src/engine/platform/esfm.cpp b/src/engine/platform/esfm.cpp index 3adab20f5..388fdf972 100644 --- a/src/engine/platform/esfm.cpp +++ b/src/engine/platform/esfm.cpp @@ -19,6 +19,7 @@ #include "esfm.h" #include "../engine.h" +#include "../bsr.h" #include "../../ta-log.h" #include #include @@ -366,21 +367,19 @@ void DivPlatformESFM::tick(bool sysTick) { } int DivPlatformESFM::octave(int freq) { - int result=1; - while (freq>0x3ff) { - freq>>=1; - result<<=1; + if (freq>0x3ff) { + return 1<<(bsr32(freq)-10); } - return result; + return 1; } int DivPlatformESFM::toFreq(int freq) { int block=0; - while (freq>0x3ff) { - freq>>=1; - block++; + if (freq>0x3ff) { + block=bsr32(freq)-10; + freq>>=block; } - return ((block&7)<<10)|(freq&0x3ff); + return (block<<10)|(freq&0x3ff); } void DivPlatformESFM::muteChannel(int ch, bool mute) { diff --git a/src/engine/platform/opl.cpp b/src/engine/platform/opl.cpp index 1204615dc..6ff60b69d 100644 --- a/src/engine/platform/opl.cpp +++ b/src/engine/platform/opl.cpp @@ -19,6 +19,7 @@ #include "opl.h" #include "../engine.h" +#include "../bsr.h" #include "../../ta-log.h" #include #include @@ -1386,39 +1387,12 @@ void DivPlatformOPL::tick(bool sysTick) { double off=(s->centerRate>=1)?((double)s->centerRate/8363.0):1.0; chan[i].freq=(int)(off*parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,2,chan[i].pitch2,chipClock,(524288*768))); if (chan[i].freq<0x400) chan[i].freq=0x400; - if (chan[i].freq>0x3ffffff) chan[i].freq=0x3ffffff; - if (chan[i].freq>=0x2000000) { + chan[i].freqH=0; + if (chan[i].freq>0x3ffffff) { + chan[i].freq=0x3ffffff; chan[i].freqH=15; - } else if (chan[i].freq>=0x1000000) { - chan[i].freqH=14; - } else if (chan[i].freq>=0x800000) { - chan[i].freqH=13; - } else if (chan[i].freq>=0x400000) { - chan[i].freqH=12; - } else if (chan[i].freq>=0x200000) { - chan[i].freqH=11; - } else if (chan[i].freq>=0x100000) { - chan[i].freqH=10; - } else if (chan[i].freq>=0x80000) { - chan[i].freqH=9; - } else if (chan[i].freq>=0x40000) { - chan[i].freqH=8; - } else if (chan[i].freq>=0x20000) { - chan[i].freqH=7; - } else if (chan[i].freq>=0x10000) { - chan[i].freqH=6; - } else if (chan[i].freq>=0x8000) { - chan[i].freqH=5; - } else if (chan[i].freq>=0x4000) { - chan[i].freqH=4; - } else if (chan[i].freq>=0x2000) { - chan[i].freqH=3; - } else if (chan[i].freq>=0x1000) { - chan[i].freqH=2; } else if (chan[i].freq>=0x800) { - chan[i].freqH=1; - } else { - chan[i].freqH=0; + chan[i].freqH=bsr32(chan[i].freq)-11; } chan[i].freqL=(chan[i].freq>>chan[i].freqH)&0x3ff; chan[i].freqH=8^chan[i].freqH; @@ -1528,44 +1502,15 @@ void DivPlatformOPL::tick(bool sysTick) { #define OPLL_C_NUM 686 int DivPlatformOPL::octave(int freq) { - if (freq>=OPLL_C_NUM*64) { - return 128; - } else if (freq>=OPLL_C_NUM*32) { - return 64; - } else if (freq>=OPLL_C_NUM*16) { - return 32; - } else if (freq>=OPLL_C_NUM*8) { - return 16; - } else if (freq>=OPLL_C_NUM*4) { - return 8; - } else if (freq>=OPLL_C_NUM*2) { - return 4; - } else if (freq>=OPLL_C_NUM) { - return 2; - } else { - return 1; - } - return 1; + freq/=OPLL_C_NUM; + if (freq==0) return 1; + return 1<=OPLL_C_NUM*64) { - return 0x1c00|((freq>>7)&0x3ff); - } else if (freq>=OPLL_C_NUM*32) { - return 0x1800|((freq>>6)&0x3ff); - } else if (freq>=OPLL_C_NUM*16) { - return 0x1400|((freq>>5)&0x3ff); - } else if (freq>=OPLL_C_NUM*8) { - return 0x1000|((freq>>4)&0x3ff); - } else if (freq>=OPLL_C_NUM*4) { - return 0xc00|((freq>>3)&0x3ff); - } else if (freq>=OPLL_C_NUM*2) { - return 0x800|((freq>>2)&0x3ff); - } else if (freq>=OPLL_C_NUM) { - return 0x400|((freq>>1)&0x3ff); - } else { - return freq&0x3ff; - } + int block=freq/OPLL_C_NUM; + if (block>0) block=bsr(block); + return (block<<10)|((freq>>block)&0x3ff); } void DivPlatformOPL::muteChannel(int ch, bool mute) { diff --git a/src/engine/platform/opll.cpp b/src/engine/platform/opll.cpp index fb3461622..a185d55bd 100644 --- a/src/engine/platform/opll.cpp +++ b/src/engine/platform/opll.cpp @@ -19,6 +19,7 @@ #include "opll.h" #include "../engine.h" +#include "../bsr.h" #include "../../ta-log.h" #include #include @@ -352,44 +353,15 @@ void DivPlatformOPLL::tick(bool sysTick) { #define OPLL_C_NUM 343 int DivPlatformOPLL::octave(int freq) { - if (freq>=OPLL_C_NUM*64) { - return 128; - } else if (freq>=OPLL_C_NUM*32) { - return 64; - } else if (freq>=OPLL_C_NUM*16) { - return 32; - } else if (freq>=OPLL_C_NUM*8) { - return 16; - } else if (freq>=OPLL_C_NUM*4) { - return 8; - } else if (freq>=OPLL_C_NUM*2) { - return 4; - } else if (freq>=OPLL_C_NUM) { - return 2; - } else { - return 1; - } - return 1; + freq/=OPLL_C_NUM; + if (freq==0) return 1; + return 1<=OPLL_C_NUM*64) { - return 0xe00|((freq>>7)&0x1ff); - } else if (freq>=OPLL_C_NUM*32) { - return 0xc00|((freq>>6)&0x1ff); - } else if (freq>=OPLL_C_NUM*16) { - return 0xa00|((freq>>5)&0x1ff); - } else if (freq>=OPLL_C_NUM*8) { - return 0x800|((freq>>4)&0x1ff); - } else if (freq>=OPLL_C_NUM*4) { - return 0x600|((freq>>3)&0x1ff); - } else if (freq>=OPLL_C_NUM*2) { - return 0x400|((freq>>2)&0x1ff); - } else if (freq>=OPLL_C_NUM) { - return 0x200|((freq>>1)&0x1ff); - } else { - return freq&0x1ff; - } + int block=freq/OPLL_C_NUM; + if (block>0) block=bsr(block); + return (block<<9)|((freq>>block)&0x1ff); } void DivPlatformOPLL::muteChannel(int ch, bool mute) { diff --git a/src/engine/platform/saa.cpp b/src/engine/platform/saa.cpp index f1e033b75..4f22cadde 100644 --- a/src/engine/platform/saa.cpp +++ b/src/engine/platform/saa.cpp @@ -19,6 +19,7 @@ #include "saa.h" #include "../engine.h" +#include "../bsr.h" #include "sound/saa1099.h" #include #include @@ -155,22 +156,9 @@ void DivPlatformSAA1099::tick(bool sysTick) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER); if (chan[i].freq>65535) chan[i].freq=65535; - if (chan[i].freq>=32768) { - chan[i].freqH=7; - } else if (chan[i].freq>=16384) { - chan[i].freqH=6; - } else if (chan[i].freq>=8192) { - chan[i].freqH=5; - } else if (chan[i].freq>=4096) { - chan[i].freqH=4; - } else if (chan[i].freq>=2048) { - chan[i].freqH=3; - } else if (chan[i].freq>=1024) { - chan[i].freqH=2; - } else if (chan[i].freq>=512) { - chan[i].freqH=1; - } else { - chan[i].freqH=0; + chan[i].freqH=0; + if (chan[i].freq>511) { + chan[i].freqH=bsr((unsigned short)chan[i].freq)-9; } chan[i].freqL=0xff-(chan[i].freq>>chan[i].freqH); chan[i].freqH=7-chan[i].freqH; diff --git a/src/gui/fmPreview.cpp b/src/gui/fmPreview.cpp index 4e11137b9..fc4eb0c6c 100644 --- a/src/gui/fmPreview.cpp +++ b/src/gui/fmPreview.cpp @@ -27,6 +27,7 @@ extern "C" { #include "../../extern/Nuked-OPLL/opll.h" } #include "../engine/platform/sound/ymfm/ymfm_opz.h" +#include "../engine/bsr.h" #define OPN_WRITE(addr,val) \ OPN2_Write((ym3438_t*)fmPreviewOPN,0,(addr)); \ @@ -388,9 +389,9 @@ void FurnaceGUI::renderFMPreviewESFM(const DivInstrumentFM& params, const DivIns double fbase=(mult0?2048.0:1024.0)*pow(2.0,(float)offset/(128.0*12.0)); int bf=round(fbase); int block=0; - while (bf>0x3ff) { - bf>>=1; - block++; + if (bf>0x3ff) { + block=bsr32(bf)-10; + bf>>=block; } freqL=bf&0xff; freqH=((block&7)<<2)|((bf>>8)&3);