K053260: implement ADPCM

This commit is contained in:
tildearrow 2023-08-29 16:43:37 -05:00
parent 4abae260f4
commit de34b5c9c4
2 changed files with 42 additions and 21 deletions

View file

@ -131,21 +131,20 @@ void DivPlatformK053260::tick(bool sysTick) {
chan[i].audPos=0; chan[i].audPos=0;
} }
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
unsigned char keyon=regPool[0x28]|(1<<i);
unsigned char keyoff=keyon&~(17<<i);
unsigned char loopon=regPool[0x2a]|(1<<i);
unsigned char loopoff=loopon&~(1<<i);
double off=1.0;
int sample=chan[i].sample; int sample=chan[i].sample;
DivSample* s=parent->getSample(sample);
unsigned char keyon=regPool[0x28]|(1<<i);
unsigned char keyoff=keyon&~(0x11<<i);
unsigned char loopoff=regPool[0x2a]&~(0x11<<i);
unsigned char loopon=loopoff|(s->isLoopable()?(1<<i):0)|(s->depth==DIV_SAMPLE_DEPTH_ADPCM_K?(0x10<<i):0);
double off=1.0;
if (sample>=0 && sample<parent->song.sampleLen) { if (sample>=0 && sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(sample);
if (s->centerRate<1) { if (s->centerRate<1) {
off=1.0; off=1.0;
} else { } else {
off=8363.0/s->centerRate; off=8363.0/s->centerRate;
} }
} }
DivSample* s=parent->getSample(sample);
chan[i].freq=0x1000-(int)(off*parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER)); chan[i].freq=0x1000-(int)(off*parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER));
if (chan[i].freq>4095) chan[i].freq=4095; if (chan[i].freq>4095) chan[i].freq=4095;
if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq<0) chan[i].freq=0;
@ -154,17 +153,26 @@ void DivPlatformK053260::tick(bool sysTick) {
unsigned int length=0; unsigned int length=0;
if (sample>=0 && sample<parent->song.sampleLen) { if (sample>=0 && sample<parent->song.sampleLen) {
start=sampleOffK053260[sample]; start=sampleOffK053260[sample];
length=s->length8; length=(s->depth==DIV_SAMPLE_DEPTH_ADPCM_K)?s->lengthK:s->length8;
if (chan[i].reverse) { if (chan[i].reverse) {
start+=length; start+=length;
keyon|=(16<<i); keyon|=(16<<i);
} }
} }
if (chan[i].audPos>0) { if (chan[i].audPos>0) {
if (chan[i].reverse) { if (s->depth==DIV_SAMPLE_DEPTH_ADPCM_K) {
start=start-MIN(chan[i].audPos,s->length8); chan[i].audPos>>=1;
if (chan[i].reverse) {
start=start-MIN(chan[i].audPos,s->lengthK);
} else {
start=start+MIN(chan[i].audPos,s->lengthK);
}
} else { } else {
start=start+MIN(chan[i].audPos,s->length8); if (chan[i].reverse) {
start=start-MIN(chan[i].audPos,s->length8);
} else {
start=start+MIN(chan[i].audPos,s->length8);
}
} }
length=MAX(1,length-chan[i].audPos); length=MAX(1,length-chan[i].audPos);
} }
@ -181,10 +189,8 @@ void DivPlatformK053260::tick(bool sysTick) {
chan[i].outVol=chan[i].vol; chan[i].outVol=chan[i].vol;
chWrite(i,7,chan[i].outVol); chWrite(i,7,chan[i].outVol);
} }
rWrite(0x2a,loopon);
rWrite(0x28,keyon); rWrite(0x28,keyon);
if (s->isLoopable()) {
rWrite(0x2a,loopon);
}
chan[i].keyOn=false; chan[i].keyOn=false;
} }
if (chan[i].keyOff) { if (chan[i].keyOff) {
@ -473,14 +479,28 @@ void DivPlatformK053260::renderSamples(int sysID) {
continue; continue;
} }
int length=MIN(65535,s->getEndPosition(DIV_SAMPLE_DEPTH_8BIT)); int length, actualLength;
int actualLength=MIN((int)(getSampleMemCapacity()-memPos-1),length);
if (actualLength>0) { if (s->depth==DIV_SAMPLE_DEPTH_ADPCM_K) {
sampleOffK053260[i]=memPos-1; length=MIN(65535,s->getEndPosition(DIV_SAMPLE_DEPTH_ADPCM_K));
for (int j=0; j<actualLength; j++) { actualLength=MIN((int)(getSampleMemCapacity()-memPos-1),length);
sampleMem[memPos++]=s->data8[j]; if (actualLength>0) {
sampleOffK053260[i]=memPos-1;
for (int j=0; j<actualLength; j++) {
sampleMem[memPos++]=s->dataK[j];
}
sampleMem[memPos++]=0; // Silence for avoid popping noise
}
} else {
length=MIN(65535,s->getEndPosition(DIV_SAMPLE_DEPTH_8BIT));
actualLength=MIN((int)(getSampleMemCapacity()-memPos-1),length);
if (actualLength>0) {
sampleOffK053260[i]=memPos-1;
for (int j=0; j<actualLength; j++) {
sampleMem[memPos++]=s->data8[j];
}
sampleMem[memPos++]=0; // Silence for avoid popping noise
} }
sampleMem[memPos++]=0; // Silence for avoid popping noise
} }
if (actualLength<length) { if (actualLength<length) {
logW("out of K053260 PCM memory for sample %d!",i); logW("out of K053260 PCM memory for sample %d!",i);

View file

@ -4512,6 +4512,7 @@ bool FurnaceGUI::loop() {
MEASURE(compatFlags,drawCompatFlags()); MEASURE(compatFlags,drawCompatFlags());
MEASURE(stats,drawStats()); MEASURE(stats,drawStats());
MEASURE(chanOsc,drawChanOsc()); MEASURE(chanOsc,drawChanOsc());
MEASURE(regView,drawRegView());
} else { } else {
globalWinFlags=0; globalWinFlags=0;
ImGui::DockSpaceOverViewport(NULL,lockLayout?(ImGuiDockNodeFlags_NoWindowMenuButton|ImGuiDockNodeFlags_NoMove|ImGuiDockNodeFlags_NoResize|ImGuiDockNodeFlags_NoCloseButton|ImGuiDockNodeFlags_NoDocking|ImGuiDockNodeFlags_NoDockingSplitMe|ImGuiDockNodeFlags_NoDockingSplitOther):0); ImGui::DockSpaceOverViewport(NULL,lockLayout?(ImGuiDockNodeFlags_NoWindowMenuButton|ImGuiDockNodeFlags_NoMove|ImGuiDockNodeFlags_NoResize|ImGuiDockNodeFlags_NoCloseButton|ImGuiDockNodeFlags_NoDocking|ImGuiDockNodeFlags_NoDockingSplitMe|ImGuiDockNodeFlags_NoDockingSplitOther):0);