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
|
- stereo separation control for AY
|
||||||
- "paste with instrument"
|
- "paste with instrument"
|
||||||
- channel appearance settings
|
|
||||||
- auto-detect system
|
- auto-detect system
|
||||||
- bug fixes
|
- 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 (int ch=0; ch<3; ch++) {
|
||||||
for (size_t i=0; i<len; i++) {
|
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 (int ch=0; ch<3; ch++) {
|
||||||
for (size_t i=0; i<len; i++) {
|
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]) {
|
if (isMuted[i]) {
|
||||||
oscBuf[i]->data[oscBuf[i]->needle++]=0;
|
oscBuf[i]->data[oscBuf[i]->needle++]=0;
|
||||||
} else {
|
} 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]) {
|
if (isMuted[i]) {
|
||||||
oscBuf[i]->data[oscBuf[i]->needle++]=0;
|
oscBuf[i]->data[oscBuf[i]->needle++]=0;
|
||||||
} else {
|
} 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;
|
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() {
|
void FurnaceGUI::drawChanOsc() {
|
||||||
if (nextWindow==GUI_WINDOW_CHAN_OSC) {
|
if (nextWindow==GUI_WINDOW_CHAN_OSC) {
|
||||||
chanOscOpen=true;
|
chanOscOpen=true;
|
||||||
|
@ -361,7 +394,6 @@ void FurnaceGUI::drawChanOsc() {
|
||||||
if (maxLevel<y) maxLevel=y;
|
if (maxLevel<y) maxLevel=y;
|
||||||
}
|
}
|
||||||
dcOff=(minLevel+maxLevel)*0.5f;
|
dcOff=(minLevel+maxLevel)*0.5f;
|
||||||
chanOscVol[ch]=MAX(chanOscVol[ch]*0.87f,maxLevel-minLevel);
|
|
||||||
for (unsigned short i=0; i<512; i++) {
|
for (unsigned short i=0; i<512; i++) {
|
||||||
float x=(float)i/512.0f;
|
float x=(float)i/512.0f;
|
||||||
float y=(float)buf->data[(unsigned short)(needlePos+(i*displaySize/512))]/65536.0f;
|
float y=(float)buf->data[(unsigned short)(needlePos+(i*displaySize/512))]/65536.0f;
|
||||||
|
|
|
@ -3471,6 +3471,8 @@ bool FurnaceGUI::loop() {
|
||||||
ImGui::EndMainMenuBar();
|
ImGui::EndMainMenuBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
calcChanOsc();
|
||||||
|
|
||||||
if (mobileUI) {
|
if (mobileUI) {
|
||||||
globalWinFlags=ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoBringToFrontOnFocus;
|
globalWinFlags=ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoBringToFrontOnFocus;
|
||||||
//globalWinFlags=ImGuiWindowFlags_NoTitleBar;
|
//globalWinFlags=ImGuiWindowFlags_NoTitleBar;
|
||||||
|
@ -3546,6 +3548,12 @@ bool FurnaceGUI::loop() {
|
||||||
drawEffectList();
|
drawEffectList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i=0; i<e->getTotalChannelCount(); i++) {
|
||||||
|
if (e->keyHit[i]) {
|
||||||
|
e->keyHit[i]=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (inspectorOpen) ImGui::ShowMetricsWindow(&inspectorOpen);
|
if (inspectorOpen) ImGui::ShowMetricsWindow(&inspectorOpen);
|
||||||
|
|
||||||
if (firstFrame) {
|
if (firstFrame) {
|
||||||
|
|
|
@ -1558,6 +1558,7 @@ class FurnaceGUI {
|
||||||
|
|
||||||
// visualizer
|
// visualizer
|
||||||
float keyHit[DIV_MAX_CHANS];
|
float keyHit[DIV_MAX_CHANS];
|
||||||
|
float keyHit1[DIV_MAX_CHANS];
|
||||||
int lastIns[DIV_MAX_CHANS];
|
int lastIns[DIV_MAX_CHANS];
|
||||||
|
|
||||||
// log window
|
// log window
|
||||||
|
@ -1612,6 +1613,7 @@ class FurnaceGUI {
|
||||||
ImVec4 channelTextColor(int ch);
|
ImVec4 channelTextColor(int ch);
|
||||||
|
|
||||||
void readOsc();
|
void readOsc();
|
||||||
|
void calcChanOsc();
|
||||||
|
|
||||||
void pushAccentColors(const ImVec4& one, const ImVec4& two, const ImVec4& border, const ImVec4& borderShadow);
|
void pushAccentColors(const ImVec4& one, const ImVec4& two, const ImVec4& border, const ImVec4& borderShadow);
|
||||||
void popAccentColors();
|
void popAccentColors();
|
||||||
|
|
|
@ -486,7 +486,6 @@ void FurnaceGUI::drawPattern() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e->keyHit[i]=false;
|
|
||||||
}
|
}
|
||||||
if (settings.channelFeedbackStyle==2 && e->isRunning()) {
|
if (settings.channelFeedbackStyle==2 && e->isRunning()) {
|
||||||
float amount=((float)(e->getChanState(i)->volume>>8)/(float)e->getMaxVolumeChan(i));
|
float amount=((float)(e->getChanState(i)->volume>>8)/(float)e->getMaxVolumeChan(i));
|
||||||
|
@ -547,6 +546,10 @@ void FurnaceGUI::drawPattern() {
|
||||||
ImRect rect=ImRect(minArea,maxArea);
|
ImRect rect=ImRect(minArea,maxArea);
|
||||||
switch (settings.channelStyle) {
|
switch (settings.channelStyle) {
|
||||||
case 0: // classic
|
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));
|
ImGui::Selectable(chanID,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale));
|
||||||
break;
|
break;
|
||||||
case 1: { // line
|
case 1: { // line
|
||||||
|
@ -672,9 +675,62 @@ void FurnaceGUI::drawPattern() {
|
||||||
inhibitMenu=true;
|
inhibitMenu=true;
|
||||||
e->toggleSolo(i);
|
e->toggleSolo(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.channelStyle==3) {
|
if (settings.channelStyle==3) {
|
||||||
ImGui::Dummy(ImVec2(1.0f,2.0f*dpiScale));
|
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) {
|
if (extraChannelButtons==2) {
|
||||||
DivPattern* pat=e->curPat[i].getPattern(e->curOrders->ord[i][ord],true);
|
DivPattern* pat=e->curPat[i].getPattern(e->curOrders->ord[i][ord],true);
|
||||||
ImGui::PushFont(mainFont);
|
ImGui::PushFont(mainFont);
|
||||||
|
|
|
@ -1327,6 +1327,9 @@ void FurnaceGUI::drawSettings() {
|
||||||
if (ImGui::RadioButton("Real##CHV3",settings.channelVolStyle==3)) {
|
if (ImGui::RadioButton("Real##CHV3",settings.channelVolStyle==3)) {
|
||||||
settings.channelVolStyle=3;
|
settings.channelVolStyle=3;
|
||||||
}
|
}
|
||||||
|
if (ImGui::RadioButton("Real (stereo)##CHV4",settings.channelVolStyle==4)) {
|
||||||
|
settings.channelVolStyle=4;
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::Text("Channel feedback style:");
|
ImGui::Text("Channel feedback style:");
|
||||||
|
|
||||||
|
@ -2389,7 +2392,7 @@ void FurnaceGUI::syncSettings() {
|
||||||
clampSetting(settings.channelColors,0,2);
|
clampSetting(settings.channelColors,0,2);
|
||||||
clampSetting(settings.channelTextColors,0,2);
|
clampSetting(settings.channelTextColors,0,2);
|
||||||
clampSetting(settings.channelStyle,0,5);
|
clampSetting(settings.channelStyle,0,5);
|
||||||
clampSetting(settings.channelVolStyle,0,3);
|
clampSetting(settings.channelVolStyle,0,4);
|
||||||
clampSetting(settings.channelFeedbackStyle,0,3);
|
clampSetting(settings.channelFeedbackStyle,0,3);
|
||||||
clampSetting(settings.channelFont,0,1);
|
clampSetting(settings.channelFont,0,1);
|
||||||
clampSetting(settings.maxRecentFile,0,30);
|
clampSetting(settings.maxRecentFile,0,30);
|
||||||
|
|
Loading…
Reference in New Issue