mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-26 22:43:01 +00:00
volume handling refactor, part 1 - BEWARE
do not use these versions for production. your modules will break until this is finished! only Amiga is done for now
This commit is contained in:
parent
4e48e87313
commit
e1cb84a076
5 changed files with 40 additions and 39 deletions
|
@ -31,7 +31,7 @@ template<typename T> struct SharedChannel {
|
||||||
int freq, baseFreq, baseNoteOverride, pitch, pitch2, arpOff;
|
int freq, baseFreq, baseNoteOverride, pitch, pitch2, arpOff;
|
||||||
int ins, note;
|
int ins, note;
|
||||||
bool active, insChanged, freqChanged, fixedArp, keyOn, keyOff, portaPause, inPorta, volChanged;
|
bool active, insChanged, freqChanged, fixedArp, keyOn, keyOff, portaPause, inPorta, volChanged;
|
||||||
T vol, outVol;
|
T vol, macroVol, outVol, maxVol;
|
||||||
DivMacroInt std;
|
DivMacroInt std;
|
||||||
void handleArp(int offset=0) {
|
void handleArp(int offset=0) {
|
||||||
if (std.arp.had) {
|
if (std.arp.had) {
|
||||||
|
@ -61,6 +61,19 @@ template<typename T> struct SharedChannel {
|
||||||
arpOff=0;
|
arpOff=0;
|
||||||
baseNoteOverride=0;
|
baseNoteOverride=0;
|
||||||
fixedArp=false;
|
fixedArp=false;
|
||||||
|
if (active && !std.brokenOutVol()) {
|
||||||
|
if (which==NULL) {
|
||||||
|
if (macroVol!=maxVol) {
|
||||||
|
macroVol=maxVol;
|
||||||
|
volChanged=true;
|
||||||
|
}
|
||||||
|
} else if (which->std.volMacro.len==0) {
|
||||||
|
if (macroVol!=maxVol) {
|
||||||
|
macroVol=maxVol;
|
||||||
|
volChanged=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SharedChannel(T initVol):
|
SharedChannel(T initVol):
|
||||||
freq(0),
|
freq(0),
|
||||||
|
@ -79,9 +92,11 @@ template<typename T> struct SharedChannel {
|
||||||
keyOff(false),
|
keyOff(false),
|
||||||
portaPause(false),
|
portaPause(false),
|
||||||
inPorta(false),
|
inPorta(false),
|
||||||
volChanged(false),
|
volChanged(true),
|
||||||
vol(initVol),
|
vol(initVol),
|
||||||
|
macroVol(initVol),
|
||||||
outVol(initVol),
|
outVol(initVol),
|
||||||
|
maxVol(initVol),
|
||||||
std() {}
|
std() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,6 @@ void DivMacroStruct::prepare(DivInstrumentMacro& source, DivEngine* e) {
|
||||||
mode=source.mode;
|
mode=source.mode;
|
||||||
type=(source.open>>1)&3;
|
type=(source.open>>1)&3;
|
||||||
activeRelease=source.open&8;
|
activeRelease=source.open&8;
|
||||||
linger=(source.macroType==DIV_MACRO_VOL && e->song.volMacroLinger);
|
|
||||||
lfoPos=LFO_PHASE;
|
lfoPos=LFO_PHASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +63,7 @@ void DivMacroStruct::doMacro(DivInstrumentMacro& source, bool released, bool tic
|
||||||
}
|
}
|
||||||
if (delay>0) {
|
if (delay>0) {
|
||||||
delay--;
|
delay--;
|
||||||
if (!linger) had=false;
|
had=false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (began && source.delay>0) {
|
if (began && source.delay>0) {
|
||||||
|
@ -98,8 +97,6 @@ void DivMacroStruct::doMacro(DivInstrumentMacro& source, bool released, bool tic
|
||||||
if (pos>=source.len) {
|
if (pos>=source.len) {
|
||||||
if (source.loop<source.len && (source.loop>=source.rel || source.rel>=source.len)) {
|
if (source.loop<source.len && (source.loop>=source.rel || source.rel>=source.len)) {
|
||||||
pos=source.loop;
|
pos=source.loop;
|
||||||
} else if (linger) {
|
|
||||||
pos--;
|
|
||||||
} else {
|
} else {
|
||||||
has=false;
|
has=false;
|
||||||
}
|
}
|
||||||
|
@ -140,7 +137,7 @@ void DivMacroStruct::doMacro(DivInstrumentMacro& source, bool released, bool tic
|
||||||
break;
|
break;
|
||||||
case 4: // end
|
case 4: // end
|
||||||
pos=0;
|
pos=0;
|
||||||
if (!linger) has=false;
|
has=false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
val=ADSR_LOW+((pos+(ADSR_HIGH-ADSR_LOW)*pos)>>8);
|
val=ADSR_LOW+((pos+(ADSR_HIGH-ADSR_LOW)*pos)>>8);
|
||||||
|
@ -253,6 +250,11 @@ void DivMacroInt::setEngine(DivEngine* eng) {
|
||||||
e=eng;
|
e=eng;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DivMacroInt::brokenOutVol() {
|
||||||
|
if (e==NULL) return false;
|
||||||
|
return e->song.brokenOutVol;
|
||||||
|
}
|
||||||
|
|
||||||
#define ADD_MACRO(m,s) \
|
#define ADD_MACRO(m,s) \
|
||||||
if (!m.masked) { \
|
if (!m.masked) { \
|
||||||
macroList[macroListLen]=&m; \
|
macroList[macroListLen]=&m; \
|
||||||
|
|
|
@ -27,14 +27,13 @@ class DivEngine;
|
||||||
struct DivMacroStruct {
|
struct DivMacroStruct {
|
||||||
int pos, lastPos, lfoPos, delay;
|
int pos, lastPos, lfoPos, delay;
|
||||||
int val;
|
int val;
|
||||||
bool has, had, actualHad, finished, will, linger, began, masked, activeRelease;
|
bool has, had, actualHad, finished, will, began, masked, activeRelease;
|
||||||
unsigned int mode, type;
|
unsigned int mode, type;
|
||||||
unsigned char macroType;
|
unsigned char macroType;
|
||||||
void doMacro(DivInstrumentMacro& source, bool released, bool tick);
|
void doMacro(DivInstrumentMacro& source, bool released, bool tick);
|
||||||
void init() {
|
void init() {
|
||||||
pos=lastPos=lfoPos=mode=type=delay=0;
|
pos=lastPos=lfoPos=mode=type=delay=0;
|
||||||
has=had=actualHad=will=false;
|
has=had=actualHad=will=false;
|
||||||
linger=false;
|
|
||||||
began=true;
|
began=true;
|
||||||
// TODO: test whether this breaks anything?
|
// TODO: test whether this breaks anything?
|
||||||
val=0;
|
val=0;
|
||||||
|
@ -51,7 +50,6 @@ struct DivMacroStruct {
|
||||||
actualHad(false),
|
actualHad(false),
|
||||||
finished(false),
|
finished(false),
|
||||||
will(false),
|
will(false),
|
||||||
linger(false),
|
|
||||||
began(true),
|
began(true),
|
||||||
masked(false),
|
masked(false),
|
||||||
activeRelease(false),
|
activeRelease(false),
|
||||||
|
@ -109,6 +107,12 @@ class DivMacroInt {
|
||||||
// state
|
// state
|
||||||
bool hasRelease;
|
bool hasRelease;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get whether brokenOutVol is enabled.
|
||||||
|
* @return the value of brokenOutVol, or false if not bound to an engine.
|
||||||
|
*/
|
||||||
|
bool brokenOutVol();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set mask on macro.
|
* set mask on macro.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -68,17 +68,6 @@ const char** DivPlatformAmiga::getRegisterSheet() {
|
||||||
return regCheatSheetAmiga;
|
return regCheatSheetAmiga;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define writeAudDat(x) \
|
|
||||||
chan[i].audDat=x; \
|
|
||||||
if (i<3 && chan[i].useV) { \
|
|
||||||
chan[i+1].outVol=(unsigned char)chan[i].audDat^0x80; \
|
|
||||||
if (chan[i+1].outVol>64) chan[i+1].outVol=64; \
|
|
||||||
} \
|
|
||||||
if (i<3 && chan[i].useP) { \
|
|
||||||
chan[i+1].freq=(unsigned char)chan[i].audDat^0x80; \
|
|
||||||
if (chan[i+1].freq<AMIGA_DIVIDER) chan[i+1].freq=AMIGA_DIVIDER; \
|
|
||||||
}
|
|
||||||
|
|
||||||
void DivPlatformAmiga::acquire(short** buf, size_t len) {
|
void DivPlatformAmiga::acquire(short** buf, size_t len) {
|
||||||
thread_local int outL, outR, output;
|
thread_local int outL, outR, output;
|
||||||
for (size_t h=0; h<len; h++) {
|
for (size_t h=0; h<len; h++) {
|
||||||
|
@ -359,8 +348,8 @@ void DivPlatformAmiga::tick(bool sysTick) {
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
chan[i].std.next();
|
chan[i].std.next();
|
||||||
if (chan[i].std.vol.had) {
|
if (chan[i].std.vol.had) {
|
||||||
chan[i].outVol=((chan[i].vol%65)*MIN(64,chan[i].std.vol.val))>>6;
|
chan[i].macroVol=chan[i].std.vol.val;
|
||||||
chan[i].writeVol=true;
|
chan[i].volChanged=true;
|
||||||
}
|
}
|
||||||
double off=1.0;
|
double off=1.0;
|
||||||
if (!chan[i].useWave && chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen) {
|
if (!chan[i].useWave && chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen) {
|
||||||
|
@ -516,8 +505,9 @@ void DivPlatformAmiga::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
if (chan[i].writeVol) {
|
if (chan[i].volChanged) {
|
||||||
chan[i].writeVol=false;
|
chan[i].outVol=((chan[i].vol%65)*MIN(64,chan[i].macroVol))>>6;
|
||||||
|
chan[i].volChanged=false;
|
||||||
chWrite(i,8,chan[i].outVol);
|
chWrite(i,8,chan[i].outVol);
|
||||||
}
|
}
|
||||||
if (chan[i].updateWave) {
|
if (chan[i].updateWave) {
|
||||||
|
@ -585,10 +575,6 @@ int DivPlatformAmiga::dispatch(DivCommand c) {
|
||||||
chan[c.chan].active=true;
|
chan[c.chan].active=true;
|
||||||
chan[c.chan].keyOn=true;
|
chan[c.chan].keyOn=true;
|
||||||
chan[c.chan].macroInit(ins);
|
chan[c.chan].macroInit(ins);
|
||||||
if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) {
|
|
||||||
chan[c.chan].outVol=chan[c.chan].vol;
|
|
||||||
chan[c.chan].writeVol=true;
|
|
||||||
}
|
|
||||||
if (chan[c.chan].useWave) {
|
if (chan[c.chan].useWave) {
|
||||||
chan[c.chan].ws.init(ins,chan[c.chan].audLen<<1,255,chan[c.chan].insChanged);
|
chan[c.chan].ws.init(ins,chan[c.chan].audLen<<1,255,chan[c.chan].insChanged);
|
||||||
chan[c.chan].updateWave=true;
|
chan[c.chan].updateWave=true;
|
||||||
|
@ -615,17 +601,12 @@ int DivPlatformAmiga::dispatch(DivCommand c) {
|
||||||
case DIV_CMD_VOLUME:
|
case DIV_CMD_VOLUME:
|
||||||
if (chan[c.chan].vol!=c.value) {
|
if (chan[c.chan].vol!=c.value) {
|
||||||
chan[c.chan].vol=c.value;
|
chan[c.chan].vol=c.value;
|
||||||
if (!chan[c.chan].std.vol.has) {
|
if (!parent->song.volMacroLinger) chan[c.chan].macroVol=chan[c.chan].maxVol;
|
||||||
chan[c.chan].outVol=c.value;
|
chan[c.chan].volChanged=true;
|
||||||
chan[c.chan].writeVol=true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_GET_VOLUME:
|
case DIV_CMD_GET_VOLUME:
|
||||||
if (chan[c.chan].std.vol.has) {
|
return chan[c.chan].vol;
|
||||||
return chan[c.chan].vol;
|
|
||||||
}
|
|
||||||
return chan[c.chan].outVol;
|
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_PITCH:
|
case DIV_CMD_PITCH:
|
||||||
chan[c.chan].pitch=c.value;
|
chan[c.chan].pitch=c.value;
|
||||||
|
|
|
@ -30,7 +30,7 @@ class DivPlatformAmiga: public DivDispatch {
|
||||||
int audSub;
|
int audSub;
|
||||||
unsigned char volPos;
|
unsigned char volPos;
|
||||||
int sample, wave;
|
int sample, wave;
|
||||||
bool useWave, setPos, useV, useP, dmaOn, audDatClock, writeVol, updateWave;
|
bool useWave, setPos, useV, useP, dmaOn, audDatClock, updateWave;
|
||||||
DivWaveSynth ws;
|
DivWaveSynth ws;
|
||||||
Channel():
|
Channel():
|
||||||
SharedChannel<signed char>(64),
|
SharedChannel<signed char>(64),
|
||||||
|
@ -49,7 +49,6 @@ class DivPlatformAmiga: public DivDispatch {
|
||||||
useP(false),
|
useP(false),
|
||||||
dmaOn(false),
|
dmaOn(false),
|
||||||
audDatClock(false),
|
audDatClock(false),
|
||||||
writeVol(true),
|
|
||||||
updateWave(true) {}
|
updateWave(true) {}
|
||||||
};
|
};
|
||||||
Channel chan[4];
|
Channel chan[4];
|
||||||
|
|
Loading…
Reference in a new issue