diff --git a/doc/4-instrument/README.md b/doc/4-instrument/README.md index dd24c7260..a1681388b 100644 --- a/doc/4-instrument/README.md +++ b/doc/4-instrument/README.md @@ -84,6 +84,9 @@ each macro has two buttons on the left. - **Step Length (ticks)**: determines how many ticks pass before each change of value. default is 1. - **Delay**: delays the start of the macro until this many ticks have passed. default is 0. - the button is highlighted if either of these is set differently from default. +- release mode. this determines how macro release is handled: + - **Active**: jumps to release position. + - **Passive**: does not jump to release position. if release position hasn't been reached yet, there will be a delay. ## macro types diff --git a/papers/newIns.md b/papers/newIns.md index 27a505c13..7b948d23d 100644 --- a/papers/newIns.md +++ b/papers/newIns.md @@ -251,6 +251,7 @@ size | description | - 1: 8-bit signed | - 2: 16-bit signed | - 3: 32-bit signed + | - bit 3: instant release (>=182) | - bit 1-2: type | - 0: normal | - 1: ADSR diff --git a/src/engine/engine.h b/src/engine/engine.h index 4bae9db9e..6d18c728f 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -52,10 +52,10 @@ class DivWorkPool; #define EXTERN_BUSY_BEGIN_SOFT e->softLocked=true; e->isBusy.lock(); #define EXTERN_BUSY_END e->isBusy.unlock(); e->softLocked=false; -//#define DIV_UNSTABLE +#define DIV_UNSTABLE -#define DIV_VERSION "0.6" -#define DIV_ENGINE_VERSION 181 +#define DIV_VERSION "dev182" +#define DIV_ENGINE_VERSION 182 // for imports #define DIV_VERSION_MOD 0xff01 #define DIV_VERSION_FC 0xff02 diff --git a/src/engine/instrument.cpp b/src/engine/instrument.cpp index 3abbe51a5..80a5a6bf1 100644 --- a/src/engine/instrument.cpp +++ b/src/engine/instrument.cpp @@ -319,7 +319,7 @@ void DivInstrument::writeMacro(SafeWriter* w, const DivInstrumentMacro& m) { w->writeC(m.loop); w->writeC(m.rel); w->writeC(m.mode); - w->writeC(m.open|wordSize); + w->writeC((m.open&0x3f)|wordSize); w->writeC(m.delay); w->writeC(m.speed); @@ -2024,7 +2024,7 @@ void DivInstrument::readFeatureMA(SafeReader& reader, short version) { target->mode=reader.readC(); unsigned char wordSize=reader.readC(); - target->open=wordSize&7; + target->open=wordSize&15; wordSize>>=6; target->delay=reader.readC(); diff --git a/src/engine/macroInt.cpp b/src/engine/macroInt.cpp index 178db00e6..557777cc8 100644 --- a/src/engine/macroInt.cpp +++ b/src/engine/macroInt.cpp @@ -42,6 +42,7 @@ void DivMacroStruct::prepare(DivInstrumentMacro& source, DivEngine* e) { has=had=actualHad=will=true; mode=source.mode; type=(source.open>>1)&3; + activeRelease=source.open&8; linger=(source.macroType==DIV_MACRO_VOL && e->song.volMacroLinger); lfoPos=LFO_PHASE; } @@ -57,6 +58,10 @@ void DivMacroStruct::doMacro(DivInstrumentMacro& source, bool released, bool tic return; } if (released && type==1 && lastPos<3) delay=0; + if (released && type==0 && pos0) { delay--; if (!linger) had=false; diff --git a/src/engine/macroInt.h b/src/engine/macroInt.h index d6c1b7993..28e605029 100644 --- a/src/engine/macroInt.h +++ b/src/engine/macroInt.h @@ -27,7 +27,7 @@ class DivEngine; struct DivMacroStruct { int pos, lastPos, lfoPos, delay; int val; - bool has, had, actualHad, finished, will, linger, began, masked; + bool has, had, actualHad, finished, will, linger, began, masked, activeRelease; unsigned int mode, type; unsigned char macroType; void doMacro(DivInstrumentMacro& source, bool released, bool tick); @@ -54,6 +54,7 @@ struct DivMacroStruct { linger(false), began(true), masked(false), + activeRelease(false), mode(0), type(0), macroType(mType) {} diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index fa7b5ed4c..491b1659e 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -1749,9 +1749,10 @@ void FurnaceGUI::drawMacroEdit(FurnaceGUIMacroDesc& i, int totalFit, float avail #define BUTTON_TO_SET_MODE(buttonType) \ if (buttonType(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; \ + if (i.macro->open>=4) { \ + i.macro->open&=(~6); \ + } else { \ + i.macro->open+=2; \ } \ \ /* check whether macro type is now ADSR/LFO or sequence */ \ @@ -1819,6 +1820,20 @@ void FurnaceGUI::drawMacroEdit(FurnaceGUIMacroDesc& i, int totalFit, float avail ImGui::EndPopup(); \ } +#define BUTTON_TO_SET_RELEASE(buttonType) \ + pushToggleColors(i.macro->open&8); \ + if (buttonType(ICON_FA_BOLT "##IMacroRelMode")) { \ + i.macro->open^=8; \ + } \ + if (ImGui::IsItemHovered()) { \ + if (i.macro->open&8) { \ + ImGui::SetTooltip("Release mode: Active (jump to release pos)"); \ + } else { \ + ImGui::SetTooltip("Release mode: Passive (delayed release)"); \ + } \ + } \ + popToggleColors(); \ + void FurnaceGUI::drawMacros(std::vector& macros, FurnaceGUIMacroEditState& state) { int index=0; float reservedSpace=(settings.oldMacroVSlider)?(20.0f*dpiScale+ImGui::GetStyle().ItemSpacing.x):ImGui::GetStyle().ScrollbarSize; @@ -1881,6 +1896,10 @@ void FurnaceGUI::drawMacros(std::vector& macros, FurnaceGUI BUTTON_TO_SET_MODE(ImGui::Button); ImGui::SameLine(); BUTTON_TO_SET_PROPS(i); + if ((i.macro->open&6)==0) { + ImGui::SameLine(); + BUTTON_TO_SET_RELEASE(ImGui::Button); + } // do not change this! // anything other than a checkbox will look ugly! // if you really need more than two macro modes please tell me. @@ -1962,6 +1981,10 @@ void FurnaceGUI::drawMacros(std::vector& macros, FurnaceGUI ImGui::SameLine(); } BUTTON_TO_SET_PROPS(i); + if ((i.macro->open&6)==0) { + ImGui::SameLine(); + BUTTON_TO_SET_RELEASE(ImGui::Button); + } if (i.modeName!=NULL) { bool modeVal=i.macro->mode; String modeName=fmt::sprintf("%s##IMacroMode",i.modeName); @@ -2073,6 +2096,10 @@ void FurnaceGUI::drawMacros(std::vector& macros, FurnaceGUI { FurnaceGUIMacroDesc& i=m; BUTTON_TO_SET_MODE(ImGui::Button); + if ((i.macro->open&6)==0) { + ImGui::SameLine(); + BUTTON_TO_SET_RELEASE(ImGui::Button); + } } if (m.modeName!=NULL) { bool modeVal=m.macro->mode;