mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-27 15:03:01 +00:00
DC offset improvements
This commit is contained in:
parent
46bf69769b
commit
38ca437190
14 changed files with 95 additions and 10 deletions
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue