From 8f20824234dd6b6f1a25f39b03afa3690d850373 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Fri, 15 Mar 2024 13:45:57 -0500 Subject: [PATCH] add delayed release effects FCxx - note release E7xx - macro release --- doc/3-pattern/effects.md | 4 ++- src/engine/engine.cpp | 5 +++ src/engine/engine.h | 3 +- src/engine/playback.cpp | 68 +++++++++++++++++++++++++++------------- src/gui/guiConst.cpp | 4 +-- 5 files changed, 58 insertions(+), 26 deletions(-) diff --git a/doc/3-pattern/effects.md b/doc/3-pattern/effects.md index e8f02c8cf..67ca51ad5 100644 --- a/doc/3-pattern/effects.md +++ b/doc/3-pattern/effects.md @@ -80,8 +80,10 @@ not all chips support these effects. - `0Cxx`: **Retrigger.** repeats current note every `xx` ticks. - this effect is not continuous; it must be entered on every row. -- `ECxx`: **Note cut.** ends current note after `xx` ticks. for FM instruments, it's equivalent to a "key off". +- `ECxx`: **Note cut.** triggers note off after `xx` ticks. this triggers key off in FM/hardware envelope chips, or cuts note otherwise. - `EDxx`: **Note delay.** delays note by `x` ticks. +- `FCxx`: **Note release.** releases current note after `xx` ticks. this releases macros and triggers key off in FM/hardware envelope chips. +- `E7xx`: **Macro release.** releases macros after `xx` ticks. this does not trigger key off. ## other diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index ee99ae002..ab8b22a99 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -105,6 +105,8 @@ const char* DivEngine::getEffectDesc(unsigned char effect, int chan, bool notNul return "E4xx: Set vibrato range"; case 0xe5: return "E5xx: Set pitch (80: center)"; + case 0xe7: + return "E7xx: Macro release"; case 0xea: return "EAxx: Legato"; case 0xeb: @@ -137,6 +139,8 @@ const char* DivEngine::getEffectDesc(unsigned char effect, int chan, bool notNul return "F9xx: Single tick volume slide down"; case 0xfa: return "FAxx: Fast volume slide (0y: down; x0: up)"; + case 0xfc: + return "FCxx: Note release"; case 0xff: return "FFxx: Stop song"; default: @@ -1687,6 +1691,7 @@ void DivEngine::playSub(bool preserveDrift, int goalRow) { } for (int i=0; i>4)/15))); dispatchCmd(DivCommand(DIV_CMD_HINT_PITCH,i,chan[i].pitch)); break; + case 0xe7: // delayed macro release + // "Bruh" + if (effectVal>0 && (song.delayBehavior==2 || effectVal0 && (song.delayBehavior==2 || effectVal0 && (song.delayBehavior==2 || effectVal0) { if (--chan[i].cut<1) { - chan[i].oldNote=chan[i].note; - //chan[i].note=-1; - if (chan[i].inPorta && song.noteOffResetsSlides) { - chan[i].keyOff=true; - chan[i].keyOn=false; - if (chan[i].stopOnOff) { - chan[i].portaNote=-1; - chan[i].portaSpeed=-1; - dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,CLAMP(chan[i].portaNote,-128,127),MAX(chan[i].portaSpeed,0))); - chan[i].stopOnOff=false; + if (chan[i].cutType==2) { + dispatchCmd(DivCommand(DIV_CMD_ENV_RELEASE,i)); + chan[i].releasing=true; + } else { + chan[i].oldNote=chan[i].note; + //chan[i].note=-1; + if (chan[i].inPorta && song.noteOffResetsSlides) { + chan[i].keyOff=true; + chan[i].keyOn=false; + if (chan[i].stopOnOff) { + chan[i].portaNote=-1; + chan[i].portaSpeed=-1; + dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,CLAMP(chan[i].portaNote,-128,127),MAX(chan[i].portaSpeed,0))); + chan[i].stopOnOff=false; + } + if (disCont[dispatchOfChan[i]].dispatch->keyOffAffectsPorta(dispatchChanOfChan[i])) { + chan[i].portaNote=-1; + chan[i].portaSpeed=-1; + dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,CLAMP(chan[i].portaNote,-128,127),MAX(chan[i].portaSpeed,0))); + } + dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0)); + chan[i].scheduledSlideReset=true; } - if (disCont[dispatchOfChan[i]].dispatch->keyOffAffectsPorta(dispatchChanOfChan[i])) { - chan[i].portaNote=-1; - chan[i].portaSpeed=-1; - dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,CLAMP(chan[i].portaNote,-128,127),MAX(chan[i].portaSpeed,0))); - /*if (i==2 && sysOfChan[i]==DIV_SYSTEM_SMS) { - chan[i+1].portaNote=-1; - chan[i+1].portaSpeed=-1; - }*/ + if (chan[i].cutType==1) { + dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF_ENV,i)); + } else { + dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF,i)); } - dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0)); - chan[i].scheduledSlideReset=true; + chan[i].releasing=true; } - dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF,i)); } } if (chan[i].resetArp) { diff --git a/src/gui/guiConst.cpp b/src/gui/guiConst.cpp index 3d7fffc90..ce93ddfb9 100644 --- a/src/gui/guiConst.cpp +++ b/src/gui/guiConst.cpp @@ -490,7 +490,7 @@ const FurnaceGUIColors fxColors[256]={ GUI_COLOR_PATTERN_EFFECT_MISC, // E4 GUI_COLOR_PATTERN_EFFECT_PITCH, // E5 GUI_COLOR_PATTERN_EFFECT_INVALID, // E6 - GUI_COLOR_PATTERN_EFFECT_INVALID, // E7 + GUI_COLOR_PATTERN_EFFECT_TIME, // E7 GUI_COLOR_PATTERN_EFFECT_INVALID, // E8 GUI_COLOR_PATTERN_EFFECT_INVALID, // E9 GUI_COLOR_PATTERN_EFFECT_MISC, // EA @@ -511,7 +511,7 @@ const FurnaceGUIColors fxColors[256]={ GUI_COLOR_PATTERN_EFFECT_VOLUME, // F9 GUI_COLOR_PATTERN_EFFECT_VOLUME, // FA GUI_COLOR_PATTERN_EFFECT_INVALID, // FB - GUI_COLOR_PATTERN_EFFECT_INVALID, // FC + GUI_COLOR_PATTERN_EFFECT_TIME, // FC GUI_COLOR_PATTERN_EFFECT_INVALID, // FD GUI_COLOR_PATTERN_EFFECT_INVALID, // FE GUI_COLOR_PATTERN_EFFECT_SONG // FF