Implementing per-op arpeggio/pitch macro
Co-authored-by: LTVA1 <87536432+LTVA1@users.noreply.github.com>
This commit is contained in:
parent
215c8c375a
commit
4459a7d659
|
@ -229,6 +229,8 @@ void DivPlatformESFM::tick(bool sysTick) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// detune/fixed pitch
|
||||
if (opE.fixed) {
|
||||
if (m.ssg.had) {
|
||||
|
@ -241,15 +243,10 @@ void DivPlatformESFM::tick(bool sysTick) {
|
|||
chan[i].freqChanged=true;
|
||||
}
|
||||
} else {
|
||||
if (m.ssg.had) {
|
||||
opE.ct=(signed char)m.ssg.val;
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (m.dt.had) {
|
||||
opE.dt=(signed char)m.dt.val;
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
chan[i].handleArpFmOp(0, o);
|
||||
chan[i].handlePitchFmOp(o);
|
||||
}
|
||||
|
||||
if (m.dt2.had) {
|
||||
opE.delay=m.dt2.val;
|
||||
rWrite(baseAddr+ADDR_FREQH_BLOCK_DELAY,chan[i].freqH[o]|(opE.delay<<5));
|
||||
|
@ -257,6 +254,8 @@ void DivPlatformESFM::tick(bool sysTick) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (int i=0; i<ESFM_REG_POOL_SIZE; i++) {
|
||||
if (pendingWrites[i]!=oldWrites[i]) {
|
||||
immWrite(i,pendingWrites[i]&0xff);
|
||||
|
@ -305,7 +304,17 @@ void DivPlatformESFM::tick(bool sysTick) {
|
|||
chan[i].freqL[o]=opE.dt;
|
||||
chan[i].freqH[o]=opE.ct&0x1f;
|
||||
} else {
|
||||
int opFreq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride+ct:chan[i].arpOff+ct,chan[i].fixedArp,false,octave(chan[i].baseFreq)*2,chan[i].pitch2+dt,chipClock,CHIP_FREQBASE);
|
||||
int arp=chan[i].fixedArp?chan[i].baseNoteOverride+ct:chan[i].arpOff+ct;
|
||||
int pitch2=chan[i].pitch2+dt;
|
||||
int fixedArp=chan[i].fixedArp;
|
||||
if(chan[i].opsState[o].hasOpArp) {
|
||||
arp=chan[i].opsState[o].fixedArp?chan[i].opsState[o].baseNoteOverride+ct:chan[i].opsState[o].arpOff+ct;
|
||||
fixedArp=chan[i].opsState[o].fixedArp;
|
||||
}
|
||||
if(chan[i].opsState[o].hasOpPitch) {
|
||||
pitch2=chan[i].opsState[o].pitch2+dt;
|
||||
}
|
||||
int opFreq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,arp,fixedArp,false,octave(chan[i].baseFreq)*2,pitch2,chipClock,CHIP_FREQBASE);
|
||||
if (opFreq<0) opFreq=0;
|
||||
if (opFreq>131071) opFreq=131071;
|
||||
int freqt=toFreq(opFreq);
|
||||
|
@ -432,6 +441,7 @@ int DivPlatformESFM::dispatch(DivCommand c) {
|
|||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_ESFM);
|
||||
|
||||
chan[c.chan].macroInit(ins);
|
||||
memset(chan[c.chan].opsState, 0, sizeof(chan[c.chan].opsState));
|
||||
if (!chan[c.chan].std.vol.will) {
|
||||
chan[c.chan].outVol=chan[c.chan].vol;
|
||||
}
|
||||
|
|
|
@ -36,13 +36,77 @@ class DivPlatformESFM: public DivDispatch {
|
|||
bool hardReset;
|
||||
unsigned char globalPan;
|
||||
int macroVolMul;
|
||||
struct {
|
||||
int baseNoteOverride;
|
||||
bool fixedArp;
|
||||
int arpOff;
|
||||
int pitch2;
|
||||
bool hasOpArp;
|
||||
bool hasOpPitch;
|
||||
} opsState[4];
|
||||
|
||||
void handleArpFmOp(int offset=0, int o=0) {
|
||||
DivMacroInt::IntOp& m=this->std.op[o];
|
||||
if (m.ssg.had) {
|
||||
opsState[o].hasOpArp=true;
|
||||
|
||||
if (m.ssg.val<0) {
|
||||
if (!(m.ssg.val&0x40000000)) {
|
||||
opsState[o].baseNoteOverride=(m.ssg.val|0x40000000)+offset;
|
||||
opsState[o].fixedArp=true;
|
||||
} else {
|
||||
opsState[o].arpOff=m.ssg.val;
|
||||
opsState[o].fixedArp=false;
|
||||
}
|
||||
} else {
|
||||
if (m.ssg.val&0x40000000) {
|
||||
opsState[o].baseNoteOverride=(m.ssg.val&(~0x40000000))+offset;
|
||||
opsState[o].fixedArp=true;
|
||||
} else {
|
||||
opsState[o].arpOff=m.ssg.val;
|
||||
opsState[o].fixedArp=false;
|
||||
}
|
||||
}
|
||||
freqChanged=true;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
opsState[o].hasOpArp=false;
|
||||
}
|
||||
}
|
||||
|
||||
void handlePitchFmOp(int o)
|
||||
{
|
||||
DivMacroInt::IntOp& m=this->std.op[o];
|
||||
|
||||
if (m.dt.had) {
|
||||
opsState[o].hasOpPitch=true;
|
||||
|
||||
if (m.dt.mode) {
|
||||
opsState[o].pitch2+=m.dt.val;
|
||||
CLAMP_VAR(opsState[o].pitch2,-131071,131071);
|
||||
} else {
|
||||
opsState[o].pitch2=m.dt.val;
|
||||
}
|
||||
this->freqChanged=true;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
opsState[o].hasOpPitch=false;
|
||||
}
|
||||
}
|
||||
|
||||
Channel():
|
||||
SharedChannel<int>(0),
|
||||
freqL{0, 0, 0, 0},
|
||||
freqH{0, 0, 0, 0},
|
||||
hardReset(false),
|
||||
globalPan(3),
|
||||
macroVolMul(64) {}
|
||||
macroVolMul(64) {
|
||||
memset(opsState, 0, sizeof(opsState));
|
||||
}
|
||||
};
|
||||
Channel chan[18];
|
||||
DivDispatchOscBuffer* oscBuf[18];
|
||||
|
|
|
@ -1245,8 +1245,10 @@ struct FurnaceGUIMacroDesc {
|
|||
bool isBitfield, blockMode, bit30;
|
||||
String (*hoverFunc)(int,float,void*);
|
||||
void* hoverFuncUser;
|
||||
bool isArp;
|
||||
bool isPitch;
|
||||
|
||||
FurnaceGUIMacroDesc(const char* name, DivInstrumentMacro* m, int macroMin, int macroMax, float macroHeight, ImVec4 col=ImVec4(1.0f,1.0f,1.0f,1.0f), bool block=false, const char* mName=NULL, String (*hf)(int,float,void*)=NULL, bool bitfield=false, const char** bfVal=NULL, unsigned int bitOff=0, bool bit30Special=false, void* hfu=NULL):
|
||||
FurnaceGUIMacroDesc(const char* name, DivInstrumentMacro* m, int macroMin, int macroMax, float macroHeight, ImVec4 col=ImVec4(1.0f,1.0f,1.0f,1.0f), bool block=false, const char* mName=NULL, String (*hf)(int,float,void*)=NULL, bool bitfield=false, const char** bfVal=NULL, unsigned int bitOff=0, bool bit30Special=false, void* hfu=NULL, bool isArp=false, bool isPitch=false):
|
||||
macro(m),
|
||||
height(macroHeight),
|
||||
displayName(name),
|
||||
|
@ -1258,7 +1260,9 @@ struct FurnaceGUIMacroDesc {
|
|||
blockMode(block),
|
||||
bit30(bit30Special),
|
||||
hoverFunc(hf),
|
||||
hoverFuncUser(hfu) {
|
||||
hoverFuncUser(hfu),
|
||||
isArp(isArp),
|
||||
isPitch(isPitch) {
|
||||
// MSVC -> hell
|
||||
this->min=macroMin;
|
||||
this->max=macroMax;
|
||||
|
|
|
@ -1537,10 +1537,10 @@ void FurnaceGUI::drawMacroEdit(FurnaceGUIMacroDesc& i, int totalFit, float avail
|
|||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,ImVec2(0.0f,0.0f));
|
||||
|
||||
if (i.macro->vZoom<1) {
|
||||
if (i.macro->macroType==DIV_MACRO_ARP) {
|
||||
if (i.macro->macroType==DIV_MACRO_ARP || i.isArp) {
|
||||
i.macro->vZoom=24;
|
||||
i.macro->vScroll=120-12;
|
||||
} else if (i.macro->macroType==DIV_MACRO_PITCH) {
|
||||
} else if (i.macro->macroType==DIV_MACRO_PITCH || i.isPitch) {
|
||||
i.macro->vZoom=128;
|
||||
i.macro->vScroll=2048-64;
|
||||
} else {
|
||||
|
@ -3937,6 +3937,9 @@ void FurnaceGUI::drawInsEdit() {
|
|||
ImGui::SetCursorPosY(ImGui::GetCursorPosY()-0.5*ImGui::GetStyle().ItemSpacing.y);
|
||||
if (ImGui::Checkbox(ESFM_NAME(ESFM_FIXED),&fixedOn)) { PARAMETER
|
||||
opE.fixed=fixedOn;
|
||||
// HACK: reset zoom and scroll in fixed pitch macros so that they draw correctly
|
||||
ins->std.opMacros[i].ssgMacro.vZoom=-1;
|
||||
ins->std.opMacros[i].dtMacro.vZoom=-1;
|
||||
}
|
||||
if (ins->type==DIV_INS_ESFM) {
|
||||
if (fixedOn) {
|
||||
|
@ -4674,6 +4677,9 @@ void FurnaceGUI::drawInsEdit() {
|
|||
}
|
||||
if (ImGui::Checkbox(ESFM_NAME(ESFM_FIXED),&fixedOn)) { PARAMETER
|
||||
opE.fixed=fixedOn;
|
||||
// HACK: reset zoom and scroll in fixed pitch macros so that they draw correctly
|
||||
ins->std.opMacros[i].ssgMacro.vZoom=-1;
|
||||
ins->std.opMacros[i].dtMacro.vZoom=-1;
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
|
@ -5198,6 +5204,9 @@ void FurnaceGUI::drawInsEdit() {
|
|||
ImGui::SameLine();
|
||||
if (ImGui::Checkbox(ESFM_NAME(ESFM_FIXED),&fixedOn)) { PARAMETER
|
||||
opE.fixed=fixedOn;
|
||||
// HACK: reset zoom and scroll in fixed pitch macros so that they draw correctly
|
||||
ins->std.opMacros[i].ssgMacro.vZoom=-1;
|
||||
ins->std.opMacros[i].dtMacro.vZoom=-1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5322,8 +5331,8 @@ void FurnaceGUI::drawInsEdit() {
|
|||
macroList.push_back(FurnaceGUIMacroDesc("Block",&ins->std.opMacros[ordi].ssgMacro,0,7,64,uiColors[GUI_COLOR_MACRO_OTHER],true));
|
||||
macroList.push_back(FurnaceGUIMacroDesc("FreqNum",&ins->std.opMacros[ordi].dtMacro,0,1023,160,uiColors[GUI_COLOR_MACRO_OTHER]));
|
||||
} else {
|
||||
macroList.push_back(FurnaceGUIMacroDesc(ESFM_NAME(ESFM_CT),&ins->std.opMacros[ordi].ssgMacro,-24,24,128,uiColors[GUI_COLOR_MACRO_OTHER],true));
|
||||
macroList.push_back(FurnaceGUIMacroDesc(ESFM_NAME(ESFM_DT),&ins->std.opMacros[ordi].dtMacro,-128,127,160,uiColors[GUI_COLOR_MACRO_OTHER]));
|
||||
macroList.push_back(FurnaceGUIMacroDesc("Op. Arpeggio",&ins->std.opMacros[ordi].ssgMacro,-120,120,160,uiColors[GUI_COLOR_MACRO_PITCH],true,NULL,macroHoverNote,false,NULL,0,true,ins->std.opMacros[ordi].ssgMacro.val,true));
|
||||
macroList.push_back(FurnaceGUIMacroDesc("Op. Pitch",&ins->std.opMacros[ordi].dtMacro,-2048,2047,160,uiColors[GUI_COLOR_MACRO_PITCH],true,macroRelativeMode,NULL,false,NULL,0,false,NULL,false,true));
|
||||
}
|
||||
|
||||
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_AM),&ins->std.opMacros[ordi].amMacro,0,1,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true));
|
||||
|
|
Loading…
Reference in a new issue