diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index b4394f608..5a1c2db64 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -319,6 +319,18 @@ class DivDispatch { */ virtual int getPortaFloor(int ch); + /** + * get the required amplification level of this dispatch's output. + * @return the amplification level. + */ + virtual float getPostAmp(); + + /** + * check whether DC offset correction is required. + * @return truth. + */ + virtual bool getDCOffRequired(); + /** * get a description of a dispatch-specific effect. * @param effect the effect. diff --git a/src/engine/dispatchContainer.cpp b/src/engine/dispatchContainer.cpp index ba72a6957..c89a0fa06 100644 --- a/src/engine/dispatchContainer.cpp +++ b/src/engine/dispatchContainer.cpp @@ -79,6 +79,11 @@ void DivDispatchContainer::flush(size_t count) { } void DivDispatchContainer::fillBuf(size_t runtotal, size_t offset, size_t size) { + if (dcOffCompensation && runtotal>0) { + dcOffCompensation=false; + prevSample[0]=bbIn[0][0]; + if (dispatch->isStereo()) prevSample[1]=bbIn[1][0]; + } if (lowQuality) { for (size_t i=0; igetDCOffRequired()) { + dcOffCompensation=true; + } // run for one cycle to determine DC offset // TODO: SAA1099 doesn't like that /*dispatch->acquire(bbIn[0],bbIn[1],0,1); diff --git a/src/engine/engine.h b/src/engine/engine.h index 68ec0ce5b..c359da253 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -154,7 +154,7 @@ struct DivDispatchContainer { int temp[2], prevSample[2]; short* bbIn[2]; short* bbOut[2]; - bool lowQuality; + bool lowQuality, dcOffCompensation; void setRates(double gotRate); void setQuality(bool lowQual); @@ -172,7 +172,8 @@ struct DivDispatchContainer { prevSample{0,0}, bbIn{NULL,NULL}, bbOut{NULL,NULL}, - lowQuality(false) {} + lowQuality(false), + dcOffCompensation(false) {} }; class DivEngine { diff --git a/src/engine/platform/abstract.cpp b/src/engine/platform/abstract.cpp index 7b6115aef..b860f6808 100644 --- a/src/engine/platform/abstract.cpp +++ b/src/engine/platform/abstract.cpp @@ -74,6 +74,14 @@ int DivDispatch::getPortaFloor(int ch) { return 0x00; } +float DivDispatch::getPostAmp() { + return 1.0f; +} + +bool DivDispatch::getDCOffRequired() { + return false; +} + const char* DivDispatch::getEffectName(unsigned char effect) { return NULL; } diff --git a/src/engine/platform/ay.cpp b/src/engine/platform/ay.cpp index b798cba4e..e174e345b 100644 --- a/src/engine/platform/ay.cpp +++ b/src/engine/platform/ay.cpp @@ -497,6 +497,10 @@ void DivPlatformAY8910::flushWrites() { while (!writes.empty()) writes.pop(); } +bool DivPlatformAY8910::getDCOffRequired() { + return true; +} + void DivPlatformAY8910::reset() { while (!writes.empty()) writes.pop(); ay->device_reset(); diff --git a/src/engine/platform/ay.h b/src/engine/platform/ay.h index 82b647f2d..b1a3ea127 100644 --- a/src/engine/platform/ay.h +++ b/src/engine/platform/ay.h @@ -95,6 +95,7 @@ class DivPlatformAY8910: public DivDispatch { void setFlags(unsigned int flags); bool isStereo(); bool keyOffAffectsArp(int ch); + bool getDCOffRequired(); void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); diff --git a/src/engine/platform/mmc5.cpp b/src/engine/platform/mmc5.cpp index 3ccf95499..102d6a2e9 100644 --- a/src/engine/platform/mmc5.cpp +++ b/src/engine/platform/mmc5.cpp @@ -89,7 +89,6 @@ void DivPlatformMMC5::acquire(short* bufL, short* bufR, size_t start, size_t len if (!isMuted[2]) { sample+=mmc5->pcm.output*2; } - sample=(sample-128)<<6; if (sample>32767) sample=32767; if (sample<-32768) sample=-32768; bufL[i]=sample; @@ -336,6 +335,10 @@ int DivPlatformMMC5::getRegisterPoolSize() { return 32; } +float DivPlatformMMC5::getPostAmp() { + return 64.0f; +} + void DivPlatformMMC5::reset() { for (int i=0; i<3; i++) { chan[i]=DivPlatformMMC5::Channel(); diff --git a/src/engine/platform/mmc5.h b/src/engine/platform/mmc5.h index a29ffc7d4..6b364d5ad 100644 --- a/src/engine/platform/mmc5.h +++ b/src/engine/platform/mmc5.h @@ -74,6 +74,7 @@ class DivPlatformMMC5: public DivDispatch { void tick(); void muteChannel(int ch, bool mute); bool keyOffAffectsArp(int ch); + float getPostAmp(); void setFlags(unsigned int flags); void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); diff --git a/src/engine/platform/nes.cpp b/src/engine/platform/nes.cpp index f61ed4fb6..9dbf55543 100644 --- a/src/engine/platform/nes.cpp +++ b/src/engine/platform/nes.cpp @@ -80,7 +80,14 @@ void DivPlatformNES::acquire(short* bufL, short* bufR, size_t start, size_t len) DivSample* s=parent->getSample(dacSample); if (s->samples>0) { if (!isMuted[4]) { - rWrite(0x4011,((unsigned char)s->data8[dacPos]+0x80)>>1); + unsigned char next=((unsigned char)s->data8[dacPos]+0x80)>>1; + if (dacAntiClickOn && dacAntiClick=s->samples) { if (s->loopStart>=0 && s->loopStart<(int)s->samples) { @@ -101,7 +108,7 @@ void DivPlatformNES::acquire(short* bufL, short* bufR, size_t start, size_t len) if (nes->apu.clocked) { nes->apu.clocked=false; } - int sample=(pulse_output(nes)+tnd_output(nes)-128)<<7; + int sample=(pulse_output(nes)+tnd_output(nes)); if (sample>32767) sample=32767; if (sample<-32768) sample=-32768; bufL[i]=sample; @@ -454,6 +461,10 @@ int DivPlatformNES::getRegisterPoolSize() { return 32; } +float DivPlatformNES::getPostAmp() { + return 128.0f; +} + void DivPlatformNES::reset() { for (int i=0; i<5; i++) { chan[i]=DivPlatformNES::Channel(); @@ -476,6 +487,9 @@ void DivPlatformNES::reset() { rWrite(0x4015,0x1f); rWrite(0x4001,chan[0].sweep); rWrite(0x4005,chan[1].sweep); + + dacAntiClickOn=true; + dacAntiClick=0; } bool DivPlatformNES::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/nes.h b/src/engine/platform/nes.h index c1b699bcf..1dbb4411b 100644 --- a/src/engine/platform/nes.h +++ b/src/engine/platform/nes.h @@ -54,10 +54,11 @@ class DivPlatformNES: public DivDispatch { Channel chan[5]; bool isMuted[5]; int dacPeriod, dacRate; - unsigned int dacPos; + unsigned int dacPos, dacAntiClick; int dacSample; unsigned char sampleBank; unsigned char apuType; + bool dacAntiClickOn; struct NESAPU* nes; unsigned char regPool[128]; @@ -74,6 +75,7 @@ class DivPlatformNES: public DivDispatch { void tick(); void muteChannel(int ch, bool mute); bool keyOffAffectsArp(int ch); + float getPostAmp(); void setFlags(unsigned int flags); void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); diff --git a/src/engine/platform/saa.cpp b/src/engine/platform/saa.cpp index 0bafaf157..49adf5b13 100644 --- a/src/engine/platform/saa.cpp +++ b/src/engine/platform/saa.cpp @@ -414,6 +414,16 @@ void DivPlatformSAA1099::reset() { extMode=false; + rWrite(8,255); + rWrite(9,255); + rWrite(10,255); + rWrite(11,255); + rWrite(12,255); + rWrite(13,255); + rWrite(16,0x77); + rWrite(17,0x77); + rWrite(18,0x77); + rWrite(0x1c,2); rWrite(0x1c,1); } diff --git a/src/engine/platform/sound/nes/apu.c b/src/engine/platform/sound/nes/apu.c index 8d53e583c..9e177a780 100644 --- a/src/engine/platform/sound/nes/apu.c +++ b/src/engine/platform/sound/nes/apu.c @@ -213,7 +213,8 @@ void apu_turn_on(struct NESAPU* a, BYTE apu_type) { a->S2.sweep.delay = 1; a->S2.sweep.divider = 1; a->TR.frequency = 1; - a->TR.sequencer = 0; + /* questo era 0 ma produce click nell'audio */ + a->TR.sequencer = 7; a->NS.frequency = 1; a->NS.shift = 1; a->DMC.frequency = 1; diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 4a5cc6465..0118acc42 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -1863,6 +1863,8 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi for (int i=0; igetPostAmp(); + volR*=disCont[i].dispatch->getPostAmp(); if (disCont[i].dispatch->isStereo()) { for (size_t j=0; jVtxBuffer.Size; - dl->AddRectFilled(rect.Min,rect.Max,0xffffffff,8.0f*dpiScale); + dl->AddRectFilled(inRect.Min,inRect.Max,0xffffffff,8.0f*dpiScale); const int v1 = dl->VtxBuffer.Size; for (int i=v0; icol); + col0.x*=conv.x; + col0.y*=conv.y; + col0.z*=conv.z; + col0.w*=conv.w; + v->col=ImGui::ColorConvertFloat4ToU32(col0); } + dl->AddLine( + ImLerp(rect.Min,rect.Max,ImVec2(0.0f,0.5f)), + ImLerp(rect.Min,rect.Max,ImVec2(0.0f,0.5f)), + refColor, + dpiScale + ); + for (size_t i=0; i<512; i++) { float x=(float)i/512.0f; float y=oscValues[i]*oscZoom; @@ -148,7 +166,7 @@ void FurnaceGUI::drawOsc() { waveform[i]=ImLerp(rect.Min,rect.Max,ImVec2(x,0.5f-y)); } dl->AddPolyline(waveform,512,color,ImDrawFlags_None,dpiScale); - dl->AddRect(rect.Min,rect.Max,borderColor,8.0f*dpiScale,0,dpiScale); + dl->AddRect(rect.Min,rect.Max,borderColor,8.0f*dpiScale,0,2.0f*dpiScale); } if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { oscZoomSlider=!oscZoomSlider;