DC offset improvements

This commit is contained in:
tildearrow 2022-04-09 18:25:25 -05:00
parent 46bf69769b
commit 38ca437190
14 changed files with 95 additions and 10 deletions

View file

@ -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.

View file

@ -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; i<runtotal; i++) {
temp[0]=bbIn[0][i];
@ -126,6 +131,9 @@ void DivDispatchContainer::clear() {
temp[1]=0;
prevSample[0]=0;
prevSample[1]=0;
if (dispatch->getDCOffRequired()) {
dcOffCompensation=true;
}
// run for one cycle to determine DC offset
// TODO: SAA1099 doesn't like that
/*dispatch->acquire(bbIn[0],bbIn[1],0,1);

View file

@ -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 {

View file

@ -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;
}

View file

@ -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();

View file

@ -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<DivRegWrite>& wlist);

View file

@ -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();

View file

@ -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);

View file

@ -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<next) {
dacAntiClick+=8;
rWrite(0x4011,dacAntiClick);
} else {
dacAntiClickOn=false;
rWrite(0x4011,next);
}
}
if (++dacPos>=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) {

View file

@ -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);

View file

@ -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);
}

View file

@ -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;

View file

@ -1863,6 +1863,8 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
for (int i=0; i<song.systemLen; i++) {
float volL=((float)song.systemVol[i]/64.0f)*((float)MIN(127,127-(int)song.systemPan[i])/127.0f)*song.masterVol;
float volR=((float)song.systemVol[i]/64.0f)*((float)MIN(127,127+(int)song.systemPan[i])/127.0f)*song.masterVol;
volL*=disCont[i].dispatch->getPostAmp();
volR*=disCont[i].dispatch->getPostAmp();
if (disCont[i].dispatch->isStereo()) {
for (size_t j=0; j<size; j++) {
out[0][j]+=((float)disCont[i].bbOut[0][j]/32768.0)*volL;

View file

@ -97,15 +97,20 @@ void FurnaceGUI::drawOsc() {
minArea.y+size.y
);
ImRect rect=ImRect(minArea,maxArea);
ImRect inRect=rect;
inRect.Min.x+=dpiScale;
inRect.Min.y+=dpiScale;
inRect.Max.x-=dpiScale;
inRect.Max.y-=dpiScale;
ImGuiStyle& style=ImGui::GetStyle();
ImU32 color=ImGui::GetColorU32(isClipping?uiColors[GUI_COLOR_OSC_WAVE_PEAK]:uiColors[GUI_COLOR_OSC_WAVE]);
ImU32 borderColor=ImGui::GetColorU32(uiColors[GUI_COLOR_OSC_BORDER]);
ImU32 refColor=ImGui::GetColorU32(uiColors[GUI_COLOR_OSC_REF]);
ImGui::ItemSize(size,style.FramePadding.y);
if (ImGui::ItemAdd(rect,ImGui::GetID("wsDisplay"))) {
// https://github.com/ocornut/imgui/issues/3710
// TODO: improve
const int v0 = dl->VtxBuffer.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; i<v1; i++) {
@ -137,9 +142,22 @@ void FurnaceGUI::drawOsc() {
col0.z+=(col1.z-col0.z)*shadeY;
col0.w+=(col1.w-col0.w)*shadeY;
ImVec4 conv=ImGui::ColorConvertU32ToFloat4(v->col);
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;