diff --git a/TODO.md b/TODO.md index a0da2bbdd..028f21077 100644 --- a/TODO.md +++ b/TODO.md @@ -2,6 +2,5 @@ - stereo separation control for AY - "paste with instrument" -- channel appearance settings - auto-detect system - bug fixes diff --git a/src/engine/platform/ay.cpp b/src/engine/platform/ay.cpp index 23f20c2a0..f475b4750 100644 --- a/src/engine/platform/ay.cpp +++ b/src/engine/platform/ay.cpp @@ -126,7 +126,7 @@ void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t l } for (int ch=0; ch<3; ch++) { for (size_t i=0; idata[oscBuf[ch]->needle++]=ayBuf[ch][i]; + oscBuf[ch]->data[oscBuf[ch]->needle++]=ayBuf[ch][i]<<2; } } } diff --git a/src/engine/platform/ay8930.cpp b/src/engine/platform/ay8930.cpp index d77457d66..123dc68ac 100644 --- a/src/engine/platform/ay8930.cpp +++ b/src/engine/platform/ay8930.cpp @@ -111,7 +111,7 @@ void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t l for (int ch=0; ch<3; ch++) { for (size_t i=0; idata[oscBuf[ch]->needle++]=ayBuf[ch][i]; + oscBuf[ch]->data[oscBuf[ch]->needle++]=ayBuf[ch][i]<<2; } } } diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index d4d77f171..e4d408f7b 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -78,7 +78,7 @@ void DivPlatformSMS::acquire_nuked(short* bufL, short* bufR, size_t start, size_ if (isMuted[i]) { oscBuf[i]->data[oscBuf[i]->needle++]=0; } else { - oscBuf[i]->data[oscBuf[i]->needle++]=sn_nuked.vol_table[sn_nuked.volume_out[i]]; + oscBuf[i]->data[oscBuf[i]->needle++]=sn_nuked.vol_table[sn_nuked.volume_out[i]]*3; } } } @@ -104,7 +104,7 @@ void DivPlatformSMS::acquire_mame(short* bufL, short* bufR, size_t start, size_t if (isMuted[i]) { oscBuf[i]->data[oscBuf[i]->needle++]=0; } else { - oscBuf[i]->data[oscBuf[i]->needle++]=sn->get_channel_output(i); + oscBuf[i]->data[oscBuf[i]->needle++]=sn->get_channel_output(i)*3; } } } diff --git a/src/gui/chanOsc.cpp b/src/gui/chanOsc.cpp index 547e59a17..08174b0b6 100644 --- a/src/gui/chanOsc.cpp +++ b/src/gui/chanOsc.cpp @@ -69,6 +69,39 @@ float FurnaceGUI::computeGradPos(int type, int chan) { return 0.0f; } +void FurnaceGUI::calcChanOsc() { + std::vector oscBufs; + std::vector oscFFTs; + std::vector oscChans; + + int chans=e->getTotalChannelCount(); + + for (int i=0; igetOscBuffer(i); + if (buf!=NULL && e->curSubSong->chanShow[i]) { + // 30ms should be enough + int displaySize=(float)(buf->rate)*0.03f; + if (e->isRunning()) { + float minLevel=1.0f; + float maxLevel=-1.0f; + unsigned short needlePos=buf->needle; + needlePos-=displaySize; + for (unsigned short i=0; i<512; i++) { + float y=(float)buf->data[(unsigned short)(needlePos+(i*displaySize/512))]/65536.0f; + if (minLevel>y) minLevel=y; + if (maxLevel1.0f) estimate=1.0f; + chanOscVol[i]=MAX(chanOscVol[i]*0.87f,estimate); + } + } else { + chanOscVol[i]=MAX(chanOscVol[i]*0.87f,0.0f); + } + if (chanOscVol[i]<0.00001f) chanOscVol[i]=0.0f; + } +} + void FurnaceGUI::drawChanOsc() { if (nextWindow==GUI_WINDOW_CHAN_OSC) { chanOscOpen=true; @@ -361,7 +394,6 @@ void FurnaceGUI::drawChanOsc() { if (maxLeveldata[(unsigned short)(needlePos+(i*displaySize/512))]/65536.0f; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 40869c425..d42ec0f88 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -3471,6 +3471,8 @@ bool FurnaceGUI::loop() { ImGui::EndMainMenuBar(); } + calcChanOsc(); + if (mobileUI) { globalWinFlags=ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoBringToFrontOnFocus; //globalWinFlags=ImGuiWindowFlags_NoTitleBar; @@ -3546,6 +3548,12 @@ bool FurnaceGUI::loop() { drawEffectList(); } + for (int i=0; igetTotalChannelCount(); i++) { + if (e->keyHit[i]) { + e->keyHit[i]=false; + } + } + if (inspectorOpen) ImGui::ShowMetricsWindow(&inspectorOpen); if (firstFrame) { diff --git a/src/gui/gui.h b/src/gui/gui.h index 09155f9be..bbfb3cf5b 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1558,6 +1558,7 @@ class FurnaceGUI { // visualizer float keyHit[DIV_MAX_CHANS]; + float keyHit1[DIV_MAX_CHANS]; int lastIns[DIV_MAX_CHANS]; // log window @@ -1612,6 +1613,7 @@ class FurnaceGUI { ImVec4 channelTextColor(int ch); void readOsc(); + void calcChanOsc(); void pushAccentColors(const ImVec4& one, const ImVec4& two, const ImVec4& border, const ImVec4& borderShadow); void popAccentColors(); diff --git a/src/gui/pattern.cpp b/src/gui/pattern.cpp index b986cedc6..f35f828c0 100644 --- a/src/gui/pattern.cpp +++ b/src/gui/pattern.cpp @@ -486,7 +486,6 @@ void FurnaceGUI::drawPattern() { } } } - e->keyHit[i]=false; } if (settings.channelFeedbackStyle==2 && e->isRunning()) { float amount=((float)(e->getChanState(i)->volume>>8)/(float)e->getMaxVolumeChan(i)); @@ -547,6 +546,10 @@ void FurnaceGUI::drawPattern() { ImRect rect=ImRect(minArea,maxArea); switch (settings.channelStyle) { case 0: // classic + if (settings.channelVolStyle!=0) { + // sorry... + ImGui::Dummy(ImVec2(dpiScale,dpiScale)); + } ImGui::Selectable(chanID,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale)); break; case 1: { // line @@ -672,9 +675,62 @@ void FurnaceGUI::drawPattern() { inhibitMenu=true; e->toggleSolo(i); } + if (settings.channelStyle==3) { ImGui::Dummy(ImVec2(1.0f,2.0f*dpiScale)); } + + // volume bar + if (settings.channelVolStyle!=0) { + ImVec2 sizeV=ImVec2( + 1.0f, + 6.0*dpiScale + ); + ImVec2 minAreaV=window->DC.CursorPos; + ImVec2 maxAreaV=ImVec2( + minAreaV.x+window->WorkRect.Max.x-window->WorkRect.Min.x, + minAreaV.y+sizeV.y + ); + ImRect rectV=ImRect(minAreaV,maxAreaV); + ImGui::ItemSize(sizeV,ImGui::GetStyle().FramePadding.y); + if (ImGui::ItemAdd(rectV,ImGui::GetID(chanID))) { + float xLeft=0.0f; + float xRight=1.0f; + + if (e->keyHit[i]) { + keyHit1[i]=1.0f; + } + + if (e->isRunning()) { + switch (settings.channelVolStyle) { + case 1: // simple + xRight=((float)(e->getChanState(i)->volume>>8)/(float)e->getMaxVolumeChan(i))*0.9+(keyHit1[i]*0.1f); + break; + case 2: // stereo + xRight=0.5+((float)(e->getChanState(i)->volume>>8)/(float)e->getMaxVolumeChan(i))*0.4+(keyHit1[i]*0.1f); + xLeft=1.0-xRight; + break; + case 3: // real + xRight=chanOscVol[i]; + break; + case 4: // real (stereo) + xRight=0.5+chanOscVol[i]*0.5; + xLeft=1.0-xRight; + break; + } + + dl->AddRectFilled( + ImLerp(rectV.Min,rectV.Max,ImVec2(xLeft,0.0f)), + ImLerp(rectV.Min,rectV.Max,ImVec2(xRight,1.0f)), + ImGui::GetColorU32(chanHeadBase) + ); + } + keyHit1[i]-=0.2f; + if (keyHit1[i]<0.0f) keyHit1[i]=0.0f; + } + } + + // extra buttons if (extraChannelButtons==2) { DivPattern* pat=e->curPat[i].getPattern(e->curOrders->ord[i][ord],true); ImGui::PushFont(mainFont); diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index c771f6a16..e5c609829 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -1327,6 +1327,9 @@ void FurnaceGUI::drawSettings() { if (ImGui::RadioButton("Real##CHV3",settings.channelVolStyle==3)) { settings.channelVolStyle=3; } + if (ImGui::RadioButton("Real (stereo)##CHV4",settings.channelVolStyle==4)) { + settings.channelVolStyle=4; + } ImGui::Text("Channel feedback style:"); @@ -2389,7 +2392,7 @@ void FurnaceGUI::syncSettings() { clampSetting(settings.channelColors,0,2); clampSetting(settings.channelTextColors,0,2); clampSetting(settings.channelStyle,0,5); - clampSetting(settings.channelVolStyle,0,3); + clampSetting(settings.channelVolStyle,0,4); clampSetting(settings.channelFeedbackStyle,0,3); clampSetting(settings.channelFont,0,1); clampSetting(settings.maxRecentFile,0,30);