GUI: implement channel volume bar
This commit is contained in:
parent
1a84812a1d
commit
e1890173b2
1
TODO.md
1
TODO.md
|
@ -2,6 +2,5 @@
|
|||
|
||||
- stereo separation control for AY
|
||||
- "paste with instrument"
|
||||
- channel appearance settings
|
||||
- auto-detect system
|
||||
- bug fixes
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue