mirror of
https://github.com/tildearrow/furnace.git
synced 2025-01-03 06:01:29 +00:00
Make some pitch command work in ADPCM-B, still partially and 01xx command is broken
Fix sample check routine Remove dac* variables, No way to enable DAC mode in YM2610*
This commit is contained in:
parent
93b3e16213
commit
f3e4810dda
4 changed files with 93 additions and 71 deletions
|
@ -313,11 +313,22 @@ const char* DivPlatformYM2610::getEffectName(unsigned char effect) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
double DivPlatformYM2610::NOTE_OPNB(int ch, int note) {
|
||||
if (ch>6) { // ADPCM
|
||||
return NOTE_ADPCMB(note);
|
||||
} else if (ch>3) { // PSG
|
||||
return NOTE_PERIODIC(note);
|
||||
}
|
||||
// FM
|
||||
return NOTE_FREQUENCY(note);
|
||||
}
|
||||
|
||||
double DivPlatformYM2610::NOTE_ADPCMB(int note) {
|
||||
DivInstrument* ins=parent->getIns(chan[13].ins);
|
||||
if (ins->type!=DIV_INS_AMIGA) return 0;
|
||||
double off=(double)(parent->getSample(ins->amiga.initSample)->centerRate)/8363.0;
|
||||
return off*parent->calcBaseFreq((double)chipClock/144,65535,note,false);
|
||||
if (chan[13].sample>=0&&chan[13].sample<parent->song.sampleLen) {
|
||||
double off=(double)(parent->getSample(chan[13].sample)->centerRate)/8363.0;
|
||||
return off*parent->calcBaseFreq((double)chipClock/144,65535,note,false);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
|
@ -691,22 +702,33 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
|||
chan[c.chan].outVol=chan[c.chan].vol;
|
||||
immWrite(0x1b,chan[c.chan].outVol);
|
||||
}
|
||||
DivSample* s=parent->getSample(ins->amiga.initSample);
|
||||
immWrite(0x12,(s->offB>>8)&0xff);
|
||||
immWrite(0x13,s->offB>>16);
|
||||
int end=s->offB+s->lengthB-1;
|
||||
immWrite(0x14,(end>>8)&0xff);
|
||||
immWrite(0x15,end>>16);
|
||||
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
|
||||
immWrite(0x10,(s->loopStart>=0)?0x90:0x80); // start/repeat
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].note=c.value;
|
||||
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
|
||||
chan[c.chan].freqChanged=true;
|
||||
chan[c.chan].sample=ins->amiga.initSample;
|
||||
if (chan[c.chan].sample>=0&&chan[c.chan].sample<parent->song.sampleLen) {
|
||||
DivSample* s=parent->getSample(chan[c.chan].sample);
|
||||
immWrite(0x12,(s->offB>>8)&0xff);
|
||||
immWrite(0x13,s->offB>>16);
|
||||
int end=s->offB+s->lengthB-1;
|
||||
immWrite(0x14,(end>>8)&0xff);
|
||||
immWrite(0x15,end>>16);
|
||||
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
|
||||
immWrite(0x10,(s->loopStart>=0)?0x90:0x80); // start/repeat
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].note=c.value;
|
||||
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
|
||||
chan[c.chan].freqChanged=true;
|
||||
}
|
||||
chan[c.chan].active=true;
|
||||
chan[c.chan].keyOn=true;
|
||||
} else {
|
||||
immWrite(0x10,0x01); // reset
|
||||
immWrite(0x12,0);
|
||||
immWrite(0x13,0);
|
||||
immWrite(0x14,0);
|
||||
immWrite(0x15,0);
|
||||
break;
|
||||
}
|
||||
chan[c.chan].active=true;
|
||||
chan[c.chan].keyOn=true;
|
||||
} else {
|
||||
chan[c.chan].sample=-1;
|
||||
chan[c.chan].std.init(NULL);
|
||||
chan[c.chan].outVol=chan[c.chan].vol;
|
||||
if ((12*sampleBank+c.value%12)>=parent->song.sampleLen) {
|
||||
|
@ -915,8 +937,8 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
case DIV_CMD_NOTE_PORTA: {
|
||||
if (c.chan>3) { // PSG
|
||||
int destFreq=NOTE_PERIODIC(c.value2);
|
||||
if (c.chan>3) { // PSG, ADPCM-B
|
||||
int destFreq=NOTE_OPNB(c.chan,c.value2);
|
||||
bool return2=false;
|
||||
if (destFreq>chan[c.chan].baseFreq) {
|
||||
chan[c.chan].baseFreq+=c.value;
|
||||
|
@ -975,11 +997,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
|||
iface.sampleBank=sampleBank;
|
||||
break;
|
||||
case DIV_CMD_LEGATO: {
|
||||
if (c.chan>3) { // PSG
|
||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
|
||||
} else {
|
||||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
|
||||
}
|
||||
chan[c.chan].baseFreq=NOTE_OPNB(c.chan,c.value);
|
||||
chan[c.chan].freqChanged=true;
|
||||
break;
|
||||
}
|
||||
|
@ -1210,11 +1228,6 @@ void DivPlatformYM2610::reset() {
|
|||
}
|
||||
|
||||
lastBusy=60;
|
||||
dacMode=0;
|
||||
dacPeriod=0;
|
||||
dacPos=0;
|
||||
dacRate=0;
|
||||
dacSample=-1;
|
||||
sampleBank=0;
|
||||
ayEnvPeriod=0;
|
||||
ayEnvMode=0;
|
||||
|
|
|
@ -47,6 +47,7 @@ class DivPlatformYM2610: public DivDispatch {
|
|||
signed char konCycles;
|
||||
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, inPorta, furnacePCM;
|
||||
int vol, outVol;
|
||||
int sample;
|
||||
unsigned char pan;
|
||||
DivMacroInt std;
|
||||
Channel():
|
||||
|
@ -70,6 +71,7 @@ class DivPlatformYM2610: public DivDispatch {
|
|||
furnacePCM(false),
|
||||
vol(0),
|
||||
outVol(15),
|
||||
sample(-1),
|
||||
pan(3) {}
|
||||
};
|
||||
Channel chan[14];
|
||||
|
@ -87,11 +89,6 @@ class DivPlatformYM2610: public DivDispatch {
|
|||
unsigned char regPool[512];
|
||||
unsigned char lastBusy;
|
||||
|
||||
bool dacMode;
|
||||
int dacPeriod;
|
||||
int dacRate;
|
||||
int dacPos;
|
||||
int dacSample;
|
||||
int ayNoiseFreq;
|
||||
unsigned char sampleBank;
|
||||
|
||||
|
@ -108,6 +105,7 @@ class DivPlatformYM2610: public DivDispatch {
|
|||
|
||||
int octave(int freq);
|
||||
int toFreq(int freq);
|
||||
double NOTE_OPNB(int ch, int note);
|
||||
double NOTE_ADPCMB(int note);
|
||||
friend void putDispatchChan(void*,int,int);
|
||||
|
||||
|
|
|
@ -377,11 +377,22 @@ const char* DivPlatformYM2610B::getEffectName(unsigned char effect) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
double DivPlatformYM2610B::NOTE_OPNB(int ch, int note) {
|
||||
if (ch>8) { // ADPCM-B
|
||||
return NOTE_ADPCMB(note);
|
||||
} else if (ch>5) { // PSG
|
||||
return NOTE_PERIODIC(note);
|
||||
}
|
||||
// FM
|
||||
return NOTE_FREQUENCY(note);
|
||||
}
|
||||
|
||||
double DivPlatformYM2610B::NOTE_ADPCMB(int note) {
|
||||
DivInstrument* ins=parent->getIns(chan[15].ins);
|
||||
if (ins->type!=DIV_INS_AMIGA) return 0;
|
||||
double off=(double)(parent->getSample(ins->amiga.initSample)->centerRate)/8363.0;
|
||||
return off*parent->calcBaseFreq((double)chipClock/144,65535,note,false);
|
||||
if (chan[15].sample>=0&&chan[15].sample<parent->song.sampleLen) {
|
||||
double off=(double)(parent->getSample(chan[15].sample)->centerRate)/8363.0;
|
||||
return off*parent->calcBaseFreq((double)chipClock/144,65535,note,false);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
|
@ -752,24 +763,35 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
|||
chan[c.chan].std.init(ins);
|
||||
if (!chan[c.chan].std.willVol) {
|
||||
chan[c.chan].outVol=chan[c.chan].vol;
|
||||
immWrite(0x1b,chan[c.chan].outVol);
|
||||
immWrite(0x1b,chan[c.chan].outVol);
|
||||
}
|
||||
DivSample* s=parent->getSample(ins->amiga.initSample);
|
||||
immWrite(0x12,(s->offB>>8)&0xff);
|
||||
immWrite(0x13,s->offB>>16);
|
||||
int end=s->offB+s->lengthB-1;
|
||||
immWrite(0x14,(end>>8)&0xff);
|
||||
immWrite(0x15,end>>16);
|
||||
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
|
||||
immWrite(0x10,(s->loopStart>=0)?0x90:0x80); // start/repeat
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].note=c.value;
|
||||
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
|
||||
chan[c.chan].freqChanged=true;
|
||||
chan[c.chan].sample=ins->amiga.initSample;
|
||||
if (chan[c.chan].sample>=0&&chan[c.chan].sample<parent->song.sampleLen) {
|
||||
DivSample* s=parent->getSample(chan[c.chan].sample);
|
||||
immWrite(0x12,(s->offB>>8)&0xff);
|
||||
immWrite(0x13,s->offB>>16);
|
||||
int end=s->offB+s->lengthB-1;
|
||||
immWrite(0x14,(end>>8)&0xff);
|
||||
immWrite(0x15,end>>16);
|
||||
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
|
||||
immWrite(0x10,(s->loopStart>=0)?0x90:0x80); // start/repeat
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].note=c.value;
|
||||
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
|
||||
chan[c.chan].freqChanged=true;
|
||||
}
|
||||
chan[c.chan].active=true;
|
||||
chan[c.chan].keyOn=true;
|
||||
} else {
|
||||
immWrite(0x10,0x01); // reset
|
||||
immWrite(0x12,0);
|
||||
immWrite(0x13,0);
|
||||
immWrite(0x14,0);
|
||||
immWrite(0x15,0);
|
||||
break;
|
||||
}
|
||||
chan[c.chan].active=true;
|
||||
chan[c.chan].keyOn=true;
|
||||
} else {
|
||||
chan[c.chan].sample=-1;
|
||||
chan[c.chan].std.init(NULL);
|
||||
chan[c.chan].outVol=chan[c.chan].vol;
|
||||
if ((12*sampleBank+c.value%12)>=parent->song.sampleLen) {
|
||||
|
@ -978,8 +1000,8 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
case DIV_CMD_NOTE_PORTA: {
|
||||
if (c.chan>5) { // PSG
|
||||
int destFreq=NOTE_PERIODIC(c.value2);
|
||||
if (c.chan>5) { // PSG, ADPCM-B
|
||||
int destFreq=NOTE_OPNB(c.chan,c.value2);
|
||||
bool return2=false;
|
||||
if (destFreq>chan[c.chan].baseFreq) {
|
||||
chan[c.chan].baseFreq+=c.value;
|
||||
|
@ -1038,11 +1060,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
|||
iface.sampleBank=sampleBank;
|
||||
break;
|
||||
case DIV_CMD_LEGATO: {
|
||||
if (c.chan>5) { // PSG
|
||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
|
||||
} else {
|
||||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
|
||||
}
|
||||
chan[c.chan].baseFreq=NOTE_OPNB(c.chan,c.value);
|
||||
chan[c.chan].freqChanged=true;
|
||||
break;
|
||||
}
|
||||
|
@ -1273,11 +1291,6 @@ void DivPlatformYM2610B::reset() {
|
|||
}
|
||||
|
||||
lastBusy=60;
|
||||
dacMode=0;
|
||||
dacPeriod=0;
|
||||
dacPos=0;
|
||||
dacRate=0;
|
||||
dacSample=-1;
|
||||
sampleBank=0;
|
||||
ayEnvPeriod=0;
|
||||
ayEnvMode=0;
|
||||
|
|
|
@ -40,6 +40,7 @@ class DivPlatformYM2610B: public DivDispatch {
|
|||
signed char konCycles;
|
||||
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, inPorta, furnacePCM;
|
||||
int vol, outVol;
|
||||
int sample;
|
||||
unsigned char pan;
|
||||
DivMacroInt std;
|
||||
Channel():
|
||||
|
@ -63,6 +64,7 @@ class DivPlatformYM2610B: public DivDispatch {
|
|||
furnacePCM(false),
|
||||
vol(0),
|
||||
outVol(15),
|
||||
sample(-1),
|
||||
pan(3) {}
|
||||
};
|
||||
Channel chan[16];
|
||||
|
@ -80,11 +82,6 @@ class DivPlatformYM2610B: public DivDispatch {
|
|||
unsigned char regPool[512];
|
||||
unsigned char lastBusy;
|
||||
|
||||
bool dacMode;
|
||||
int dacPeriod;
|
||||
int dacRate;
|
||||
int dacPos;
|
||||
int dacSample;
|
||||
int ayNoiseFreq;
|
||||
unsigned char sampleBank;
|
||||
|
||||
|
@ -101,6 +98,7 @@ class DivPlatformYM2610B: public DivDispatch {
|
|||
|
||||
int octave(int freq);
|
||||
int toFreq(int freq);
|
||||
double NOTE_OPNB(int ch, int note);
|
||||
double NOTE_ADPCMB(int note);
|
||||
friend void putDispatchChan(void*,int,int);
|
||||
|
||||
|
|
Loading…
Reference in a new issue