prepare for macro release points

issue #142
This commit is contained in:
tildearrow 2022-02-08 03:50:42 -05:00
parent 8991fa98ba
commit 4ce116ca0a
10 changed files with 278 additions and 90 deletions

View file

@ -25,10 +25,12 @@ furthermore, an `or reserved` indicates this field is always present, but is res
the format versions are: the format versions are:
- 42: Furnace 0.5.5pre1 - 44: Furnace 0.5.5pre2
- 41: Furnace 0.5.4 - 43: Furnace 0.5.5pre1
- 40: Furnace 0.5.3 - 42: Furnace 0.5.4
- 39: Furnace 0.5.2 - 41: Furnace 0.5.3
- 40: Furnace 0.5.2
- 39: Furnace 0.5.2pre3
- 38: Furnace 0.5.2pre2 - 38: Furnace 0.5.2pre2
- 37: Furnace 0.5.2pre1 - 37: Furnace 0.5.2pre1
- 36: Furnace 0.5.1 - 36: Furnace 0.5.1
@ -353,6 +355,32 @@ size | description
1?? | DT macro 1?? | DT macro
1?? | D2R macro 1?? | D2R macro
1?? | SSG-EG macro 1?? | SSG-EG macro
--- | **release points** (>=44)
4 | volume macro release
4 | arp macro release
4 | duty macro release
4 | wave macro release
4 | pitch macro release
4 | extra 1 macro release
4 | extra 2 macro release
4 | extra 3 macro release
4 | alg macro release
4 | fb macro release
4 | fms macro release
4 | ams macro release
--- | **operator release points** × 4 (>=44)
4 | AM macro release
4 | AR macro release
4 | DR macro release
4 | MULT macro release
4 | RR macro release
4 | SL macro release
4 | TL macro release
4 | DT2 macro release
4 | RS macro release
4 | DT macro release
4 | D2R macro release
4 | SSG-EG macro release
# wavetable # wavetable

View file

@ -13,6 +13,8 @@
enum DivDispatchCmds { enum DivDispatchCmds {
DIV_CMD_NOTE_ON=0, DIV_CMD_NOTE_ON=0,
DIV_CMD_NOTE_OFF, DIV_CMD_NOTE_OFF,
DIV_CMD_NOTE_OFF_ENV,
DIV_CMD_ENV_RELEASE,
DIV_CMD_INSTRUMENT, DIV_CMD_INSTRUMENT,
DIV_CMD_VOLUME, DIV_CMD_VOLUME,
DIV_CMD_GET_VOLUME, DIV_CMD_GET_VOLUME,

View file

@ -11,8 +11,8 @@
#include <map> #include <map>
#include <queue> #include <queue>
#define DIV_VERSION "0.5.5pre1" #define DIV_VERSION "0.5.5pre2"
#define DIV_ENGINE_VERSION 43 #define DIV_ENGINE_VERSION 44
enum DivStatusView { enum DivStatusView {
DIV_STATUS_NOTHING=0, DIV_STATUS_NOTHING=0,

View file

@ -253,6 +253,36 @@ void DivInstrument::putInsData(SafeWriter* w) {
w->writeC(op.ssgMacro[j]); w->writeC(op.ssgMacro[j]);
} }
} }
// release points
w->writeI(std.volMacroRel);
w->writeI(std.arpMacroRel);
w->writeI(std.dutyMacroRel);
w->writeI(std.waveMacroRel);
w->writeI(std.pitchMacroRel);
w->writeI(std.ex1MacroRel);
w->writeI(std.ex2MacroRel);
w->writeI(std.ex3MacroRel);
w->writeI(std.algMacroRel);
w->writeI(std.fbMacroRel);
w->writeI(std.fmsMacroRel);
w->writeI(std.amsMacroRel);
for (int i=0; i<4; i++) {
DivInstrumentSTD::OpMacro& op=std.opMacros[i];
w->writeI(op.amMacroRel);
w->writeI(op.arMacroRel);
w->writeI(op.drMacroRel);
w->writeI(op.multMacroRel);
w->writeI(op.rrMacroRel);
w->writeI(op.slMacroRel);
w->writeI(op.tlMacroRel);
w->writeI(op.dt2MacroRel);
w->writeI(op.rsMacroRel);
w->writeI(op.dtMacroRel);
w->writeI(op.d2rMacroRel);
w->writeI(op.ssgMacroRel);
}
} }
DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version) { DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version) {
@ -484,6 +514,39 @@ DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version) {
} }
} }
// release points
if (version>=44) {
std.volMacroRel=reader.readI();
std.arpMacroRel=reader.readI();
std.dutyMacroRel=reader.readI();
std.waveMacroRel=reader.readI();
std.pitchMacroRel=reader.readI();
std.ex1MacroRel=reader.readI();
std.ex2MacroRel=reader.readI();
std.ex3MacroRel=reader.readI();
std.algMacroRel=reader.readI();
std.fbMacroRel=reader.readI();
std.fmsMacroRel=reader.readI();
std.amsMacroRel=reader.readI();
for (int i=0; i<4; i++) {
DivInstrumentSTD::OpMacro& op=std.opMacros[i];
op.amMacroRel=reader.readI();
op.arMacroRel=reader.readI();
op.drMacroRel=reader.readI();
op.multMacroRel=reader.readI();
op.rrMacroRel=reader.readI();
op.slMacroRel=reader.readI();
op.tlMacroRel=reader.readI();
op.dt2MacroRel=reader.readI();
op.rsMacroRel=reader.readI();
op.dtMacroRel=reader.readI();
op.d2rMacroRel=reader.readI();
op.ssgMacroRel=reader.readI();
}
}
return DIV_DATA_SUCCESS; return DIV_DATA_SUCCESS;
} }

View file

@ -123,6 +123,9 @@ struct DivInstrumentSTD {
signed char volMacroLoop, arpMacroLoop, dutyMacroLoop, waveMacroLoop; signed char volMacroLoop, arpMacroLoop, dutyMacroLoop, waveMacroLoop;
signed char pitchMacroLoop, ex1MacroLoop, ex2MacroLoop, ex3MacroLoop; signed char pitchMacroLoop, ex1MacroLoop, ex2MacroLoop, ex3MacroLoop;
signed char algMacroLoop, fbMacroLoop, fmsMacroLoop, amsMacroLoop; signed char algMacroLoop, fbMacroLoop, fmsMacroLoop, amsMacroLoop;
signed char volMacroRel, arpMacroRel, dutyMacroRel, waveMacroRel;
signed char pitchMacroRel, ex1MacroRel, ex2MacroRel, ex3MacroRel;
signed char algMacroRel, fbMacroRel, fmsMacroRel, amsMacroRel;
struct OpMacro { struct OpMacro {
// ar, dr, mult, rr, sl, tl, dt2, rs, dt, d2r, ssgEnv; // ar, dr, mult, rr, sl, tl, dt2, rs, dt, d2r, ssgEnv;
unsigned char amMacro[256]; unsigned char amMacro[256];
@ -146,6 +149,9 @@ struct DivInstrumentSTD {
signed char amMacroLoop, arMacroLoop, drMacroLoop, multMacroLoop; signed char amMacroLoop, arMacroLoop, drMacroLoop, multMacroLoop;
signed char rrMacroLoop, slMacroLoop, tlMacroLoop, dt2MacroLoop; signed char rrMacroLoop, slMacroLoop, tlMacroLoop, dt2MacroLoop;
signed char rsMacroLoop, dtMacroLoop, d2rMacroLoop, ssgMacroLoop; signed char rsMacroLoop, dtMacroLoop, d2rMacroLoop, ssgMacroLoop;
signed char amMacroRel, arMacroRel, drMacroRel, multMacroRel;
signed char rrMacroRel, slMacroRel, tlMacroRel, dt2MacroRel;
signed char rsMacroRel, dtMacroRel, d2rMacroRel, ssgMacroRel;
OpMacro(): OpMacro():
amMacroOpen(false), arMacroOpen(false), drMacroOpen(false), multMacroOpen(false), amMacroOpen(false), arMacroOpen(false), drMacroOpen(false), multMacroOpen(false),
rrMacroOpen(false), slMacroOpen(false), tlMacroOpen(true), dt2MacroOpen(false), rrMacroOpen(false), slMacroOpen(false), tlMacroOpen(true), dt2MacroOpen(false),
@ -155,7 +161,10 @@ struct DivInstrumentSTD {
rsMacroLen(0), dtMacroLen(0), d2rMacroLen(0), ssgMacroLen(0), rsMacroLen(0), dtMacroLen(0), d2rMacroLen(0), ssgMacroLen(0),
amMacroLoop(-1), arMacroLoop(-1), drMacroLoop(-1), multMacroLoop(-1), amMacroLoop(-1), arMacroLoop(-1), drMacroLoop(-1), multMacroLoop(-1),
rrMacroLoop(-1), slMacroLoop(-1), tlMacroLoop(-1), dt2MacroLoop(-1), rrMacroLoop(-1), slMacroLoop(-1), tlMacroLoop(-1), dt2MacroLoop(-1),
rsMacroLoop(-1), dtMacroLoop(-1), d2rMacroLoop(-1), ssgMacroLoop(-1) { rsMacroLoop(-1), dtMacroLoop(-1), d2rMacroLoop(-1), ssgMacroLoop(-1),
amMacroRel(-1), arMacroRel(-1), drMacroRel(-1), multMacroRel(-1),
rrMacroRel(-1), slMacroRel(-1), tlMacroRel(-1), dt2MacroRel(-1),
rsMacroRel(-1), dtMacroRel(-1), d2rMacroRel(-1), ssgMacroRel(-1) {
memset(amMacro,0,256); memset(amMacro,0,256);
memset(arMacro,0,256); memset(arMacro,0,256);
memset(drMacro,0,256); memset(drMacro,0,256);
@ -210,7 +219,19 @@ struct DivInstrumentSTD {
algMacroLoop(-1), algMacroLoop(-1),
fbMacroLoop(-1), fbMacroLoop(-1),
fmsMacroLoop(-1), fmsMacroLoop(-1),
amsMacroLoop(-1) { amsMacroLoop(-1),
volMacroRel(-1),
arpMacroRel(-1),
dutyMacroRel(-1),
waveMacroRel(-1),
pitchMacroRel(-1),
ex1MacroRel(-1),
ex2MacroRel(-1),
ex3MacroRel(-1),
algMacroRel(-1),
fbMacroRel(-1),
fmsMacroRel(-1),
amsMacroRel(-1) {
memset(volMacro,0,256*sizeof(int)); memset(volMacro,0,256*sizeof(int));
memset(arpMacro,0,256*sizeof(int)); memset(arpMacro,0,256*sizeof(int));
memset(dutyMacro,0,256*sizeof(int)); memset(dutyMacro,0,256*sizeof(int));

View file

@ -1,7 +1,7 @@
#include "macroInt.h" #include "macroInt.h"
#include "instrument.h" #include "instrument.h"
#define doMacro(finished,had,has,val,pos,source,sourceLen,sourceLoop) \ #define doMacro(finished,had,has,val,pos,source,sourceLen,sourceLoop,sourceRel) \
if (finished) finished=false; \ if (finished) finished=false; \
if (had!=has) { \ if (had!=has) { \
finished=true; \ finished=true; \
@ -9,6 +9,9 @@
had=has; \ had=has; \
if (has) { \ if (has) { \
val=source[pos++]; \ val=source[pos++]; \
if (pos==sourceRel && !released) { \
pos--; \
} \
if (pos>=sourceLen) { \ if (pos>=sourceLen) { \
if (sourceLoop<sourceLen && sourceLoop>=0) { \ if (sourceLoop<sourceLen && sourceLoop>=0) { \
pos=sourceLoop; \ pos=sourceLoop; \
@ -21,41 +24,45 @@
void DivMacroInt::next() { void DivMacroInt::next() {
if (ins==NULL) return; if (ins==NULL) return;
doMacro(finishedVol,hadVol,hasVol,vol,volPos,ins->std.volMacro,ins->std.volMacroLen,ins->std.volMacroLoop); doMacro(finishedVol,hadVol,hasVol,vol,volPos,ins->std.volMacro,ins->std.volMacroLen,ins->std.volMacroLoop,ins->std.volMacroRel);
doMacro(finishedArp,hadArp,hasArp,arp,arpPos,ins->std.arpMacro,ins->std.arpMacroLen,ins->std.arpMacroLoop); doMacro(finishedArp,hadArp,hasArp,arp,arpPos,ins->std.arpMacro,ins->std.arpMacroLen,ins->std.arpMacroLoop,ins->std.arpMacroRel);
doMacro(finishedDuty,hadDuty,hasDuty,duty,dutyPos,ins->std.dutyMacro,ins->std.dutyMacroLen,ins->std.dutyMacroLoop); doMacro(finishedDuty,hadDuty,hasDuty,duty,dutyPos,ins->std.dutyMacro,ins->std.dutyMacroLen,ins->std.dutyMacroLoop,ins->std.dutyMacroRel);
doMacro(finishedWave,hadWave,hasWave,wave,wavePos,ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop); doMacro(finishedWave,hadWave,hasWave,wave,wavePos,ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,ins->std.waveMacroRel);
doMacro(finishedPitch,hadPitch,hasPitch,pitch,pitchPos,ins->std.pitchMacro,ins->std.pitchMacroLen,ins->std.pitchMacroLoop); doMacro(finishedPitch,hadPitch,hasPitch,pitch,pitchPos,ins->std.pitchMacro,ins->std.pitchMacroLen,ins->std.pitchMacroLoop,ins->std.pitchMacroRel);
doMacro(finishedEx1,hadEx1,hasEx1,ex1,ex1Pos,ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop); doMacro(finishedEx1,hadEx1,hasEx1,ex1,ex1Pos,ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel);
doMacro(finishedEx2,hadEx2,hasEx2,ex2,ex2Pos,ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop); doMacro(finishedEx2,hadEx2,hasEx2,ex2,ex2Pos,ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel);
doMacro(finishedEx3,hadEx3,hasEx3,ex3,ex3Pos,ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop); doMacro(finishedEx3,hadEx3,hasEx3,ex3,ex3Pos,ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel);
doMacro(finishedAlg,hadAlg,hasAlg,alg,algPos,ins->std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop); doMacro(finishedAlg,hadAlg,hasAlg,alg,algPos,ins->std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop,ins->std.algMacroRel);
doMacro(finishedFb,hadFb,hasFb,fb,fbPos,ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop); doMacro(finishedFb,hadFb,hasFb,fb,fbPos,ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop,ins->std.fbMacroRel);
doMacro(finishedFms,hadFms,hasFms,fms,fmsPos,ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop); doMacro(finishedFms,hadFms,hasFms,fms,fmsPos,ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop,ins->std.fmsMacroRel);
doMacro(finishedAms,hadAms,hasAms,ams,amsPos,ins->std.amsMacro,ins->std.amsMacroLen,ins->std.amsMacroLoop); doMacro(finishedAms,hadAms,hasAms,ams,amsPos,ins->std.amsMacro,ins->std.amsMacroLen,ins->std.amsMacroLoop,ins->std.amsMacroRel);
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
DivInstrumentSTD::OpMacro& m=ins->std.opMacros[i]; DivInstrumentSTD::OpMacro& m=ins->std.opMacros[i];
IntOp& o=op[i]; IntOp& o=op[i];
doMacro(o.finishedAm,o.hadAm,o.hasAm,o.am,o.amPos,m.amMacro,m.amMacroLen,m.amMacroLoop); doMacro(o.finishedAm,o.hadAm,o.hasAm,o.am,o.amPos,m.amMacro,m.amMacroLen,m.amMacroLoop,m.amMacroRel);
doMacro(o.finishedAr,o.hadAr,o.hasAr,o.ar,o.arPos,m.arMacro,m.arMacroLen,m.arMacroLoop); doMacro(o.finishedAr,o.hadAr,o.hasAr,o.ar,o.arPos,m.arMacro,m.arMacroLen,m.arMacroLoop,m.arMacroRel);
doMacro(o.finishedDr,o.hadDr,o.hasDr,o.dr,o.drPos,m.drMacro,m.drMacroLen,m.drMacroLoop); doMacro(o.finishedDr,o.hadDr,o.hasDr,o.dr,o.drPos,m.drMacro,m.drMacroLen,m.drMacroLoop,m.drMacroRel);
doMacro(o.finishedMult,o.hadMult,o.hasMult,o.mult,o.multPos,m.multMacro,m.multMacroLen,m.multMacroLoop); doMacro(o.finishedMult,o.hadMult,o.hasMult,o.mult,o.multPos,m.multMacro,m.multMacroLen,m.multMacroLoop,m.multMacroRel);
doMacro(o.finishedRr,o.hadRr,o.hasRr,o.rr,o.rrPos,m.rrMacro,m.rrMacroLen,m.rrMacroLoop); doMacro(o.finishedRr,o.hadRr,o.hasRr,o.rr,o.rrPos,m.rrMacro,m.rrMacroLen,m.rrMacroLoop,m.rrMacroRel);
doMacro(o.finishedSl,o.hadSl,o.hasSl,o.sl,o.slPos,m.slMacro,m.slMacroLen,m.slMacroLoop); doMacro(o.finishedSl,o.hadSl,o.hasSl,o.sl,o.slPos,m.slMacro,m.slMacroLen,m.slMacroLoop,m.slMacroRel);
doMacro(o.finishedTl,o.hadTl,o.hasTl,o.tl,o.tlPos,m.tlMacro,m.tlMacroLen,m.tlMacroLoop); doMacro(o.finishedTl,o.hadTl,o.hasTl,o.tl,o.tlPos,m.tlMacro,m.tlMacroLen,m.tlMacroLoop,m.tlMacroRel);
doMacro(o.finishedDt2,o.hadDt2,o.hasDt2,o.dt2,o.dt2Pos,m.dt2Macro,m.dt2MacroLen,m.dt2MacroLoop); doMacro(o.finishedDt2,o.hadDt2,o.hasDt2,o.dt2,o.dt2Pos,m.dt2Macro,m.dt2MacroLen,m.dt2MacroLoop,m.dt2MacroRel);
doMacro(o.finishedRs,o.hadRs,o.hasRs,o.rs,o.rsPos,m.rsMacro,m.rsMacroLen,m.rsMacroLoop); doMacro(o.finishedRs,o.hadRs,o.hasRs,o.rs,o.rsPos,m.rsMacro,m.rsMacroLen,m.rsMacroLoop,m.rsMacroRel);
doMacro(o.finishedDt,o.hadDt,o.hasDt,o.dt,o.dtPos,m.dtMacro,m.dtMacroLen,m.dtMacroLoop); doMacro(o.finishedDt,o.hadDt,o.hasDt,o.dt,o.dtPos,m.dtMacro,m.dtMacroLen,m.dtMacroLoop,m.dtMacroRel);
doMacro(o.finishedD2r,o.hadD2r,o.hasD2r,o.d2r,o.d2rPos,m.d2rMacro,m.d2rMacroLen,m.d2rMacroLoop); doMacro(o.finishedD2r,o.hadD2r,o.hasD2r,o.d2r,o.d2rPos,m.d2rMacro,m.d2rMacroLen,m.d2rMacroLoop,m.d2rMacroRel);
doMacro(o.finishedSsg,o.hadSsg,o.hasSsg,o.ssg,o.ssgPos,m.ssgMacro,m.ssgMacroLen,m.ssgMacroLoop); doMacro(o.finishedSsg,o.hadSsg,o.hasSsg,o.ssg,o.ssgPos,m.ssgMacro,m.ssgMacroLen,m.ssgMacroLoop,m.ssgMacroRel);
} }
} }
void DivMacroInt::release() {
released=true;
}
void DivMacroInt::init(DivInstrument* which) { void DivMacroInt::init(DivInstrument* which) {
ins=which; ins=which;
volPos=0; volPos=0;
@ -71,6 +78,8 @@ void DivMacroInt::init(DivInstrument* which) {
fmsPos=0; fmsPos=0;
amsPos=0; amsPos=0;
released=false;
hasVol=false; hasVol=false;
hasArp=false; hasArp=false;
hasDuty=false; hasDuty=false;

View file

@ -7,6 +7,7 @@ class DivMacroInt {
DivInstrument* ins; DivInstrument* ins;
int volPos, arpPos, dutyPos, wavePos, pitchPos, ex1Pos, ex2Pos, ex3Pos; int volPos, arpPos, dutyPos, wavePos, pitchPos, ex1Pos, ex2Pos, ex3Pos;
int algPos, fbPos, fmsPos, amsPos; int algPos, fbPos, fmsPos, amsPos;
bool released;
public: public:
int vol; int vol;
int arp; int arp;
@ -80,6 +81,7 @@ class DivMacroInt {
willRr(false), willSl(false), willTl(false), willDt2(false), willRr(false), willSl(false), willTl(false), willDt2(false),
willRs(false), willDt(false), willD2r(false), willSsg(false) {} willRs(false), willDt(false), willD2r(false), willSsg(false) {}
} op[4]; } op[4];
void release();
void next(); void next();
void init(DivInstrument* which); void init(DivInstrument* which);
void notifyInsDeletion(DivInstrument* which); void notifyInsDeletion(DivInstrument* which);
@ -97,6 +99,7 @@ class DivMacroInt {
fbPos(0), fbPos(0),
fmsPos(0), fmsPos(0),
amsPos(0), amsPos(0),
released(false),
vol(0), vol(0),
arp(0), arp(0),
duty(0), duty(0),

View file

@ -25,6 +25,8 @@ const char* notes[12]={
const char* cmdName[DIV_CMD_MAX]={ const char* cmdName[DIV_CMD_MAX]={
"NOTE_ON", "NOTE_ON",
"NOTE_OFF", "NOTE_OFF",
"NOTE_OFF_ENV",
"ENV_RELEASE",
"INSTRUMENT", "INSTRUMENT",
"VOLUME", "VOLUME",
"GET_VOLUME", "GET_VOLUME",
@ -95,6 +97,10 @@ const char* formatNote(unsigned char note, unsigned char octave) {
static char ret[4]; static char ret[4];
if (note==100) { if (note==100) {
return "OFF"; return "OFF";
} else if (note==101) {
return "===";
} else if (note==102) {
return "REL";
} else if (octave==0 && note==0) { } else if (octave==0 && note==0) {
return "---"; return "---";
} }
@ -456,7 +462,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
dispatchCmd(DivCommand(DIV_CMD_INSTRUMENT,i,pat->data[whatRow][2])); dispatchCmd(DivCommand(DIV_CMD_INSTRUMENT,i,pat->data[whatRow][2]));
} }
// note // note
if (pat->data[whatRow][0]==100) { if (pat->data[whatRow][0]==100) { // note off
//chan[i].note=-1; //chan[i].note=-1;
chan[i].keyOn=false; chan[i].keyOn=false;
chan[i].keyOff=true; chan[i].keyOff=true;
@ -477,6 +483,29 @@ void DivEngine::processRow(int i, bool afterDelay) {
chan[i].scheduledSlideReset=true; chan[i].scheduledSlideReset=true;
} }
dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF,i)); dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF,i));
} else if (pat->data[whatRow][0]==101) { // note off + env release
//chan[i].note=-1;
chan[i].keyOn=false;
chan[i].keyOff=true;
if (chan[i].inPorta) {
if (chan[i].stopOnOff) {
chan[i].portaNote=-1;
chan[i].portaSpeed=-1;
chan[i].stopOnOff=false;
}
if (disCont[dispatchOfChan[i]].dispatch->keyOffAffectsPorta(dispatchChanOfChan[i])) {
chan[i].portaNote=-1;
chan[i].portaSpeed=-1;
if (i==2 && sysOfChan[i]==DIV_SYSTEM_SMS) {
chan[i+1].portaNote=-1;
chan[i+1].portaSpeed=-1;
}
}
chan[i].scheduledSlideReset=true;
}
dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF_ENV,i));
} else if (pat->data[whatRow][0]==102) { // env release
dispatchCmd(DivCommand(DIV_CMD_ENV_RELEASE,i));
} else if (!(pat->data[whatRow][0]==0 && pat->data[whatRow][1]==0)) { } else if (!(pat->data[whatRow][0]==0 && pat->data[whatRow][1]==0)) {
chan[i].oldNote=chan[i].note; chan[i].oldNote=chan[i].note;
chan[i].note=pat->data[whatRow][0]+((signed char)pat->data[whatRow][1])*12; chan[i].note=pat->data[whatRow][0]+((signed char)pat->data[whatRow][1])*12;

View file

@ -153,8 +153,12 @@ void FurnaceGUI::bindEngine(DivEngine* eng) {
} }
const char* noteNameNormal(short note, short octave) { const char* noteNameNormal(short note, short octave) {
if (note==100) { if (note==100) { // note cut
return "OFF"; return "OFF";
} else if (note==101) { // note off and envelope release
return "===";
} else if (note==102) { // envelope release only
return "REL";
} else if (octave==0 && note==0) { } else if (octave==0 && note==0) {
return "..."; return "...";
} }
@ -168,6 +172,10 @@ const char* noteNameNormal(short note, short octave) {
const char* FurnaceGUI::noteName(short note, short octave) { const char* FurnaceGUI::noteName(short note, short octave) {
if (note==100) { if (note==100) {
return "OFF"; return "OFF";
} else if (note==101) { // note off and envelope release
return "===";
} else if (note==102) { // envelope release only
return "REL";
} else if (octave==0 && note==0) { } else if (octave==0 && note==0) {
return "..."; return "...";
} }
@ -211,11 +219,12 @@ bool FurnaceGUI::decodeNote(const char* what, short& note, short& octave) {
return false; return false;
} }
void FurnaceGUI::encodeMMLStr(String& target, unsigned char* macro, unsigned char macroLen, signed char macroLoop) { void FurnaceGUI::encodeMMLStr(String& target, unsigned char* macro, unsigned char macroLen, signed char macroLoop, signed char macroRel) {
target=""; target="";
char buf[32]; char buf[32];
for (int i=0; i<macroLen; i++) { for (int i=0; i<macroLen; i++) {
if (i==macroLoop) target+="| "; if (i==macroLoop) target+="| ";
if (i==macroRel) target+="/ ";
if (i==macroLen-1) { if (i==macroLen-1) {
snprintf(buf,31,"%d",macro[i]); snprintf(buf,31,"%d",macro[i]);
} else { } else {
@ -225,11 +234,12 @@ void FurnaceGUI::encodeMMLStr(String& target, unsigned char* macro, unsigned cha
} }
} }
void FurnaceGUI::encodeMMLStr(String& target, int* macro, int macroLen, int macroLoop) { void FurnaceGUI::encodeMMLStr(String& target, int* macro, int macroLen, int macroLoop, int macroRel) {
target=""; target="";
char buf[32]; char buf[32];
for (int i=0; i<macroLen; i++) { for (int i=0; i<macroLen; i++) {
if (i==macroLoop) target+="| "; if (i==macroLoop) target+="| ";
if (i==macroRel) target+="/ ";
if (i==macroLen-1) { if (i==macroLen-1) {
snprintf(buf,31,"%d",macro[i]); snprintf(buf,31,"%d",macro[i]);
} else { } else {
@ -283,7 +293,7 @@ void FurnaceGUI::decodeMMLStrW(String& source, int* macro, int& macroLen, int ma
} }
} }
void FurnaceGUI::decodeMMLStr(String& source, unsigned char* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax) { void FurnaceGUI::decodeMMLStr(String& source, unsigned char* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax, signed char& macroRel) {
int buf=0; int buf=0;
bool hasVal=false; bool hasVal=false;
macroLen=0; macroLen=0;
@ -311,6 +321,11 @@ void FurnaceGUI::decodeMMLStr(String& source, unsigned char* macro, unsigned cha
macroLoop=macroLen; macroLoop=macroLen;
} }
break; break;
case '/':
if (macroRel==-1) {
macroRel=macroLen;
}
break;
} }
if (macroLen>=128) break; if (macroLen>=128) break;
} }
@ -324,7 +339,7 @@ void FurnaceGUI::decodeMMLStr(String& source, unsigned char* macro, unsigned cha
} }
} }
void FurnaceGUI::decodeMMLStr(String& source, int* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax) { void FurnaceGUI::decodeMMLStr(String& source, int* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax, signed char& macroRel) {
int buf=0; int buf=0;
bool negaBuf=false; bool negaBuf=false;
bool hasVal=false; bool hasVal=false;
@ -360,6 +375,11 @@ void FurnaceGUI::decodeMMLStr(String& source, int* macro, unsigned char& macroLe
macroLoop=macroLen; macroLoop=macroLen;
} }
break; break;
case '/':
if (macroRel==-1) {
macroRel=macroLen;
}
break;
} }
if (macroLen>=128) break; if (macroLen>=128) break;
} }
@ -1381,7 +1401,7 @@ const int orderedOps[4]={
#define PARAMETER modified=true; e->notifyInsChange(curIns); #define PARAMETER modified=true; e->notifyInsChange(curIns);
#define NORMAL_MACRO(macro,macroLen,macroLoop,macroMin,macroHeight,macroName,displayName,displayHeight,displayLoop,bitfield,bfVal,drawSlider,sliderVal,sliderLow,macroDispMin,bitOff,macroMode,macroColor,mmlStr,macroAMin,macroAMax) \ #define NORMAL_MACRO(macro,macroLen,macroLoop,macroRel,macroMin,macroHeight,macroName,displayName,displayHeight,displayLoop,bitfield,bfVal,drawSlider,sliderVal,sliderLow,macroDispMin,bitOff,macroMode,macroColor,mmlStr,macroAMin,macroAMax) \
ImGui::TableNextRow(); \ ImGui::TableNextRow(); \
ImGui::TableNextColumn(); \ ImGui::TableNextColumn(); \
ImGui::Text("%s",displayName); \ ImGui::Text("%s",displayName); \
@ -1454,15 +1474,15 @@ const int orderedOps[4]={
} \ } \
ImGui::SetNextItemWidth(availableWidth); \ ImGui::SetNextItemWidth(availableWidth); \
if (ImGui::InputText("##IMacroMML_" macroName,&mmlStr)) { \ if (ImGui::InputText("##IMacroMML_" macroName,&mmlStr)) { \
decodeMMLStr(mmlStr,macro,macroLen,macroLoop,macroAMin,(bitfield)?((1<<macroAMax)-1):macroAMax); \ decodeMMLStr(mmlStr,macro,macroLen,macroLoop,macroAMin,(bitfield)?((1<<macroAMax)-1):macroAMax,macroRel); \
} \ } \
if (!ImGui::IsItemActive()) { \ if (!ImGui::IsItemActive()) { \
encodeMMLStr(mmlStr,macro,macroLen,macroLoop); \ encodeMMLStr(mmlStr,macro,macroLen,macroLoop,macroRel); \
} \ } \
} \ } \
ImGui::PopStyleVar(); ImGui::PopStyleVar();
#define OP_MACRO(macro,macroLen,macroLoop,macroHeight,op,macroName,displayName,displayHeight,displayLoop,bitfield,bfVal,mmlStr) \ #define OP_MACRO(macro,macroLen,macroLoop,macroRel,macroHeight,op,macroName,displayName,displayHeight,displayLoop,bitfield,bfVal,mmlStr) \
ImGui::TableNextRow(); \ ImGui::TableNextRow(); \
ImGui::TableNextColumn(); \ ImGui::TableNextColumn(); \
ImGui::Text("%s",displayName); \ ImGui::Text("%s",displayName); \
@ -1524,10 +1544,10 @@ const int orderedOps[4]={
} \ } \
ImGui::SetNextItemWidth(availableWidth); \ ImGui::SetNextItemWidth(availableWidth); \
if (ImGui::InputText("##IOPMacroMML_" macroName,&mmlStr)) { \ if (ImGui::InputText("##IOPMacroMML_" macroName,&mmlStr)) { \
decodeMMLStr(mmlStr,macro,macroLen,macroLoop,0,bitfield?((1<<macroHeight)-1):(macroHeight)); \ decodeMMLStr(mmlStr,macro,macroLen,macroLoop,0,bitfield?((1<<macroHeight)-1):(macroHeight),macroRel); \
} \ } \
if (!ImGui::IsItemActive()) { \ if (!ImGui::IsItemActive()) { \
encodeMMLStr(mmlStr,macro,macroLen,macroLoop); \ encodeMMLStr(mmlStr,macro,macroLen,macroLoop,macroRel); \
} \ } \
} \ } \
ImGui::PopStyleVar(); ImGui::PopStyleVar();
@ -1651,15 +1671,15 @@ void FurnaceGUI::drawInsEdit() {
} }
if (ImGui::BeginTabItem("Macros (FM)")) { if (ImGui::BeginTabItem("Macros (FM)")) {
MACRO_BEGIN(0); MACRO_BEGIN(0);
NORMAL_MACRO(ins->std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop,0,7,"alg",FM_NAME(FM_ALG),96,ins->std.algMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[0],0,7); NORMAL_MACRO(ins->std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop,ins->std.algMacroRel,0,7,"alg",FM_NAME(FM_ALG),96,ins->std.algMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[0],0,7);
NORMAL_MACRO(ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop,0,7,"fb",FM_NAME(FM_FB),96,ins->std.fbMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[1],0,7); NORMAL_MACRO(ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop,ins->std.fbMacroRel,0,7,"fb",FM_NAME(FM_FB),96,ins->std.fbMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[1],0,7);
NORMAL_MACRO(ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop,0,7,"fms",FM_NAME(FM_FMS),96,ins->std.fmsMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[2],0,7); NORMAL_MACRO(ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop,ins->std.fmsMacroRel,0,7,"fms",FM_NAME(FM_FMS),96,ins->std.fmsMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[2],0,7);
NORMAL_MACRO(ins->std.amsMacro,ins->std.amsMacroLen,ins->std.amsMacroLoop,0,3,"ams",FM_NAME(FM_AMS),48,ins->std.amsMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[3],0,3); NORMAL_MACRO(ins->std.amsMacro,ins->std.amsMacroLen,ins->std.amsMacroLoop,ins->std.amsMacroRel,0,3,"ams",FM_NAME(FM_AMS),48,ins->std.amsMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[3],0,3);
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,0,127,"ex1","AM Depth",128,ins->std.ex1MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,127); NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,127,"ex1","AM Depth",128,ins->std.ex1MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,127);
NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,0,127,"ex2","PM Depth",128,ins->std.ex2MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,127); NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,127,"ex2","PM Depth",128,ins->std.ex2MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,127);
NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,0,255,"ex3","LFO Speed",128,ins->std.ex3MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,255); NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel,0,255,"ex3","LFO Speed",128,ins->std.ex3MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,255);
NORMAL_MACRO(ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,0,3,"wave","LFO Shape",48,ins->std.waveMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_WAVE],mmlString[7],0,3); NORMAL_MACRO(ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,ins->std.waveMacroRel,0,3,"wave","LFO Shape",48,ins->std.waveMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_WAVE],mmlString[7],0,3);
MACRO_END; MACRO_END;
ImGui::EndTabItem(); ImGui::EndTabItem();
} }
@ -1669,18 +1689,18 @@ void FurnaceGUI::drawInsEdit() {
ImGui::PushID(i); ImGui::PushID(i);
MACRO_BEGIN(0); MACRO_BEGIN(0);
int ordi=orderedOps[i]; int ordi=orderedOps[i];
OP_MACRO(ins->std.opMacros[ordi].tlMacro,ins->std.opMacros[ordi].tlMacroLen,ins->std.opMacros[ordi].tlMacroLoop,127,ordi,"tl",FM_NAME(FM_TL),128,ins->std.opMacros[ordi].tlMacroOpen,false,NULL,mmlString[0]); OP_MACRO(ins->std.opMacros[ordi].tlMacro,ins->std.opMacros[ordi].tlMacroLen,ins->std.opMacros[ordi].tlMacroLoop,ins->std.opMacros[ordi].tlMacroRel,127,ordi,"tl",FM_NAME(FM_TL),128,ins->std.opMacros[ordi].tlMacroOpen,false,NULL,mmlString[0]);
OP_MACRO(ins->std.opMacros[ordi].arMacro,ins->std.opMacros[ordi].arMacroLen,ins->std.opMacros[ordi].arMacroLoop,31,ordi,"ar",FM_NAME(FM_AR),64,ins->std.opMacros[ordi].arMacroOpen,false,NULL,mmlString[1]); OP_MACRO(ins->std.opMacros[ordi].arMacro,ins->std.opMacros[ordi].arMacroLen,ins->std.opMacros[ordi].arMacroLoop,ins->std.opMacros[ordi].arMacroRel,31,ordi,"ar",FM_NAME(FM_AR),64,ins->std.opMacros[ordi].arMacroOpen,false,NULL,mmlString[1]);
OP_MACRO(ins->std.opMacros[ordi].drMacro,ins->std.opMacros[ordi].drMacroLen,ins->std.opMacros[ordi].drMacroLoop,31,ordi,"dr",FM_NAME(FM_DR),64,ins->std.opMacros[ordi].drMacroOpen,false,NULL,mmlString[2]); OP_MACRO(ins->std.opMacros[ordi].drMacro,ins->std.opMacros[ordi].drMacroLen,ins->std.opMacros[ordi].drMacroLoop,ins->std.opMacros[ordi].drMacroRel,31,ordi,"dr",FM_NAME(FM_DR),64,ins->std.opMacros[ordi].drMacroOpen,false,NULL,mmlString[2]);
OP_MACRO(ins->std.opMacros[ordi].d2rMacro,ins->std.opMacros[ordi].d2rMacroLen,ins->std.opMacros[ordi].d2rMacroLoop,31,ordi,"d2r",FM_NAME(FM_D2R),64,ins->std.opMacros[ordi].d2rMacroOpen,false,NULL,mmlString[3]); OP_MACRO(ins->std.opMacros[ordi].d2rMacro,ins->std.opMacros[ordi].d2rMacroLen,ins->std.opMacros[ordi].d2rMacroLoop,ins->std.opMacros[ordi].d2rMacroRel,31,ordi,"d2r",FM_NAME(FM_D2R),64,ins->std.opMacros[ordi].d2rMacroOpen,false,NULL,mmlString[3]);
OP_MACRO(ins->std.opMacros[ordi].rrMacro,ins->std.opMacros[ordi].rrMacroLen,ins->std.opMacros[ordi].rrMacroLoop,15,ordi,"rr",FM_NAME(FM_RR),64,ins->std.opMacros[ordi].rrMacroOpen,false,NULL,mmlString[4]); OP_MACRO(ins->std.opMacros[ordi].rrMacro,ins->std.opMacros[ordi].rrMacroLen,ins->std.opMacros[ordi].rrMacroLoop,ins->std.opMacros[ordi].rrMacroRel,15,ordi,"rr",FM_NAME(FM_RR),64,ins->std.opMacros[ordi].rrMacroOpen,false,NULL,mmlString[4]);
OP_MACRO(ins->std.opMacros[ordi].slMacro,ins->std.opMacros[ordi].slMacroLen,ins->std.opMacros[ordi].slMacroLoop,15,ordi,"sl",FM_NAME(FM_SL),64,ins->std.opMacros[ordi].slMacroOpen,false,NULL,mmlString[5]); OP_MACRO(ins->std.opMacros[ordi].slMacro,ins->std.opMacros[ordi].slMacroLen,ins->std.opMacros[ordi].slMacroLoop,ins->std.opMacros[ordi].slMacroRel,15,ordi,"sl",FM_NAME(FM_SL),64,ins->std.opMacros[ordi].slMacroOpen,false,NULL,mmlString[5]);
OP_MACRO(ins->std.opMacros[ordi].rsMacro,ins->std.opMacros[ordi].rsMacroLen,ins->std.opMacros[ordi].rsMacroLoop,3,ordi,"rs",FM_NAME(FM_RS),32,ins->std.opMacros[ordi].rsMacroOpen,false,NULL,mmlString[6]); OP_MACRO(ins->std.opMacros[ordi].rsMacro,ins->std.opMacros[ordi].rsMacroLen,ins->std.opMacros[ordi].rsMacroLoop,ins->std.opMacros[ordi].rsMacroRel,3,ordi,"rs",FM_NAME(FM_RS),32,ins->std.opMacros[ordi].rsMacroOpen,false,NULL,mmlString[6]);
OP_MACRO(ins->std.opMacros[ordi].multMacro,ins->std.opMacros[ordi].multMacroLen,ins->std.opMacros[ordi].multMacroLoop,15,ordi,"mult",FM_NAME(FM_MULT),64,ins->std.opMacros[ordi].multMacroOpen,false,NULL,mmlString[7]); OP_MACRO(ins->std.opMacros[ordi].multMacro,ins->std.opMacros[ordi].multMacroLen,ins->std.opMacros[ordi].multMacroLoop,ins->std.opMacros[ordi].multMacroRel,15,ordi,"mult",FM_NAME(FM_MULT),64,ins->std.opMacros[ordi].multMacroOpen,false,NULL,mmlString[7]);
OP_MACRO(ins->std.opMacros[ordi].dtMacro,ins->std.opMacros[ordi].dtMacroLen,ins->std.opMacros[ordi].dtMacroLoop,7,ordi,"dt",FM_NAME(FM_DT),64,ins->std.opMacros[ordi].dtMacroOpen,false,NULL,mmlString[8]); OP_MACRO(ins->std.opMacros[ordi].dtMacro,ins->std.opMacros[ordi].dtMacroLen,ins->std.opMacros[ordi].dtMacroLoop,ins->std.opMacros[ordi].dtMacroRel,7,ordi,"dt",FM_NAME(FM_DT),64,ins->std.opMacros[ordi].dtMacroOpen,false,NULL,mmlString[8]);
OP_MACRO(ins->std.opMacros[ordi].dt2Macro,ins->std.opMacros[ordi].dt2MacroLen,ins->std.opMacros[ordi].dt2MacroLoop,3,ordi,"dt2",FM_NAME(FM_DT2),32,ins->std.opMacros[ordi].dt2MacroOpen,false,NULL,mmlString[9]); OP_MACRO(ins->std.opMacros[ordi].dt2Macro,ins->std.opMacros[ordi].dt2MacroLen,ins->std.opMacros[ordi].dt2MacroLoop,ins->std.opMacros[ordi].dt2MacroRel,3,ordi,"dt2",FM_NAME(FM_DT2),32,ins->std.opMacros[ordi].dt2MacroOpen,false,NULL,mmlString[9]);
OP_MACRO(ins->std.opMacros[ordi].amMacro,ins->std.opMacros[ordi].amMacroLen,ins->std.opMacros[ordi].amMacroLoop,1,ordi,"am",FM_NAME(FM_AM),32,ins->std.opMacros[ordi].amMacroOpen,true,NULL,mmlString[10]); OP_MACRO(ins->std.opMacros[ordi].amMacro,ins->std.opMacros[ordi].amMacroLen,ins->std.opMacros[ordi].amMacroLoop,ins->std.opMacros[ordi].amMacroRel,1,ordi,"am",FM_NAME(FM_AM),32,ins->std.opMacros[ordi].amMacroOpen,true,NULL,mmlString[10]);
OP_MACRO(ins->std.opMacros[ordi].ssgMacro,ins->std.opMacros[ordi].ssgMacroLen,ins->std.opMacros[ordi].ssgMacroLoop,4,ordi,"ssg",FM_NAME(FM_SSG),64,ins->std.opMacros[ordi].ssgMacroOpen,true,ssgEnvBits,mmlString[11]); OP_MACRO(ins->std.opMacros[ordi].ssgMacro,ins->std.opMacros[ordi].ssgMacroLen,ins->std.opMacros[ordi].ssgMacroLoop,ins->std.opMacros[ordi].ssgMacroRel,4,ordi,"ssg",FM_NAME(FM_SSG),64,ins->std.opMacros[ordi].ssgMacroOpen,true,ssgEnvBits,mmlString[11]);
MACRO_END; MACRO_END;
ImGui::PopID(); ImGui::PopID();
ImGui::EndTabItem(); ImGui::EndTabItem();
@ -1881,41 +1901,41 @@ void FurnaceGUI::drawInsEdit() {
if (settings.macroView==0) { // modern view if (settings.macroView==0) { // modern view
MACRO_BEGIN(28*dpiScale); MACRO_BEGIN(28*dpiScale);
NORMAL_MACRO(ins->std.volMacro,ins->std.volMacroLen,ins->std.volMacroLoop,volMin,volMax,"vol",volumeLabel,160,ins->std.volMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_VOLUME],mmlString[0],volMin,volMax); NORMAL_MACRO(ins->std.volMacro,ins->std.volMacroLen,ins->std.volMacroLoop,ins->std.volMacroRel,volMin,volMax,"vol",volumeLabel,160,ins->std.volMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_VOLUME],mmlString[0],volMin,volMax);
NORMAL_MACRO(ins->std.arpMacro,ins->std.arpMacroLen,ins->std.arpMacroLoop,arpMacroScroll,arpMacroScroll+24,"arp","Arpeggio",160,ins->std.arpMacroOpen,false,NULL,true,&arpMacroScroll,(arpMode?0:-80),0,0,&ins->std.arpMacroMode,uiColors[GUI_COLOR_MACRO_PITCH],mmlString[1],-92,94); NORMAL_MACRO(ins->std.arpMacro,ins->std.arpMacroLen,ins->std.arpMacroLoop,ins->std.arpMacroRel,arpMacroScroll,arpMacroScroll+24,"arp","Arpeggio",160,ins->std.arpMacroOpen,false,NULL,true,&arpMacroScroll,(arpMode?0:-80),0,0,&ins->std.arpMacroMode,uiColors[GUI_COLOR_MACRO_PITCH],mmlString[1],-92,94);
if (dutyMax>0) { if (dutyMax>0) {
NORMAL_MACRO(ins->std.dutyMacro,ins->std.dutyMacroLen,ins->std.dutyMacroLoop,0,dutyMax,"duty",dutyLabel,160,ins->std.dutyMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[2],0,dutyMax); NORMAL_MACRO(ins->std.dutyMacro,ins->std.dutyMacroLen,ins->std.dutyMacroLoop,ins->std.dutyMacroRel,0,dutyMax,"duty",dutyLabel,160,ins->std.dutyMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[2],0,dutyMax);
} }
if (waveMax>0) { if (waveMax>0) {
NORMAL_MACRO(ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,0,waveMax,"wave","Waveform",bitMode?64:160,ins->std.waveMacroOpen,bitMode,waveNames,false,NULL,0,0,((ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930)?1:0),NULL,uiColors[GUI_COLOR_MACRO_WAVE],mmlString[3],0,waveMax); NORMAL_MACRO(ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,ins->std.waveMacroRel,0,waveMax,"wave","Waveform",bitMode?64:160,ins->std.waveMacroOpen,bitMode,waveNames,false,NULL,0,0,((ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930)?1:0),NULL,uiColors[GUI_COLOR_MACRO_WAVE],mmlString[3],0,waveMax);
} }
if (ex1Max>0) { if (ex1Max>0) {
if (ins->type==DIV_INS_C64) { if (ins->type==DIV_INS_C64) {
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,0,ex1Max,"ex1","Filter Mode",64,ins->std.ex1MacroOpen,true,filtModeBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max); NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Filter Mode",64,ins->std.ex1MacroOpen,true,filtModeBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max);
} else if (ins->type==DIV_INS_SAA1099) { } else if (ins->type==DIV_INS_SAA1099) {
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,0,ex1Max,"ex1","Envelope",160,ins->std.ex1MacroOpen,true,saaEnvBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max); NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Envelope",160,ins->std.ex1MacroOpen,true,saaEnvBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max);
} else { } else {
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,0,ex1Max,"ex1","Duty",160,ins->std.ex1MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max); NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Duty",160,ins->std.ex1MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max);
} }
} }
if (ex2Max>0) { if (ex2Max>0) {
if (ins->type==DIV_INS_C64) { if (ins->type==DIV_INS_C64) {
NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,0,ex2Max,"ex2","Resonance",64,ins->std.ex2MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max); NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,ex2Max,"ex2","Resonance",64,ins->std.ex2MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max);
} else { } else {
NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,0,ex2Max,"ex2","Envelope",64,ins->std.ex2MacroOpen,true,ayEnvBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max); NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,ex2Max,"ex2","Envelope",64,ins->std.ex2MacroOpen,true,ayEnvBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max);
} }
} }
if (ins->type==DIV_INS_C64) { if (ins->type==DIV_INS_C64) {
NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,0,2,"ex3","Special",32,ins->std.ex3MacroOpen,true,c64SpecialBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,2); NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel,0,2,"ex3","Special",32,ins->std.ex3MacroOpen,true,c64SpecialBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,2);
} }
if (ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930) { if (ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930) {
NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,0,15,"ex3","AutoEnv Num",96,ins->std.ex3MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,15); NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel,0,15,"ex3","AutoEnv Num",96,ins->std.ex3MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,15);
NORMAL_MACRO(ins->std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop,0,15,"alg","AutoEnv Den",96,ins->std.algMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[7],0,15); NORMAL_MACRO(ins->std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop,ins->std.algMacroRel,0,15,"alg","AutoEnv Den",96,ins->std.algMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[7],0,15);
} }
if (ins->type==DIV_INS_AY8930) { if (ins->type==DIV_INS_AY8930) {
// oh my i am running out of macros // oh my i am running out of macros
NORMAL_MACRO(ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop,0,8,"fb","Noise AND Mask",96,ins->std.fbMacroOpen,true,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[8],0,8); NORMAL_MACRO(ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop,ins->std.fbMacroRel,0,8,"fb","Noise AND Mask",96,ins->std.fbMacroOpen,true,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[8],0,8);
NORMAL_MACRO(ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop,0,8,"fms","Noise OR Mask",96,ins->std.fmsMacroOpen,true,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[9],0,8); NORMAL_MACRO(ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop,ins->std.fmsMacroRel,0,8,"fms","Noise OR Mask",96,ins->std.fmsMacroOpen,true,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[9],0,8);
} }
MACRO_END; MACRO_END;
@ -2295,7 +2315,7 @@ void FurnaceGUI::drawWaveEdit() {
decodeMMLStrW(mmlStringW,wave->data,wave->len,wave->max); decodeMMLStrW(mmlStringW,wave->data,wave->len,wave->max);
} }
if (!ImGui::IsItemActive()) { if (!ImGui::IsItemActive()) {
encodeMMLStr(mmlStringW,wave->data,wave->len,-1); encodeMMLStr(mmlStringW,wave->data,wave->len,-1,-1);
} }
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,ImVec2(0.0f,0.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,ImVec2(0.0f,0.0f));
@ -4443,7 +4463,7 @@ void FurnaceGUI::doTranspose(int amount) {
if (iFine==0) { if (iFine==0) {
int origNote=pat->data[j][0]; int origNote=pat->data[j][0];
int origOctave=(signed char)pat->data[j][1]; int origOctave=(signed char)pat->data[j][1];
if (origNote!=0 && origNote!=100) { if (origNote!=0 && origNote!=100 && origNote!=101 && origNote!=102) {
origNote+=amount; origNote+=amount;
while (origNote>12) { while (origNote>12) {
origNote-=12; origNote-=12;
@ -4759,6 +4779,8 @@ void FurnaceGUI::stopPreviewNote(SDL_Scancode scancode) {
int num=12*curOctave+key; int num=12*curOctave+key;
if (key==100) return; if (key==100) return;
if (key==101) return;
if (key==102) return;
for (size_t i=0; i<activeNotes.size(); i++) { for (size_t i=0; i<activeNotes.size(); i++) {
if (activeNotes[i].note==num) { if (activeNotes[i].note==num) {
@ -4974,6 +4996,12 @@ void FurnaceGUI::keyDown(SDL_Event& ev) {
if (key==100) { // note off if (key==100) { // note off
pat->data[cursor.y][0]=100; pat->data[cursor.y][0]=100;
pat->data[cursor.y][1]=0; pat->data[cursor.y][1]=0;
} else if (key==101) { // note off + env release
pat->data[cursor.y][0]=101;
pat->data[cursor.y][1]=0;
} else if (key==102) { // env release only
pat->data[cursor.y][0]=102;
pat->data[cursor.y][1]=0;
} else { } else {
pat->data[cursor.y][0]=num%12; pat->data[cursor.y][0]=num%12;
pat->data[cursor.y][1]=num/12; pat->data[cursor.y][1]=num/12;
@ -4989,7 +5017,7 @@ void FurnaceGUI::keyDown(SDL_Event& ev) {
editAdvance(); editAdvance();
curNibble=false; curNibble=false;
} else { } else {
if (key!=100) { if (key!=100 && key!=101 && key!=102) {
previewNote(cursor.xCoarse,num); previewNote(cursor.xCoarse,num);
} }
} }
@ -5052,7 +5080,7 @@ void FurnaceGUI::keyDown(SDL_Event& ev) {
try { try {
int key=noteKeys.at(ev.key.keysym.scancode); int key=noteKeys.at(ev.key.keysym.scancode);
int num=12*curOctave+key; int num=12*curOctave+key;
if (key!=100) { if (key!=100 && key!=101 && key!=102) {
previewNote(cursor.xCoarse,num); previewNote(cursor.xCoarse,num);
} }
} catch (std::out_of_range& e) { } catch (std::out_of_range& e) {
@ -5065,7 +5093,7 @@ void FurnaceGUI::keyDown(SDL_Event& ev) {
try { try {
int key=noteKeys.at(ev.key.keysym.scancode); int key=noteKeys.at(ev.key.keysym.scancode);
int num=12*curOctave+key; int num=12*curOctave+key;
if (key!=100) { if (key!=100 && key!=101 && key!=102) {
e->previewSample(curSample,num); e->previewSample(curSample,num);
samplePreviewOn=true; samplePreviewOn=true;
samplePreviewKey=ev.key.keysym.scancode; samplePreviewKey=ev.key.keysym.scancode;
@ -5081,7 +5109,7 @@ void FurnaceGUI::keyDown(SDL_Event& ev) {
try { try {
int key=noteKeys.at(ev.key.keysym.scancode); int key=noteKeys.at(ev.key.keysym.scancode);
int num=12*curOctave+key; int num=12*curOctave+key;
if (key!=100) { if (key!=100 && key!=101 && key!=102) {
e->previewWave(curWave,num); e->previewWave(curWave,num);
wavePreviewOn=true; wavePreviewOn=true;
wavePreviewKey=ev.key.keysym.scancode; wavePreviewKey=ev.key.keysym.scancode;
@ -6777,10 +6805,15 @@ FurnaceGUI::FurnaceGUI():
noteKeys[SDL_SCANCODE_RIGHTBRACKET]=31; noteKeys[SDL_SCANCODE_RIGHTBRACKET]=31;
// note off // note off
noteKeys[SDL_SCANCODE_EQUALS]=100;
noteKeys[SDL_SCANCODE_TAB]=100; noteKeys[SDL_SCANCODE_TAB]=100;
noteKeys[SDL_SCANCODE_1]=100; noteKeys[SDL_SCANCODE_1]=100;
// note off + env release
noteKeys[SDL_SCANCODE_EQUALS]=101;
// env release
noteKeys[SDL_SCANCODE_GRAVE]=102;
// value keys // value keys
valueKeys[SDLK_0]=0; valueKeys[SDLK_0]=0;
valueKeys[SDLK_1]=1; valueKeys[SDLK_1]=1;

View file

@ -401,10 +401,10 @@ class FurnaceGUI {
void applyUISettings(); void applyUISettings();
void encodeMMLStr(String& target, int* macro, int macroLen, int macroLoop); void encodeMMLStr(String& target, int* macro, int macroLen, int macroLoop, int macroRel);
void encodeMMLStr(String& target, unsigned char* macro, unsigned char macroLen, signed char macroLoop); void encodeMMLStr(String& target, unsigned char* macro, unsigned char macroLen, signed char macroLoop, signed char macroRel);
void decodeMMLStr(String& source, unsigned char* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax); void decodeMMLStr(String& source, unsigned char* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax, signed char& macroRel);
void decodeMMLStr(String& source, int* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax); void decodeMMLStr(String& source, int* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax, signed char& macroRel);
void decodeMMLStrW(String& source, int* macro, int& macroLen, int macroMax); void decodeMMLStrW(String& source, int* macro, int& macroLen, int macroMax);
const char* getSystemName(DivSystem which); const char* getSystemName(DivSystem which);