mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-27 06:53:01 +00:00
OPLL: 80%
accuracy fixes pending though then macros and then drum mode
This commit is contained in:
parent
c52258f943
commit
271b3fb0fe
5 changed files with 255 additions and 156 deletions
|
@ -196,6 +196,7 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
|
|||
break;
|
||||
case DIV_SYSTEM_OPLL:
|
||||
case DIV_SYSTEM_OPLL_DRUMS:
|
||||
case DIV_SYSTEM_VRC7:
|
||||
dispatch=new DivPlatformOPLL;
|
||||
break;
|
||||
case DIV_SYSTEM_SAA1099: {
|
||||
|
|
|
@ -299,10 +299,16 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
|
|||
for (int j=0; j<ins->fm.ops; j++) {
|
||||
ins->fm.op[j].am=reader.readC();
|
||||
ins->fm.op[j].ar=reader.readC();
|
||||
if (ds.system[0]==DIV_SYSTEM_SMS_OPLL || ds.system[0]==DIV_SYSTEM_NES_VRC7) {
|
||||
ins->fm.op[j].ar&=15;
|
||||
}
|
||||
if (ds.version<0x13) {
|
||||
ins->fm.op[j].dam=reader.readC();
|
||||
}
|
||||
ins->fm.op[j].dr=reader.readC();
|
||||
if (ds.system[0]==DIV_SYSTEM_SMS_OPLL || ds.system[0]==DIV_SYSTEM_NES_VRC7) {
|
||||
ins->fm.op[j].dr&=15;
|
||||
}
|
||||
if (ds.version<0x13) {
|
||||
ins->fm.op[j].dvb=reader.readC();
|
||||
ins->fm.op[j].egt=reader.readC();
|
||||
|
|
|
@ -54,7 +54,7 @@ struct DivInstrumentFM {
|
|||
unsigned char alg, fb, fms, ams, ops, opllPreset;
|
||||
struct Operator {
|
||||
unsigned char am, ar, dr, mult, rr, sl, tl, dt2, rs, dt, d2r, ssgEnv;
|
||||
unsigned char dam, dvb, egt, ksl, sus, vib, ws, ksr; // YMU759
|
||||
unsigned char dam, dvb, egt, ksl, sus, vib, ws, ksr; // YMU759/OPL
|
||||
Operator():
|
||||
am(0),
|
||||
ar(0),
|
||||
|
|
|
@ -85,13 +85,12 @@ void DivPlatformOPLL::acquire_nuked(short* bufL, short* bufR, size_t start, size
|
|||
QueuedWrite& w=writes.front();
|
||||
if (w.addrOrVal) {
|
||||
OPLL_Write(&fm,1,w.val);
|
||||
printf("write: %x = %.2x\n",w.addr,w.val);
|
||||
//printf("write: %x = %.2x\n",w.addr,w.val);
|
||||
regPool[w.addr&0xff]=w.val;
|
||||
writes.pop();
|
||||
delay=21;
|
||||
} else {
|
||||
//printf("busycounter: %d\n",lastBusy);
|
||||
//w.addr=rand()&0x3f;
|
||||
OPLL_Write(&fm,0,w.addr);
|
||||
w.addrOrVal=true;
|
||||
delay=3;
|
||||
|
@ -240,8 +239,7 @@ void DivPlatformOPLL::tick() {
|
|||
}*/
|
||||
|
||||
if (chan[i].keyOn || chan[i].keyOff) {
|
||||
// TODO: FIX
|
||||
immWrite(0x20+i,0x00);
|
||||
immWrite(0x20+i,(chan[i].freqH)|(chan[i].state.alg?0x20:0));
|
||||
//chan[i].keyOn=false;
|
||||
chan[i].keyOff=false;
|
||||
}
|
||||
|
@ -262,31 +260,32 @@ void DivPlatformOPLL::tick() {
|
|||
chan[i].freqH=freqt>>8;
|
||||
chan[i].freqL=freqt&0xff;
|
||||
immWrite(0x10+i,freqt&0xff);
|
||||
|
||||
chan[i].freqChanged=false;
|
||||
}
|
||||
if (chan[i].keyOn) {
|
||||
if (chan[i].keyOn || chan[i].freqChanged) {
|
||||
//immWrite(0x28,0xf0|konOffs[i]);
|
||||
immWrite(0x20+i,(chan[i].freqH)|(chan[i].active<<4)|0x20);
|
||||
immWrite(0x20+i,(chan[i].freqH)|(chan[i].active<<4)|(chan[i].state.alg?0x20:0));
|
||||
chan[i].keyOn=false;
|
||||
}
|
||||
chan[i].freqChanged=false;
|
||||
}
|
||||
}
|
||||
|
||||
#define OPLL_C_NUM 343
|
||||
|
||||
int DivPlatformOPLL::octave(int freq) {
|
||||
if (freq>=32768) {
|
||||
if (freq>=OPLL_C_NUM*64) {
|
||||
return 128;
|
||||
} else if (freq>=16384) {
|
||||
} else if (freq>=OPLL_C_NUM*32) {
|
||||
return 64;
|
||||
} else if (freq>=8192) {
|
||||
} else if (freq>=OPLL_C_NUM*16) {
|
||||
return 32;
|
||||
} else if (freq>=4096) {
|
||||
} else if (freq>=OPLL_C_NUM*8) {
|
||||
return 16;
|
||||
} else if (freq>=2048) {
|
||||
} else if (freq>=OPLL_C_NUM*4) {
|
||||
return 8;
|
||||
} else if (freq>=1024) {
|
||||
} else if (freq>=OPLL_C_NUM*2) {
|
||||
return 4;
|
||||
} else if (freq>=512) {
|
||||
} else if (freq>=OPLL_C_NUM) {
|
||||
return 2;
|
||||
} else {
|
||||
return 1;
|
||||
|
@ -295,19 +294,19 @@ int DivPlatformOPLL::octave(int freq) {
|
|||
}
|
||||
|
||||
int DivPlatformOPLL::toFreq(int freq) {
|
||||
if (freq>=32768) {
|
||||
if (freq>=OPLL_C_NUM*64) {
|
||||
return 0xe00|((freq>>7)&0x1ff);
|
||||
} else if (freq>=16384) {
|
||||
} else if (freq>=OPLL_C_NUM*32) {
|
||||
return 0xc00|((freq>>6)&0x1ff);
|
||||
} else if (freq>=8192) {
|
||||
} else if (freq>=OPLL_C_NUM*16) {
|
||||
return 0xa00|((freq>>5)&0x1ff);
|
||||
} else if (freq>=4096) {
|
||||
} else if (freq>=OPLL_C_NUM*8) {
|
||||
return 0x800|((freq>>4)&0x1ff);
|
||||
} else if (freq>=2048) {
|
||||
} else if (freq>=OPLL_C_NUM*4) {
|
||||
return 0x600|((freq>>3)&0x1ff);
|
||||
} else if (freq>=1024) {
|
||||
} else if (freq>=OPLL_C_NUM*2) {
|
||||
return 0x400|((freq>>2)&0x1ff);
|
||||
} else if (freq>=512) {
|
||||
} else if (freq>=OPLL_C_NUM) {
|
||||
return 0x200|((freq>>1)&0x1ff);
|
||||
} else {
|
||||
return freq&0x1ff;
|
||||
|
@ -346,39 +345,23 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
|
|||
chan[c.chan].outVol=chan[c.chan].vol;
|
||||
}
|
||||
|
||||
/*
|
||||
for (int i=0; i<2; i++) {
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
if (isMuted[c.chan]) {
|
||||
rWrite(baseAddr+ADDR_TL,127);
|
||||
} else {
|
||||
if (isOutput[chan[c.chan].state.alg][i]) {
|
||||
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
||||
rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[c.chan].outVol&0x7f))/127));
|
||||
}
|
||||
} else {
|
||||
if (chan[c.chan].insChanged) {
|
||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (chan[c.chan].insChanged) {
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||
}
|
||||
}
|
||||
if (chan[c.chan].insChanged) {
|
||||
rWrite(chanOffs[c.chan]+ADDR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3));
|
||||
rWrite(chanOffs[c.chan]+ADDR_LRAF,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|(chan[c.chan].state.fms&7)|((chan[c.chan].state.ams&3)<<4));
|
||||
// update custom preset
|
||||
if (chan[c.chan].state.opllPreset==0) {
|
||||
DivInstrumentFM::Operator& mod=chan[c.chan].state.op[0];
|
||||
DivInstrumentFM::Operator& car=chan[c.chan].state.op[1];
|
||||
rWrite(0x00,(mod.am<<7)|(mod.vib<<6)|((mod.ssgEnv&8)<<2)|(mod.ksr<<4)|(mod.mult));
|
||||
rWrite(0x01,(car.am<<7)|(car.vib<<6)|((car.ssgEnv&8)<<2)|(car.ksr<<4)|(car.mult));
|
||||
rWrite(0x02,(car.ksl<<6)|(mod.tl&63));
|
||||
rWrite(0x03,(mod.ksl<<6)|((chan[c.chan].state.fms&1)<<4)|((chan[c.chan].state.ams&1)<<3)|chan[c.chan].state.fb);
|
||||
rWrite(0x04,(mod.ar<<4)|(mod.dr));
|
||||
rWrite(0x05,(car.ar<<4)|(car.dr));
|
||||
rWrite(0x06,(mod.sl<<4)|(mod.rr));
|
||||
rWrite(0x07,(car.sl<<4)|(car.rr));
|
||||
}
|
||||
rWrite(0x30+c.chan,(15-(chan[c.chan].outVol*(15-chan[c.chan].state.op[1].tl))/15)|(chan[c.chan].state.opllPreset<<4));
|
||||
}
|
||||
*/
|
||||
// for now
|
||||
rWrite(0x30+c.chan,0x0|(ins->fm.opllPreset<<4));
|
||||
|
||||
chan[c.chan].insChanged=false;
|
||||
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
|
@ -409,20 +392,7 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
|
|||
if (!chan[c.chan].std.hasVol) {
|
||||
chan[c.chan].outVol=c.value;
|
||||
}
|
||||
/*
|
||||
for (int i=0; i<4; i++) {
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
if (isMuted[c.chan]) {
|
||||
rWrite(baseAddr+ADDR_TL,127);
|
||||
} else {
|
||||
if (isOutput[chan[c.chan].state.alg][i]) {
|
||||
rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[c.chan].outVol&0x7f))/127));
|
||||
} else {
|
||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
rWrite(0x30+c.chan,(15-(chan[c.chan].outVol*(15-chan[c.chan].state.op[1].tl))/15)|(chan[c.chan].state.opllPreset<<4));
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_GET_VOLUME: {
|
||||
|
@ -457,12 +427,12 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
|
|||
return2=true;
|
||||
}
|
||||
}
|
||||
if (!chan[c.chan].portaPause) {
|
||||
/*if (!chan[c.chan].portaPause) {
|
||||
if (octave(chan[c.chan].baseFreq)!=octave(newFreq)) {
|
||||
chan[c.chan].portaPause=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
chan[c.chan].baseFreq=newFreq;
|
||||
chan[c.chan].portaPause=false;
|
||||
chan[c.chan].freqChanged=true;
|
||||
|
@ -528,7 +498,7 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
|
|||
return 0;
|
||||
break;
|
||||
case DIV_CMD_GET_VOLMAX:
|
||||
return 127;
|
||||
return 15;
|
||||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
chan[c.chan].inPorta=c.value;
|
||||
|
@ -543,38 +513,26 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
|
|||
}
|
||||
|
||||
void DivPlatformOPLL::forceIns() {
|
||||
/*
|
||||
for (int i=0; i<6; i++) {
|
||||
for (int j=0; j<4; j++) {
|
||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||
if (isMuted[i]) {
|
||||
rWrite(baseAddr+ADDR_TL,127);
|
||||
} else {
|
||||
if (isOutput[chan[i].state.alg][j]) {
|
||||
rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[i].outVol&0x7f))/127));
|
||||
} else {
|
||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||
}
|
||||
}
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||
for (int i=0; i<9; i++) {
|
||||
// update custom preset
|
||||
if (chan[i].state.opllPreset==0) {
|
||||
DivInstrumentFM::Operator& mod=chan[i].state.op[0];
|
||||
DivInstrumentFM::Operator& car=chan[i].state.op[1];
|
||||
rWrite(0x00,(mod.am<<7)|(mod.vib<<6)|((mod.ssgEnv&8)<<2)|(mod.ksr<<4)|(mod.mult));
|
||||
rWrite(0x01,(car.am<<7)|(car.vib<<6)|((car.ssgEnv&8)<<2)|(car.ksr<<4)|(car.mult));
|
||||
rWrite(0x02,(car.ksl<<6)|(mod.tl&63));
|
||||
rWrite(0x03,(mod.ksl<<6)|((chan[i].state.fms&1)<<4)|((chan[i].state.ams&1)<<3)|chan[i].state.fb);
|
||||
rWrite(0x04,(mod.ar<<4)|(mod.dr));
|
||||
rWrite(0x05,(car.ar<<4)|(car.dr));
|
||||
rWrite(0x06,(mod.sl<<4)|(mod.rr));
|
||||
rWrite(0x07,(car.sl<<4)|(car.rr));
|
||||
}
|
||||
rWrite(chanOffs[i]+ADDR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3));
|
||||
rWrite(chanOffs[i]+ADDR_LRAF,(isMuted[i]?0:(chan[i].pan<<6))|(chan[i].state.fms&7)|((chan[i].state.ams&3)<<4));
|
||||
rWrite(0x30+i,(15-(chan[i].outVol*(15-chan[i].state.op[1].tl))/15)|(chan[i].state.opllPreset<<4));
|
||||
if (chan[i].active) {
|
||||
chan[i].keyOn=true;
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
}
|
||||
if (dacMode) {
|
||||
rWrite(0x2b,0x80);
|
||||
}
|
||||
immWrite(0x22,lfoValue);*/
|
||||
}
|
||||
|
||||
void DivPlatformOPLL::toggleRegisterDump(bool enable) {
|
||||
|
@ -590,7 +548,7 @@ unsigned char* DivPlatformOPLL::getRegisterPool() {
|
|||
}
|
||||
|
||||
int DivPlatformOPLL::getRegisterPoolSize() {
|
||||
return 256;
|
||||
return 64;
|
||||
}
|
||||
|
||||
void DivPlatformOPLL::reset() {
|
||||
|
|
|
@ -58,13 +58,13 @@ const char* ssgEnvTypes[8]={
|
|||
"Down Down Down", "Down.", "Down Up Down Up", "Down UP", "Up Up Up", "Up.", "Up Down Up Down", "Up DOWN"
|
||||
};
|
||||
|
||||
const char* fmParamNames[3][16]={
|
||||
{"Algorithm", "Feedback", "LFO > Freq", "LFO > Amp", "Attack", "Decay", "Decay 2", "Release", "Sustain", "Level", "EnvScale", "Multiplier", "Detune", "Detune 2", "SSG-EG", "AM"},
|
||||
{"ALG", "FB", "FMS/PMS", "AMS", "AR", "DR", "SR", "RR", "SL", "TL", "KS", "MULT", "DT", "DT2", "SSG-EG", "AM"},
|
||||
{"ALG", "FB", "FMS/PMS", "AMS", "AR", "DR", "D2R", "RR", "SL", "TL", "RS", "MULT", "DT", "DT2", "SSG-EG", "AM"}
|
||||
const char* fmParamNames[3][27]={
|
||||
{"Algorithm", "Feedback", "LFO > Freq", "LFO > Amp", "Attack", "Decay", "Decay 2", "Release", "Sustain", "Level", "EnvScale", "Multiplier", "Detune", "Detune 2", "SSG-EG", "AM", "AM Depth", "Vibrato Depth", "EnvAlternate", "EnvAlternate", "LevelScale/key", "Sustain", "Vibrato", "Waveform", "EnvScale/key", "OP2 HalfSine", "OP1 HalfSine"},
|
||||
{"ALG", "FB", "FMS/PMS", "AMS", "AR", "DR", "SR", "RR", "SL", "TL", "KS", "MULT", "DT", "DT2", "SSG-EG", "AM", "AMD", "FMD", "EGT", "EGT", "KSL", "SUS", "VIB", "WS", "KSR", "DC", "DM"},
|
||||
{"ALG", "FB", "FMS/PMS", "AMS", "AR", "DR", "D2R", "RR", "SL", "TL", "RS", "MULT", "DT", "DT2", "SSG-EG", "AM", "DAM", "DVB", "EGT", "EGS", "KSL", "SUS", "VIB", "WS", "KSR", "DC", "DM"}
|
||||
};
|
||||
|
||||
const char* opllInsNames[18]={
|
||||
const char* opllInsNames[17]={
|
||||
"User",
|
||||
"Violin",
|
||||
"Guitar",
|
||||
|
@ -100,7 +100,18 @@ enum FMParams {
|
|||
FM_DT=12,
|
||||
FM_DT2=13,
|
||||
FM_SSG=14,
|
||||
FM_AM=15
|
||||
FM_AM=15,
|
||||
FM_DAM=16,
|
||||
FM_DVB=17,
|
||||
FM_EGT=18,
|
||||
FM_EGS=19,
|
||||
FM_KSL=20,
|
||||
FM_SUS=21,
|
||||
FM_VIB=22,
|
||||
FM_WS=23,
|
||||
FM_KSR=24,
|
||||
FM_DC=25,
|
||||
FM_DM=26
|
||||
};
|
||||
|
||||
#define FM_NAME(x) fmParamNames[settings.fmNames][x]
|
||||
|
@ -429,6 +440,41 @@ void FurnaceGUI::drawAlgorithm(unsigned char alg, FurnaceGUIFMAlgs algType, cons
|
|||
}
|
||||
}
|
||||
break;
|
||||
case FM_ALGS_2OP_OPL:
|
||||
switch (alg) {
|
||||
case 0: { // 1 > 2
|
||||
ImVec2 pos1=ImLerp(rect.Min,rect.Max,ImVec2(0.33,0.5));
|
||||
ImVec2 pos2=ImLerp(rect.Min,rect.Max,ImVec2(0.67,0.5));
|
||||
dl->AddCircleFilled(pos1,4.0f*dpiScale+1.0f,color);
|
||||
dl->AddCircle(pos1,6.0f*dpiScale+1.0f,color);
|
||||
dl->AddLine(pos1,pos2,colorL);
|
||||
dl->AddCircleFilled(pos2,4.0f*dpiScale+1.0f,color);
|
||||
|
||||
pos1.x-=ImGui::CalcTextSize("2").x+circleRadius+3.0*dpiScale;
|
||||
pos2.x+=circleRadius+3.0*dpiScale;
|
||||
pos1.y-=ImGui::CalcTextSize("1").y*0.5;
|
||||
pos2.y-=ImGui::CalcTextSize("2").y*0.5;
|
||||
dl->AddText(pos1,color,"1");
|
||||
dl->AddText(pos2,color,"2");
|
||||
break;
|
||||
}
|
||||
case 1: { // 1 + 2
|
||||
ImVec2 pos1=ImLerp(rect.Min,rect.Max,ImVec2(0.33,0.5));
|
||||
ImVec2 pos2=ImLerp(rect.Min,rect.Max,ImVec2(0.67,0.5));
|
||||
dl->AddCircleFilled(pos1,4.0f*dpiScale+1.0f,color);
|
||||
dl->AddCircle(pos1,6.0f*dpiScale+1.0f,color);
|
||||
dl->AddCircleFilled(pos2,4.0f*dpiScale+1.0f,color);
|
||||
|
||||
pos1.x-=ImGui::CalcTextSize("2").x+circleRadius+3.0*dpiScale;
|
||||
pos2.x+=circleRadius+3.0*dpiScale;
|
||||
pos1.y-=ImGui::CalcTextSize("1").y*0.5;
|
||||
pos2.y-=ImGui::CalcTextSize("2").y*0.5;
|
||||
dl->AddText(pos1,color,"1");
|
||||
dl->AddText(pos2,color,"2");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -735,7 +781,7 @@ void FurnaceGUI::drawInsEdit() {
|
|||
}
|
||||
|
||||
if (ImGui::BeginTabBar("insEditTab")) {
|
||||
if (ins->type==DIV_INS_FM) {
|
||||
if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPLL || ins->type==DIV_INS_OPZ) {
|
||||
char label[32];
|
||||
float asFloat[256];
|
||||
int asInt[256];
|
||||
|
@ -746,19 +792,72 @@ void FurnaceGUI::drawInsEdit() {
|
|||
ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.0);
|
||||
ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch,0.0);
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
P(ImGui::SliderScalar(FM_NAME(FM_FB),ImGuiDataType_U8,&ins->fm.fb,&_ZERO,&_SEVEN));
|
||||
P(ImGui::SliderScalar(FM_NAME(FM_FMS),ImGuiDataType_U8,&ins->fm.fms,&_ZERO,&_SEVEN));
|
||||
ImGui::TableNextColumn();
|
||||
P(ImGui::SliderScalar(FM_NAME(FM_ALG),ImGuiDataType_U8,&ins->fm.alg,&_ZERO,&_SEVEN));
|
||||
P(ImGui::SliderScalar(FM_NAME(FM_AMS),ImGuiDataType_U8,&ins->fm.ams,&_ZERO,&_THREE));
|
||||
ImGui::TableNextColumn();
|
||||
drawAlgorithm(ins->fm.alg,FM_ALGS_4OP,ImVec2(ImGui::GetContentRegionAvail().x,48.0*dpiScale));
|
||||
switch (ins->type) {
|
||||
case DIV_INS_FM:
|
||||
case DIV_INS_OPZ:
|
||||
ImGui::TableNextColumn();
|
||||
P(ImGui::SliderScalar(FM_NAME(FM_FB),ImGuiDataType_U8,&ins->fm.fb,&_ZERO,&_SEVEN));
|
||||
P(ImGui::SliderScalar(FM_NAME(FM_FMS),ImGuiDataType_U8,&ins->fm.fms,&_ZERO,&_SEVEN));
|
||||
ImGui::TableNextColumn();
|
||||
P(ImGui::SliderScalar(FM_NAME(FM_ALG),ImGuiDataType_U8,&ins->fm.alg,&_ZERO,&_SEVEN));
|
||||
P(ImGui::SliderScalar(FM_NAME(FM_AMS),ImGuiDataType_U8,&ins->fm.ams,&_ZERO,&_THREE));
|
||||
ImGui::TableNextColumn();
|
||||
drawAlgorithm(ins->fm.alg,FM_ALGS_4OP,ImVec2(ImGui::GetContentRegionAvail().x,48.0*dpiScale));
|
||||
break;
|
||||
case DIV_INS_OPL:
|
||||
case DIV_INS_OPLL: {
|
||||
bool dc=ins->fm.fms;
|
||||
bool dm=ins->fm.ams;
|
||||
bool sus=ins->fm.alg;
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::BeginDisabled(ins->fm.opllPreset!=0);
|
||||
P(ImGui::SliderScalar(FM_NAME(FM_FB),ImGuiDataType_U8,&ins->fm.fb,&_ZERO,&_SEVEN));
|
||||
if (ImGui::Checkbox(FM_NAME(FM_DC),&dc)) { PARAMETER
|
||||
ins->fm.fms=dc;
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Checkbox(FM_NAME(FM_SUS),&sus)) { PARAMETER
|
||||
ins->fm.alg=sus;
|
||||
}
|
||||
ImGui::BeginDisabled(ins->fm.opllPreset!=0);
|
||||
if (ImGui::Checkbox(FM_NAME(FM_DM),&dm)) { PARAMETER
|
||||
ins->fm.ams=dm;
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::TableNextColumn();
|
||||
drawAlgorithm(0,FM_ALGS_2OP_OPL,ImVec2(ImGui::GetContentRegionAvail().x,24.0*dpiScale));
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
if (ImGui::BeginCombo("##LLPreset",opllInsNames[ins->fm.opllPreset])) {
|
||||
for (int i=0; i<17; i++) {
|
||||
if (ImGui::Selectable(opllInsNames[i])) {
|
||||
ins->fm.opllPreset=i;
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
if (ImGui::BeginTable("FMOperators",2,ImGuiTableFlags_SizingStretchSame)) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=ins->fm.op[opOrder[i]];
|
||||
|
||||
if (ins->type==DIV_INS_OPLL && ins->fm.opllPreset==16) {
|
||||
ImGui::Text("the Drums patch is only there for compatibility.\nit is highly encouraged you use the OPLL (drums) system instead!");
|
||||
}
|
||||
|
||||
bool willDisplayOps=true;
|
||||
int opCount=4;
|
||||
if (ins->type==DIV_INS_OPLL && ins->fm.opllPreset!=0) willDisplayOps=false;
|
||||
if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPLL) opCount=2;
|
||||
if (!willDisplayOps && ins->type==DIV_INS_OPLL) {
|
||||
P(ImGui::SliderScalar("Volume##TL",ImGuiDataType_U8,&ins->fm.op[1].tl,&_FIFTEEN,&_ZERO));
|
||||
}
|
||||
if (willDisplayOps) if (ImGui::BeginTable("FMOperators",2,ImGuiTableFlags_SizingStretchSame)) {
|
||||
for (int i=0; i<opCount; i++) {
|
||||
DivInstrumentFM::Operator& op=ins->fm.op[(opCount==4)?opOrder[i]:i];
|
||||
if ((i+1)&1) ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Separator();
|
||||
|
@ -775,13 +874,27 @@ void FurnaceGUI::drawInsEdit() {
|
|||
|
||||
ImGui::SameLine();
|
||||
|
||||
int maxTl=127;
|
||||
if (ins->type==DIV_INS_OPLL) {
|
||||
if (i==1) {
|
||||
maxTl=15;
|
||||
} else {
|
||||
maxTl=63;
|
||||
}
|
||||
}
|
||||
|
||||
bool ssgOn=op.ssgEnv&8;
|
||||
bool ksrOn=op.ksr;
|
||||
bool vibOn=op.vib;
|
||||
unsigned char ssgEnv=op.ssgEnv&7;
|
||||
if (ImGui::Checkbox("SSG On",&ssgOn)) { PARAMETER
|
||||
int maxArDr=(ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ)?31:15;
|
||||
if (ImGui::Checkbox((ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPLL)?FM_NAME(FM_EGS):"SSG On",&ssgOn)) { PARAMETER
|
||||
op.ssgEnv=(op.ssgEnv&7)|(ssgOn<<3);
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Only for Genesis and Neo Geo systems");
|
||||
if (ins->type==DIV_INS_FM) {
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Only for Genesis and Neo Geo systems");
|
||||
}
|
||||
}
|
||||
|
||||
//52.0 controls vert scaling; default 96
|
||||
|
@ -794,14 +907,14 @@ void FurnaceGUI::drawInsEdit() {
|
|||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
P(ImGui::SliderScalar("##AR",ImGuiDataType_U8,&op.ar,&_THIRTY_ONE,&_ZERO));
|
||||
P(ImGui::SliderScalar("##AR",ImGuiDataType_U8,&op.ar,&maxArDr,&_ZERO));
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_AR));
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
P(ImGui::SliderScalar("##DR",ImGuiDataType_U8,&op.dr,&_THIRTY_ONE,&_ZERO));
|
||||
P(ImGui::SliderScalar("##DR",ImGuiDataType_U8,&op.dr,&maxArDr,&_ZERO));
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_DR));
|
||||
|
||||
|
@ -812,12 +925,14 @@ void FurnaceGUI::drawInsEdit() {
|
|||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_SL));
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
P(ImGui::SliderScalar("##D2R",ImGuiDataType_U8,&op.d2r,&_THIRTY_ONE,&_ZERO));
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_D2R));
|
||||
if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
P(ImGui::SliderScalar("##D2R",ImGuiDataType_U8,&op.d2r,&_THIRTY_ONE,&_ZERO));
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_D2R));
|
||||
}
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
@ -829,7 +944,7 @@ void FurnaceGUI::drawInsEdit() {
|
|||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
P(ImGui::SliderScalar("##TL",ImGuiDataType_U8,&op.tl,&_ONE_HUNDRED_TWENTY_SEVEN,&_ZERO));
|
||||
P(ImGui::SliderScalar("##TL",ImGuiDataType_U8,&op.tl,&maxTl,&_ZERO));
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_TL));
|
||||
|
||||
|
@ -842,9 +957,15 @@ void FurnaceGUI::drawInsEdit() {
|
|||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
P(ImGui::SliderScalar("##RS",ImGuiDataType_U8,&op.rs,&_ZERO,&_THREE));
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_RS));
|
||||
if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ) {
|
||||
P(ImGui::SliderScalar("##RS",ImGuiDataType_U8,&op.rs,&_ZERO,&_THREE));
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_RS));
|
||||
} else {
|
||||
P(ImGui::SliderScalar("##KSL",ImGuiDataType_U8,&op.ksl,&_ZERO,&_THREE));
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_KSL));
|
||||
}
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
@ -853,37 +974,50 @@ void FurnaceGUI::drawInsEdit() {
|
|||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_MULT));
|
||||
|
||||
int detune=(op.dt&7)-3;
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
if (ImGui::SliderInt("##DT",&detune,-3,3)) { PARAMETER
|
||||
op.dt=detune+3;
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_DT));
|
||||
if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ) {
|
||||
int detune=(op.dt&7)-3;
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
if (ImGui::SliderInt("##DT",&detune,-3,3)) { PARAMETER
|
||||
op.dt=detune+3;
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_DT));
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
P(ImGui::SliderScalar("##DT2",ImGuiDataType_U8,&op.dt2,&_ZERO,&_THREE));
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Only for Arcade system");
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_DT2));
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
P(ImGui::SliderScalar("##DT2",ImGuiDataType_U8,&op.dt2,&_ZERO,&_THREE));
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Only for Arcade system");
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_DT2));
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
if (ImGui::SliderScalar("##SSG",ImGuiDataType_U8,&ssgEnv,&_ZERO,&_SEVEN,ssgEnvTypes[ssgEnv])) { PARAMETER
|
||||
op.ssgEnv=(op.ssgEnv&8)|(ssgEnv&7);
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
if (ImGui::SliderScalar("##SSG",ImGuiDataType_U8,&ssgEnv,&_ZERO,&_SEVEN,ssgEnvTypes[ssgEnv])) { PARAMETER
|
||||
op.ssgEnv=(op.ssgEnv&8)|(ssgEnv&7);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_SSG));
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_SSG));
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
if (ins->type==DIV_INS_OPLL || ins->type==DIV_INS_OPL) {
|
||||
if (ImGui::Checkbox(FM_NAME(FM_VIB),&vibOn)) { PARAMETER
|
||||
op.vib=vibOn;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Checkbox(FM_NAME(FM_KSR),&ksrOn)) { PARAMETER
|
||||
op.ksr=ksrOn;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::EndTable();
|
||||
|
|
Loading…
Reference in a new issue