Merge branch 'master' of https://github.com/tildearrow/furnace into es5506_alt
* 'master' of https://github.com/tildearrow/furnace: dev94 - add a full linear pitch mode, part 1 YM2610(B): use f-num/block baseFreq calculation GUI: remove insLoadAlwaysReplace setting GUI: right click menu for open instrument GUI: add a threshold for macro right click OPZ: remove debug printf GUI: add macro right click menu GUI: prepare for macro right click menu update gitignore add something prepare for something did i fix macOS build? GUI: macro edit improvements
This commit is contained in:
commit
54e78699a7
84 changed files with 6364 additions and 337 deletions
|
|
@ -987,6 +987,9 @@ int DivEngine::calcBaseFreq(double clock, double divider, int note, bool period)
|
|||
}*/
|
||||
|
||||
double DivEngine::calcBaseFreq(double clock, double divider, int note, bool period) {
|
||||
if (song.linearPitch==2) { // full linear
|
||||
return (note<<7);
|
||||
}
|
||||
double base=(period?(song.tuning*0.0625):song.tuning)*pow(2.0,(float)(note+3)/12.0);
|
||||
return period?
|
||||
(clock/base)/divider:
|
||||
|
|
@ -994,19 +997,27 @@ double DivEngine::calcBaseFreq(double clock, double divider, int note, bool peri
|
|||
}
|
||||
|
||||
unsigned short DivEngine::calcBaseFreqFNumBlock(double clock, double divider, int note, int bits) {
|
||||
if (song.linearPitch==2) { // full linear
|
||||
return (note<<7);
|
||||
}
|
||||
double tuning=song.tuning;
|
||||
if (tuning<400.0) tuning=400.0;
|
||||
if (tuning>500.0) tuning=500.0;
|
||||
int bf=calcBaseFreq(clock,divider,note,false);
|
||||
int boundaryBottom=tuning*pow(2.0,0.25)*(divider/clock);
|
||||
int boundaryTop=2.0*tuning*pow(2.0,0.25)*(divider/clock);
|
||||
int block=note/12;
|
||||
if (block<0) block=0;
|
||||
if (block>7) block=7;
|
||||
bf>>=block;
|
||||
if (bf<0) bf=0;
|
||||
// octave boundaries
|
||||
while (bf>0 && bf<644 && block>0) {
|
||||
while (bf>0 && bf<boundaryBottom && block>0) {
|
||||
bf<<=1;
|
||||
block--;
|
||||
}
|
||||
if (bf>1288) {
|
||||
while (block<7) {
|
||||
if (bf>boundaryTop) {
|
||||
while (block<7 && bf>boundaryTop) {
|
||||
bf>>=1;
|
||||
block++;
|
||||
}
|
||||
|
|
@ -1014,11 +1025,19 @@ unsigned short DivEngine::calcBaseFreqFNumBlock(double clock, double divider, in
|
|||
bf=(1<<bits)-1;
|
||||
}
|
||||
}
|
||||
//logV("f-num: %d block: %d",bf,block);
|
||||
return bf|(block<<bits);
|
||||
}
|
||||
|
||||
int DivEngine::calcFreq(int base, int pitch, bool period, int octave, int pitch2) {
|
||||
if (song.linearPitch) {
|
||||
int DivEngine::calcFreq(int base, int pitch, bool period, int octave, int pitch2, double clock, double divider) {
|
||||
if (song.linearPitch==2) {
|
||||
// do frequency calculation here
|
||||
double fbase=(period?(song.tuning*0.0625):song.tuning)*pow(2.0,(float)(base+pitch+384)/(128.0*12.0));
|
||||
return period?
|
||||
(clock/fbase)/divider:
|
||||
fbase*(divider/clock);
|
||||
}
|
||||
if (song.linearPitch==1) {
|
||||
// global pitch multiplier
|
||||
int whatTheFuck=(1024+(globalPitch<<6)-(globalPitch<0?globalPitch-6:0));
|
||||
if (whatTheFuck<1) whatTheFuck=1; // avoids division by zero but please kill me
|
||||
|
|
@ -1213,7 +1232,7 @@ void DivEngine::reset() {
|
|||
chan[i]=DivChannelState();
|
||||
if (i<chans) chan[i].volMax=(disCont[dispatchOfChan[i]].dispatch->dispatch(DivCommand(DIV_CMD_GET_VOLMAX,dispatchChanOfChan[i]))<<8)|0xff;
|
||||
chan[i].volume=chan[i].volMax;
|
||||
if (!song.linearPitch) chan[i].vibratoFine=4;
|
||||
if (song.linearPitch==0) chan[i].vibratoFine=4;
|
||||
}
|
||||
extValue=0;
|
||||
extValuePresent=0;
|
||||
|
|
@ -2662,6 +2681,8 @@ bool DivEngine::init() {
|
|||
// init config
|
||||
#ifdef _WIN32
|
||||
configPath=getWinConfigPath();
|
||||
#elif defined(ANDROID)
|
||||
configPath=SDL_GetPrefPath("tildearrow","furnace");
|
||||
#else
|
||||
struct stat st;
|
||||
char* home=getenv("HOME");
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@
|
|||
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
|
||||
#define BUSY_END isBusy.unlock(); softLocked=false;
|
||||
|
||||
#define DIV_VERSION "dev93"
|
||||
#define DIV_ENGINE_VERSION 93
|
||||
#define DIV_VERSION "dev94"
|
||||
#define DIV_ENGINE_VERSION 94
|
||||
|
||||
// for imports
|
||||
#define DIV_VERSION_MOD 0xff01
|
||||
|
|
@ -486,7 +486,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 pitch2=0);
|
||||
int calcFreq(int base, int pitch, bool period=false, int octave=0, int pitch2=0, double clock=1.0, double divider=1.0);
|
||||
|
||||
// convert panning formats
|
||||
int convertPanSplitToLinear(unsigned int val, unsigned char bits, int range);
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
|
|||
|
||||
// compatibility flags
|
||||
ds.limitSlides=true;
|
||||
ds.linearPitch=true;
|
||||
ds.linearPitch=1;
|
||||
ds.loopModality=0;
|
||||
ds.properNoiseLayout=false;
|
||||
ds.waveDutyIsVol=false;
|
||||
|
|
@ -173,12 +173,14 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
|
|||
ds.legacyVolumeSlides=false;
|
||||
}
|
||||
|
||||
// Neo Geo detune
|
||||
// Neo Geo detune is caused by Defle running Neo Geo at the wrong clock.
|
||||
/*
|
||||
if (ds.system[0]==DIV_SYSTEM_YM2610 || ds.system[0]==DIV_SYSTEM_YM2610_EXT
|
||||
|| ds.system[0]==DIV_SYSTEM_YM2610_FULL || ds.system[0]==DIV_SYSTEM_YM2610_FULL_EXT
|
||||
|| ds.system[0]==DIV_SYSTEM_YM2610B || ds.system[0]==DIV_SYSTEM_YM2610B_EXT) {
|
||||
ds.tuning=443.23;
|
||||
}
|
||||
*/
|
||||
|
||||
logI("reading module data...");
|
||||
if (ds.version>0x0c) {
|
||||
|
|
@ -948,7 +950,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
|||
|
||||
if (ds.version<37) { // compat flags not stored back then
|
||||
ds.limitSlides=true;
|
||||
ds.linearPitch=true;
|
||||
ds.linearPitch=1;
|
||||
ds.loopModality=0;
|
||||
}
|
||||
if (ds.version<43) {
|
||||
|
|
@ -1390,7 +1392,12 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
|||
} else {
|
||||
reader.readC();
|
||||
}
|
||||
for (int i=0; i<19; i++) {
|
||||
if (ds.version>=94) {
|
||||
ds.pitchSlideSpeed=reader.readC();
|
||||
} else {
|
||||
reader.readC();
|
||||
}
|
||||
for (int i=0; i<18; i++) {
|
||||
reader.readC();
|
||||
}
|
||||
}
|
||||
|
|
@ -1654,7 +1661,7 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) {
|
|||
DivSong ds;
|
||||
ds.tuning=436.0;
|
||||
ds.version=DIV_VERSION_MOD;
|
||||
ds.linearPitch=false;
|
||||
ds.linearPitch=0;
|
||||
ds.noSlidesOnFirstTick=true;
|
||||
ds.rowResetsArpPos=true;
|
||||
ds.ignoreJumpAtEnd=false;
|
||||
|
|
@ -2713,7 +2720,8 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) {
|
|||
w->writeC(song.fbPortaPause);
|
||||
w->writeC(song.snDutyReset);
|
||||
w->writeC(song.pitchMacroIsLinear);
|
||||
for (int i=0; i<19; i++) {
|
||||
w->writeC(song.pitchSlideSpeed);
|
||||
for (int i=0; i<18; i++) {
|
||||
w->writeC(0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -220,7 +220,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,0,chan[i].pitch2);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
|
||||
if (chan[i].freq>4095) chan[i].freq=4095;
|
||||
if (chan[i].freq<0) chan[i].freq=0;
|
||||
if (chan[i].keyOn) {
|
||||
|
|
|
|||
|
|
@ -251,7 +251,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,0,chan[i].pitch2);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
|
||||
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)));
|
||||
|
|
|
|||
|
|
@ -280,7 +280,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,0,chan[i].pitch2);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
|
||||
if (chan[i].freq>65535) chan[i].freq=65535;
|
||||
if (chan[i].keyOn) {
|
||||
if (chan[i].insChanged) {
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ void DivPlatformBubSysWSG::tick(bool sysTick) {
|
|||
}
|
||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SCC);
|
||||
chan[i].freq=0x1000-parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].pitch2;
|
||||
chan[i].freq=0x1000-parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
|
||||
if (chan[i].freq<0) chan[i].freq=0;
|
||||
if (chan[i].freq>4095) chan[i].freq=4095;
|
||||
k005289->load(i,chan[i].freq);
|
||||
|
|
|
|||
|
|
@ -217,7 +217,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].pitch2);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,8,chan[i].pitch2,chipClock,CHIP_FREQBASE);
|
||||
if (chan[i].freq>0xffff) chan[i].freq=0xffff;
|
||||
if (chan[i].keyOn) {
|
||||
rWrite(i*7+5,(chan[i].attack<<4)|(chan[i].decay));
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ void DivPlatformDummy::tick(bool sysTick) {
|
|||
|
||||
if (chan[i].freqChanged) {
|
||||
chan[i].freqChanged=false;
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,0,0,chipClock,CHIP_FREQBASE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,7 +220,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,2,chan[i].pitch2);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].pitch2,chipClock,CHIP_FREQBASE);
|
||||
if (chan[i].freq>4095) chan[i].freq=4095;
|
||||
if (chan[i].freq<0) chan[i].freq=0;
|
||||
if (chan[i].keyOn) {
|
||||
|
|
|
|||
|
|
@ -237,7 +237,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,0,chan[i].pitch2);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
|
||||
if (chan[i].freq>2047) chan[i].freq=2047;
|
||||
if (chan[i].freq<0) chan[i].freq=0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -727,6 +727,8 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
int boundaryBottom=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,0,false);
|
||||
int boundaryTop=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,12,false);
|
||||
int destFreq=NOTE_FNUM_BLOCK(c.value2,11);
|
||||
int newFreq;
|
||||
bool return2=false;
|
||||
|
|
@ -749,13 +751,13 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
|
|||
// check for octave boundary
|
||||
// what the heck!
|
||||
if (!chan[c.chan].portaPause) {
|
||||
if ((newFreq&0x7ff)>1288 && (newFreq&0xf800)<0x3800) {
|
||||
chan[c.chan].portaPauseFreq=(644)|((newFreq+0x800)&0xf800);
|
||||
if ((newFreq&0x7ff)>boundaryTop && (newFreq&0xf800)<0x3800) {
|
||||
chan[c.chan].portaPauseFreq=(boundaryBottom)|((newFreq+0x800)&0xf800);
|
||||
chan[c.chan].portaPause=true;
|
||||
break;
|
||||
}
|
||||
if ((newFreq&0x7ff)<644 && (newFreq&0xf800)>0) {
|
||||
chan[c.chan].portaPauseFreq=newFreq=(1287)|((newFreq-0x800)&0xf800);
|
||||
if ((newFreq&0x7ff)<boundaryBottom && (newFreq&0xf800)>0) {
|
||||
chan[c.chan].portaPauseFreq=newFreq=(boundaryTop-1)|((newFreq-0x800)&0xf800);
|
||||
chan[c.chan].portaPause=true;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,6 +127,8 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
case DIV_CMD_NOTE_PORTA: {
|
||||
int boundaryBottom=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,0,false);
|
||||
int boundaryTop=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,12,false);
|
||||
int destFreq=NOTE_FNUM_BLOCK(c.value2,11);
|
||||
int newFreq;
|
||||
bool return2=false;
|
||||
|
|
@ -148,18 +150,18 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) {
|
|||
}
|
||||
// what the heck!
|
||||
if (!opChan[ch].portaPause) {
|
||||
if ((newFreq&0x7ff)>1288 && (newFreq&0xf800)<0x3800) {
|
||||
if ((newFreq&0x7ff)>boundaryTop && (newFreq&0xf800)<0x3800) {
|
||||
if (parent->song.fbPortaPause) {
|
||||
opChan[ch].portaPauseFreq=(644)|((newFreq+0x800)&0xf800);
|
||||
opChan[ch].portaPauseFreq=(boundaryBottom)|((newFreq+0x800)&0xf800);
|
||||
opChan[ch].portaPause=true;
|
||||
break;
|
||||
} else {
|
||||
newFreq=(newFreq>>1)|((newFreq+0x800)&0xf800);
|
||||
}
|
||||
}
|
||||
if ((newFreq&0x7ff)<644 && (newFreq&0xf800)>0) {
|
||||
if ((newFreq&0x7ff)<boundaryBottom && (newFreq&0xf800)>0) {
|
||||
if (parent->song.fbPortaPause) {
|
||||
opChan[ch].portaPauseFreq=newFreq=(1287)|((newFreq-0x800)&0xf800);
|
||||
opChan[ch].portaPauseFreq=newFreq=(boundaryTop-1)|((newFreq-0x800)&0xf800);
|
||||
opChan[ch].portaPause=true;
|
||||
break;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -201,7 +201,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,0,chan[i].pitch2);
|
||||
chan[i].fd=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
|
||||
if (chan[i].std.duty.had) {
|
||||
chan[i].duty=chan[i].std.duty.val;
|
||||
WRITE_FEEDBACK(i, chan[i].duty.feedback);
|
||||
|
|
|
|||
|
|
@ -147,7 +147,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,0,chan[i].pitch2)-1;
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER)-1;
|
||||
if (chan[i].freq>2047) chan[i].freq=2047;
|
||||
if (chan[i].freq<0) chan[i].freq=0;
|
||||
if (chan[i].keyOn) {
|
||||
|
|
|
|||
|
|
@ -357,7 +357,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].pitch2);
|
||||
chan[i].freq=parent->calcFreq((((chan[i].baseFreq*chan[i].waveLen)*(chanMax+1))/16),chan[i].pitch,false,0,chan[i].pitch2,chipClock,CHIP_FREQBASE);
|
||||
if (chan[i].freq<0) chan[i].freq=0;
|
||||
if (chan[i].freq>0x3ffff) chan[i].freq=0x3ffff;
|
||||
if (chan[i].keyOn) {
|
||||
|
|
|
|||
|
|
@ -309,7 +309,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,0,chan[i].pitch2)-1;
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER)-1;
|
||||
if (chan[i].freq>2047) chan[i].freq=2047;
|
||||
if (chan[i].freq<0) chan[i].freq=0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -511,7 +511,7 @@ void DivPlatformOPL::tick(bool sysTick) {
|
|||
bool updateDrums=false;
|
||||
for (int i=0; i<totalChans; i++) {
|
||||
if (chan[i].freqChanged) {
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq),chan[i].pitch2);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq),chan[i].pitch2,chipClock,CHIP_FREQBASE);
|
||||
if (chan[i].freq>131071) chan[i].freq=131071;
|
||||
int freqt=toFreq(chan[i].freq)+chan[i].pitch2;
|
||||
chan[i].freqH=freqt>>8;
|
||||
|
|
|
|||
|
|
@ -300,7 +300,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].pitch2);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq),chan[i].pitch2,chipClock,CHIP_FREQBASE);
|
||||
if (chan[i].freq>262143) chan[i].freq=262143;
|
||||
int freqt=toFreq(chan[i].freq)+chan[i].pitch2;
|
||||
chan[i].freqL=freqt&0xff;
|
||||
|
|
|
|||
|
|
@ -227,7 +227,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,0,chan[i].pitch2);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
|
||||
if (chan[i].furnaceDac) {
|
||||
double off=1.0;
|
||||
if (chan[i].dacSample>=0 && chan[i].dacSample<parent->song.sampleLen) {
|
||||
|
|
|
|||
|
|
@ -223,7 +223,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,0,chan[i].pitch2)-1;
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER)-1;
|
||||
if (chan[i].freq<0) chan[i].freq=0;
|
||||
if (chan[i].freq>65535) chan[i].freq=65535;
|
||||
if (chan[i].keyOn) {
|
||||
|
|
|
|||
|
|
@ -118,7 +118,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,0,chan.pitch2);
|
||||
chan.freq=parent->calcFreq(chan.baseFreq,chan.pitch,true,0,chan.pitch2,chipClock,CHIP_DIVIDER);
|
||||
if (chan.freq>257) chan.freq=257;
|
||||
if (chan.freq<2) chan.freq=2;
|
||||
rWrite(8,chan.freq-2);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
#include <map>
|
||||
|
||||
#define CHIP_DIVIDER (1248*2)
|
||||
#define QS_NOTE_FREQUENCY(x) parent->calcBaseFreq(440,0x1000,(x)-3,false)
|
||||
#define QS_NOTE_FREQUENCY(x) parent->calcBaseFreq(440,4096,(x)-3,false)
|
||||
|
||||
#define rWrite(a,v) {if(!skipRegisterWrites) {qsound_write_data(&chip,a,v); if(dumpWrites) addWrite(a,v); }}
|
||||
#define immWrite(a,v) {qsound_write_data(&chip,a,v); if(dumpWrites) addWrite(a,v);}
|
||||
|
|
@ -296,14 +296,8 @@ void DivPlatformQSound::tick(bool sysTick) {
|
|||
uint16_t qsound_addr = 0;
|
||||
uint16_t qsound_loop = 0;
|
||||
uint16_t qsound_end = 0;
|
||||
double off=1.0;
|
||||
if (chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen) {
|
||||
DivSample* s=parent->getSample(chan[i].sample);
|
||||
if (s->centerRate<1) {
|
||||
off=1.0;
|
||||
} else {
|
||||
off=(double)s->centerRate/24038.0/16.0;
|
||||
}
|
||||
qsound_bank = 0x8000 | (s->offQSound >> 16);
|
||||
qsound_addr = s->offQSound & 0xffff;
|
||||
|
||||
|
|
@ -322,15 +316,15 @@ void DivPlatformQSound::tick(bool sysTick) {
|
|||
if (chan[i].std.arp.had) {
|
||||
if (!chan[i].inPorta) {
|
||||
if (chan[i].std.arp.mode) {
|
||||
chan[i].baseFreq=off*QS_NOTE_FREQUENCY(chan[i].std.arp.val);
|
||||
chan[i].baseFreq=QS_NOTE_FREQUENCY(chan[i].std.arp.val);
|
||||
} else {
|
||||
chan[i].baseFreq=off*QS_NOTE_FREQUENCY(chan[i].note+chan[i].std.arp.val);
|
||||
chan[i].baseFreq=QS_NOTE_FREQUENCY(chan[i].note+chan[i].std.arp.val);
|
||||
}
|
||||
}
|
||||
chan[i].freqChanged=true;
|
||||
} else {
|
||||
if (chan[i].std.arp.mode && chan[i].std.arp.finished) {
|
||||
chan[i].baseFreq=off*QS_NOTE_FREQUENCY(chan[i].note);
|
||||
chan[i].baseFreq=QS_NOTE_FREQUENCY(chan[i].note);
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
}
|
||||
|
|
@ -354,7 +348,16 @@ 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,2,chan[i].pitch2);
|
||||
double off=1.0;
|
||||
if (chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen) {
|
||||
DivSample* s=parent->getSample(chan[i].sample);
|
||||
if (s->centerRate<1) {
|
||||
off=1.0;
|
||||
} else {
|
||||
off=(double)s->centerRate/24038.0/16.0;
|
||||
}
|
||||
}
|
||||
chan[i].freq=off*parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].pitch2,440.0,4096.0);
|
||||
if (chan[i].freq>0xffff) chan[i].freq=0xffff;
|
||||
if (chan[i].keyOn) {
|
||||
rWrite(q1_reg_map[Q1V_BANK][i], qsound_bank);
|
||||
|
|
@ -388,17 +391,8 @@ int DivPlatformQSound::dispatch(DivCommand c) {
|
|||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA);
|
||||
chan[c.chan].sample=ins->amiga.initSample;
|
||||
double off=1.0;
|
||||
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
|
||||
DivSample* s=parent->getSample(chan[c.chan].sample);
|
||||
if (s->centerRate<1) {
|
||||
off=1.0;
|
||||
} else {
|
||||
off=(double)s->centerRate/24038.0/16.0;
|
||||
}
|
||||
}
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=off*QS_NOTE_FREQUENCY(c.value);
|
||||
chan[c.chan].baseFreq=QS_NOTE_FREQUENCY(c.value);
|
||||
}
|
||||
if (chan[c.chan].sample<0 || chan[c.chan].sample>=parent->song.sampleLen) {
|
||||
chan[c.chan].sample=-1;
|
||||
|
|
@ -467,16 +461,7 @@ int DivPlatformQSound::dispatch(DivCommand c) {
|
|||
chan[c.chan].freqChanged=true;
|
||||
break;
|
||||
case DIV_CMD_NOTE_PORTA: {
|
||||
double off=1.0;
|
||||
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
|
||||
DivSample* s=parent->getSample(chan[c.chan].sample);
|
||||
if (s->centerRate<1) {
|
||||
off=1.0;
|
||||
} else {
|
||||
off=(double)s->centerRate/24038.0/16.0;
|
||||
}
|
||||
}
|
||||
int destFreq=off*QS_NOTE_FREQUENCY(c.value2);
|
||||
int destFreq=QS_NOTE_FREQUENCY(c.value2);
|
||||
bool return2=false;
|
||||
if (destFreq>chan[c.chan].baseFreq) {
|
||||
chan[c.chan].baseFreq+=c.value;
|
||||
|
|
@ -499,16 +484,7 @@ int DivPlatformQSound::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
case DIV_CMD_LEGATO: {
|
||||
double off=1.0;
|
||||
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
|
||||
DivSample* s=parent->getSample(chan[c.chan].sample);
|
||||
if (s->centerRate<1) {
|
||||
off=1.0;
|
||||
} else {
|
||||
off=(double)s->centerRate/24038.0/16.0;
|
||||
}
|
||||
}
|
||||
chan[c.chan].baseFreq=off*QS_NOTE_FREQUENCY(c.value+((chan[c.chan].std.arp.will && !chan[c.chan].std.arp.mode)?(chan[c.chan].std.arp.val-12):(0)));
|
||||
chan[c.chan].baseFreq=QS_NOTE_FREQUENCY(c.value+((chan[c.chan].std.arp.will && !chan[c.chan].std.arp.mode)?(chan[c.chan].std.arp.val-12):(0)));
|
||||
chan[c.chan].freqChanged=true;
|
||||
chan[c.chan].note=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -200,7 +200,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,0,chan[i].pitch2);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,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;
|
||||
|
|
|
|||
|
|
@ -121,7 +121,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,0,chan[i].pitch2);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,64);
|
||||
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;
|
||||
|
|
@ -136,7 +136,7 @@ void DivPlatformSMS::tick(bool sysTick) {
|
|||
}
|
||||
}
|
||||
if (chan[3].freqChanged || updateSNMode) {
|
||||
chan[3].freq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch,true,0,chan[3].pitch2);
|
||||
chan[3].freq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch,true,0,chan[3].pitch2,chipClock,isRealSN?60:64);
|
||||
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
|
||||
|
|
|
|||
|
|
@ -183,7 +183,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,2,chan[i].pitch2);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].pitch2,chipClock,CHIP_FREQBASE);
|
||||
if (chan[i].pcm) {
|
||||
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SU);
|
||||
DivSample* sample=parent->getSample(ins->amiga.initSample);
|
||||
|
|
|
|||
|
|
@ -203,7 +203,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,0,chan[i].pitch2);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
|
||||
if (i==1 && pcm && furnaceDac) {
|
||||
double off=1.0;
|
||||
if (dacSample>=0 && dacSample<parent->song.sampleLen) {
|
||||
|
|
|
|||
|
|
@ -919,7 +919,6 @@ int DivPlatformTX81Z::dispatch(DivCommand c) {
|
|||
}
|
||||
case DIV_CMD_FM_FIXFREQ: {
|
||||
if (c.value<0 || c.value>3) break;
|
||||
printf("fixfreq %x\n",c.value2);
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.egt=(c.value2>0);
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ void DivPlatformVERA::reset() {
|
|||
chan[16].pan=3;
|
||||
}
|
||||
|
||||
// TODO: linear pitch stuff
|
||||
int DivPlatformVERA::calcNoteFreq(int ch, int note) {
|
||||
if (ch<16) {
|
||||
return parent->calcBaseFreq(chipClock,2097152,note,false);
|
||||
|
|
@ -208,7 +209,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].pitch2);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,8,chan[i].pitch2,chipClock,2097152);
|
||||
if (chan[i].freq>65535) chan[i].freq=65535;
|
||||
rWrite(i,0,chan[i].freq&0xff);
|
||||
rWrite(i,1,(chan[i].freq>>8)&0xff);
|
||||
|
|
|
|||
|
|
@ -132,7 +132,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,0,chan[i].pitch2);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
|
||||
if (i<3) {
|
||||
chan[i].freq>>=(2-i);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -197,9 +197,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,0,chan[i].pitch2)-1;
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,14)-1;
|
||||
} else { // pulse
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2)-1;
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,16)-1;
|
||||
if (chan[i].furnaceDac) {
|
||||
double off=1.0;
|
||||
if (chan[i].dacSample>=0 && chan[i].dacSample<parent->song.sampleLen) {
|
||||
|
|
|
|||
|
|
@ -260,6 +260,7 @@ void DivPlatformX1_010::acquire(short* bufL, short* bufR, size_t start, size_t l
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: linear pitch stuff
|
||||
double DivPlatformX1_010::NoteX1_010(int ch, int note) {
|
||||
if (chan[ch].pcm) { // PCM note
|
||||
double off=1.0;
|
||||
|
|
@ -487,7 +488,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,2,chan[i].pitch2);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].pitch2,chipClock,CHIP_FREQBASE);
|
||||
if (chan[i].pcm) {
|
||||
if (chan[i].freq<1) chan[i].freq=1;
|
||||
if (chan[i].freq>255) chan[i].freq=255;
|
||||
|
|
|
|||
|
|
@ -456,7 +456,7 @@ double DivPlatformYM2610::NOTE_OPNB(int ch, int note) {
|
|||
return NOTE_PERIODIC(note);
|
||||
}
|
||||
// FM
|
||||
return NOTE_FREQUENCY(note);
|
||||
return NOTE_FNUM_BLOCK(note,11);
|
||||
}
|
||||
|
||||
double DivPlatformYM2610::NOTE_ADPCMB(int note) {
|
||||
|
|
@ -559,15 +559,15 @@ void DivPlatformYM2610::tick(bool sysTick) {
|
|||
if (chan[i].std.arp.had) {
|
||||
if (!chan[i].inPorta) {
|
||||
if (chan[i].std.arp.mode) {
|
||||
chan[i].baseFreq=NOTE_FREQUENCY(chan[i].std.arp.val);
|
||||
chan[i].baseFreq=NOTE_FNUM_BLOCK(chan[i].std.arp.val,11);
|
||||
} else {
|
||||
chan[i].baseFreq=NOTE_FREQUENCY(chan[i].note+(signed char)chan[i].std.arp.val);
|
||||
chan[i].baseFreq=NOTE_FNUM_BLOCK(chan[i].note+(signed char)chan[i].std.arp.val,11);
|
||||
}
|
||||
}
|
||||
chan[i].freqChanged=true;
|
||||
} else {
|
||||
if (chan[i].std.arp.mode && chan[i].std.arp.finished) {
|
||||
chan[i].baseFreq=NOTE_FREQUENCY(chan[i].note);
|
||||
chan[i].baseFreq=NOTE_FNUM_BLOCK(chan[i].note,11);
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
}
|
||||
|
|
@ -742,11 +742,20 @@ 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].pitch2);
|
||||
if (chan[i].freq>262143) chan[i].freq=262143;
|
||||
int freqt=toFreq(chan[i].freq)+chan[i].pitch2;
|
||||
immWrite(chanOffs[i]+ADDR_FREQH,freqt>>8);
|
||||
immWrite(chanOffs[i]+ADDR_FREQ,freqt&0xff);
|
||||
int fNum=parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,false,4,chan[i].pitch2);
|
||||
int block=(chan[i].baseFreq&0xf800)>>11;
|
||||
if (fNum<0) fNum=0;
|
||||
if (fNum>2047) {
|
||||
while (block<7) {
|
||||
fNum>>=1;
|
||||
block++;
|
||||
}
|
||||
if (fNum>2047) fNum=2047;
|
||||
}
|
||||
chan[i].freq=(block<<11)|fNum;
|
||||
if (chan[i].freq>0x3fff) chan[i].freq=0x3fff;
|
||||
immWrite(chanOffs[i]+ADDR_FREQH,chan[i].freq>>8);
|
||||
immWrite(chanOffs[i]+ADDR_FREQ,chan[i].freq&0xff);
|
||||
chan[i].freqChanged=false;
|
||||
}
|
||||
if (chan[i].keyOn) {
|
||||
|
|
@ -756,47 +765,6 @@ void DivPlatformYM2610::tick(bool sysTick) {
|
|||
}
|
||||
}
|
||||
|
||||
int DivPlatformYM2610::octave(int freq) {
|
||||
if (freq>=622.0f*128) {
|
||||
return 128;
|
||||
} else if (freq>=622.0f*64) {
|
||||
return 64;
|
||||
} else if (freq>=622.0f*32) {
|
||||
return 32;
|
||||
} else if (freq>=622.0f*16) {
|
||||
return 16;
|
||||
} else if (freq>=622.0f*8) {
|
||||
return 8;
|
||||
} else if (freq>=622.0f*4) {
|
||||
return 4;
|
||||
} else if (freq>=622.0f*2) {
|
||||
return 2;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int DivPlatformYM2610::toFreq(int freq) {
|
||||
if (freq>=622.0f*128) {
|
||||
return 0x3800|((freq>>7)&0x7ff);
|
||||
} else if (freq>=622.0f*64) {
|
||||
return 0x3000|((freq>>6)&0x7ff);
|
||||
} else if (freq>=622.0f*32) {
|
||||
return 0x2800|((freq>>5)&0x7ff);
|
||||
} else if (freq>=622.0f*16) {
|
||||
return 0x2000|((freq>>4)&0x7ff);
|
||||
} else if (freq>=622.0f*8) {
|
||||
return 0x1800|((freq>>3)&0x7ff);
|
||||
} else if (freq>=622.0f*4) {
|
||||
return 0x1000|((freq>>2)&0x7ff);
|
||||
} else if (freq>=622.0f*2) {
|
||||
return 0x800|((freq>>1)&0x7ff);
|
||||
} else {
|
||||
return freq&0x7ff;
|
||||
}
|
||||
}
|
||||
|
||||
int DivPlatformYM2610::dispatch(DivCommand c) {
|
||||
if (c.chan>3 && c.chan<7) {
|
||||
c.chan-=4;
|
||||
|
|
@ -928,7 +896,7 @@ int DivPlatformYM2610::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].freqChanged=true;
|
||||
chan[c.chan].note=c.value;
|
||||
|
|
@ -1048,33 +1016,48 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
int destFreq=NOTE_FREQUENCY(c.value2);
|
||||
int boundaryBottom=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,0,false);
|
||||
int boundaryTop=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,12,false);
|
||||
int destFreq=NOTE_FNUM_BLOCK(c.value2,11);
|
||||
int newFreq;
|
||||
bool return2=false;
|
||||
if (chan[c.chan].portaPause) {
|
||||
chan[c.chan].baseFreq=chan[c.chan].portaPauseFreq;
|
||||
}
|
||||
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
|
||||
// what the heck!
|
||||
if (!chan[c.chan].portaPause) {
|
||||
if (octave(chan[c.chan].baseFreq)!=octave(newFreq)) {
|
||||
if ((newFreq&0x7ff)>boundaryTop && (newFreq&0xf800)<0x3800) {
|
||||
chan[c.chan].portaPauseFreq=(boundaryBottom)|((newFreq+0x800)&0xf800);
|
||||
chan[c.chan].portaPause=true;
|
||||
break;
|
||||
}
|
||||
if ((newFreq&0x7ff)<boundaryBottom && (newFreq&0xf800)>0) {
|
||||
chan[c.chan].portaPauseFreq=newFreq=(boundaryTop-1)|((newFreq-0x800)&0xf800);
|
||||
chan[c.chan].portaPause=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
chan[c.chan].baseFreq=newFreq;
|
||||
chan[c.chan].portaPause=false;
|
||||
chan[c.chan].freqChanged=true;
|
||||
if (return2) return 2;
|
||||
chan[c.chan].baseFreq=newFreq;
|
||||
if (return2) {
|
||||
chan[c.chan].inPorta=false;
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_SAMPLE_BANK:
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ class DivPlatformYM2610: public DivPlatformYM2610Base {
|
|||
struct Channel {
|
||||
DivInstrumentFM state;
|
||||
unsigned char freqH, freqL;
|
||||
int freq, baseFreq, pitch, pitch2, note, ins;
|
||||
int freq, baseFreq, pitch, pitch2, portaPauseFreq, note, ins;
|
||||
unsigned char psgMode, autoEnvNum, autoEnvDen;
|
||||
signed char konCycles;
|
||||
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, inPorta, furnacePCM, hardReset;
|
||||
|
|
@ -80,6 +80,7 @@ class DivPlatformYM2610: public DivPlatformYM2610Base {
|
|||
baseFreq(0),
|
||||
pitch(0),
|
||||
pitch2(0),
|
||||
portaPauseFreq(0),
|
||||
note(0),
|
||||
ins(-1),
|
||||
psgMode(1),
|
||||
|
|
@ -125,8 +126,6 @@ class DivPlatformYM2610: public DivPlatformYM2610Base {
|
|||
short oldWrites[512];
|
||||
short pendingWrites[512];
|
||||
|
||||
int octave(int freq);
|
||||
int toFreq(int freq);
|
||||
double NOTE_OPNB(int ch, int note);
|
||||
double NOTE_ADPCMB(int note);
|
||||
friend void putDispatchChan(void*,int,int);
|
||||
|
|
|
|||
|
|
@ -436,7 +436,7 @@ double DivPlatformYM2610B::NOTE_OPNB(int ch, int note) {
|
|||
return NOTE_PERIODIC(note);
|
||||
}
|
||||
// FM
|
||||
return NOTE_FREQUENCY(note);
|
||||
return NOTE_FNUM_BLOCK(note,11);
|
||||
}
|
||||
|
||||
double DivPlatformYM2610B::NOTE_ADPCMB(int note) {
|
||||
|
|
@ -538,15 +538,15 @@ void DivPlatformYM2610B::tick(bool sysTick) {
|
|||
if (chan[i].std.arp.had) {
|
||||
if (!chan[i].inPorta) {
|
||||
if (chan[i].std.arp.mode) {
|
||||
chan[i].baseFreq=NOTE_FREQUENCY(chan[i].std.arp.val);
|
||||
chan[i].baseFreq=NOTE_FNUM_BLOCK(chan[i].std.arp.val,11);
|
||||
} else {
|
||||
chan[i].baseFreq=NOTE_FREQUENCY(chan[i].note+(signed char)chan[i].std.arp.val);
|
||||
chan[i].baseFreq=NOTE_FNUM_BLOCK(chan[i].note+(signed char)chan[i].std.arp.val,11);
|
||||
}
|
||||
}
|
||||
chan[i].freqChanged=true;
|
||||
} else {
|
||||
if (chan[i].std.arp.mode && chan[i].std.arp.finished) {
|
||||
chan[i].baseFreq=NOTE_FREQUENCY(chan[i].note);
|
||||
chan[i].baseFreq=NOTE_FNUM_BLOCK(chan[i].note,11);
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
}
|
||||
|
|
@ -720,11 +720,20 @@ 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].pitch2);
|
||||
if (chan[i].freq>262143) chan[i].freq=262143;
|
||||
int freqt=toFreq(chan[i].freq)+chan[i].pitch2;
|
||||
immWrite(chanOffs[i]+ADDR_FREQH,freqt>>8);
|
||||
immWrite(chanOffs[i]+ADDR_FREQ,freqt&0xff);
|
||||
int fNum=parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,false,4,chan[i].pitch2);
|
||||
int block=(chan[i].baseFreq&0xf800)>>11;
|
||||
if (fNum<0) fNum=0;
|
||||
if (fNum>2047) {
|
||||
while (block<7) {
|
||||
fNum>>=1;
|
||||
block++;
|
||||
}
|
||||
if (fNum>2047) fNum=2047;
|
||||
}
|
||||
chan[i].freq=(block<<11)|fNum;
|
||||
if (chan[i].freq>0x3fff) chan[i].freq=0x3fff;
|
||||
immWrite(chanOffs[i]+ADDR_FREQH,chan[i].freq>>8);
|
||||
immWrite(chanOffs[i]+ADDR_FREQ,chan[i].freq&0xff);
|
||||
chan[i].freqChanged=false;
|
||||
}
|
||||
if (chan[i].keyOn) {
|
||||
|
|
@ -734,47 +743,6 @@ void DivPlatformYM2610B::tick(bool sysTick) {
|
|||
}
|
||||
}
|
||||
|
||||
int DivPlatformYM2610B::octave(int freq) {
|
||||
if (freq>=622.0f*128) {
|
||||
return 128;
|
||||
} else if (freq>=622.0f*64) {
|
||||
return 64;
|
||||
} else if (freq>=622.0f*32) {
|
||||
return 32;
|
||||
} else if (freq>=622.0f*16) {
|
||||
return 16;
|
||||
} else if (freq>=622.0f*8) {
|
||||
return 8;
|
||||
} else if (freq>=622.0f*4) {
|
||||
return 4;
|
||||
} else if (freq>=622.0f*2) {
|
||||
return 2;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int DivPlatformYM2610B::toFreq(int freq) {
|
||||
if (freq>=622.0f*128) {
|
||||
return 0x3800|((freq>>7)&0x7ff);
|
||||
} else if (freq>=622.0f*64) {
|
||||
return 0x3000|((freq>>6)&0x7ff);
|
||||
} else if (freq>=622.0f*32) {
|
||||
return 0x2800|((freq>>5)&0x7ff);
|
||||
} else if (freq>=622.0f*16) {
|
||||
return 0x2000|((freq>>4)&0x7ff);
|
||||
} else if (freq>=622.0f*8) {
|
||||
return 0x1800|((freq>>3)&0x7ff);
|
||||
} else if (freq>=622.0f*4) {
|
||||
return 0x1000|((freq>>2)&0x7ff);
|
||||
} else if (freq>=622.0f*2) {
|
||||
return 0x800|((freq>>1)&0x7ff);
|
||||
} else {
|
||||
return freq&0x7ff;
|
||||
}
|
||||
}
|
||||
|
||||
int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||
if (c.chan>5 && c.chan<9) {
|
||||
c.chan-=6;
|
||||
|
|
@ -906,7 +874,7 @@ int DivPlatformYM2610B::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].freqChanged=true;
|
||||
chan[c.chan].note=c.value;
|
||||
|
|
@ -1026,33 +994,48 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
int destFreq=NOTE_FREQUENCY(c.value2);
|
||||
int boundaryBottom=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,0,false);
|
||||
int boundaryTop=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,12,false);
|
||||
int destFreq=NOTE_FNUM_BLOCK(c.value2,11);
|
||||
int newFreq;
|
||||
bool return2=false;
|
||||
if (chan[c.chan].portaPause) {
|
||||
chan[c.chan].baseFreq=chan[c.chan].portaPauseFreq;
|
||||
}
|
||||
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
|
||||
// what the heck!
|
||||
if (!chan[c.chan].portaPause) {
|
||||
if (octave(chan[c.chan].baseFreq)!=octave(newFreq)) {
|
||||
if ((newFreq&0x7ff)>boundaryTop && (newFreq&0xf800)<0x3800) {
|
||||
chan[c.chan].portaPauseFreq=(boundaryBottom)|((newFreq+0x800)&0xf800);
|
||||
chan[c.chan].portaPause=true;
|
||||
break;
|
||||
}
|
||||
if ((newFreq&0x7ff)<boundaryBottom && (newFreq&0xf800)>0) {
|
||||
chan[c.chan].portaPauseFreq=newFreq=(boundaryTop-1)|((newFreq-0x800)&0xf800);
|
||||
chan[c.chan].portaPause=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
chan[c.chan].baseFreq=newFreq;
|
||||
chan[c.chan].portaPause=false;
|
||||
chan[c.chan].freqChanged=true;
|
||||
if (return2) return 2;
|
||||
chan[c.chan].baseFreq=newFreq;
|
||||
if (return2) {
|
||||
chan[c.chan].inPorta=false;
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_SAMPLE_BANK:
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class DivPlatformYM2610B: public DivPlatformYM2610Base {
|
|||
struct Channel {
|
||||
DivInstrumentFM state;
|
||||
unsigned char freqH, freqL;
|
||||
int freq, baseFreq, pitch, pitch2, note, ins;
|
||||
int freq, baseFreq, pitch, pitch2, portaPauseFreq, note, ins;
|
||||
unsigned char psgMode, autoEnvNum, autoEnvDen;
|
||||
signed char konCycles;
|
||||
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, inPorta, furnacePCM, hardReset;
|
||||
|
|
@ -54,6 +54,7 @@ class DivPlatformYM2610B: public DivPlatformYM2610Base {
|
|||
baseFreq(0),
|
||||
pitch(0),
|
||||
pitch2(0),
|
||||
portaPauseFreq(0),
|
||||
note(0),
|
||||
ins(-1),
|
||||
psgMode(1),
|
||||
|
|
@ -98,8 +99,6 @@ class DivPlatformYM2610B: public DivPlatformYM2610Base {
|
|||
short oldWrites[512];
|
||||
short pendingWrites[512];
|
||||
|
||||
int octave(int freq);
|
||||
int toFreq(int freq);
|
||||
double NOTE_OPNB(int ch, int note);
|
||||
double NOTE_ADPCMB(int note);
|
||||
friend void putDispatchChan(void*,int,int);
|
||||
|
|
|
|||
|
|
@ -120,31 +120,51 @@ int DivPlatformYM2610BExt::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
case DIV_CMD_NOTE_PORTA: {
|
||||
int destFreq=NOTE_FREQUENCY(c.value2);
|
||||
int boundaryBottom=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,0,false);
|
||||
int boundaryTop=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,12,false);
|
||||
int destFreq=NOTE_FNUM_BLOCK(c.value2,11);
|
||||
int newFreq;
|
||||
bool return2=false;
|
||||
if (opChan[ch].portaPause) {
|
||||
opChan[ch].baseFreq=opChan[ch].portaPauseFreq;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
// what the heck!
|
||||
if (!opChan[ch].portaPause) {
|
||||
if (octave(opChan[ch].baseFreq)!=octave(newFreq)) {
|
||||
opChan[ch].portaPause=true;
|
||||
break;
|
||||
if ((newFreq&0x7ff)>boundaryTop && (newFreq&0xf800)<0x3800) {
|
||||
if (parent->song.fbPortaPause) {
|
||||
opChan[ch].portaPauseFreq=(boundaryBottom)|((newFreq+0x800)&0xf800);
|
||||
opChan[ch].portaPause=true;
|
||||
break;
|
||||
} else {
|
||||
newFreq=(newFreq>>1)|((newFreq+0x800)&0xf800);
|
||||
}
|
||||
}
|
||||
if ((newFreq&0x7ff)<boundaryBottom && (newFreq&0xf800)>0) {
|
||||
if (parent->song.fbPortaPause) {
|
||||
opChan[ch].portaPauseFreq=newFreq=(boundaryTop-1)|((newFreq-0x800)&0xf800);
|
||||
opChan[ch].portaPause=true;
|
||||
break;
|
||||
} else {
|
||||
newFreq=(newFreq<<1)|((newFreq-0x800)&0xf800);
|
||||
}
|
||||
}
|
||||
}
|
||||
opChan[ch].baseFreq=newFreq;
|
||||
opChan[ch].portaPause=false;
|
||||
opChan[ch].freqChanged=true;
|
||||
opChan[ch].baseFreq=newFreq;
|
||||
if (return2) return 2;
|
||||
break;
|
||||
}
|
||||
|
|
@ -364,14 +384,20 @@ void DivPlatformYM2610BExt::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,false,octave(opChan[i].baseFreq),opChan[i].pitch2);
|
||||
if (opChan[i].freq>262143) opChan[i].freq=262143;
|
||||
int freqt=toFreq(opChan[i].freq);
|
||||
opChan[i].freqH=freqt>>8;
|
||||
opChan[i].freqL=freqt&0xff;
|
||||
immWrite(opChanOffsH[i],opChan[i].freqH);
|
||||
immWrite(opChanOffsL[i],opChan[i].freqL);
|
||||
opChan[i].freqChanged=false;
|
||||
int fNum=parent->calcFreq(opChan[i].baseFreq&0x7ff,opChan[i].pitch,false,4,opChan[i].pitch2);
|
||||
int block=(opChan[i].baseFreq&0xf800)>>11;
|
||||
if (fNum<0) fNum=0;
|
||||
if (fNum>2047) {
|
||||
while (block<7) {
|
||||
fNum>>=1;
|
||||
block++;
|
||||
}
|
||||
if (fNum>2047) fNum=2047;
|
||||
}
|
||||
opChan[i].freq=(block<<11)|fNum;
|
||||
if (opChan[i].freq>0x3fff) opChan[i].freq=0x3fff;
|
||||
immWrite(opChanOffsH[i],opChan[i].freq>>8);
|
||||
immWrite(opChanOffsL[i],opChan[i].freq&0xff);
|
||||
}
|
||||
writeMask|=opChan[i].active<<(4+i);
|
||||
if (opChan[i].keyOn) {
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ class DivPlatformYM2610BExt: public DivPlatformYM2610B {
|
|||
struct OpChannel {
|
||||
DivMacroInt std;
|
||||
unsigned char freqH, freqL;
|
||||
int freq, baseFreq, pitch, pitch2, ins;
|
||||
int freq, baseFreq, pitch, pitch2, portaPauseFreq, ins;
|
||||
signed char konCycles;
|
||||
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause;
|
||||
int vol;
|
||||
unsigned char pan;
|
||||
OpChannel(): freqH(0), freqL(0), freq(0), baseFreq(0), pitch(0), pitch2(0), ins(-1), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), portaPause(false), vol(0), pan(3) {}
|
||||
OpChannel(): freqH(0), freqL(0), freq(0), baseFreq(0), pitch(0), pitch2(0), portaPauseFreq(0), ins(-1), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), portaPause(false), vol(0), pan(3) {}
|
||||
};
|
||||
OpChannel opChan[4];
|
||||
bool isOpMuted[4];
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ int DivPlatformYM2610Ext::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;
|
||||
}
|
||||
|
|
@ -120,36 +120,56 @@ int DivPlatformYM2610Ext::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
case DIV_CMD_NOTE_PORTA: {
|
||||
int destFreq=NOTE_FREQUENCY(c.value2);
|
||||
int boundaryBottom=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,0,false);
|
||||
int boundaryTop=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,12,false);
|
||||
int destFreq=NOTE_FNUM_BLOCK(c.value2,11);
|
||||
int newFreq;
|
||||
bool return2=false;
|
||||
if (opChan[ch].portaPause) {
|
||||
opChan[ch].baseFreq=opChan[ch].portaPauseFreq;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
// what the heck!
|
||||
if (!opChan[ch].portaPause) {
|
||||
if (octave(opChan[ch].baseFreq)!=octave(newFreq)) {
|
||||
opChan[ch].portaPause=true;
|
||||
break;
|
||||
if ((newFreq&0x7ff)>boundaryTop && (newFreq&0xf800)<0x3800) {
|
||||
if (parent->song.fbPortaPause) {
|
||||
opChan[ch].portaPauseFreq=(boundaryBottom)|((newFreq+0x800)&0xf800);
|
||||
opChan[ch].portaPause=true;
|
||||
break;
|
||||
} else {
|
||||
newFreq=(newFreq>>1)|((newFreq+0x800)&0xf800);
|
||||
}
|
||||
}
|
||||
if ((newFreq&0x7ff)<boundaryBottom && (newFreq&0xf800)>0) {
|
||||
if (parent->song.fbPortaPause) {
|
||||
opChan[ch].portaPauseFreq=newFreq=(boundaryTop-1)|((newFreq-0x800)&0xf800);
|
||||
opChan[ch].portaPause=true;
|
||||
break;
|
||||
} else {
|
||||
newFreq=(newFreq<<1)|((newFreq-0x800)&0xf800);
|
||||
}
|
||||
}
|
||||
}
|
||||
opChan[ch].baseFreq=newFreq;
|
||||
opChan[ch].portaPause=false;
|
||||
opChan[ch].freqChanged=true;
|
||||
opChan[ch].baseFreq=newFreq;
|
||||
if (return2) return 2;
|
||||
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;
|
||||
}
|
||||
|
|
@ -364,14 +384,20 @@ void DivPlatformYM2610Ext::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,false,octave(opChan[i].baseFreq),opChan[i].pitch2);
|
||||
if (opChan[i].freq>262143) opChan[i].freq=262143;
|
||||
int freqt=toFreq(opChan[i].freq);
|
||||
opChan[i].freqH=freqt>>8;
|
||||
opChan[i].freqL=freqt&0xff;
|
||||
immWrite(opChanOffsH[i],opChan[i].freqH);
|
||||
immWrite(opChanOffsL[i],opChan[i].freqL);
|
||||
opChan[i].freqChanged=false;
|
||||
int fNum=parent->calcFreq(opChan[i].baseFreq&0x7ff,opChan[i].pitch,false,4,opChan[i].pitch2);
|
||||
int block=(opChan[i].baseFreq&0xf800)>>11;
|
||||
if (fNum<0) fNum=0;
|
||||
if (fNum>2047) {
|
||||
while (block<7) {
|
||||
fNum>>=1;
|
||||
block++;
|
||||
}
|
||||
if (fNum>2047) fNum=2047;
|
||||
}
|
||||
opChan[i].freq=(block<<11)|fNum;
|
||||
if (opChan[i].freq>0x3fff) opChan[i].freq=0x3fff;
|
||||
immWrite(opChanOffsH[i],opChan[i].freq>>8);
|
||||
immWrite(opChanOffsL[i],opChan[i].freq&0xff);
|
||||
}
|
||||
writeMask|=opChan[i].active<<(4+i);
|
||||
if (opChan[i].keyOn) {
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ class DivPlatformYM2610Ext: public DivPlatformYM2610 {
|
|||
struct OpChannel {
|
||||
DivMacroInt std;
|
||||
unsigned char freqH, freqL;
|
||||
int freq, baseFreq, pitch, pitch2, ins;
|
||||
int freq, baseFreq, pitch, pitch2, portaPauseFreq, ins;
|
||||
signed char konCycles;
|
||||
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause;
|
||||
int vol;
|
||||
unsigned char pan;
|
||||
OpChannel(): freqH(0), freqL(0), freq(0), baseFreq(0), pitch(0), pitch2(0), ins(-1), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), portaPause(false), vol(0), pan(3) {}
|
||||
OpChannel(): freqH(0), freqL(0), freq(0), baseFreq(0), pitch(0), pitch2(0), portaPauseFreq(0), ins(-1), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), portaPause(false), vol(0), pan(3) {}
|
||||
};
|
||||
OpChannel opChan[4];
|
||||
bool isOpMuted[4];
|
||||
|
|
|
|||
|
|
@ -642,7 +642,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
chan[i].scheduledSlideReset=false;
|
||||
chan[i].inPorta=false;
|
||||
if (!song.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,true,0));
|
||||
dispatchCmd(DivCommand(DIV_CMD_NOTE_PORTA,i,chan[i].portaSpeed,chan[i].portaNote));
|
||||
dispatchCmd(DivCommand(DIV_CMD_NOTE_PORTA,i,chan[i].portaSpeed*(song.linearPitch==2?song.pitchSlideSpeed:1),chan[i].portaNote));
|
||||
chan[i].portaNote=-1;
|
||||
chan[i].portaSpeed=-1;
|
||||
chan[i].inPorta=false;
|
||||
|
|
@ -966,7 +966,7 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
|
|||
}
|
||||
if (!song.noSlidesOnFirstTick || !firstTick) {
|
||||
if ((chan[i].keyOn || chan[i].keyOff) && chan[i].portaSpeed>0) {
|
||||
if (dispatchCmd(DivCommand(DIV_CMD_NOTE_PORTA,i,chan[i].portaSpeed,chan[i].portaNote))==2 && chan[i].portaStop && song.targetResetsSlides) {
|
||||
if (dispatchCmd(DivCommand(DIV_CMD_NOTE_PORTA,i,chan[i].portaSpeed*(song.linearPitch==2?song.pitchSlideSpeed:1),chan[i].portaNote))==2 && chan[i].portaStop && song.targetResetsSlides) {
|
||||
chan[i].portaSpeed=0;
|
||||
chan[i].oldNote=chan[i].note;
|
||||
chan[i].note=chan[i].portaNote;
|
||||
|
|
|
|||
|
|
@ -302,7 +302,12 @@ struct DivSong {
|
|||
|
||||
// compatibility flags
|
||||
bool limitSlides;
|
||||
bool linearPitch;
|
||||
// linear pitch
|
||||
// 0: not linear
|
||||
// 1: only pitch changes (04xy/E5xx) linear
|
||||
// 2: full linear
|
||||
unsigned char linearPitch;
|
||||
unsigned char pitchSlideSpeed;
|
||||
// loop behavior
|
||||
// 0: reset on loop
|
||||
// 1: fake reset on loop
|
||||
|
|
@ -413,7 +418,8 @@ struct DivSong {
|
|||
masterVol(1.0f),
|
||||
tuning(440.0f),
|
||||
limitSlides(false),
|
||||
linearPitch(true),
|
||||
linearPitch(1),
|
||||
pitchSlideSpeed(4),
|
||||
loopModality(0),
|
||||
properNoiseLayout(false),
|
||||
waveDutyIsVol(false),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue