Update ES5506:

Remove transwave for now
- It consumes high CPU usage, so possibly little headroom for anything else.
Fix per-voice OSC via git master
Fix default channel for ES5506
Fix macro order - Filter macro must be executed after key on
Add SSV preset
This commit is contained in:
cam900 2022-10-22 17:19:39 +09:00
parent 683abd8c69
commit 87cb3c49a4
10 changed files with 168 additions and 689 deletions

View file

@ -73,8 +73,6 @@ enum DivDispatchCmds {
DIV_CMD_SAMPLE_BANK, // (bank)
DIV_CMD_SAMPLE_POS, // (pos)
DIV_CMD_SAMPLE_DIR, // (direction)
DIV_CMD_SAMPLE_TRANSWAVE_SLICE_MODE, // (enabled)
DIV_CMD_SAMPLE_TRANSWAVE_SLICE_POS, // (slice)
DIV_CMD_FM_HARD_RESET, // (enabled)
DIV_CMD_FM_LFO, // (speed)

View file

@ -361,65 +361,6 @@ struct DivInstrumentAmiga {
reversed(r) {}
};
struct TransWaveSlice {
// states
double sliceSize;
double sliceBound;
double sliceStart;
double sliceEnd;
// inlines
inline void updateSize(double length, double loopStart, double loopEnd) {
sliceSize=loopEnd-loopStart;
sliceBound=(length-sliceSize);
}
inline double slicePos(double slice) {
double pos=sliceBound*slice;
if (sliceStart!=pos) {
sliceStart=pos;
}
if (sliceEnd!=(sliceSize+pos)) {
sliceEnd=(sliceSize+pos);
}
return pos;
}
TransWaveSlice():
sliceSize(0),
sliceBound(0),
sliceStart(0),
sliceEnd(0) {}
};
struct TransWave: TransWaveSlice {
bool enable;
bool sliceEnable;
int ind;
unsigned short slice;
TransWave():
TransWaveSlice(),
enable(false),
sliceEnable(false),
ind(0),
slice(0) {}
};
struct TransWaveMap: TransWaveSlice {
short ind;
DivReverseMode reversed;
int loopStart, loopEnd;
DivSampleLoopMode loopMode;
TransWaveMap():
TransWaveSlice(),
ind(-1),
reversed(DivInstrumentAmiga::DivReverseMode::DIV_REVERSE_DEFAULT),
loopStart(-1),
loopEnd(-1),
loopMode(DIV_SAMPLE_LOOP_MAX) {}
};
short initSample;
DivInstrumentAmiga::DivReverseMode reversed;
bool useNoteMap;
@ -427,8 +368,6 @@ struct DivInstrumentAmiga {
bool useWave;
unsigned char waveLen;
SampleMap noteMap[120];
TransWave transWave;
std::vector<TransWaveMap> transWaveMap;
/**
* get the sample at specified note.
@ -475,9 +414,7 @@ struct DivInstrumentAmiga {
useNoteMap(false),
useSample(false),
useWave(false),
waveLen(31),
transWave(TransWave()),
transWaveMap(1) {
waveLen(31) {
for (SampleMap& elem: noteMap) {
elem=SampleMap();
}

View file

@ -206,97 +206,6 @@ void DivPlatformES5506::e_pin(bool state) {
}
irqTrigger=false;
}
} else {
unsigned char ch=w.state&0x1f;
if (chan[ch].transwaveIRQ) {
if ((chan[ch].cr&0x37)==0x34) { // IRQE = 1, BLE = 1, LPE = 0, LEI = 1
DivInstrument* ins=parent->getIns(chan[ch].ins);
if (!ins->amiga.useNoteMap && ins->amiga.transWave.enable) {
const int next=chan[ch].pcm.next;
if (next>=0 && next<(int)ins->amiga.transWaveMap.size()) {
DivInstrumentAmiga::TransWaveMap& transWaveInd=ins->amiga.transWaveMap[next];
int sample=transWaveInd.ind;
if (sample>=0 && sample<parent->song.sampleLen) {
const unsigned int offES5506=sampleOffES5506[sample];
chan[ch].pcm.index=sample;
chan[ch].transWave.ind=next;
DivSample* s=parent->getSample(sample);
// get frequency offset
double off=1.0;
double center=(double)s->centerRate;
if (center<1) {
off=1.0;
} else {
off=(double)center/8363.0;
}
// get loop mode, transwave loop
double loopStart=(double)s->loopStart;
double loopEnd=(double)s->loopEnd;
DivSampleLoopMode loopMode=s->isLoopable()?s->loopMode:DIV_SAMPLE_LOOP_MAX;
if (transWaveInd.loopMode!=DIV_SAMPLE_LOOP_MAX) {
loopMode=transWaveInd.loopMode;
} else if ((chan[ch].pcm.loopMode==DIV_SAMPLE_LOOP_MAX) || (!s->isLoopable())) { // default
loopMode=DIV_SAMPLE_LOOP_PINGPONG;
}
// get loop position
loopStart=(double)transWaveInd.loopStart;
loopEnd=(double)transWaveInd.loopEnd;
if (ins->amiga.transWave.sliceEnable) { // sliced loop position?
chan[ch].transWave.updateSize(s->samples,loopStart,loopEnd);
chan[ch].transWave.slicePos(double(chan[ch].transWave.slice)/4095.0);
loopStart=transWaveInd.sliceStart;
loopEnd=transWaveInd.sliceEnd;
}
// get reversed
bool reversed=ins->amiga.reversed;
if (transWaveInd.reversed!=DivInstrumentAmiga::DivReverseMode::DIV_REVERSE_DEFAULT) {
reversed=transWaveInd.reversed;
}
const unsigned int start=offES5506<<10;
const unsigned int length=s->samples-1;
const unsigned int end=start+(length<<11);
const double nextFreqOffs=PITCH_OFFSET*off;
chan[ch].pcm.loopMode=loopMode;
chan[ch].pcm.reversed=reversed;
chan[ch].pcm.bank=(offES5506>>22)&3;
chan[ch].pcm.start=start;
chan[ch].pcm.loopStart=(start+(unsigned int)(loopStart*2048.0))&0xfffff800;
chan[ch].pcm.loopEnd=(start+(unsigned int)((loopEnd-1.0)*2048.0))&0xffffff80;
chan[ch].pcm.end=end;
chan[ch].pcm.length=length;
pageWrite(0x20|ch,0x01,chan[ch].pcm.loopStart);
pageWrite(0x20|ch,0x02,chan[ch].pcm.loopEnd);
pageWrite(0x20|ch,0x03,(chan[ch].pcm.reversed)?chan[ch].pcm.loopEnd:chan[ch].pcm.loopStart);
unsigned int loopFlag=(chan[ch].pcm.bank<<14)|(chan[ch].pcm.reversed?0x0040:0x0000);
chan[ch].isReverseLoop=false;
switch (chan[ch].pcm.loopMode) {
case DIV_SAMPLE_LOOP_FORWARD: // Foward loop
loopFlag|=0x0008;
break;
case DIV_SAMPLE_LOOP_BACKWARD: // Backward loop: IRQ enable
loopFlag|=0x0038;
chan[ch].isReverseLoop=true;
break;
case DIV_SAMPLE_LOOP_PINGPONG: // Pingpong loop: Hardware support
loopFlag|=0x0018;
break;
case DIV_SAMPLE_LOOP_MAX: // no loop
default:
break;
}
// Set loop mode & Bank
pageWriteMask(0x00|ch,0x5f,0x00,loopFlag,0xfcfc);
if (chan[ch].pcm.nextFreqOffs!=nextFreqOffs) {
chan[ch].pcm.nextFreqOffs=nextFreqOffs;
chan[ch].noteChanged.offs=1;
}
}
}
chan[ch].pcmChanged.changed=0;
}
}
chan[ch].transwaveIRQ=false;
}
}
queuedReadState.pop();
}
@ -306,11 +215,6 @@ void DivPlatformES5506::e_pin(bool state) {
pageWriteMask(0x00|ch,0x5f,0x00,(chan[ch].pcm.reversed?0x0000:0x0040)|0x08,0x78);
chan[ch].isReverseLoop=false;
}
if (chan[ch].isTranswave) {
pageReadMask(0x00|ch,0x5f,0x00,ch,&chan[ch].cr);
chan[ch].transwaveIRQ=true;
chan[ch].isTranswave=false;
}
queuedRead.pop();
}
isReaded=false;
@ -504,29 +408,7 @@ void DivPlatformES5506::tick(bool sysTick) {
}
}
}
// transwave macros
if (chan[i].transWave.enable) {
if (chan[i].std.wave.had) {
if (chan[i].std.wave.val>=0 && chan[i].std.wave.val<(int)ins->amiga.transWaveMap.size()) {
if (chan[i].pcm.next!=chan[i].std.wave.val) {
chan[i].pcm.next=chan[i].std.wave.val;
chan[i].pcmChanged.transwaveInd=1;
}
}
}
if (chan[i].std.fb.had) {
if (chan[i].transWave.sliceEnable!=(bool)(chan[i].std.fb.val&1)) {
chan[i].transWave.sliceEnable=chan[i].std.fb.val&1;
chan[i].pcmChanged.slice=1;
}
}
if (chan[i].std.fms.had) {
if (chan[i].transWave.slice!=(unsigned short)(chan[i].std.fms.val&0xfff)) {
chan[i].transWave.slice=chan[i].std.fms.val&0xfff;
chan[i].pcmChanged.slice=1;
}
}
} else if (chan[i].pcm.isNoteMap) {
if (chan[i].pcm.isNoteMap) {
// note map macros
if (chan[i].std.wave.had) {
if (chan[i].std.wave.val>=0 && chan[i].std.wave.val<120) {
@ -536,7 +418,7 @@ void DivPlatformES5506::tick(bool sysTick) {
}
}
}
} else if (!chan[i].transWave.enable && !chan[i].pcm.isNoteMap) {
} else if (!chan[i].pcm.isNoteMap) {
if (chan[i].std.wave.had) {
if (chan[i].std.wave.val>=0 && chan[i].std.wave.val<parent->song.sampleLen) {
if (chan[i].pcm.next!=chan[i].std.wave.val) {
@ -551,13 +433,13 @@ void DivPlatformES5506::tick(bool sysTick) {
if (!isMuted[i]) { // calculate volume (16 bit)
if (chan[i].volChanged.lVol) {
chan[i].resLVol=VOL_SCALE_LOG(chan[i].outVol,chan[i].outLVol,0xffff);
if (!chan[i].keyOn) {
if (!chan[i].keyOn && chan[i].active) {
pageWrite(0x00|i,0x02,chan[i].resLVol);
}
}
if (chan[i].volChanged.rVol) {
chan[i].resRVol=VOL_SCALE_LOG(chan[i].outVol,chan[i].outRVol,0xffff);
if (!chan[i].keyOn) {
if (!chan[i].keyOn && chan[i].active) {
pageWrite(0x00|i,0x04,chan[i].resRVol);
}
}
@ -568,205 +450,125 @@ void DivPlatformES5506::tick(bool sysTick) {
chan[i].volChanged.changed=0;
}
if (chan[i].pcmChanged.changed) {
if (!chan[i].isTranswave) {
if (chan[i].pcmChanged.transwaveInd && (!ins->amiga.useNoteMap && ins->amiga.transWave.enable)) {
const int next=chan[i].pcm.next;
if (next>=0 && next<(int)ins->amiga.transWaveMap.size()) {
DivInstrumentAmiga::TransWaveMap& transWaveInd=ins->amiga.transWaveMap[next];
int sample=transWaveInd.ind;
if (sample>=0 && sample<parent->song.sampleLen) {
if (chan[i].pcm.index!=sample) {
pageWriteMask(0x00|i,0x5f,0x00,0x0034,0x00ff); // Set IRQ
chan[i].isTranswave=true;
} else {
chan[i].transWave.ind=next;
DivSample* s=parent->getSample(sample);
// get loop mode, transwave loop
double loopStart=(double)s->loopStart;
double loopEnd=(double)s->loopEnd;
DivSampleLoopMode loopMode=s->isLoopable()?s->loopMode:DIV_SAMPLE_LOOP_MAX;
if (transWaveInd.loopMode!=DIV_SAMPLE_LOOP_MAX) {
loopMode=transWaveInd.loopMode;
} else if ((chan[i].pcm.loopMode==DIV_SAMPLE_LOOP_MAX) || (!s->isLoopable())) { // default
loopMode=DIV_SAMPLE_LOOP_PINGPONG;
}
// get loop position
loopStart=(double)transWaveInd.loopStart;
loopEnd=(double)transWaveInd.loopEnd;
if (ins->amiga.transWave.sliceEnable) { // sliced loop position?
chan[i].transWave.updateSize(s->samples,loopStart,loopEnd);
chan[i].transWave.slicePos(double(chan[i].transWave.slice)/4095.0);
loopStart=transWaveInd.sliceStart;
loopEnd=transWaveInd.sliceEnd;
}
// get reversed
bool reversed=ins->amiga.reversed;
if (transWaveInd.reversed!=DivInstrumentAmiga::DivReverseMode::DIV_REVERSE_DEFAULT) {
reversed=transWaveInd.reversed;
}
chan[i].pcmChanged.slice=1;
if ((chan[i].pcm.loopMode!=loopMode) || (chan[i].pcm.reversed!=reversed)) {
chan[i].pcm.loopMode=loopMode;
chan[i].pcm.reversed=reversed;
chan[i].pcmChanged.loopBank=1;
}
}
if (chan[i].pcmChanged.index) {
const int next=chan[i].pcm.next;
bool sampleVaild=false;
if (((ins->amiga.useNoteMap) && (next>=0 && next<120)) ||
((!ins->amiga.useNoteMap) && (next>=0 && next<parent->song.sampleLen))) {
DivInstrumentAmiga::SampleMap& noteMapind=ins->amiga.noteMap[next];
int sample=next;
if (ins->amiga.useNoteMap) {
sample=noteMapind.map;
}
if (sample>=0 && sample<parent->song.sampleLen) {
const unsigned int offES5506=sampleOffES5506[sample];
sampleVaild=true;
chan[i].pcm.index=sample;
chan[i].pcm.isNoteMap=ins->amiga.useNoteMap;
DivSample* s=parent->getSample(sample);
// get frequency offset
double off=1.0;
double center=(double)s->centerRate;
if (center<1) {
off=1.0;
} else {
off=(double)center/8363.0;
}
if (ins->amiga.useNoteMap) {
off*=(double)noteMapind.freq/((double)MAX(1,center)*pow(2.0,((double)next-48.0)/12.0));
chan[i].pcm.note=next;
}
// get loop mode
double loopStart=(double)s->loopStart;
double loopEnd=(double)s->loopEnd;
DivSampleLoopMode loopMode=s->isLoopable()?s->loopMode:DIV_SAMPLE_LOOP_MAX;
// get reversed
bool reversed=ins->amiga.reversed;
if (ins->amiga.useNoteMap&&noteMapind.reversed!=DivInstrumentAmiga::DivReverseMode::DIV_REVERSE_DEFAULT) {
reversed=noteMapind.reversed;
}
const unsigned int start=offES5506<<10;
const unsigned int length=s->samples-1;
const unsigned int end=start+(length<<11);
const unsigned int nextBank=(offES5506>>22)&3;
const double nextFreqOffs=PITCH_OFFSET*off;
chan[i].pcm.loopMode=loopMode;
chan[i].pcm.reversed=reversed;
chan[i].pcm.bank=nextBank;
chan[i].pcm.start=start;
chan[i].pcm.end=end;
chan[i].pcm.length=length;
if ((chan[i].pcm.loopMode!=loopMode) || (chan[i].pcm.reversed!=reversed) || (chan[i].pcm.bank!=nextBank)) {
chan[i].pcm.loopMode=loopMode;
chan[i].pcm.reversed=reversed;
chan[i].pcm.bank=nextBank;
chan[i].pcmChanged.loopBank=1;
}
if (chan[i].pcm.nextFreqOffs!=nextFreqOffs) {
chan[i].pcm.nextFreqOffs=nextFreqOffs;
chan[i].noteChanged.offs=1;
}
}
chan[i].pcmChanged.transwaveInd=0;
}
if ((!chan[i].pcmChanged.transwaveInd) && (!chan[i].isTranswave)) {
if (chan[i].pcmChanged.index) {
const int next=chan[i].pcm.next;
bool sampleVaild=false;
if (((ins->amiga.useNoteMap && !ins->amiga.transWave.enable) && (next>=0 && next<120)) ||
((!ins->amiga.useNoteMap && ins->amiga.transWave.enable) && (next>=0 && next<(int)ins->amiga.transWaveMap.size())) ||
((!ins->amiga.useNoteMap && !ins->amiga.transWave.enable) && (next>=0 && next<parent->song.sampleLen))) {
DivInstrumentAmiga::SampleMap& noteMapind=ins->amiga.noteMap[next];
DivInstrumentAmiga::TransWaveMap& transWaveInd=ins->amiga.transWaveMap[next];
int sample=next;
if (ins->amiga.transWave.enable) {
sample=transWaveInd.ind;
} else if (ins->amiga.useNoteMap) {
sample=noteMapind.map;
}
if (sample>=0 && sample<parent->song.sampleLen) {
const unsigned int offES5506=sampleOffES5506[sample];
sampleVaild=true;
chan[i].pcm.index=sample;
chan[i].pcm.isNoteMap=ins->amiga.useNoteMap && !ins->amiga.transWave.enable;
chan[i].transWave.enable=!ins->amiga.useNoteMap && ins->amiga.transWave.enable;
chan[i].transWave.ind=next;
DivSample* s=parent->getSample(sample);
// get frequency offset
double off=1.0;
double center=(double)s->centerRate;
if (center<1) {
off=1.0;
} else {
off=(double)center/8363.0;
}
if (ins->amiga.useNoteMap) {
off*=(double)noteMapind.freq/((double)MAX(1,center)*pow(2.0,((double)next-48.0)/12.0));
chan[i].pcm.note=next;
}
// get loop mode, transwave loop
double loopStart=(double)s->loopStart;
double loopEnd=(double)s->loopEnd;
DivSampleLoopMode loopMode=s->isLoopable()?s->loopMode:DIV_SAMPLE_LOOP_MAX;
if (ins->amiga.transWave.enable) {
if (transWaveInd.loopMode!=DIV_SAMPLE_LOOP_MAX) {
loopMode=transWaveInd.loopMode;
} else if ((chan[i].pcm.loopMode==DIV_SAMPLE_LOOP_MAX) || (!s->isLoopable())) { // default
loopMode=DIV_SAMPLE_LOOP_PINGPONG;
}
// get loop position
loopStart=(double)transWaveInd.loopStart;
loopEnd=(double)transWaveInd.loopEnd;
if (ins->amiga.transWave.sliceEnable) { // sliced loop position?
chan[i].transWave.updateSize(s->samples,loopStart,loopEnd);
chan[i].transWave.slicePos(double(chan[i].transWave.slice)/4095.0);
loopStart=transWaveInd.sliceStart;
loopEnd=transWaveInd.sliceEnd;
}
}
// get reversed
bool reversed=ins->amiga.reversed;
if (ins->amiga.transWave.enable&&transWaveInd.reversed!=DivInstrumentAmiga::DivReverseMode::DIV_REVERSE_DEFAULT) {
reversed=transWaveInd.reversed;
} else if (ins->amiga.useNoteMap&&noteMapind.reversed!=DivInstrumentAmiga::DivReverseMode::DIV_REVERSE_DEFAULT) {
reversed=noteMapind.reversed;
}
const unsigned int start=offES5506<<10;
const unsigned int length=s->samples-1;
const unsigned int end=start+(length<<11);
const unsigned int nextBank=(offES5506>>22)&3;
const double nextFreqOffs=PITCH_OFFSET*off;
chan[i].pcm.loopMode=loopMode;
chan[i].pcm.reversed=reversed;
chan[i].pcm.bank=nextBank;
chan[i].pcm.start=start;
chan[i].pcm.end=end;
chan[i].pcm.length=length;
if ((chan[i].pcm.loopMode!=loopMode) || (chan[i].pcm.reversed!=reversed) || (chan[i].pcm.bank!=nextBank)) {
chan[i].pcm.loopMode=loopMode;
chan[i].pcm.reversed=reversed;
chan[i].pcm.bank=nextBank;
chan[i].pcmChanged.loopBank=1;
}
if (chan[i].pcm.nextFreqOffs!=nextFreqOffs) {
chan[i].pcm.nextFreqOffs=nextFreqOffs;
chan[i].noteChanged.offs=1;
}
}
}
if (sampleVaild) {
if (!chan[i].keyOn) {
pageWrite(0x20|i,0x03,(chan[i].pcm.reversed)?chan[i].pcm.end:chan[i].pcm.start);
}
chan[i].pcmChanged.slice=1;
}
chan[i].pcmChanged.index=0;
if (sampleVaild) {
if (!chan[i].keyOn) {
pageWrite(0x20|i,0x03,(chan[i].pcm.reversed)?chan[i].pcm.end:chan[i].pcm.start);
}
if (chan[i].pcmChanged.slice) {
if (!chan[i].keyOn) {
if (chan[i].pcm.index>=0 && chan[i].pcm.index<parent->song.sampleLen) {
// get loop mode, transwave loop
DivSample* s=parent->getSample(chan[i].pcm.index);
double loopStart=(double)s->loopStart;
double loopEnd=(double)s->loopEnd;
if (ins->amiga.transWave.sliceEnable) { // sliced loop position?
chan[i].transWave.updateSize(s->samples,loopStart,loopEnd);
chan[i].transWave.slicePos(double(chan[i].transWave.slice)/4095.0);
loopStart=chan[i].transWave.sliceStart;
loopEnd=chan[i].transWave.sliceEnd;
}
const unsigned int start=sampleOffES5506[chan[i].pcm.index]<<10;
const unsigned int nextLoopStart=(start+(unsigned int)(loopStart*2048.0))&0xfffff800;
const unsigned int nextLoopEnd=(start+(unsigned int)((loopEnd-1.0)*2048.0))&0xffffff80;
if ((chan[i].pcm.loopStart!=nextLoopStart) || (chan[i].pcm.loopEnd!=nextLoopEnd)) {
chan[i].pcm.loopStart=nextLoopStart;
chan[i].pcm.loopEnd=nextLoopEnd;
chan[i].pcmChanged.position=1;
}
}
}
chan[i].pcmChanged.slice=0;
}
if (chan[i].pcmChanged.position) {
if (!chan[i].keyOn) {
pageWrite(0x20|i,0x01,(chan[i].pcm.loopMode==DIV_SAMPLE_LOOP_MAX)?chan[i].pcm.start:chan[i].pcm.loopStart);
pageWrite(0x20|i,0x02,(chan[i].pcm.loopMode==DIV_SAMPLE_LOOP_MAX)?chan[i].pcm.end:chan[i].pcm.loopEnd);
}
chan[i].pcmChanged.position=0;
}
if (chan[i].pcmChanged.loopBank) {
if (!chan[i].keyOn) {
unsigned int loopFlag=(chan[i].pcm.bank<<14)|(chan[i].pcm.reversed?0x0040:0x0000);
chan[i].isReverseLoop=false;
switch (chan[i].pcm.loopMode) {
case DIV_SAMPLE_LOOP_FORWARD: // Foward loop
loopFlag|=0x0008;
break;
case DIV_SAMPLE_LOOP_BACKWARD: // Backward loop: IRQ enable
loopFlag|=0x0038;
chan[i].isReverseLoop=true;
break;
case DIV_SAMPLE_LOOP_PINGPONG: // Pingpong loop: Hardware support
loopFlag|=0x0018;
break;
case DIV_SAMPLE_LOOP_MAX: // no loop
default:
break;
}
// Set loop mode & Bank
pageWriteMask(0x00|i,0x5f,0x00,loopFlag,0xfcfd);
}
chan[i].pcmChanged.loopBank=0;
}
chan[i].pcmChanged.dummy=0;
chan[i].pcmChanged.slice=1;
}
chan[i].pcmChanged.index=0;
}
if (chan[i].pcmChanged.slice) {
if (!chan[i].keyOn) {
if (chan[i].pcm.index>=0 && chan[i].pcm.index<parent->song.sampleLen) {
// get loop mode
DivSample* s=parent->getSample(chan[i].pcm.index);
double loopStart=(double)s->loopStart;
double loopEnd=(double)s->loopEnd;
const unsigned int start=sampleOffES5506[chan[i].pcm.index]<<10;
const unsigned int nextLoopStart=(start+(unsigned int)(loopStart*2048.0))&0xfffff800;
const unsigned int nextLoopEnd=(start+(unsigned int)((loopEnd-1.0)*2048.0))&0xffffff80;
if ((chan[i].pcm.loopStart!=nextLoopStart) || (chan[i].pcm.loopEnd!=nextLoopEnd)) {
chan[i].pcm.loopStart=nextLoopStart;
chan[i].pcm.loopEnd=nextLoopEnd;
chan[i].pcmChanged.position=1;
}
}
}
chan[i].pcmChanged.slice=0;
}
if (chan[i].pcmChanged.position) {
if (!chan[i].keyOn) {
pageWrite(0x20|i,0x01,(chan[i].pcm.loopMode==DIV_SAMPLE_LOOP_MAX)?chan[i].pcm.start:chan[i].pcm.loopStart);
pageWrite(0x20|i,0x02,(chan[i].pcm.loopMode==DIV_SAMPLE_LOOP_MAX)?chan[i].pcm.end:chan[i].pcm.loopEnd);
}
chan[i].pcmChanged.position=0;
}
if (chan[i].pcmChanged.loopBank) {
if (!chan[i].keyOn) {
unsigned int loopFlag=(chan[i].pcm.bank<<14)|(chan[i].pcm.reversed?0x0040:0x0000);
chan[i].isReverseLoop=false;
switch (chan[i].pcm.loopMode) {
case DIV_SAMPLE_LOOP_FORWARD: // Foward loop
loopFlag|=0x0008;
break;
case DIV_SAMPLE_LOOP_BACKWARD: // Backward loop: IRQ enable
loopFlag|=0x0038;
chan[i].isReverseLoop=true;
break;
case DIV_SAMPLE_LOOP_PINGPONG: // Pingpong loop: Hardware support
loopFlag|=0x0018;
break;
case DIV_SAMPLE_LOOP_MAX: // no loop
default:
break;
}
// Set loop mode & Bank
pageWriteMask(0x00|i,0x5f,0x00,loopFlag,0xfcfd);
}
chan[i].pcmChanged.loopBank=0;
}
chan[i].pcmChanged.dummy=0;
}
if (chan[i].filterChanged.changed) {
if (!chan[i].keyOn) {
@ -843,11 +645,18 @@ void DivPlatformES5506::tick(bool sysTick) {
chan[i].freq=CLAMP(parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].pitch2,chipClock,chan[i].pcm.freqOffs),0,0x1ffff);
if (chan[i].keyOn) {
if (chan[i].pcm.index>=0 && chan[i].pcm.index<parent->song.sampleLen) {
unsigned int startPos=chan[i].pcm.reversed?chan[i].pcm.end:chan[i].pcm.start;
if (chan[i].pcm.nextPos) {
const unsigned int start=chan[i].pcm.start;
const unsigned int end=chan[i].pcm.length;
startPos+=(chan[i].pcm.reversed?(end-chan[i].pcm.nextPos):chan[i].pcm.nextPos)<<11;
chan[i].pcm.nextPos=0;
}
chan[i].k1Prev=0xffff;
chan[i].k2Prev=0xffff;
pageWriteMask(0x00|i,0x5f,0x00,0x0303); // Wipeout CR
pageWrite(0x00|i,0x06,0); // Clear ECOUNT
pageWrite(0x20|i,0x03,chan[i].pcm.reversed?chan[i].pcm.end:chan[i].pcm.start); // Set ACCUM to start address
pageWrite(0x20|i,0x03,startPos); // Set ACCUM to start address
pageWrite(0x00|i,0x07,0xffff); // Set K1 and K2 to 0xffff
pageWrite(0x00|i,0x09,0xffff,~0,(chanMax+1)*4*2); // needs to 4 sample period delay
pageWrite(0x00|i,0x01,chan[i].freq);
@ -910,7 +719,7 @@ void DivPlatformES5506::tick(bool sysTick) {
if (chan[i].keyOff) chan[i].keyOff=false;
chan[i].freqChanged=false;
}
if (!chan[i].keyOn) {
if (!chan[i].keyOn && chan[i].active) {
if (chan[i].k2Prev!=k2) {
pageWrite(0x00|i,0x07,k2);
chan[i].k2Prev=k2;
@ -928,81 +737,18 @@ int DivPlatformES5506::dispatch(DivCommand c) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_ES5506);
bool sampleVaild=false;
if (((ins->amiga.useNoteMap && !ins->amiga.transWave.enable) && (c.value>=0 && c.value<120)) ||
((!ins->amiga.useNoteMap && ins->amiga.transWave.enable) && (ins->amiga.transWave.ind>=0 && ins->amiga.transWave.ind<(int)ins->amiga.transWaveMap.size())) ||
((!ins->amiga.useNoteMap && !ins->amiga.transWave.enable) && (ins->amiga.initSample>=0 && ins->amiga.initSample<parent->song.sampleLen))) {
if (((ins->amiga.useNoteMap) && (c.value>=0 && c.value<120)) ||
((!ins->amiga.useNoteMap) && (ins->amiga.initSample>=0 && ins->amiga.initSample<parent->song.sampleLen))) {
DivInstrumentAmiga::SampleMap& noteMapind=ins->amiga.noteMap[c.value];
DivInstrumentAmiga::TransWaveMap& transWaveInd=ins->amiga.transWaveMap[ins->amiga.transWave.ind];
int sample=ins->amiga.initSample;
if (ins->amiga.transWave.enable) {
sample=transWaveInd.ind;
} else if (ins->amiga.useNoteMap) {
if (ins->amiga.useNoteMap) {
sample=noteMapind.map;
}
if (sample>=0 && sample<parent->song.sampleLen) {
const unsigned int offES5506=sampleOffES5506[sample];
sampleVaild=true;
chan[c.chan].pcm.index=chan[c.chan].pcm.next=sample;
chan[c.chan].pcm.pause=(chan[c.chan].std.alg.will)?(chan[c.chan].std.alg.val&1):false;
chan[c.chan].pcm.isNoteMap=ins->amiga.useNoteMap && !ins->amiga.transWave.enable;
chan[c.chan].transWave.enable=!ins->amiga.useNoteMap && ins->amiga.transWave.enable;
chan[c.chan].transWave.sliceEnable=ins->amiga.transWave.sliceEnable;
chan[c.chan].transWave.ind=ins->amiga.transWave.ind;
DivSample* s=parent->getSample(sample);
// get frequency offset
double off=1.0;
double center=(double)s->centerRate;
if (center<1) {
off=1.0;
} else {
off=(double)center/8363.0;
}
if (ins->amiga.useNoteMap) {
off*=(double)noteMapind.freq/((double)MAX(1,center)*pow(2.0,((double)c.value-48.0)/12.0));
chan[c.chan].pcm.note=c.value;
}
// get loop mode, transwave loop
double loopStart=(double)s->loopStart;
double loopEnd=(double)s->loopEnd;
DivSampleLoopMode loopMode=s->isLoopable()?s->loopMode:DIV_SAMPLE_LOOP_MAX;
if (ins->amiga.transWave.enable) {
if (transWaveInd.loopMode!=DIV_SAMPLE_LOOP_MAX) {
loopMode=transWaveInd.loopMode;
} else if ((chan[c.chan].pcm.loopMode==DIV_SAMPLE_LOOP_MAX) || (!s->isLoopable())) { // default
loopMode=DIV_SAMPLE_LOOP_PINGPONG;
}
// get loop position
loopStart=(double)transWaveInd.loopStart;
loopEnd=(double)transWaveInd.loopEnd;
if (ins->amiga.transWave.sliceEnable) { // sliced loop position?
chan[c.chan].transWave.updateSize(s->samples,loopStart,loopEnd);
chan[c.chan].transWave.slice=ins->amiga.transWave.slice;
chan[c.chan].transWave.slicePos(double(ins->amiga.transWave.slice)/4095.0);
loopStart=transWaveInd.sliceStart;
loopEnd=transWaveInd.sliceEnd;
}
}
// get reversed
bool reversed=ins->amiga.reversed;
if (ins->amiga.transWave.enable&&transWaveInd.reversed!=DivInstrumentAmiga::DivReverseMode::DIV_REVERSE_DEFAULT) {
reversed=transWaveInd.reversed;
} else if (ins->amiga.useNoteMap&&noteMapind.reversed!=DivInstrumentAmiga::DivReverseMode::DIV_REVERSE_DEFAULT) {
reversed=noteMapind.reversed;
}
const unsigned int start=offES5506<<10;
const unsigned int length=s->samples-1;
const unsigned int end=start+(length<<11);
chan[c.chan].pcm.loopMode=loopMode;
chan[c.chan].pcm.freqOffs=PITCH_OFFSET*off;
chan[c.chan].pcm.reversed=reversed;
chan[c.chan].pcm.bank=(offES5506>>22)&3;
chan[c.chan].pcm.start=start;
chan[c.chan].pcm.end=end;
chan[c.chan].pcm.length=length;
chan[c.chan].pcm.loopStart=(start+(unsigned int)(loopStart*2048.0))&0xfffff800;
chan[c.chan].pcm.loopEnd=(start+(unsigned int)((loopEnd-1.0)*2048.0))&0xffffff80;
chan[c.chan].volMacroMax=ins->type==DIV_INS_AMIGA?64:0xffff;
chan[c.chan].panMacroMax=ins->type==DIV_INS_AMIGA?127:0xffff;
chan[c.chan].pcm.next=sample;
chan[c.chan].filter=ins->es5506.filter;
chan[c.chan].envelope=ins->es5506.envelope;
}
@ -1017,6 +763,7 @@ int DivPlatformES5506::dispatch(DivCommand c) {
chan[c.chan].nextNote=chan[c.chan].note;
chan[c.chan].pcm.nextFreqOffs=chan[c.chan].pcm.freqOffs;
chan[c.chan].freqChanged=true;
chan[c.chan].pcmChanged.changed=0xff;
chan[c.chan].noteChanged.changed=0xff;
chan[c.chan].volChanged.changed=0xff;
}
@ -1099,32 +846,15 @@ int DivPlatformES5506::dispatch(DivCommand c) {
if (!chan[c.chan].useWave) {
if (chan[c.chan].active) {
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_ES5506);
if (((ins->amiga.useNoteMap && !ins->amiga.transWave.enable) && (c.value>=0 && c.value<120)) ||
((!ins->amiga.useNoteMap && ins->amiga.transWave.enable) && (c.value>=0 && c.value<(int)ins->amiga.transWaveMap.size())) ||
((!ins->amiga.useNoteMap && !ins->amiga.transWave.enable) && (c.value>=0 && c.value<parent->song.sampleLen))) {
if (((ins->amiga.useNoteMap) && (c.value>=0 && c.value<120)) ||
((!ins->amiga.useNoteMap) && (c.value>=0 && c.value<parent->song.sampleLen))) {
chan[c.chan].pcm.next=c.value;
if (!ins->amiga.useNoteMap && ins->amiga.transWave.enable) {
chan[c.chan].pcmChanged.transwaveInd=1;
} else {
chan[c.chan].pcmChanged.index=1;
}
chan[c.chan].pcmChanged.index=1;
}
}
}
// reserved for useWave
break;
case DIV_CMD_SAMPLE_TRANSWAVE_SLICE_MODE:
if (chan[c.chan].transWave.sliceEnable!=(bool)(c.value&1)) {
chan[c.chan].transWave.sliceEnable=c.value&1;
chan[c.chan].pcmChanged.slice=1;
}
break;
case DIV_CMD_SAMPLE_TRANSWAVE_SLICE_POS:
if (chan[c.chan].transWave.sliceEnable && (chan[c.chan].transWave.slice!=(unsigned short)(c.value&0xfff))) {
chan[c.chan].transWave.slice=c.value&0xfff;
chan[c.chan].pcmChanged.slice=1;
}
break;
// Filter commands
case DIV_CMD_ES5506_FILTER_MODE:
chan[c.chan].filter.mode=DivInstrumentES5506::Filter::FilterMode(c.value&3);
@ -1216,13 +946,17 @@ int DivPlatformES5506::dispatch(DivCommand c) {
case DIV_CMD_SAMPLE_POS: {
if (chan[c.chan].useWave) break;
if (chan[c.chan].active) {
const unsigned int start=chan[c.chan].transWave.enable?chan[c.chan].pcm.loopStart:chan[c.chan].pcm.start;
const unsigned int end=chan[c.chan].transWave.enable?chan[c.chan].pcm.loopEnd:chan[c.chan].pcm.length;
const unsigned int start=chan[c.chan].pcm.start;
const unsigned int end=chan[c.chan].pcm.length;
const unsigned int pos=chan[c.chan].pcm.reversed?(end-c.value):c.value;
if ((chan[c.chan].pcm.reversed && pos>0) || ((!chan[c.chan].pcm.reversed) && pos<end)) {
pageWrite(0x20|c.chan,0x03,start+(pos<<11));
}
break;
} else {
if (chan[c.chan].pcm.nextPos!=0) {
chan[c.chan].pcm.nextPos=c.value;
}
}
break;
}
@ -1284,7 +1018,6 @@ void DivPlatformES5506::reset() {
isMasked=false;
isReaded=false;
irqTrigger=false;
transwaveCh=0;
prevChanCycle=0;
chanMax=initChanMax;
@ -1325,7 +1058,7 @@ void DivPlatformES5506::notifyInsDeletion(void* ins) {
}
void DivPlatformES5506::setFlags(const DivConfig& flags) {
initChanMax=MAX(4,flags.getInt("channels",0)&0x1f);
initChanMax=MAX(4,flags.getInt("channels",0x1f)&0x1f);
chanMax=initChanMax;
pageWriteMask(0x00,0x60,0x0b,chanMax);
}

View file

@ -44,6 +44,7 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
unsigned int length;
unsigned int loopStart;
unsigned int loopEnd;
unsigned int nextPos;
DivSampleLoopMode loopMode;
PCM():
isNoteMap(false),
@ -60,11 +61,12 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
length(0),
loopStart(0),
loopEnd(0),
nextPos(0),
loopMode(DIV_SAMPLE_LOOP_MAX) {}
} pcm;
int freq, baseFreq, nextFreq, pitch, pitch2, note, nextNote, currNote, ins, wave;
unsigned int volMacroMax, panMacroMax;
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, useWave, isReverseLoop, isTranswave, transwaveIRQ;
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, useWave, isReverseLoop;
unsigned int cr;
struct NoteChanged { // Note changed flags
@ -135,8 +137,7 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
unsigned char slice: 1; // transwave slice
unsigned char position: 1; // sample position in memory
unsigned char loopBank: 1; // Loop mode and Bank
unsigned char transwaveInd: 1; // transwave index
unsigned char dummy: 3; // dummy for bit padding
unsigned char dummy: 4; // dummy for bit padding
};
unsigned char changed;
};
@ -151,7 +152,6 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
signed int lOut, rOut, oscOut;
DivInstrumentES5506::Filter filter;
DivInstrumentES5506::Envelope envelope;
DivInstrumentAmiga::TransWave transWave;
DivMacroInt std;
void macroInit(DivInstrument* which) {
std.init(which);
@ -186,8 +186,6 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
inPorta(false),
useWave(false),
isReverseLoop(false),
isTranswave(false),
transwaveIRQ(false),
cr(0),
k1Offs(0),
k2Offs(0),
@ -258,7 +256,6 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
bool isMasked, isReaded;
bool irqTrigger;
unsigned int curCR;
unsigned char transwaveCh;
unsigned char prevChanCycle;
unsigned char initChanMax, chanMax;

View file

@ -74,8 +74,6 @@ const char* cmdName[]={
"SAMPLE_BANK",
"SAMPLE_POS",
"SAMPLE_DIR",
"SAMPLE_TRANSWAVE_SLICE_MODE", // (enabled)
"SAMPLE_TRANSWAVE_SLICE_POS", // (slice)
"FM_HARD_RESET",
"FM_LFO",

View file

@ -1466,13 +1466,19 @@ void DivEngine::registerSystems() {
);
EffectHandlerMap es5506PreEffectHandlerMap={
{0x10, {DIV_CMD_WAVE, "10xx: Change waveform or sample, transwave index (00 to FF)",effectVal}},
{0x10, {DIV_CMD_WAVE, "10xx: Change waveform or sample (00 to FF)",effectVal}}
};
EffectHandlerMap es5506PostEffectHandlerMap={
{0x11, {DIV_CMD_ES5506_FILTER_MODE, "11xx: Set filter mode (00 to 03)",effectValAnd<3>}},
{0x13, {DIV_CMD_SAMPLE_TRANSWAVE_SLICE_MODE, "130x: Set transwave slice mode (bit 0)",effectValAnd<1>}},
{0x12, {DIV_CMD_ES5506_PAUSE, "120x: Set pause (bit 0)",effectValAnd<1>}},
{0x14, {DIV_CMD_ES5506_FILTER_K1, "14xx: Set filter coefficient K1 low byte (00 to FF)",effectValShift<0>,constVal<0x00ff>}},
{0x15, {DIV_CMD_ES5506_FILTER_K1, "15xx: Set filter coefficient K1 high byte (00 to FF)",effectValShift<8>,constVal<0xff00>}},
{0x16, {DIV_CMD_ES5506_FILTER_K2, "16xx: Set filter coefficient K2 low byte (00 to FF)",effectValShift<0>,constVal<0x00ff>}},
{0x17, {DIV_CMD_ES5506_FILTER_K2, "17xx: Set filter coefficient K2 high byte (00 to FF)",effectValShift<8>,constVal<0xff00>}},
{0x18, {DIV_CMD_ES5506_FILTER_K1_SLIDE, "18xx: Set filter coefficient K1 slide up (00 to FF)",effectVal,constVal<0>}},
{0x19, {DIV_CMD_ES5506_FILTER_K1_SLIDE, "19xx: Set filter coefficient K1 slide down (00 to FF)",effectVal,constVal<1>}},
{0x1a, {DIV_CMD_ES5506_FILTER_K2_SLIDE, "1Axx: Set filter coefficient K2 slide up (00 to FF)",effectVal,constVal<0>}},
{0x1b, {DIV_CMD_ES5506_FILTER_K2_SLIDE, "1Bxx: Set filter coefficient K2 slide down (00 to FF)",effectVal,constVal<1>}},
{0x22, {DIV_CMD_ES5506_ENVELOPE_LVRAMP, "22xx: Set envelope left volume ramp (signed) (00 to FF)",effectVal}},
{0x23, {DIV_CMD_ES5506_ENVELOPE_RVRAMP, "23xx: Set envelope right volume ramp (signed) (00 to FF)",effectVal}},
{0x24, {DIV_CMD_ES5506_ENVELOPE_K1RAMP, "24xx: Set envelope filter coefficient k1 ramp (signed) (00 to FF)",effectVal,constVal<0>}},
@ -1480,21 +1486,12 @@ void DivEngine::registerSystems() {
{0x26, {DIV_CMD_ES5506_ENVELOPE_K2RAMP, "26xx: Set envelope filter coefficient k2 ramp (signed) (00 to FF)",effectVal,constVal<0>}},
{0x27, {DIV_CMD_ES5506_ENVELOPE_K2RAMP, "27xx: Set envelope filter coefficient k2 ramp (signed, slower) (00 to FF)",effectVal,constVal<1>}}
};
EffectHandlerMap es5506PostEffectHandlerMap={
{0x12, {DIV_CMD_ES5506_PAUSE, "120x: Set pause (bit 0)",effectValAnd<1>}},
{0x18, {DIV_CMD_ES5506_FILTER_K1_SLIDE, "18xx: Set filter coefficient K1 slide up (00 to FF)",effectVal,constVal<0>}},
{0x19, {DIV_CMD_ES5506_FILTER_K1_SLIDE, "19xx: Set filter coefficient K1 slide down (00 to FF)",effectVal,constVal<1>}},
{0x1a, {DIV_CMD_ES5506_FILTER_K2_SLIDE, "1Axx: Set filter coefficient K2 slide up (00 to FF)",effectVal,constVal<0>}},
{0x1b, {DIV_CMD_ES5506_FILTER_K2_SLIDE, "1Bxx: Set filter coefficient K2 slide down (00 to FF)",effectVal,constVal<1>}},
};
const EffectHandler es5506ECountHandler(DIV_CMD_ES5506_ENVELOPE_COUNT, "2xxx: Set envelope count (000 to 1FF)", effectValLong<9>);
const EffectHandler es5506K1Handler(DIV_CMD_ES5506_FILTER_K1, "3xxx: Set filter coefficient K1 (000 to FFF)", effectValLongShift<12,4>);
const EffectHandler es5506K2Handler(DIV_CMD_ES5506_FILTER_K2, "4xxx: Set filter coefficient K2 (000 to FFF)", effectValLongShift<12,4>);
const EffectHandler transWaveSlicePositionHandler(DIV_CMD_SAMPLE_TRANSWAVE_SLICE_POS, "5xxx: Set transwave slice point (000 to FFF)", effectValLong<12>);
for (int i=0; i<2; i++) es5506PreEffectHandlerMap.emplace(0x20+i,es5506ECountHandler);
for (int i=0; i<16; i++) es5506PreEffectHandlerMap.emplace(0x30+i, es5506K1Handler);
for (int i=0; i<16; i++) es5506PreEffectHandlerMap.emplace(0x40+i, es5506K2Handler);
for (int i=0; i<16; i++) es5506PreEffectHandlerMap.emplace(0x50+i, transWaveSlicePositionHandler);
for (int i=0; i<2; i++) es5506PostEffectHandlerMap.emplace(0x20+i,es5506ECountHandler);
for (int i=0; i<16; i++) es5506PostEffectHandlerMap.emplace(0x30+i, es5506K1Handler);
for (int i=0; i<16; i++) es5506PostEffectHandlerMap.emplace(0x40+i, es5506K2Handler);
// TODO: custom sample format
sysDefs[DIV_SYSTEM_ES5506]=new DivSysDef(

View file

@ -1078,6 +1078,7 @@ void putDispatchChan(void* data, int chanNum, int type) {
ImGui::Text(" - loopStart: %.8x",ch->pcm.loopStart);
ImGui::Text(" - loopEnd: %.8x",ch->pcm.loopEnd);
ImGui::Text(" - loopMode: %d",ch->pcm.loopMode);
ImGui::Text(" - nextPos: %d",ch->pcm.nextPos);
ImGui::Text("* Filter:");
ImGui::Text(" - Mode: %d",ch->filter.mode);
ImGui::Text(" - K1: %.4x",ch->filter.k1);
@ -1122,10 +1123,7 @@ void putDispatchChan(void* data, int chanNum, int type) {
ImGui::TextColored(ch->pcmChanged.slice?colorOn:colorOff,">> PCMSliceChanged");
ImGui::TextColored(ch->pcmChanged.position?colorOn:colorOff,">> PCMPositionChanged");
ImGui::TextColored(ch->pcmChanged.loopBank?colorOn:colorOff,">> PCMLoopBankChanged");
ImGui::TextColored(ch->pcmChanged.transwaveInd?colorOn:colorOff,">> PCMTranswaveIndexChanged");
ImGui::TextColored(ch->isReverseLoop?colorOn:colorOff,">> IsReverseLoop");
ImGui::TextColored(ch->isTranswave?colorOn:colorOff,">> IsTranswave");
ImGui::TextColored(ch->transwaveIRQ?colorOn:colorOff,">> TranswaveIRQ");
ImGui::TextColored(ch->pcm.reversed?colorOn:colorOff,">> PCMReversed");
ImGui::TextColored(ch->envelope.k1Slow?colorOn:colorOff,">> EnvK1Slow");
ImGui::TextColored(ch->envelope.k2Slow?colorOn:colorOff,">> EnvK2Slow");

View file

@ -290,10 +290,6 @@ const char* es5506ControlModes[2]={
"pause", NULL
};
const char* transwaveControlModes[2]={
"slice", NULL
};
const int orderedOps[4]={
0, 2, 1, 3
};
@ -4055,7 +4051,7 @@ void FurnaceGUI::drawInsEdit() {
ImGui::EndDisabled();
// Wavetable
if (ins->type==DIV_INS_AMIGA || ins->type==DIV_INS_SNES) {
ImGui::BeginDisabled(ins->amiga.useNoteMap||ins->amiga.transWave.enable);
ImGui::BeginDisabled(ins->amiga.useNoteMap);
P(ImGui::Checkbox("Use wavetable (Amiga/SNES/Generic DAC only)",&ins->amiga.useWave));
if (ins->amiga.useWave) {
int len=ins->amiga.waveLen+1;
@ -4080,7 +4076,7 @@ void FurnaceGUI::drawInsEdit() {
ImGui::EndDisabled();
}
// Note map
ImGui::BeginDisabled(ins->amiga.useWave||ins->amiga.transWave.enable);
ImGui::BeginDisabled(ins->amiga.useWave);
P(ImGui::Checkbox("Use sample map (does not work yet!)",&ins->amiga.useNoteMap));
if (ins->amiga.useNoteMap) {
// TODO: frequency map?
@ -4151,186 +4147,8 @@ void FurnaceGUI::drawInsEdit() {
}
}
ImGui::EndDisabled();
// Transwave
ImGui::BeginDisabled(ins->amiga.useNoteMap||ins->amiga.useWave||ins->amiga.useNoteMap);
P(ImGui::Checkbox("Use Transwave##UseTransWave",&ins->amiga.transWave.enable));
if (ins->amiga.transWave.enable) {
int size=ins->amiga.transWaveMap.size();
if (ImGui::InputInt("Transwave Map Size##TransWaveSize",&size,1,16)) { PARAMETER
if (size<=ins->amiga.transWave.ind) size=ins->amiga.transWave.ind+1;
if (size<1) size=1;
if (size>256) size=256;
if (ins->amiga.transWaveMap.size()!=(size_t)(size)) {
ins->amiga.transWaveMap.resize(size,DivInstrumentAmiga::TransWaveMap());
if (ins->amiga.transWaveMap.capacity()>(size_t)(size)) {
ins->amiga.transWaveMap.shrink_to_fit();
}
}
}
if (ImGui::InputInt("Initial Transwave Index##TransWaveInit",&ins->amiga.transWave.ind,1,16)) { PARAMETER
if (ins->amiga.transWave.ind<1) ins->amiga.transWave.ind=0;
if (ins->amiga.transWave.ind>=(int)(ins->amiga.transWaveMap.size())) ins->amiga.transWave.ind=ins->amiga.transWaveMap.size()-1;
if (ins->amiga.transWave.sliceEnable) {
DivInstrumentAmiga::TransWaveMap ind=ins->amiga.transWaveMap[ins->amiga.transWave.ind];
if (ind.ind>=0 && ind.ind<(short)(e->song.sampleLen)) {
DivSample* s=e->song.sample[ind.ind];
ins->amiga.transWave.updateSize(s->samples,ind.loopStart,ind.loopEnd);
ins->amiga.transWave.slicePos((double)(ins->amiga.transWave.slice)/4095.0);
}
}
}
if (ImGui::Checkbox("Use Transwave Slice##UseTransWaveSlice",&ins->amiga.transWave.sliceEnable)) { PARAMETER
if (ins->amiga.transWave.sliceEnable) {
ins->amiga.transWave.slicePos((double)(ins->amiga.transWave.slice)/4095.0);
if (ins->amiga.transWave.sliceEnable) {
DivInstrumentAmiga::TransWaveMap ind=ins->amiga.transWaveMap[ins->amiga.transWave.ind];
if (ind.ind>=0 && ind.ind<(short)(e->song.sampleLen)) {
DivSample* s=e->song.sample[ind.ind];
ins->amiga.transWave.updateSize(s->samples,ind.loopStart,ind.loopEnd);
ins->amiga.transWave.slicePos((double)(ins->amiga.transWave.slice)/4095.0);
}
}
}
}
DivInstrumentAmiga::TransWaveMap ind=ins->amiga.transWaveMap[ins->amiga.transWave.ind];
if (ins->amiga.transWave.sliceEnable && (ind.ind>=0 && ind.ind<e->song.sampleLen)) {
ins->amiga.transWave.slicePos((double)(ins->amiga.transWave.slice)/4095.0);
double sliceStart=ins->amiga.transWave.sliceStart;
double sliceEnd=ins->amiga.transWave.sliceEnd;
if (CWSliderScalar("Initial Transwave Slice##TransWaveSliceInit",ImGuiDataType_U16,&ins->amiga.transWave.slice,&_ZERO,&_FOUR_THOUSAND_NINETY_FIVE,fmt::sprintf("%d: %.6f - %.6f",ins->amiga.transWave.slice,sliceStart,sliceEnd).c_str())) { PARAMETER
ins->amiga.transWave.slicePos((double)(ins->amiga.transWave.slice)/4095.0);
} rightClickable
}
if (ImGui::BeginTable("TransWaveMap",6,ImGuiTableFlags_ScrollY|ImGuiTableFlags_Borders|ImGuiTableFlags_SizingStretchSame)) {
ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); // Number
ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch); // Sample index
ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch); // Loop start
ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthStretch); // Loop end
ImGui::TableSetupColumn("c4",ImGuiTableColumnFlags_WidthStretch); // Loop mode
ImGui::TableSetupColumn("c5",ImGuiTableColumnFlags_WidthStretch); // Reversed
ImGui::TableSetupScrollFreeze(0,1);
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
ImGui::TableNextColumn();
ImGui::TableNextColumn();
ImGui::Text("Sample");
ImGui::TableNextColumn();
ImGui::Text("Loop Start");
ImGui::TableNextColumn();
ImGui::Text("Loop End");
ImGui::TableNextColumn();
ImGui::Text("Loop Mode");
ImGui::TableNextColumn();
ImGui::Text("Reversed");
for (size_t i=0; i<ins->amiga.transWaveMap.size(); i++) {
DivInstrumentAmiga::TransWaveMap& transWaveMap=ins->amiga.transWaveMap[i];
ImGui::TableNextRow();
ImGui::PushID(fmt::sprintf("TransWaveMap_%d",i).c_str());
ImGui::TableNextColumn();
ImGui::Text("%d",(int)(i));
ImGui::TableNextColumn();
if (transWaveMap.ind<0 || transWaveMap.ind>=e->song.sampleLen) {
sName="-- empty --";
transWaveMap.ind=-1;
} else {
sName=e->song.sample[transWaveMap.ind]->name;
}
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::BeginCombo(fmt::sprintf("##TransWaveMap_Index_%d",i).c_str(),sName.c_str())) {
String id;
if (ImGui::Selectable("-- empty --",transWaveMap.ind==-1)) { PARAMETER
transWaveMap.ind=-1;
}
for (int j=0; j<e->song.sampleLen; j++) {
DivSample* s=e->song.sample[j];
id=fmt::sprintf("%d: %s",j,s->name);
if (ImGui::Selectable(id.c_str(),transWaveMap.ind==j)) { PARAMETER
transWaveMap.ind=j;
if (transWaveMap.loopStart<0 || transWaveMap.loopStart>(int)(s->samples)) {
transWaveMap.loopStart=CLAMP(s->loopStart,0,(int)s->samples);
}
if (transWaveMap.loopEnd<0 || transWaveMap.loopEnd>(int)(s->samples)) {
transWaveMap.loopEnd=CLAMP(s->loopEnd,0,(int)s->samples);
}
transWaveMap.updateSize(s->samples,transWaveMap.loopStart,transWaveMap.loopEnd);
if (ins->amiga.transWave.sliceEnable && (int)i==ins->amiga.transWave.ind) {
ins->amiga.transWave.updateSize(s->samples,transWaveMap.loopStart,transWaveMap.loopEnd);
ins->amiga.transWave.slicePos((double)(ins->amiga.transWave.slice)/4095.0);
}
}
}
ImGui::EndCombo();
}
ImGui::BeginDisabled(transWaveMap.ind<0 || transWaveMap.ind>=e->song.sampleLen);
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::InputInt(fmt::sprintf("##TransWaveMap_LoopStart_%d",i).c_str(),&transWaveMap.loopStart,256,4096)) { PARAMETER
if (transWaveMap.ind>=0 && transWaveMap.ind<e->song.sampleLen) {
DivSample* s=e->song.sample[transWaveMap.ind];
if (transWaveMap.loopStart<0) transWaveMap.loopStart=0;
if (transWaveMap.loopStart>transWaveMap.loopEnd) transWaveMap.loopStart=transWaveMap.loopEnd;
transWaveMap.updateSize(s->samples,transWaveMap.loopStart,transWaveMap.loopEnd);
if (ins->amiga.transWave.sliceEnable && (int)i==ins->amiga.transWave.ind) {
ins->amiga.transWave.updateSize(s->samples,transWaveMap.loopStart,transWaveMap.loopEnd);
ins->amiga.transWave.slicePos((double)(ins->amiga.transWave.slice)/4095.0);
}
}
}
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::InputInt(fmt::sprintf("##TransWaveMap_LoopEnd_%d",i).c_str(),&transWaveMap.loopEnd,256,4096)) { PARAMETER
if (transWaveMap.ind>=0 && transWaveMap.ind<e->song.sampleLen) {
DivSample* s=e->song.sample[transWaveMap.ind];
if (transWaveMap.loopEnd<transWaveMap.loopStart) transWaveMap.loopEnd=transWaveMap.loopStart;
if (transWaveMap.loopEnd>(int)(s->samples)) transWaveMap.loopEnd=s->samples;
transWaveMap.updateSize(s->samples,transWaveMap.loopStart,transWaveMap.loopEnd);
if (ins->amiga.transWave.sliceEnable) {
ins->amiga.transWave.updateSize(s->samples,transWaveMap.loopStart,transWaveMap.loopEnd);
ins->amiga.transWave.slicePos((double)(ins->amiga.transWave.slice)/4095.0);
}
}
}
ImGui::TableNextColumn();
if (ImGui::RadioButton(fmt::sprintf("Forward##TransWaveMap_LoopMode_Forward_%d",i).c_str(),transWaveMap.loopMode==DIV_SAMPLE_LOOP_FORWARD)) { MARK_MODIFIED
transWaveMap.loopMode=DIV_SAMPLE_LOOP_FORWARD;
}
if (ImGui::RadioButton(fmt::sprintf("Backward##TransWaveMap_LoopMode_Backward_%d",i).c_str(),transWaveMap.loopMode==DIV_SAMPLE_LOOP_BACKWARD)) { MARK_MODIFIED
transWaveMap.loopMode=DIV_SAMPLE_LOOP_BACKWARD;
}
if (ImGui::RadioButton(fmt::sprintf("Pingpong##TransWaveMap_LoopMode_Pingpong_%d",i).c_str(),transWaveMap.loopMode==DIV_SAMPLE_LOOP_PINGPONG)) { MARK_MODIFIED
transWaveMap.loopMode=DIV_SAMPLE_LOOP_PINGPONG;
}
if (ImGui::RadioButton(fmt::sprintf("Use sample setting##TransWaveMap_LoopMode_Default_%d",i).c_str(),transWaveMap.loopMode==DIV_SAMPLE_LOOP_MAX)) { MARK_MODIFIED
transWaveMap.loopMode=DIV_SAMPLE_LOOP_MAX;
}
ImGui::TableNextColumn();
if (ImGui::RadioButton(fmt::sprintf("Disable##TransWaveMap_Reversed_Disable_%d",i).c_str(),transWaveMap.reversed==DivInstrumentAmiga::DivReverseMode::DIV_REVERSE_DISABLE)) { MARK_MODIFIED
transWaveMap.reversed=DivInstrumentAmiga::DivReverseMode::DIV_REVERSE_DISABLE;
}
if (ImGui::RadioButton(fmt::sprintf("Enable##TransWaveMap_Reversed_Enable_%d",i).c_str(),transWaveMap.reversed==DivInstrumentAmiga::DivReverseMode::DIV_REVERSE_ENABLE)) { MARK_MODIFIED
transWaveMap.reversed=DivInstrumentAmiga::DivReverseMode::DIV_REVERSE_ENABLE;
}
if (ImGui::RadioButton(fmt::sprintf("Use instrument setting##TransWaveMap_Reversed_Default_%d",i).c_str(),transWaveMap.reversed==DivInstrumentAmiga::DivReverseMode::DIV_REVERSE_DEFAULT)) { MARK_MODIFIED
transWaveMap.reversed=DivInstrumentAmiga::DivReverseMode::DIV_REVERSE_DEFAULT;
}
ImGui::EndDisabled();
ImGui::PopID();
}
ImGui::EndTable();
}
}
ImGui::EndDisabled();
ImGui::EndTabItem();
}
if (ins->amiga.transWave.enable) {
if (ImGui::BeginTabItem("Transwave Macros")) {
macroList.push_back(FurnaceGUIMacroDesc("Transwave control",&ins->std.fbMacro,0,1,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true,transwaveControlModes));
macroList.push_back(FurnaceGUIMacroDesc("Transwave slice",&ins->std.fmsMacro,0,4095,160,uiColors[GUI_COLOR_MACRO_OTHER]));
drawMacros(macroList);
ImGui::EndTabItem();
}
}
}
if (ins->type==DIV_INS_N163) if (ImGui::BeginTabItem(settings.c163Name.c_str())) {
if (ImGui::InputInt("Waveform##WAVE",&ins->n163.wave,1,10)) { PARAMETER
@ -4987,10 +4805,7 @@ void FurnaceGUI::drawInsEdit() {
if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS || ins->type==DIV_INS_OPZ || ins->type==DIV_INS_OPM) waveMax=0;
if (ins->type==DIV_INS_MIKEY) waveMax=0;
if ((ins->type==DIV_INS_AMIGA && !ins->amiga.useWave) || ins->type==DIV_INS_ES5506) {
if (ins->amiga.transWave.enable) {
waveLabel="Transwave index";
waveMax=MAX(0,(int)(ins->amiga.transWaveMap.size())-1);
} else if (!ins->amiga.useWave) {
if (!ins->amiga.useWave) {
waveLabel="Sample index";
waveMax=ins->amiga.useNoteMap?120:MAX(0,(int)(e->song.sampleLen)-1);
} else {

View file

@ -2168,6 +2168,12 @@ void FurnaceGUI::initSystemPresets() {
0
}
));
cat.systems.push_back(FurnaceGUISysDef(
"Sammy/Seta/Visco SSV", {
DIV_SYSTEM_ES5506, 64, 0, 31,
0
}
));
cat.systems.push_back(FurnaceGUISysDef(
"Cave 68000", {
DIV_SYSTEM_YMZ280B, 64, 0, 0,

View file

@ -785,7 +785,7 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
break;
}
case DIV_SYSTEM_ES5506: {
int channels=flags.getInt("channels",0)+1;
int channels=flags.getInt("channels",0x1f)+1;
ImGui::Text("Initial channel limit:");
if (CWSliderInt("##OTTO_InitialChannelLimit",&channels,5,32)) {
if (channels<5) channels=5;