diff --git a/src/engine/dispatchContainer.cpp b/src/engine/dispatchContainer.cpp index 54768f373..684984aba 100644 --- a/src/engine/dispatchContainer.cpp +++ b/src/engine/dispatchContainer.cpp @@ -620,11 +620,6 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do break; case DIV_SYSTEM_SWAN: dispatch=new DivPlatformSwan; - if (isRender) { - ((DivPlatformSwan*)dispatch)->setCoreQuality(eng->getConfInt("swanQualityRender",3)); - } else { - ((DivPlatformSwan*)dispatch)->setCoreQuality(eng->getConfInt("swanQuality",3)); - } break; case DIV_SYSTEM_T6W28: dispatch=new DivPlatformT6W28; diff --git a/src/engine/platform/sound/swan.cpp b/src/engine/platform/sound/swan.cpp index 685fefe94..405198a2b 100644 --- a/src/engine/platform/sound/swan.cpp +++ b/src/engine/platform/sound/swan.cpp @@ -49,18 +49,23 @@ } -#define SYNCSAMPLE(wt) /* \ +#define SYNCSAMPLE(wt) \ { \ - int32_t left = sample_cache[ch][0], right = sample_cache[ch][1]; \ - WaveSynth.offset_inline(wt, left - last_val[ch][0], sbuf[0]); \ - WaveSynth.offset_inline(wt, right - last_val[ch][1], sbuf[1]); \ - last_val[ch][0] = left; \ - last_val[ch][1] = right; \ - } */ + int32_t left = sample_cache[ch][0] << 5, right = sample_cache[ch][1] << 5; \ + if (left!=last_val[ch][0]) { \ + blip_add_delta(sbuf[0], wt, left - last_val[ch][0]); \ + last_val[ch][0] = left; \ + } \ + if (right!=last_val[ch][1]) { \ + blip_add_delta(sbuf[1], wt, right - last_val[ch][1]); \ + last_val[ch][1] = right; \ + } \ + oscBuf[ch]->putSample(wt,(left+right)<<1); \ + } #define SYNCSAMPLE_NOISE(wt) SYNCSAMPLE(wt) -void WSwan::SoundUpdate(uint32_t v30mz_timestamp) +void WSwan::SoundUpdate(void) { int32_t run_time; @@ -68,9 +73,6 @@ void WSwan::SoundUpdate(uint32_t v30mz_timestamp) //printf("%02x %02x\n", control, noise_control); run_time = v30mz_timestamp - last_ts; - for(int y = 0; y < 2; y++) - sbuf[y] = 0; - for(unsigned int ch = 0; ch < 4; ch++) { // Channel is disabled? @@ -85,6 +87,7 @@ void WSwan::SoundUpdate(uint32_t v30mz_timestamp) else if(ch == 2 && (control & 0x40) && sweep_value) // Sweep { uint32_t tmp_pt = 2048 - period[ch]; + uint32_t meow_timestamp = v30mz_timestamp - run_time; uint32_t tmp_run_time = run_time; while(tmp_run_time) @@ -106,6 +109,7 @@ void WSwan::SoundUpdate(uint32_t v30mz_timestamp) } } + meow_timestamp += sub_run_time; if(tmp_pt > 4) { period_counter[ch] -= sub_run_time; @@ -114,6 +118,7 @@ void WSwan::SoundUpdate(uint32_t v30mz_timestamp) sample_pos[ch] = (sample_pos[ch] + 1) & 0x1F; MK_SAMPLE_CACHE; + SYNCSAMPLE(meow_timestamp + period_counter[ch]); period_counter[ch] += tmp_pt; } } @@ -162,8 +167,6 @@ void WSwan::SoundUpdate(uint32_t v30mz_timestamp) } } } - sbuf[0] += sample_cache[ch][0]; - sbuf[1] += sample_cache[ch][1]; } if(HVoiceCtrl & 0x80) @@ -181,21 +184,25 @@ void WSwan::SoundUpdate(uint32_t v30mz_timestamp) sample >>= 5; int32_t left, right; - left = (HVoiceChanCtrl & 0x40) ? sample : 0; - right = (HVoiceChanCtrl & 0x20) ? sample : 0; + left = (HVoiceChanCtrl & 0x40) ? (sample << 5) : 0; + right = (HVoiceChanCtrl & 0x20) ? (sample << 5) : 0; - // WaveSynth.offset_inline(v30mz_timestamp, left - last_hv_val[0], sbuf[0]); - // WaveSynth.offset_inline(v30mz_timestamp, right - last_hv_val[1], sbuf[1]); - // last_hv_val[0] = left; - // last_hv_val[1] = right; - sbuf[0] += left; - sbuf[1] += right; + if (left!=last_hv_val[0]) { + blip_add_delta(sbuf[0], v30mz_timestamp, left - last_hv_val[0]); + last_hv_val[0] = left; + } + if (right!=last_hv_val[1]) { + blip_add_delta(sbuf[1], v30mz_timestamp, right - last_hv_val[1]); + last_hv_val[1] = right; + } } last_ts = v30mz_timestamp; } void WSwan::SoundWrite(uint32_t A, uint8_t V) { + SoundUpdate(); + if(A >= 0x80 && A <= 0x87) { int ch = (A - 0x80) >> 1; @@ -262,10 +269,13 @@ void WSwan::SoundWrite(uint32_t A, uint8_t V) case 0x95: HyperVoice = V; break; // Pick a port, any port?! //default: printf("%04x:%02x\n", A, V); break; } + SoundUpdate(); } uint8_t WSwan::SoundRead(uint32_t A) { + SoundUpdate(); + if(A >= 0x80 && A <= 0x87) { int ch = (A - 0x80) >> 1; @@ -303,22 +313,8 @@ int32_t WSwan::SoundFlush(int16_t *SoundBuf, const int32_t MaxSoundFrames) { int32_t FrameCount = 0; - if(SoundBuf) - { - for(int y = 0; y < 2; y++) - { - // sbuf[y]->end_frame(v30mz_timestamp); - // FrameCount = sbuf[y]->read_samples(SoundBuf + y, MaxSoundFrames, true); - int32_t left = sbuf[0]; - int32_t right = sbuf[1]; - if (left >= 0x400) left = 0x3FF; - else if (left < -0x400) left = -0x400; - if (right >= 0x400) left = 0x3FF; - else if (right < -0x400) left = -0x400; - SoundBuf[0] = (int16_t)left << 5; - SoundBuf[1] = (int16_t)right << 5; - } - } + SoundUpdate(); + last_ts = 0; @@ -326,51 +322,11 @@ int32_t WSwan::SoundFlush(int16_t *SoundBuf, const int32_t MaxSoundFrames) } // Call before wsRAM is updated -// void WSwan::SoundCheckRAMWrite(uint32_t A) -// { -// if((A >> 6) == SampleRAMPos) -// SoundUpdate(); -// } - -// static void RedoVolume(void) -// { -// WaveSynth.volume(2.5); -// } - -// void WSwan::SoundInit(void) -// { -// for(int i = 0; i < 2; i++) -// { -// sbuf[i] = new Blip_Buffer(); - -// sbuf[i]->set_sample_rate(0 ? 0 : 44100, 60); -// sbuf[i]->clock_rate((long)(3072000)); -// sbuf[i]->bass_freq(20); -// } - -// RedoVolume(); -// } - -// void WSwan::SoundKill(void) -// { -// for(int i = 0; i < 2; i++) -// { -// if(sbuf[i]) -// { -// delete sbuf[i]; -// sbuf[i] = NULL; -// } -// } - -// } - -// bool WSwan::SetSoundRate(uint32_t rate) -// { -// for(int i = 0; i < 2; i++) -// sbuf[i]->set_sample_rate(rate?rate:44100, 60); - -// return(true); -// } +void WSwan::SoundCheckRAMWrite(uint32_t A) +{ + if((A >> 6) == SampleRAMPos) + SoundUpdate(); +} void WSwan::SoundReset(void) { @@ -394,7 +350,7 @@ void WSwan::SoundReset(void) nreg = 0; memset(sample_cache, 0, sizeof(sample_cache)); - // memset(last_val, 0, sizeof(last_val)); + memset(last_val, 0, sizeof(last_val)); last_v_val = 0; HyperVoice = 0; @@ -402,8 +358,6 @@ void WSwan::SoundReset(void) HVoiceCtrl = 0; HVoiceChanCtrl = 0; - for(int y = 0; y < 2; y++) - // sbuf[y]->clear(); - sbuf[y] = 0; last_ts = 0; + v30mz_timestamp = 0; } diff --git a/src/engine/platform/sound/swan.h b/src/engine/platform/sound/swan.h index bd421a74c..32fb37a82 100644 --- a/src/engine/platform/sound/swan.h +++ b/src/engine/platform/sound/swan.h @@ -23,32 +23,29 @@ #define __WSWAN_SOUND_H #include +#include "blip_buf.h" +#include "../../dispatch.h" class WSwan { public: int32_t SoundFlush(int16_t *SoundBuf, const int32_t MaxSoundFrames); - // void SoundInit(void); - // void SoundKill(void); - // void SetSoundMultiplier(double multiplier); - // bool SetSoundRate(uint32_t rate); - void SoundWrite(uint32_t, uint8_t); uint8_t SoundRead(uint32_t); void SoundReset(void); - // void SoundCheckRAMWrite(uint32_t A); + void SoundCheckRAMWrite(uint32_t A); - void SoundUpdate(uint32_t); + void SoundUpdate(); void RAMWrite(uint32_t, uint8_t); int32_t sample_cache[4][2]; -private: // Blip_Synth WaveSynth; // Blip_Buffer *sbuf[2] = { NULL }; - int32_t sbuf[2]; + blip_buffer_t* sbuf[2]; + DivDispatchOscBuffer* oscBuf[4]; uint16_t period[4]; uint8_t volume[4]; // left volume in upper 4 bits, right in lower 4 bits @@ -70,10 +67,11 @@ private: uint8_t HVoiceCtrl, HVoiceChanCtrl; int32_t period_counter[4]; - // int32_t last_val[4][2]; // Last outputted value, l&r + int32_t last_val[4][2]; // Last outputted value, l&r uint8_t sample_pos[4]; uint16_t nreg; uint32_t last_ts; + uint32_t v30mz_timestamp; uint8_t wsRAM[64]; }; diff --git a/src/engine/platform/swan.cpp b/src/engine/platform/swan.cpp index 338f8fd0b..a7ef3ae06 100644 --- a/src/engine/platform/swan.cpp +++ b/src/engine/platform/swan.cpp @@ -53,16 +53,36 @@ const char** DivPlatformSwan::getRegisterSheet() { return regCheatSheetWS; } -void DivPlatformSwan::acquire(short** buf, size_t len) { +void DivPlatformSwan::acquireDirect(blip_buffer_t** bb, size_t len) { for (int i=0; i<4; i++) { oscBuf[i]->begin(len); + ws->oscBuf[i]=oscBuf[i]; } + ws->sbuf[0]=bb[0]; + ws->sbuf[1]=bb[1]; + for (size_t h=0; hv30mz_timestamp=h; + // heuristic + int pcmAdvance=1; + if (writes.empty()) { + if (!pcm || dacSample==-1) { + break; + } else { + pcmAdvance=len-h; + if (dacRate>0) { + int remainTime=(rate-dacPeriod+dacRate-1)/dacRate; + if (remainTimerate) { + dacPeriod+=dacRate*pcmAdvance; + while (dacPeriod>=rate) { DivSample* s=parent->getSample(dacSample); if (s->samples<=0 || dacPos>=s->samples) { dacSample=-1; @@ -78,25 +98,27 @@ void DivPlatformSwan::acquire(short** buf, size_t len) { dacPeriod-=rate; } } + + h+=pcmAdvance-1; // the rest while (!writes.empty()) { QueuedWrite w=writes.front(); regPool[w.addr]=w.val; - if (w.addr<0x40) ws->SoundWrite(w.addr|0x80,w.val); - else ws->RAMWrite(w.addr&0x3f,w.val); + if (w.addr<0x40) { + ws->SoundWrite(w.addr|0x80,w.val); + } else { + ws->SoundCheckRAMWrite(w.addr&0x3f); + ws->RAMWrite(w.addr&0x3f,w.val); + } writes.pop(); } - int16_t samp[2]{0, 0}; - ws->SoundUpdate(coreQuality); - ws->SoundFlush(samp,1); - buf[0][h]=samp[0]; - buf[1][h]=samp[1]; - for (int i=0; i<4; i++) { - oscBuf[i]->putSample(h,(ws->sample_cache[i][0]+ws->sample_cache[i][1])<<6); - } } + ws->v30mz_timestamp=len; + ws->SoundUpdate(); + ws->SoundFlush(NULL,0); + for (int i=0; i<4; i++) { oscBuf[i]->end(len); } @@ -587,6 +609,10 @@ int DivPlatformSwan::getOutputCount() { return 2; } +bool DivPlatformSwan::hasAcquireDirect() { + return true; +} + void DivPlatformSwan::notifyWaveChange(int wave) { for (int i=0; i<4; i++) { if (chan[i].wave==wave) { @@ -613,38 +639,12 @@ void DivPlatformSwan::poke(std::vector& wlist) { void DivPlatformSwan::setFlags(const DivConfig& flags) { chipClock=3072000; CHECK_CUSTOM_CLOCK; - rate=chipClock/coreQuality; + rate=chipClock; for (int i=0; i<4; i++) { oscBuf[i]->setRate(rate); } } -void DivPlatformSwan::setCoreQuality(unsigned char q) { - switch (q) { - case 0: - coreQuality=96; - break; - case 1: - coreQuality=64; - break; - case 2: - coreQuality=32; - break; - case 3: - coreQuality=16; - break; - case 4: - coreQuality=4; - break; - case 5: - coreQuality=1; - break; - default: - coreQuality=16; - break; - } -} - int DivPlatformSwan::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; diff --git a/src/engine/platform/swan.h b/src/engine/platform/swan.h index f65702d37..095b338aa 100644 --- a/src/engine/platform/swan.h +++ b/src/engine/platform/swan.h @@ -53,13 +53,12 @@ class DivPlatformSwan: public DivDispatch { }; FixedQueue writes; FixedQueue postDACWrites; - int coreQuality; WSwan* ws; void updateWave(int ch); friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); public: - void acquire(short** buf, size_t len); + void acquireDirect(blip_buffer_t** bb, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -76,10 +75,10 @@ class DivPlatformSwan: public DivDispatch { void notifyWaveChange(int wave); void notifyInsDeletion(void* ins); int getOutputCount(); + bool hasAcquireDirect(); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - void setCoreQuality(unsigned char q); int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformSwan(); diff --git a/src/gui/gui.h b/src/gui/gui.h index ae6c36b28..a4f9a4e25 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1802,7 +1802,6 @@ class FurnaceGUI { int pnQuality; int saaQuality; int smQuality; - int swanQuality; int arcadeCoreRender; int ym2612CoreRender; int snCoreRender; @@ -1826,7 +1825,6 @@ class FurnaceGUI { int pnQualityRender; int saaQualityRender; int smQualityRender; - int swanQualityRender; int pcSpeakerOutMethod; String yrw801Path; String tg100Path; @@ -2061,7 +2059,6 @@ class FurnaceGUI { pnQuality(3), saaQuality(3), smQuality(3), - swanQuality(3), arcadeCoreRender(1), ym2612CoreRender(0), snCoreRender(0), @@ -2085,7 +2082,6 @@ class FurnaceGUI { pnQualityRender(3), saaQualityRender(3), smQualityRender(3), - swanQualityRender(3), pcSpeakerOutMethod(0), yrw801Path(""), tg100Path(""), diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index 598845e21..a4efbfd14 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -2127,7 +2127,6 @@ void FurnaceGUI::drawSettings() { CORE_QUALITY("SAA1099",saaQuality,saaQualityRender); CORE_QUALITY("SID (dSID)",dsidQuality,dsidQualityRender); CORE_QUALITY("SM8521",smQuality,smQualityRender); - CORE_QUALITY("WonderSwan",swanQuality,swanQualityRender); ImGui::EndTable(); } @@ -5135,7 +5134,6 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { settings.pnQuality=conf.getInt("pnQuality",3); settings.saaQuality=conf.getInt("saaQuality",3); settings.smQuality=conf.getInt("smQuality",3); - settings.swanQuality=conf.getInt("swanQuality",3); settings.arcadeCoreRender=conf.getInt("arcadeCoreRender",1); settings.ym2612CoreRender=conf.getInt("ym2612CoreRender",0); @@ -5161,7 +5159,6 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { settings.pnQualityRender=conf.getInt("pnQualityRender",3); settings.saaQualityRender=conf.getInt("saaQualityRender",3); settings.smQualityRender=conf.getInt("smQualityRender",3); - settings.swanQualityRender=conf.getInt("swanQualityRender",3); settings.pcSpeakerOutMethod=conf.getInt("pcSpeakerOutMethod",0); @@ -5203,7 +5200,6 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { clampSetting(settings.pnQuality,0,5); clampSetting(settings.saaQuality,0,5); clampSetting(settings.smQuality,0,5); - clampSetting(settings.swanQuality,0,5); clampSetting(settings.arcadeCoreRender,0,1); clampSetting(settings.ym2612CoreRender,0,2); clampSetting(settings.snCoreRender,0,1); @@ -5227,7 +5223,6 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { clampSetting(settings.pnQualityRender,0,5); clampSetting(settings.saaQualityRender,0,5); clampSetting(settings.smQualityRender,0,5); - clampSetting(settings.swanQualityRender,0,5); clampSetting(settings.pcSpeakerOutMethod,0,4); clampSetting(settings.mainFont,0,6); clampSetting(settings.patFont,0,6); @@ -5725,7 +5720,6 @@ void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { conf.set("pnQuality",settings.pnQuality); conf.set("saaQuality",settings.saaQuality); conf.set("smQuality",settings.smQuality); - conf.set("swanQuality",settings.swanQuality); conf.set("arcadeCoreRender",settings.arcadeCoreRender); conf.set("ym2612CoreRender",settings.ym2612CoreRender); @@ -5751,7 +5745,6 @@ void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { conf.set("pnQualityRender",settings.pnQualityRender); conf.set("saaQualityRender",settings.saaQualityRender); conf.set("smQualityRender",settings.smQualityRender); - conf.set("swanQualityRender",settings.swanQualityRender); conf.set("pcSpeakerOutMethod",settings.pcSpeakerOutMethod); @@ -5811,7 +5804,6 @@ void FurnaceGUI::commitSettings() { settings.pnQuality!=e->getConfInt("pnQuality",3) || settings.saaQuality!=e->getConfInt("saaQuality",3) || settings.smQuality!=e->getConfInt("smQuality",3) || - settings.swanQuality!=e->getConfInt("swanQuality",3) || settings.audioQuality!=e->getConfInt("audioQuality",0) || settings.audioHiPass!=e->getConfInt("audioHiPass",1) );