GUI: add chan osc DC off correction strat options

off: no DC offset correction
normal: the old algorithm
high-pass: a new algorithm

also fix a hang!
This commit is contained in:
tildearrow 2025-03-17 04:07:22 -05:00
parent 30ef81779d
commit 0f4d70a34e
4 changed files with 82 additions and 53 deletions

View file

@ -183,6 +183,21 @@ void FurnaceGUI::drawChanOsc() {
if (ImGui::Checkbox(_("Randomize phase on note"),&chanOscRandomPhase)) {
}
ImGui::TableNextColumn();
ImGui::Text("DC offset correction");
ImGui::SameLine();
if (ImGui::RadioButton("Off###_cocs0",chanOscCenterStrat==0)) {
chanOscCenterStrat=0;
}
ImGui::SameLine();
if (ImGui::RadioButton("Normal###_cocs1",chanOscCenterStrat==1)) {
chanOscCenterStrat=1;
}
ImGui::SameLine();
if (ImGui::RadioButton("High-pass###_cocs2",chanOscCenterStrat==2)) {
chanOscCenterStrat=2;
}
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding();
@ -710,6 +725,21 @@ void FurnaceGUI::drawChanOsc() {
break;
}
}
if (chanOscCenterStrat==0) { // DC correction off
fft->dcOff=0;
} else if (chanOscCenterStrat==1) { // normal DC correction
if (minLevel>y) minLevel=y;
if (maxLevel<y) maxLevel=y;
for (unsigned short j=fft->needle; j!=((fft->needle+displaySize)&0xffff); j++) {
const short y_s=buf->data[j];
if (y_s!=-1) {
y=(float)y_s/32768.0f;
if (minLevel>y) minLevel=y;
if (maxLevel<y) maxLevel=y;
}
}
fft->dcOff=(minLevel+maxLevel)*0.5f;
}
// render chan osc
if (displaySize<precision) {
for (int j=0; j<precision; j++) {
@ -722,9 +752,7 @@ void FurnaceGUI::drawChanOsc() {
}
if (j<0) continue;
float yOut=y-fft->dcOff;
if (!settings.audioHiPass) {
fft->dcOff=0;
} else {
if (chanOscCenterStrat==2) {
fft->dcOff+=(y-fft->dcOff)*0.001;
}
if (yOut<-0.5f) yOut=-0.5f;
@ -734,7 +762,7 @@ void FurnaceGUI::drawChanOsc() {
}
} else {
int k=0;
for (unsigned short j=fft->needle; j!=fft->needle+displaySize; j++, k++) {
for (unsigned short j=fft->needle; j!=((fft->needle+displaySize)&0xffff); j++, k++) {
const short y_s=buf->data[j];
const int kTex=(k*precision)/displaySize;
if (kTex>=precision) break;
@ -746,9 +774,7 @@ void FurnaceGUI::drawChanOsc() {
}
if (kTex<0) continue;
float yOut=y-fft->dcOff;
if (!settings.audioHiPass) {
fft->dcOff=0;
} else {
if (chanOscCenterStrat==2) {
fft->dcOff+=(y-fft->dcOff)*0.001;
}
if (yOut<-0.5f) yOut=-0.5f;
@ -757,7 +783,6 @@ void FurnaceGUI::drawChanOsc() {
fft->oscTex[kTex]=yOut;
}
}
//dcOff=(minLevel+maxLevel)*0.5f;
if (!(rend->supportsDrawOsc() && settings.shaderOsc)) {
for (unsigned short j=0; j<precision; j++) {

View file

@ -8076,6 +8076,7 @@ void FurnaceGUI::syncState() {
chanOscAutoColsType=e->getConfInt("chanOscAutoColsType",0);
chanOscColorX=e->getConfInt("chanOscColorX",GUI_OSCREF_CENTER);
chanOscColorY=e->getConfInt("chanOscColorY",GUI_OSCREF_CENTER);
chanOscCenterStrat=e->getConfInt("chanOscCenterStrat",1);
chanOscTextX=e->getConfFloat("chanOscTextX",0.0f);
chanOscTextY=e->getConfFloat("chanOscTextY",0.0f);
chanOscAmplify=e->getConfFloat("chanOscAmplify",0.95f);
@ -8227,6 +8228,7 @@ void FurnaceGUI::commitState(DivConfig& conf) {
conf.set("chanOscAutoColsType",chanOscAutoColsType);
conf.set("chanOscColorX",chanOscColorX);
conf.set("chanOscColorY",chanOscColorY);
conf.set("chanOscCenterStrat",chanOscCenterStrat);
conf.set("chanOscTextX",chanOscTextX);
conf.set("chanOscTextY",chanOscTextY);
conf.set("chanOscAmplify",chanOscAmplify);
@ -8793,6 +8795,7 @@ FurnaceGUI::FurnaceGUI():
chanOscAutoColsType(0),
chanOscColorX(GUI_OSCREF_CENTER),
chanOscColorY(GUI_OSCREF_CENTER),
chanOscCenterStrat(1),
chanOscWindowSize(20.0f),
chanOscTextX(0.0f),
chanOscTextY(0.0f),

View file

@ -1998,6 +1998,7 @@ class FurnaceGUI {
int autoFillSave;
int autoMacroStepSize;
int backgroundPlay;
int chanOscDCOffStrat;
unsigned int maxUndoSteps;
float vibrationStrength;
int vibrationLength;
@ -2588,7 +2589,7 @@ class FurnaceGUI {
bool oscZoomSlider;
// per-channel oscilloscope
int chanOscCols, chanOscAutoColsType, chanOscColorX, chanOscColorY;
int chanOscCols, chanOscAutoColsType, chanOscColorX, chanOscColorY, chanOscCenterStrat;
float chanOscWindowSize, chanOscTextX, chanOscTextY, chanOscAmplify, chanOscLineSize;
bool chanOscWaveCorr, chanOscOptions, updateChanOscGradTex, chanOscUseGrad, chanOscNormalize, chanOscRandomPhase;
String chanOscTextFormat;

View file

@ -790,50 +790,6 @@ void FurnaceGUI::drawSettings() {
ImGui::SetTooltip(_("may cause issues with high-polling-rate mice when previewing notes."));
}
pushWarningColor(settings.chanOscThreads>cpuCores,settings.chanOscThreads>(cpuCores*2));
if (ImGui::InputInt(_("Per-channel oscilloscope threads"),&settings.chanOscThreads)) {
if (settings.chanOscThreads<0) settings.chanOscThreads=0;
if (settings.chanOscThreads>(cpuCores*3)) settings.chanOscThreads=cpuCores*3;
if (settings.chanOscThreads>256) settings.chanOscThreads=256;
settingsChanged=true;
}
if (settings.chanOscThreads>=(cpuCores*3)) {
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(_("you're being silly, aren't you? that's enough."));
}
} else if (settings.chanOscThreads>(cpuCores*2)) {
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(_("what are you doing? stop!"));
}
} else if (settings.chanOscThreads>cpuCores) {
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(_("it is a bad idea to set this number higher than your CPU core count (%d)!"),cpuCores);
}
}
popWarningColor();
ImGui::Text(_("Oscilloscope rendering engine:"));
ImGui::Indent();
if (ImGui::RadioButton(_("ImGui line plot"),settings.shaderOsc==0)) {
settings.shaderOsc=0;
settingsChanged=true;
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(_("render using Dear ImGui's built-in line drawing functions."));
}
if (ImGui::RadioButton(_("GLSL (if available)"),settings.shaderOsc==1)) {
settings.shaderOsc=1;
settingsChanged=true;
}
if (ImGui::IsItemHovered()) {
#ifdef USE_GLES
ImGui::SetTooltip(_("render using shaders that run on the graphics card.\nonly available in OpenGL ES 2.0 render backend."));
#else
ImGui::SetTooltip(_("render using shaders that run on the graphics card.\nonly available in OpenGL 3.0 render backend."));
#endif
}
ImGui::Unindent();
#ifdef IS_MOBILE
// SUBSECTION VIBRATION
CONFIG_SUBSECTION(_("Vibration"));
@ -3843,6 +3799,50 @@ void FurnaceGUI::drawSettings() {
settingsChanged=true;
} rightClickable
pushWarningColor(settings.chanOscThreads>cpuCores,settings.chanOscThreads>(cpuCores*2));
if (ImGui::InputInt(_("Per-channel oscilloscope threads"),&settings.chanOscThreads)) {
if (settings.chanOscThreads<0) settings.chanOscThreads=0;
if (settings.chanOscThreads>(cpuCores*3)) settings.chanOscThreads=cpuCores*3;
if (settings.chanOscThreads>256) settings.chanOscThreads=256;
settingsChanged=true;
}
if (settings.chanOscThreads>=(cpuCores*3)) {
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(_("you're being silly, aren't you? that's enough."));
}
} else if (settings.chanOscThreads>(cpuCores*2)) {
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(_("what are you doing? stop!"));
}
} else if (settings.chanOscThreads>cpuCores) {
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(_("it is a bad idea to set this number higher than your CPU core count (%d)!"),cpuCores);
}
}
popWarningColor();
ImGui::Text(_("Oscilloscope rendering engine:"));
ImGui::Indent();
if (ImGui::RadioButton(_("ImGui line plot"),settings.shaderOsc==0)) {
settings.shaderOsc=0;
settingsChanged=true;
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(_("render using Dear ImGui's built-in line drawing functions."));
}
if (ImGui::RadioButton(_("GLSL (if available)"),settings.shaderOsc==1)) {
settings.shaderOsc=1;
settingsChanged=true;
}
if (ImGui::IsItemHovered()) {
#ifdef USE_GLES
ImGui::SetTooltip(_("render using shaders that run on the graphics card.\nonly available in OpenGL ES 2.0 render backend."));
#else
ImGui::SetTooltip(_("render using shaders that run on the graphics card.\nonly available in OpenGL 3.0 render backend."));
#endif
}
ImGui::Unindent();
// SUBSECTION SONG COMMENTS
CONFIG_SUBSECTION(_("Song Comments"));
bool songNotesWrapB=settings.songNotesWrap;