GUI: implement channel volume bar

This commit is contained in:
tildearrow 2022-09-20 02:32:23 -05:00
parent 1a84812a1d
commit e1890173b2
9 changed files with 108 additions and 8 deletions

View File

@ -2,6 +2,5 @@
- stereo separation control for AY
- "paste with instrument"
- channel appearance settings
- auto-detect system
- bug fixes

View File

@ -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; i<len; i++) {
oscBuf[ch]->data[oscBuf[ch]->needle++]=ayBuf[ch][i];
oscBuf[ch]->data[oscBuf[ch]->needle++]=ayBuf[ch][i]<<2;
}
}
}

View File

@ -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; i<len; i++) {
oscBuf[ch]->data[oscBuf[ch]->needle++]=ayBuf[ch][i];
oscBuf[ch]->data[oscBuf[ch]->needle++]=ayBuf[ch][i]<<2;
}
}
}

View File

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

View File

@ -69,6 +69,39 @@ float FurnaceGUI::computeGradPos(int type, int chan) {
return 0.0f;
}
void FurnaceGUI::calcChanOsc() {
std::vector<DivDispatchOscBuffer*> oscBufs;
std::vector<ChanOscStatus*> oscFFTs;
std::vector<int> oscChans;
int chans=e->getTotalChannelCount();
for (int i=0; i<chans; i++) {
DivDispatchOscBuffer* buf=e->getOscBuffer(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 (maxLevel<y) maxLevel=y;
}
float estimate=pow(maxLevel-minLevel,0.5f);
if (estimate>1.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 (maxLevel<y) maxLevel=y;
}
dcOff=(minLevel+maxLevel)*0.5f;
chanOscVol[ch]=MAX(chanOscVol[ch]*0.87f,maxLevel-minLevel);
for (unsigned short i=0; i<512; i++) {
float x=(float)i/512.0f;
float y=(float)buf->data[(unsigned short)(needlePos+(i*displaySize/512))]/65536.0f;

View File

@ -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; i<e->getTotalChannelCount(); i++) {
if (e->keyHit[i]) {
e->keyHit[i]=false;
}
}
if (inspectorOpen) ImGui::ShowMetricsWindow(&inspectorOpen);
if (firstFrame) {

View File

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

View File

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

View File

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