first attempt, arp & pitch macros work

This commit is contained in:
LTVA1 2024-08-25 13:33:01 +03:00
parent 332b449f0e
commit e58518ed62
3 changed files with 206 additions and 12 deletions

View file

@ -102,6 +102,15 @@ inline int hScale(int note) {
return ((note/12)<<4)+(noteMap[note%12]);
}
int DivPlatformTX81Z::toFreq(int freq) {
int block=0;
while (freq>0xff) {
freq>>=1;
block++;
}
return ((block&7)<<8)|(freq&0xff);
}
void DivPlatformTX81Z::tick(bool sysTick) {
for (int i=0; i<8; i++) {
chan[i].std.next();
@ -289,6 +298,66 @@ void DivPlatformTX81Z::tick(bool sysTick) {
op.dt2=m.dt2.val;
rWrite(baseAddr+ADDR_DT2_D2R,(op.d2r&31)|(op.dt2<<6));
}
/*if (ImGui::InputInt(_("Block"),&block,1,1)) {
if (block<0) block=0;
if (block>7) block=7;
op.dt=block;
}
if (ImGui::InputInt(_("FreqNum"),&freqNum,1,16)) {
if (freqNum<0) freqNum=0;
if (freqNum>255) freqNum=255;
op.mult=freqNum>>4;
op.dvb=freqNum&15;
}*/
// fixed pitch
bool freqChangeOp = false;
if(op.egt)
{
if (op.sus) {
chan[i].handleArpFmOp(freqChangeOp, 0, j); //arp and pitch macros
chan[i].handlePitchFmOp(freqChangeOp, j);
} else {
if (m.ssg.had) { //block and f-num macros
op.dt=m.ssg.val&7;
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|((op.egt?(op.dt&7):dtTable[op.dt&7])<<4));
}
if (m.sus.had) {
op.mult=(m.sus.val & 0xff) >> 4;
op.dvb=(m.sus.val & 0xf);
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|((op.egt?(op.dt&7):dtTable[op.dt&7])<<4));
rWrite(baseAddr+ADDR_WS_FINE,(op.dvb&15)|(op.ws<<4));
}
}
}
if(freqChangeOp)
{
int arp=chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff;
int pitch2=chan[i].pitch2;
int fixedArp=chan[i].fixedArp;
if(chan[i].opsState[j].hasOpArp) {
arp=chan[i].opsState[j].fixedArp?chan[i].opsState[j].baseNoteOverride:chan[i].opsState[j].arpOff;
fixedArp=chan[i].opsState[j].fixedArp;
}
if(chan[i].opsState[j].hasOpPitch) {
pitch2=chan[i].opsState[j].pitch2;
}
int opFreq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,arp,fixedArp,false,2, pitch2,chipClock,524288 / 4,0);
if (opFreq<0) opFreq=0;
if (opFreq>65280) opFreq=65280;
int freqt=toFreq(opFreq);
op.dt=(freqt >> 8) & 7;
op.mult=(freqt & 0xff) >> 4;
op.dvb=(freqt & 0xf);
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|((op.egt?(op.dt&7):dtTable[op.dt&7])<<4));
rWrite(baseAddr+ADDR_WS_FINE,(op.dvb&15)|(op.ws<<4));
}
}
}
@ -444,6 +513,7 @@ int DivPlatformTX81Z::dispatch(DivCommand c) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_OPZ);
memset(chan[c.chan].opsState, 0, sizeof(chan[c.chan].opsState));
chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;

View file

@ -36,10 +36,74 @@ class DivPlatformTX81Z: public DivPlatformOPM {
struct Channel: public FMChannel {
unsigned char chVolL, chVolR;
struct {
int baseNoteOverride;
bool fixedArp;
int arpOff;
int pitch2;
bool hasOpArp;
bool hasOpPitch;
} opsState[4];
void handleArpFmOp(bool& freqChange, 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;
}
}
freqChange = true;
}
else
{
opsState[o].hasOpArp=false;
}
}
void handlePitchFmOp(bool& freqChange, int o)
{
DivMacroInt::IntOp& m=this->std.op[o];
if (m.sus.had) {
opsState[o].hasOpPitch=true;
if (m.sus.mode) {
opsState[o].pitch2+=m.sus.val;
CLAMP_VAR(opsState[o].pitch2,-131071,131071);
} else {
opsState[o].pitch2=m.sus.val;
}
freqChange = true;
}
else
{
opsState[o].hasOpPitch=false;
}
}
Channel():
FMChannel(),
chVolL(1),
chVolR(1) {}
chVolR(1) {
memset(opsState, 0, sizeof(opsState));
}
};
Channel chan[8];
DivDispatchOscBuffer* oscBuf[8];

View file

@ -3803,7 +3803,22 @@ void FurnaceGUI::insTabFM(DivInstrument* ins) {
if (ins->type==DIV_INS_OPZ) {
ImGui::TableNextColumn();
CENTER_VSLIDER;
P(CWVSliderScalar("##FINE",ImVec2(20.0f*dpiScale,sliderHeight),ImGuiDataType_U8,&op.dvb,&_ZERO,&_FIFTEEN)); rightClickable
bool egtOn=op.egt;
if(egtOn)
{
bool susOn=op.sus;
if (ImGui::Checkbox("Pitch control",&susOn)) { PARAMETER
op.sus=susOn;
}
if(ImGui::IsItemHovered())
{
ImGui::SetTooltip(_("Use op's arpeggio and pitch macros control instead of block/f-num macros"));
}
}
else
{
P(CWVSliderScalar("##FINE",ImVec2(20.0f*dpiScale,sliderHeight),ImGuiDataType_U8,&op.dvb,&_ZERO,&_FIFTEEN)); rightClickable
}
}
if (ins->type==DIV_INS_ESFM) {
@ -4593,6 +4608,17 @@ void FurnaceGUI::insTabFM(DivInstrument* ins) {
snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_FINE));
P(CWSliderScalar("##FINE",ImGuiDataType_U8,&op.dvb,&_ZERO,&_FIFTEEN,tempID)); rightClickable
}
else
{
bool susOn=op.sus;
if (ImGui::Checkbox("Pitch control",&susOn)) { PARAMETER
op.sus=susOn;
}
if(ImGui::IsItemHovered())
{
ImGui::SetTooltip(_("Use op's arpeggio and pitch macros control instead of block/f-num macros"));
}
}
ImGui::TableNextColumn();
bool amOn=op.am;
@ -4897,6 +4923,18 @@ void FurnaceGUI::insTabFM(DivInstrument* ins) {
if (ImGui::Checkbox(_("Fixed"),&fixedOn)) { PARAMETER
op.egt=fixedOn;
}
bool susOn=op.sus;
if(fixedOn)
{
ImGui::SameLine();
if (ImGui::Checkbox("Pitch control",&susOn)) { PARAMETER
op.sus=susOn;
}
if(ImGui::IsItemHovered())
{
ImGui::SetTooltip(_("Use op's arpeggio and pitch macros control instead of block/f-num macros"));
}
}
}
//52.0 controls vert scaling; default 96
@ -5555,6 +5593,13 @@ void FurnaceGUI::drawInsEdit() {
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_EGS),&ins->std.opMacros[ordi].egtMacro,0,1,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true));
} else if (ins->type==DIV_INS_ESFM) {
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_TL),&ins->std.opMacros[ordi].tlMacro,0,maxTl,128,uiColors[GUI_COLOR_MACRO_VOLUME]));
if (ins->esfm.op[ordi].fixed) {
macroList.push_back(FurnaceGUIMacroDesc(_("Block"),&ins->std.opMacros[ordi].ssgMacro,0,7,64,uiColors[GUI_COLOR_MACRO_PITCH],true));
macroList.push_back(FurnaceGUIMacroDesc(_("FreqNum"),&ins->std.opMacros[ordi].dtMacro,0,1023,160,uiColors[GUI_COLOR_MACRO_PITCH]));
} else {
macroList.push_back(FurnaceGUIMacroDesc(_("Op. Arpeggio"),&ins->std.opMacros[ordi].ssgMacro,-120,120,160,uiColors[GUI_COLOR_MACRO_PITCH],true,NULL,macroHoverNote,false,NULL,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,false,NULL,false,true));
}
macroList.push_back(FurnaceGUIMacroDesc(ESFM_NAME(ESFM_DELAY),&ins->std.opMacros[ordi].dt2Macro,0,7,64,uiColors[GUI_COLOR_MACRO_ENVELOPE]));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_AR),&ins->std.opMacros[ordi].arMacro,0,maxArDr,64,uiColors[GUI_COLOR_MACRO_ENVELOPE]));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_DR),&ins->std.opMacros[ordi].drMacro,0,maxArDr,64,uiColors[GUI_COLOR_MACRO_ENVELOPE]));
@ -5565,14 +5610,6 @@ void FurnaceGUI::drawInsEdit() {
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_WS),&ins->std.opMacros[ordi].wsMacro,0,7,64,uiColors[GUI_COLOR_MACRO_OTHER]));
macroList.push_back(FurnaceGUIMacroDesc(ESFM_NAME(ESFM_OUTLVL),&ins->std.opMacros[ordi].egtMacro,0,7,64,uiColors[GUI_COLOR_MACRO_VOLUME]));
macroList.push_back(FurnaceGUIMacroDesc(ESFM_NAME(ESFM_MODIN),&ins->std.opMacros[ordi].d2rMacro,0,7,64,uiColors[GUI_COLOR_MACRO_VOLUME]));
if (ins->esfm.op[ordi].fixed) {
macroList.push_back(FurnaceGUIMacroDesc(_("Block"),&ins->std.opMacros[ordi].ssgMacro,0,7,64,uiColors[GUI_COLOR_MACRO_PITCH],true));
macroList.push_back(FurnaceGUIMacroDesc(_("FreqNum"),&ins->std.opMacros[ordi].dtMacro,0,1023,160,uiColors[GUI_COLOR_MACRO_PITCH]));
} else {
macroList.push_back(FurnaceGUIMacroDesc(_("Op. Arpeggio"),&ins->std.opMacros[ordi].ssgMacro,-120,120,160,uiColors[GUI_COLOR_MACRO_PITCH],true,NULL,macroHoverNote,false,NULL,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,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));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_VIB),&ins->std.opMacros[ordi].vibMacro,0,1,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_DAM),&ins->std.opMacros[ordi].damMacro,0,1,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true));
@ -5580,7 +5617,7 @@ void FurnaceGUI::drawInsEdit() {
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_KSR),&ins->std.opMacros[ordi].ksrMacro,0,1,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_SUS),&ins->std.opMacros[ordi].susMacro,0,1,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true));
macroList.push_back(FurnaceGUIMacroDesc(_("Op. Panning"),&ins->std.opMacros[ordi].rsMacro,0,2,40,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true,panBits));
} else {
} else if(ins->type==DIV_INS_FM || ins->type==DIV_INS_OPM) {
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_TL),&ins->std.opMacros[ordi].tlMacro,0,maxTl,128,uiColors[GUI_COLOR_MACRO_VOLUME]));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_AR),&ins->std.opMacros[ordi].arMacro,0,maxArDr,64,uiColors[GUI_COLOR_MACRO_ENVELOPE]));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_DR),&ins->std.opMacros[ordi].drMacro,0,maxArDr,64,uiColors[GUI_COLOR_MACRO_ENVELOPE]));
@ -5590,7 +5627,7 @@ void FurnaceGUI::drawInsEdit() {
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_RS),&ins->std.opMacros[ordi].rsMacro,0,3,32,uiColors[GUI_COLOR_MACRO_OTHER]));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_MULT),&ins->std.opMacros[ordi].multMacro,0,15,64,uiColors[GUI_COLOR_MACRO_OTHER]));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_DT),&ins->std.opMacros[ordi].dtMacro,0,7,64,uiColors[GUI_COLOR_MACRO_PITCH]));
if (ins->type==DIV_INS_OPM || ins->type==DIV_INS_OPZ) {
if (ins->type==DIV_INS_OPM) {
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_DT2),&ins->std.opMacros[ordi].dt2Macro,0,3,32,uiColors[GUI_COLOR_MACRO_PITCH]));
}
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));
@ -5598,6 +5635,29 @@ void FurnaceGUI::drawInsEdit() {
if (ins->type==DIV_INS_FM) {
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_SSG),&ins->std.opMacros[ordi].ssgMacro,0,4,64,uiColors[GUI_COLOR_MACRO_ENVELOPE],false,NULL,NULL,true,ssgEnvBits));
}
} else if(ins->type==DIV_INS_OPZ) {
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_TL),&ins->std.opMacros[ordi].tlMacro,0,maxTl,128,uiColors[GUI_COLOR_MACRO_VOLUME]));
if (ins->fm.op[ordi].egt)
{
if (!ins->fm.op[ordi].sus) {
macroList.push_back(FurnaceGUIMacroDesc(_("Block"),&ins->std.opMacros[ordi].ssgMacro,0,7,64,uiColors[GUI_COLOR_MACRO_PITCH],true));
macroList.push_back(FurnaceGUIMacroDesc(_("FreqNum"),&ins->std.opMacros[ordi].susMacro,0,255,160,uiColors[GUI_COLOR_MACRO_PITCH]));
} else {
macroList.push_back(FurnaceGUIMacroDesc(_("Op. Arpeggio"),&ins->std.opMacros[ordi].ssgMacro,-120,120,160,uiColors[GUI_COLOR_MACRO_PITCH],true,NULL,macroHoverNote,false,NULL,true,ins->std.opMacros[ordi].ssgMacro.val,true));
macroList.push_back(FurnaceGUIMacroDesc(_("Op. Pitch"),&ins->std.opMacros[ordi].susMacro,-2048,2047,160,uiColors[GUI_COLOR_MACRO_PITCH],true,macroRelativeMode,NULL,false,NULL,false,NULL,false,true));
}
}
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_AR),&ins->std.opMacros[ordi].arMacro,0,maxArDr,64,uiColors[GUI_COLOR_MACRO_ENVELOPE]));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_DR),&ins->std.opMacros[ordi].drMacro,0,maxArDr,64,uiColors[GUI_COLOR_MACRO_ENVELOPE]));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_D2R),&ins->std.opMacros[ordi].d2rMacro,0,31,64,uiColors[GUI_COLOR_MACRO_ENVELOPE]));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_RR),&ins->std.opMacros[ordi].rrMacro,0,15,64,uiColors[GUI_COLOR_MACRO_ENVELOPE]));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_SL),&ins->std.opMacros[ordi].slMacro,0,15,64,uiColors[GUI_COLOR_MACRO_ENVELOPE]));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_RS),&ins->std.opMacros[ordi].rsMacro,0,3,32,uiColors[GUI_COLOR_MACRO_OTHER]));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_MULT),&ins->std.opMacros[ordi].multMacro,0,15,64,uiColors[GUI_COLOR_MACRO_OTHER]));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_DT),&ins->std.opMacros[ordi].dtMacro,0,7,64,uiColors[GUI_COLOR_MACRO_PITCH]));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_DT2),&ins->std.opMacros[ordi].dt2Macro,0,3,32,uiColors[GUI_COLOR_MACRO_PITCH]));
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));
}
drawMacros(macroList,macroEditStateOP[ordi]);
ImGui::PopID();