QuadTone: Fix PCM playback and add no hiss flag

This commit is contained in:
Natt Akuma 2024-02-03 06:16:35 +07:00
parent 731b7a1bd6
commit 1200e76469
3 changed files with 53 additions and 29 deletions

View file

@ -30,13 +30,14 @@ const char** DivPlatformZXBeeperQuadTone::getRegisterSheet() {
}
void DivPlatformZXBeeperQuadTone::acquire(short** buf, size_t len) {
bool o=false;
for (size_t h=0; h<len; h++) {
if (curSample>=0 && curSample<parent->song.sampleLen && !isMuted[4]) {
bool sampleActive=false;
if (curSample>=0 && curSample<parent->song.sampleLen) {
sampleActive=!isMuted[4];
while (curSamplePeriod>=chan[4].freq) {
DivSample* s=parent->getSample(curSample);
if (s->samples>0) {
if (!isMuted[4]) o=(s->data8[curSamplePos++]>0);
chan[4].out=(s->data8[curSamplePos++]>0);
if (curSamplePos>=s->samples) curSample=-1;
// (theoretical) 32KiB limit
if (curSamplePos>=32768*8) curSample=-1;
@ -46,46 +47,49 @@ void DivPlatformZXBeeperQuadTone::acquire(short** buf, size_t len) {
curSamplePeriod-=chan[4].freq;
}
curSamplePeriod+=40;
}
if (sampleActive) {
buf[0][h]=chan[4].out?32767:0;
if ((outputClock&3)==0) {
oscBuf[0]->data[oscBuf[0]->needle++]=0;
oscBuf[1]->data[oscBuf[1]->needle++]=0;
oscBuf[2]->data[oscBuf[2]->needle++]=0;
oscBuf[3]->data[oscBuf[3]->needle++]=0;
oscBuf[4]->data[oscBuf[4]->needle++]=o?32767:0;
oscBuf[4]->data[oscBuf[4]->needle++]=buf[0][h];
}
} else {
int ch=outputClock/2;
int b=ch*4;
bool o=false;
if ((outputClock&1)==0) {
short oscOut;
chan[ch].sPosition+=(regPool[1+b]<<8)|regPool[0+b];
chan[ch].out=regPool[3+b]+((((chan[ch].sPosition>>8)&0xff)<regPool[2+b])?1:0);
if (isMuted[ch]) chan[ch].out=0;
if ((chan[ch].out&0x18)==0x18) {
oscOut=32767;
} else if ((chan[ch].out&0x18)==0) {
oscOut=0;
} else {
oscOut=16383;
}
oscBuf[ch]->data[oscBuf[ch]->needle++]=oscOut;
}
if ((outputClock&3)==0) {
oscBuf[4]->data[oscBuf[4]->needle++]=0;
}
o=chan[ch].out&0x10;
oscBuf[ch]->data[oscBuf[ch]->needle++]=o?32767:0;
chan[ch].out<<=1;
// if muted, ztill run sample
if (curSample>=0 && curSample<parent->song.sampleLen && isMuted[4]) {
while (curSamplePeriod>=chan[4].freq) {
DivSample* s=parent->getSample(curSample);
if (s->samples>0) {
if (curSamplePos>=s->samples) curSample=-1;
// (theoretical) 32KiB limit
if (curSamplePos>=32768*8) curSample=-1;
} else {
curSample=-1;
}
curSamplePeriod-=chan[4].freq;
if (!isMuted[ch]) o=chan[ch].out&0x10;
if (noHiss) {
deHisser[outputClock]=o;
buf[0][h]=-1;
for (int i=0; i<8; i++) {
buf[0][h]+=deHisser[i]?4096:0;
}
curSamplePeriod+=40;
} else {
buf[0][h]=o?32767:0;
}
chan[ch].out<<=1;
}
outputClock=(outputClock+1)&7;
buf[0][h]=o?32767:0;
}
}
@ -157,6 +161,7 @@ void DivPlatformZXBeeperQuadTone::tick(bool sysTick) {
chan[4].freq=parent->calcFreq(chan[4].baseFreq,chan[4].pitch,chan[4].fixedArp?chan[4].baseNoteOverride:chan[4].arpOff,chan[4].fixedArp,true,2,chan[4].pitch2,chipClock,off);
if (chan[4].freq>258) chan[4].freq=258;
if (chan[4].freq<3) chan[4].freq=3;
rWrite(16,(chan[4].freq-2)&255);
chan[4].freq*=13;
}
if (chan[4].keyOn) chan[4].keyOn=false;
@ -340,11 +345,12 @@ unsigned char* DivPlatformZXBeeperQuadTone::getRegisterPool() {
}
int DivPlatformZXBeeperQuadTone::getRegisterPoolSize() {
return 16;
return 17;
}
void DivPlatformZXBeeperQuadTone::reset() {
memset(regPool,0,16);
memset(regPool,0,17);
memset(deHisser,0,8);
for (int i=0; i<5; i++) {
chan[i]=DivPlatformZXBeeperQuadTone::Channel();
chan[i].std.setEngine(parent);
@ -353,7 +359,6 @@ void DivPlatformZXBeeperQuadTone::reset() {
cycles=0;
curChan=0;
sOffTimer=0;
ulaOut=0;
curSample=-1;
curSamplePos=0;
curSamplePeriod=0;
@ -381,7 +386,8 @@ void DivPlatformZXBeeperQuadTone::setFlags(const DivConfig& flags) {
}
CHECK_CUSTOM_CLOCK;
rate=chipClock/40;
for (int i=0; i<4; i++) {
noHiss=flags.getBool("noHiss",false);
for (int i=0; i<5; i++) {
oscBuf[i]->rate=rate/4;
}
}

View file

@ -36,12 +36,13 @@ class DivPlatformZXBeeperQuadTone: public DivDispatch {
Channel chan[5];
DivDispatchOscBuffer* oscBuf[5];
bool isMuted[5];
unsigned char ulaOut;
bool noHiss;
bool deHisser[8];
int cycles, curChan, sOffTimer, delay, curSample, curSamplePeriod;
unsigned int curSamplePos;
unsigned int outputClock;
unsigned char regPool[16];
unsigned char regPool[17];
friend void putDispatchChip(void*,int);
friend void putDispatchChan(void*,int,int);
public:

View file

@ -2270,6 +2270,23 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl
}
break;
}
case DIV_SYSTEM_SFX_BEEPER_QUADTONE: {
bool sysPal=flags.getInt("clockSel",0);
bool noHiss=flags.getBool("noHiss",false);
if (ImGui::Checkbox("PAL",&sysPal)) {
altered=true;
}
if (ImGui::Checkbox("Disable hissing",&noHiss)) {
altered=true;
}
if (altered) {
e->lockSave([&]() {
flags.set("clockSel",(int)sysPal);
flags.set("noHiss",noHiss);
});
}
break;
}
case DIV_SYSTEM_SWAN:
case DIV_SYSTEM_BUBSYS_WSG:
case DIV_SYSTEM_PET: