mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-23 13:05:11 +00:00
ES5506: Amiga pitch option......
This commit is contained in:
parent
de935c3aac
commit
6d8a343ead
7 changed files with 233 additions and 77 deletions
|
@ -39,17 +39,11 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) {
|
|||
try {
|
||||
DivSong ds;
|
||||
ds.version=DIV_VERSION_XM;
|
||||
//ds.linearPitch=0;
|
||||
//ds.pitchMacroIsLinear=false;
|
||||
ds.noSlidesOnFirstTick=true;
|
||||
ds.rowResetsArpPos=true;
|
||||
ds.ignoreJumpAtEnd=false;
|
||||
ds.pitchSlideSpeed=4;
|
||||
|
||||
ds.system[0]=DIV_SYSTEM_ES5506;
|
||||
ds.systemFlags[0].set("amigaVol",true);
|
||||
ds.systemLen=1;
|
||||
|
||||
logV("Impulse Tracker module");
|
||||
|
||||
// load here
|
||||
|
@ -81,6 +75,12 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) {
|
|||
unsigned short flags=reader.readS();
|
||||
unsigned short special=reader.readS();
|
||||
|
||||
if (flags&8) {
|
||||
ds.linearPitch=2;
|
||||
} else {
|
||||
ds.linearPitch=0;
|
||||
}
|
||||
|
||||
unsigned char globalVol=reader.readC();
|
||||
unsigned char masterVol=reader.readC();
|
||||
unsigned char initSpeed=reader.readC();
|
||||
|
@ -399,6 +399,7 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) {
|
|||
}
|
||||
|
||||
// read patterns
|
||||
int maxChan=0;
|
||||
for (int i=0; i<patCount; i++) {
|
||||
unsigned char mask[64];
|
||||
unsigned char note[64];
|
||||
|
@ -449,6 +450,8 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) {
|
|||
}
|
||||
chan&=63;
|
||||
|
||||
if (chan>maxChan) maxChan=chan;
|
||||
|
||||
if (mask[chan]&1) {
|
||||
note[chan]=reader.readC();
|
||||
hasNote=true;
|
||||
|
@ -510,8 +513,14 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) {
|
|||
}
|
||||
}
|
||||
|
||||
logV("DAMN IT: %x",insPtr[0]);
|
||||
logV("DAMN IT: %x",samplePtr[0]);
|
||||
for (int i=0; i<(maxChan+32)>>5; i++) {
|
||||
ds.system[i]=DIV_SYSTEM_ES5506;
|
||||
ds.systemFlags[i].set("amigaVol",true);
|
||||
if (ds.linearPitch!=2) {
|
||||
ds.systemFlags[i].set("amigaPitch",true);
|
||||
}
|
||||
}
|
||||
ds.systemLen=(maxChan+32)>>5;
|
||||
|
||||
if (active) quitDispatch();
|
||||
BUSY_BEGIN_SOFT;
|
||||
|
|
|
@ -67,8 +67,6 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
|
|||
bool doesVolSlide[32];
|
||||
bool doesArp[32];
|
||||
|
||||
bool mustCommitPanning=true;
|
||||
|
||||
memset(doesPitchSlide,0,32*sizeof(bool));
|
||||
memset(doesVibrato,0,32*sizeof(bool));
|
||||
memset(doesPanning,0,32*sizeof(bool));
|
||||
|
@ -78,8 +76,8 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
|
|||
try {
|
||||
DivSong ds;
|
||||
ds.version=DIV_VERSION_S3M;
|
||||
//ds.linearPitch=0;
|
||||
//ds.pitchMacroIsLinear=false;
|
||||
ds.linearPitch=0;
|
||||
ds.pitchMacroIsLinear=false;
|
||||
ds.noSlidesOnFirstTick=true;
|
||||
ds.rowResetsArpPos=true;
|
||||
ds.ignoreJumpAtEnd=false;
|
||||
|
@ -167,8 +165,6 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
|
|||
reader.readC(); // UC
|
||||
unsigned char defaultPan=(unsigned char)reader.readC();
|
||||
|
||||
mustCommitPanning=masterVol&128;
|
||||
|
||||
logV("defaultPan: %d",defaultPan);
|
||||
|
||||
reader.readS(); // reserved
|
||||
|
@ -251,16 +247,16 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
|
|||
if (hasFM && hasPCM) break;
|
||||
}
|
||||
|
||||
logV("numChans: %d",numChans);
|
||||
|
||||
ds.systemName="PC";
|
||||
// would use ES5506 but it has log volume
|
||||
if (hasPCM) {
|
||||
for (int i=0; i<numChans; i++) {
|
||||
ds.system[ds.systemLen]=DIV_SYSTEM_PCM_DAC;
|
||||
ds.systemVol[ds.systemLen]=(float)globalVol/256.0;
|
||||
ds.systemPan[ds.systemLen]=0;
|
||||
ds.systemFlags[ds.systemLen].set("volMax",64);
|
||||
ds.systemLen++;
|
||||
}
|
||||
ds.system[ds.systemLen]=DIV_SYSTEM_ES5506;
|
||||
ds.systemVol[ds.systemLen]=(float)globalVol/256.0;
|
||||
ds.systemPan[ds.systemLen]=0;
|
||||
ds.systemFlags[ds.systemLen].set("amigaVol",true);
|
||||
ds.systemFlags[ds.systemLen].set("amigaPitch",true);
|
||||
ds.systemLen++;
|
||||
}
|
||||
if (hasFM) {
|
||||
ds.system[ds.systemLen]=DIV_SYSTEM_OPL2;
|
||||
|
@ -285,7 +281,7 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
|
|||
reader.read(magic,4);
|
||||
|
||||
if (memcmp(magic,"SCRS",4)==0) {
|
||||
ins->type=DIV_INS_AMIGA;
|
||||
ins->type=DIV_INS_ES5506;
|
||||
} else if (memcmp(magic,"SCRI",4)==0) {
|
||||
ins->type=DIV_INS_OPL;
|
||||
} else {
|
||||
|
@ -305,7 +301,7 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
|
|||
|
||||
unsigned char type=reader.readC();
|
||||
|
||||
if (ins->type==DIV_INS_AMIGA) {
|
||||
if (ins->type==DIV_INS_ES5506) {
|
||||
if (type>1) {
|
||||
logE("invalid instrument type! %d",type);
|
||||
lastError="invalid instrument!";
|
||||
|
@ -325,7 +321,7 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
|
|||
|
||||
String dosName=reader.readString(12);
|
||||
|
||||
if (ins->type==DIV_INS_AMIGA) {
|
||||
if (ins->type==DIV_INS_ES5506) {
|
||||
unsigned int memSeg=0;
|
||||
memSeg=(unsigned char)reader.readC();
|
||||
memSeg|=((unsigned short)reader.readS())<<8;
|
||||
|
@ -491,6 +487,77 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
|
|||
}
|
||||
ds.sampleLen=ds.sample.size();
|
||||
|
||||
// scan pattern data for effect use
|
||||
for (int i=0; i<patCount; i++) {
|
||||
logV("scanning pattern %d...",i);
|
||||
if (!reader.seek(patPtr[i],SEEK_SET)) {
|
||||
logE("premature end of file!");
|
||||
lastError="incomplete file";
|
||||
ds.unload();
|
||||
delete[] file;
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned short dataLen=reader.readS();
|
||||
unsigned int dataEnd=reader.tell()+dataLen;
|
||||
|
||||
while (reader.tell()<dataEnd) {
|
||||
unsigned char what=reader.readC();
|
||||
|
||||
if (what==0) {
|
||||
curRow++;
|
||||
if (curRow>=64) break;
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned char chan=what&31;
|
||||
bool hasNoteIns=what&32;
|
||||
bool hasVol=what&64;
|
||||
bool hasEffect=what&128;
|
||||
|
||||
if (hasNoteIns) {
|
||||
reader.readC();
|
||||
reader.readC();
|
||||
}
|
||||
if (hasVol) {
|
||||
reader.readC();
|
||||
}
|
||||
if (hasEffect) {
|
||||
unsigned char effect=reader.readC();
|
||||
reader.readC(); // effect val
|
||||
|
||||
switch (effect+'A'-1) {
|
||||
case 'D': // vol slide
|
||||
doesVolSlide[chan]=true;
|
||||
break;
|
||||
case 'E': // pitch down
|
||||
doesPitchSlide[chan]=true;
|
||||
break;
|
||||
case 'F': // pitch up
|
||||
doesPitchSlide[chan]=true;
|
||||
break;
|
||||
case 'G': // porta
|
||||
doesPitchSlide[chan]=true;
|
||||
break;
|
||||
case 'H': // vibrato
|
||||
doesVibrato[chan]=true;
|
||||
break;
|
||||
case 'J': // arp
|
||||
doesArp[chan]=true;
|
||||
break;
|
||||
case 'K': // vol slide + vibrato
|
||||
doesVolSlide[chan]=true;
|
||||
doesVibrato[chan]=true;
|
||||
break;
|
||||
case 'L': // vol slide + porta
|
||||
doesVolSlide[chan]=true;
|
||||
doesPitchSlide[chan]=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// load pattern data
|
||||
for (int i=0; i<patCount; i++) {
|
||||
unsigned char effectCol[32];
|
||||
|
@ -609,27 +676,11 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
|
|||
p->data[curRow][effectCol[j]++]=0;
|
||||
}
|
||||
|
||||
// TEMPORARY: shall be moved to the end after subsong copying.
|
||||
if (j<16) {
|
||||
if (mustCommitPanning && i==ds.subsong[0]->orders.ord[j][0]) {
|
||||
p->data[curRow][effectCol[j]++]=0x80;
|
||||
if (chanPan[j]&16) {
|
||||
p->data[curRow][effectCol[j]++]=(j&1)?0xcc:0x33;
|
||||
} else {
|
||||
p->data[curRow][effectCol[j]++]=(chanPan[j]&15)|((chanPan[j]&15)<<4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((effectCol[j]>>1)-2>ds.subsong[0]->pat[j].effectCols) {
|
||||
ds.subsong[0]->pat[j].effectCols=(effectCol[j]>>1)-1;
|
||||
}
|
||||
}
|
||||
|
||||
if (i==ds.subsong[0]->orders.ord[0][0]) {
|
||||
mustCommitPanning=false;
|
||||
}
|
||||
|
||||
curRow++;
|
||||
memset(effectCol,4,32);
|
||||
memcpy(vibingOld,vibing,32*sizeof(bool));
|
||||
|
@ -821,17 +872,38 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// copy patterns to the rest of subsongs
|
||||
for (size_t i=1; i<ds.subsong.size(); i++) {
|
||||
for (int j=0; j<DIV_MAX_CHANS; j++) {
|
||||
for (int k=0; k<patCount; k++) {
|
||||
if (ds.subsong[0]->pat[j].data[k]) ds.subsong[0]->pat[j].data[k]->copyOn(ds.subsong[i]->pat[j].getPattern(k,true));
|
||||
}
|
||||
ds.subsong[i]->pat[j].effectCols=ds.subsong[0]->pat[j].effectCols;
|
||||
// copy patterns to the rest of subsongs
|
||||
for (size_t i=1; i<ds.subsong.size(); i++) {
|
||||
for (int j=0; j<DIV_MAX_CHANS; j++) {
|
||||
for (int k=0; k<patCount; k++) {
|
||||
if (ds.subsong[0]->pat[j].data[k]) ds.subsong[0]->pat[j].data[k]->copyOn(ds.subsong[i]->pat[j].getPattern(k,true));
|
||||
}
|
||||
ds.subsong[i]->pat[j].effectCols=ds.subsong[0]->pat[j].effectCols;
|
||||
}
|
||||
ds.subsong[i]->speeds=ds.subsong[0]->speeds;
|
||||
ds.subsong[i]->hz=ds.subsong[0]->hz;
|
||||
}
|
||||
|
||||
// populate subsongs with default panning values
|
||||
if (masterVol&128) { // only in stereo mode
|
||||
for (size_t i=0; i<ds.subsong.size(); i++) {
|
||||
for (int j=0; j<16; j++) {
|
||||
DivPattern* p=ds.subsong[i]->pat[j].getPattern(ds.subsong[i]->orders.ord[j][0],true);
|
||||
for (int k=0; k<DIV_MAX_EFFECTS; k++) {
|
||||
if (p->data[0][4+(k<<1)]==-1) {
|
||||
p->data[0][4+(k<<1)]=0x80;
|
||||
if (chanPan[j]&16) {
|
||||
p->data[0][5+(k<<1)]=(j&1)?0xcc:0x33;
|
||||
} else {
|
||||
p->data[0][5+(k<<1)]=(chanPan[j]&15)|((chanPan[j]&15)<<4);
|
||||
}
|
||||
if (ds.subsong[i]->pat[j].effectCols<=k) ds.subsong[i]->pat[j].effectCols=k+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ds.subsong[i]->speeds=ds.subsong[0]->speeds;
|
||||
ds.subsong[i]->hz=ds.subsong[0]->hz;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -103,6 +103,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
|
|||
for (int i=0; i<(totalChans+31)>>5; i++) {
|
||||
ds.system[i]=DIV_SYSTEM_ES5506;
|
||||
ds.systemFlags[i].set("amigaVol",true);
|
||||
ds.systemFlags[i].set("amigaPitch",(ds.linearPitch==0));
|
||||
}
|
||||
ds.systemLen=(totalChans+31)>>5;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <math.h>
|
||||
|
||||
#define PITCH_OFFSET ((double)(16*2048*(chanMax+1)))
|
||||
#define NOTE_ES5506(c,note) (parent->calcBaseFreq(chipClock,chan[c].pcm.freqOffs,note,false))
|
||||
#define NOTE_ES5506(c,note) ((amigaPitch && parent->song.linearPitch!=2)?parent->calcBaseFreq(COLOR_NTSC,chan[c].pcm.freqOffs,note,true):parent->calcBaseFreq(chipClock,chan[c].pcm.freqOffs,note,false))
|
||||
|
||||
#define rWrite(a,...) {if(!skipRegisterWrites) {hostIntf32.push_back(QueuedHostIntf(4,(a),__VA_ARGS__)); }}
|
||||
#define immWrite(a,...) {hostIntf32.push_back(QueuedHostIntf(4,(a),__VA_ARGS__));}
|
||||
|
@ -183,7 +183,7 @@ void DivPlatformES5506::irqb(bool state) {
|
|||
|
||||
// modified GUSVolumeTable from Impulse Tracker (SoundDrivers/GUS.INC)
|
||||
static const short amigaVolTable[65]={
|
||||
0x400, 0x8FF, 0x9FF, 0xA80,
|
||||
0x000, 0x8FF, 0x9FF, 0xA80,
|
||||
0xAFF, 0xB40, 0xB80, 0xBC0,
|
||||
0xBFF, 0xC20, 0xC40, 0xC60,
|
||||
0xC80, 0xCA0, 0xCC0, 0xCE0,
|
||||
|
@ -202,6 +202,26 @@ static const short amigaVolTable[65]={
|
|||
0xEFF
|
||||
};
|
||||
|
||||
// same thing
|
||||
static const short amigaPanTable[128]={
|
||||
0x000, 0x8FF, 0x9FF, 0xA80, 0xAFF, 0xB40, 0xB80, 0xBC0,
|
||||
0xBFF, 0xC20, 0xC40, 0xC60, 0xC80, 0xCA0, 0xCC0, 0xCE0,
|
||||
0xCFF, 0xD10, 0xD20, 0xD30, 0xD40, 0xD50, 0xD60, 0xD70,
|
||||
0xD80, 0xD90, 0xDA0, 0xDB0, 0xDC0, 0xDD0, 0xDE0, 0xDF0,
|
||||
0xDFF, 0xE08, 0xE10, 0xE18, 0xE20, 0xE28, 0xE30, 0xE38,
|
||||
0xE40, 0xE48, 0xE50, 0xE58, 0xE60, 0xE68, 0xE70, 0xE78,
|
||||
0xE80, 0xE88, 0xE90, 0xE98, 0xEA0, 0xEA8, 0xEB0, 0xEB8,
|
||||
0xEC0, 0xEC8, 0xED0, 0xED8, 0xEE0, 0xEE8, 0xEF0, 0xEF8,
|
||||
0xEFF, 0xF04, 0xF08, 0xF0C, 0xF10, 0xF14, 0xF18, 0xF1C,
|
||||
0xF20, 0xF24, 0xF28, 0xF2C, 0xF30, 0xF34, 0xF38, 0xF3C,
|
||||
0xF40, 0xF44, 0xF48, 0xF4C, 0xF50, 0xF54, 0xF58, 0xF5C,
|
||||
0xF60, 0xF64, 0xF68, 0xF6C, 0xF70, 0xF74, 0xF78, 0xF7C,
|
||||
0xF80, 0xF84, 0xF88, 0xF8C, 0xF90, 0xF94, 0xF98, 0xF9C,
|
||||
0xFA0, 0xFA4, 0xFA8, 0xFAC, 0xFB0, 0xFB4, 0xFB8, 0xFBC,
|
||||
0xFC0, 0xFC4, 0xFC8, 0xFCC, 0xFD0, 0xFD4, 0xFD8, 0xFDC,
|
||||
0xFE0, 0xFE4, 0xFE8, 0xFEC, 0xFF0, 0xFF4, 0xFF8, 0xFFF
|
||||
};
|
||||
|
||||
void DivPlatformES5506::tick(bool sysTick) {
|
||||
for (int i=0; i<=chanMax; i++) {
|
||||
chan[i].std.next();
|
||||
|
@ -453,7 +473,7 @@ void DivPlatformES5506::tick(bool sysTick) {
|
|||
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;
|
||||
const double nextFreqOffs=((amigaPitch && parent->song.linearPitch!=2)?16:PITCH_OFFSET)*off;
|
||||
chan[i].pcm.loopMode=loopMode;
|
||||
chan[i].pcm.bank=nextBank;
|
||||
chan[i].pcm.start=start;
|
||||
|
@ -616,7 +636,12 @@ void DivPlatformES5506::tick(bool sysTick) {
|
|||
chan[i].pcm.nextPos=0;
|
||||
}
|
||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||
chan[i].freq=CLAMP(parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,2,chan[i].pitch2,chipClock,chan[i].pcm.freqOffs),0,0x1ffff);
|
||||
if (amigaPitch && parent->song.linearPitch!=2) {
|
||||
chan[i].freq=CLAMP(parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,true,2,chan[i].pitch2,COLOR_NTSC,chan[i].pcm.freqOffs),1,0xffff);
|
||||
chan[i].freq=32768*(COLOR_NTSC/chan[i].freq)/(chipClock/32.0);
|
||||
} else {
|
||||
chan[i].freq=CLAMP(parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,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) {
|
||||
const int ind=chan[i].pcm.index;
|
||||
|
@ -631,7 +656,7 @@ void DivPlatformES5506::tick(bool sysTick) {
|
|||
}
|
||||
chan[i].pcm.loopStart=(chan[i].pcm.start+(s->loopStart<<11))&0xfffff800;
|
||||
chan[i].pcm.loopEnd=(chan[i].pcm.start+((s->loopEnd)<<11))&0xffffff80;
|
||||
chan[i].pcm.freqOffs=PITCH_OFFSET*off;
|
||||
chan[i].pcm.freqOffs=((amigaPitch && parent->song.linearPitch!=2)?16:PITCH_OFFSET)*off;
|
||||
unsigned int startPos=chan[i].pcm.direction?chan[i].pcm.end:chan[i].pcm.start;
|
||||
if (chan[i].pcm.nextPos) {
|
||||
const unsigned int start=chan[i].pcm.start;
|
||||
|
@ -817,11 +842,20 @@ int DivPlatformES5506::dispatch(DivCommand c) {
|
|||
chan[c.chan].outVol=(0xfff*chan[c.chan].vol)/0xff;
|
||||
}
|
||||
}
|
||||
if (!chan[c.chan].std.panL.will) {
|
||||
chan[c.chan].outLVol=(0xfff*chan[c.chan].lVol)/0xff;
|
||||
}
|
||||
if (!chan[c.chan].std.panR.will) {
|
||||
chan[c.chan].outRVol=(0xfff*chan[c.chan].rVol)/0xff;
|
||||
if (amigaVol) {
|
||||
if (!chan[c.chan].std.panL.will) {
|
||||
chan[c.chan].outLVol=amigaPanTable[(chan[c.chan].lVol>>1)&127];
|
||||
}
|
||||
if (!chan[c.chan].std.panR.will) {
|
||||
chan[c.chan].outRVol=amigaPanTable[(chan[c.chan].rVol>>1)&127];
|
||||
}
|
||||
} else {
|
||||
if (!chan[c.chan].std.panL.will) {
|
||||
chan[c.chan].outLVol=(0xfff*chan[c.chan].lVol)/0xff;
|
||||
}
|
||||
if (!chan[c.chan].std.panR.will) {
|
||||
chan[c.chan].outRVol=(0xfff*chan[c.chan].rVol)/0xff;
|
||||
}
|
||||
}
|
||||
chan[c.chan].active=true;
|
||||
chan[c.chan].keyOn=true;
|
||||
|
@ -865,20 +899,39 @@ int DivPlatformES5506::dispatch(DivCommand c) {
|
|||
chan[c.chan].ca=0;
|
||||
chan[c.chan].volChanged.ca=1;
|
||||
}
|
||||
// Left volume
|
||||
if (chan[c.chan].lVol!=c.value) {
|
||||
chan[c.chan].lVol=c.value;
|
||||
if (!chan[c.chan].std.panL.has) {
|
||||
chan[c.chan].outLVol=(0xfff*c.value)/0xff;
|
||||
chan[c.chan].volChanged.lVol=1;
|
||||
if (amigaVol) {
|
||||
// Left volume
|
||||
if (chan[c.chan].lVol!=c.value) {
|
||||
chan[c.chan].lVol=c.value;
|
||||
if (!chan[c.chan].std.panL.has) {
|
||||
chan[c.chan].outLVol=amigaPanTable[(c.value>>1)&127];
|
||||
chan[c.chan].volChanged.lVol=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Right volume
|
||||
if (chan[c.chan].rVol!=c.value2) {
|
||||
chan[c.chan].rVol=c.value2;
|
||||
if (!chan[c.chan].std.panR.has) {
|
||||
chan[c.chan].outRVol=(0xfff*c.value2)/0xff;
|
||||
chan[c.chan].volChanged.rVol=1;
|
||||
// Right volume
|
||||
if (chan[c.chan].rVol!=c.value2) {
|
||||
chan[c.chan].rVol=c.value2;
|
||||
if (!chan[c.chan].std.panR.has) {
|
||||
chan[c.chan].outRVol=amigaPanTable[(c.value2>>1)&127];
|
||||
chan[c.chan].volChanged.rVol=1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Left volume
|
||||
if (chan[c.chan].lVol!=c.value) {
|
||||
chan[c.chan].lVol=c.value;
|
||||
if (!chan[c.chan].std.panL.has) {
|
||||
chan[c.chan].outLVol=(0xfff*c.value)/0xff;
|
||||
chan[c.chan].volChanged.lVol=1;
|
||||
}
|
||||
}
|
||||
// Right volume
|
||||
if (chan[c.chan].rVol!=c.value2) {
|
||||
chan[c.chan].rVol=c.value2;
|
||||
if (!chan[c.chan].std.panR.has) {
|
||||
chan[c.chan].outRVol=(0xfff*c.value2)/0xff;
|
||||
chan[c.chan].volChanged.rVol=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1028,7 +1081,7 @@ int DivPlatformES5506::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_NOTE_PORTA: {
|
||||
int nextFreq=chan[c.chan].baseFreq;
|
||||
const int destFreq=NOTE_ES5506(c.chan,c.value2+chan[c.chan].sampleNoteDelta);
|
||||
int destFreq=NOTE_ES5506(c.chan,c.value2+chan[c.chan].sampleNoteDelta);
|
||||
bool return2=false;
|
||||
if (destFreq>nextFreq) {
|
||||
nextFreq+=c.value;
|
||||
|
@ -1193,6 +1246,7 @@ void DivPlatformES5506::setFlags(const DivConfig& flags) {
|
|||
initChanMax=MAX(4,flags.getInt("channels",0x1f)&0x1f);
|
||||
volScale=4095-flags.getInt("volScale",4095);
|
||||
amigaVol=flags.getBool("amigaVol",false);
|
||||
amigaPitch=flags.getBool("amigaPitch",false);
|
||||
chanMax=initChanMax;
|
||||
pageWriteMask(0x00,0x60,0x0b,chanMax);
|
||||
|
||||
|
|
|
@ -272,7 +272,7 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
|
|||
unsigned char maskedVal;
|
||||
unsigned int irqv;
|
||||
bool isMasked, isReaded;
|
||||
bool irqTrigger, amigaVol;
|
||||
bool irqTrigger, amigaVol, amigaPitch;
|
||||
unsigned int curCR;
|
||||
|
||||
unsigned char initChanMax, chanMax;
|
||||
|
|
|
@ -7173,8 +7173,17 @@ void FurnaceGUI::drawInsEdit() {
|
|||
macroList.push_back(FurnaceGUIMacroDesc(_("Arpeggio"),&ins->std.arpMacro,-120,120,160,uiColors[GUI_COLOR_MACRO_PITCH],true,NULL,macroHoverNote,false,NULL,true,ins->std.arpMacro.val));
|
||||
macroList.push_back(FurnaceGUIMacroDesc(_("Pitch"),&ins->std.pitchMacro,-2048,2047,160,uiColors[GUI_COLOR_MACRO_PITCH],true,macroRelativeMode));
|
||||
break;
|
||||
case DIV_INS_ES5506:
|
||||
macroList.push_back(FurnaceGUIMacroDesc(_("Volume"),&ins->std.volMacro,0,4095,160,uiColors[GUI_COLOR_MACRO_VOLUME]));
|
||||
case DIV_INS_ES5506: {
|
||||
float usesAmigaVol=true;
|
||||
for (int i=0; i<e->song.systemLen; i++) {
|
||||
if (e->song.system[i]==DIV_SYSTEM_ES5506) {
|
||||
if (!e->song.systemFlags[i].getBool("amigaVol",false)) {
|
||||
usesAmigaVol=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
macroList.push_back(FurnaceGUIMacroDesc(_("Volume"),&ins->std.volMacro,0,usesAmigaVol?64:4095,160,uiColors[GUI_COLOR_MACRO_VOLUME]));
|
||||
macroList.push_back(FurnaceGUIMacroDesc(_("Arpeggio"),&ins->std.arpMacro,-120,120,160,uiColors[GUI_COLOR_MACRO_PITCH],true,NULL,macroHoverNote,false,NULL,true,ins->std.arpMacro.val));
|
||||
macroList.push_back(FurnaceGUIMacroDesc(_("Filter Mode"),&ins->std.dutyMacro,0,3,160,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,¯oHoverES5506FilterMode));
|
||||
macroList.push_back(FurnaceGUIMacroDesc(_("Panning (left)"),&ins->std.panLMacro,0,4095,160,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL));
|
||||
|
@ -7186,6 +7195,7 @@ void FurnaceGUI::drawInsEdit() {
|
|||
macroList.push_back(FurnaceGUIMacroDesc(_("Outputs"),&ins->std.fbMacro,0,5,64,uiColors[GUI_COLOR_MACRO_OTHER]));
|
||||
macroList.push_back(FurnaceGUIMacroDesc(_("Control"),&ins->std.algMacro,0,2,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true,es5506ControlModes));
|
||||
break;
|
||||
}
|
||||
case DIV_INS_MULTIPCM:
|
||||
macroList.push_back(FurnaceGUIMacroDesc(_("Volume"),&ins->std.volMacro,0,127,160,uiColors[GUI_COLOR_MACRO_VOLUME]));
|
||||
macroList.push_back(FurnaceGUIMacroDesc(_("Arpeggio"),&ins->std.arpMacro,-120,120,160,uiColors[GUI_COLOR_MACRO_PITCH],true,NULL,macroHoverNote,false,NULL,true,ins->std.arpMacro.val));
|
||||
|
|
|
@ -1273,6 +1273,7 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl
|
|||
int channels=flags.getInt("channels",0x1f)+1;
|
||||
int volScale=flags.getInt("volScale",4095);
|
||||
bool amigaVol=flags.getBool("amigaVol",false);
|
||||
bool amigaPitch=flags.getBool("amigaPitch",false);
|
||||
ImGui::Text(_("Initial channel limit:"));
|
||||
if (CWSliderInt("##OTTO_InitialChannelLimit",&channels,5,32)) {
|
||||
if (channels<5) channels=5;
|
||||
|
@ -1291,12 +1292,21 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl
|
|||
if (ImGui::Checkbox(_("Amiga channel volumes (64)"),&amigaVol)) {
|
||||
altered=true;
|
||||
}
|
||||
pushWarningColor(amigaPitch && e->song.linearPitch==2);
|
||||
if (ImGui::Checkbox(_("Amiga-like pitch (non-linear pitch only)"),&amigaPitch)) {
|
||||
altered=true;
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("pitch linearity is set to linear. this won't do anything!");
|
||||
}
|
||||
popWarningColor();
|
||||
|
||||
if (altered) {
|
||||
e->lockSave([&]() {
|
||||
flags.set("channels",channels-1);
|
||||
flags.set("volScale",volScale);
|
||||
flags.set("amigaVol",amigaVol);
|
||||
flags.set("amigaPitch",amigaPitch);
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue