diff --git a/src/engine/instrument.h b/src/engine/instrument.h index 6587fecc..a63b2975 100644 --- a/src/engine/instrument.h +++ b/src/engine/instrument.h @@ -182,6 +182,8 @@ struct DivInstrumentMacro { // the following variables are used by the GUI and not saved in the file int vScroll, vZoom; + int typeMemory[16]; + unsigned char lenMemory; explicit DivInstrumentMacro(const String& n, bool initOpen=false): name(n), @@ -193,8 +195,10 @@ struct DivInstrumentMacro { loop(255), rel(255), vScroll(0), - vZoom(-1) { + vZoom(-1), + lenMemory(0) { memset(val,0,256*sizeof(int)); + memset(typeMemory,0,16*sizeof(int)); } }; diff --git a/src/engine/macroInt.cpp b/src/engine/macroInt.cpp index c463e7b2..9e619cb8 100644 --- a/src/engine/macroInt.cpp +++ b/src/engine/macroInt.cpp @@ -332,7 +332,14 @@ void DivMacroInt::init(DivInstrument* which) { for (size_t i=0; iprepare(*macroSource[i],e); - hasRelease=(macroSource[i]->rellen); + // check ADSR mode + if ((macroSource[i]->open&6)==4) { + hasRelease=false; + } else if ((macroSource[i]->open&6)==2) { + hasRelease=true; + } else { + hasRelease=(macroSource[i]->rellen); + } } else { hasRelease=false; } diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 3609bc2d..166bd8a5 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -210,6 +210,10 @@ const char* macroTypeLabels[4]={ ICON_FA_SIGN_OUT "##IMacroType" }; +const char* macroLFOShapes[4]={ + "Triangle", "Saw", "Square", "How did you even" +}; + const char* fmOperatorBits[5]={ "op1", "op2", "op3", "op4", NULL }; @@ -1347,10 +1351,33 @@ void FurnaceGUI::drawMacros(std::vector& macros) { } } if (ImGui::Button(macroTypeLabels[(i.macro->open>>1)&3])) { + unsigned char prevOpen=i.macro->open; i.macro->open+=2; if (i.macro->open>=6) { i.macro->open-=6; } + + // check whether macro type is now ADSR/LFO or sequence + if (((prevOpen&6)?1:0)!=((i.macro->open&6)?1:0)) { + // swap memory + // this way the macro isn't corrupted if the user decides to go + // back to sequence mode + i.macro->len^=i.macro->lenMemory; + i.macro->lenMemory^=i.macro->len; + i.macro->len^=i.macro->lenMemory; + + for (int j=0; j<16; j++) { + i.macro->val[j]^=i.macro->typeMemory[j]; + i.macro->typeMemory[j]^=i.macro->val[j]; + i.macro->val[j]^=i.macro->typeMemory[j]; + } + + // if ADSR/LFO, populate min/max + if (i.macro->open&6) { + i.macro->val[0]=i.min; + i.macro->val[1]=i.max; + } + } PARAMETER; } if (ImGui::IsItemHovered()) { @@ -1369,6 +1396,9 @@ void FurnaceGUI::drawMacros(std::vector& macros) { break; } } + if (i.macro->open&6) { + i.macro->len=16; + } ImGui::SameLine(); ImGui::Button(ICON_FA_ELLIPSIS_H "##IMacroSet"); if (ImGui::IsItemHovered()) { @@ -1754,7 +1784,7 @@ void FurnaceGUI::drawMacros(std::vector& macros) { ImGui::Text("Shape"); ImGui::TableNextColumn(); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (CWSliderInt("##MLShape",&i.macro->val[12],0,2)) { PARAMETER + if (CWSliderInt("##MLShape",&i.macro->val[12],0,2,macroLFOShapes[i.macro->val[12]&3])) { PARAMETER if (i.macro->val[12]<0) i.macro->val[12]=0; if (i.macro->val[12]>2) i.macro->val[12]=2; }