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:
tildearrow 2023-11-03 14:46:23 -05:00
parent 4e48e87313
commit e1cb84a076
5 changed files with 40 additions and 39 deletions

View file

@ -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() {}
}; };

View file

@ -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; \

View file

@ -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.
*/ */

View file

@ -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;

View file

@ -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];