yay ADPCM-A and QSound work again!

This commit is contained in:
tildearrow 2022-02-24 16:16:02 -05:00
parent 1e98f0c4a1
commit f7bd06c4eb
6 changed files with 47 additions and 43 deletions

View file

@ -444,46 +444,45 @@ void DivEngine::renderSamples() {
sPreview.sample=-1; sPreview.sample=-1;
sPreview.pos=0; sPreview.pos=0;
// step 1: render samples
for (int i=0; i<song.sampleLen; i++) { for (int i=0; i<song.sampleLen; i++) {
song.sample[i]->render(); song.sample[i]->render();
} }
/* // step 2: allocate ADPCM-A samples
// step 3: allocate ADPCM samples if (adpcmAMem==NULL) adpcmAMem=new unsigned char[16777216];
if (adpcmMem==NULL) adpcmMem=new unsigned char[16777216];
size_t memPos=0; size_t memPos=0;
for (int i=0; i<song.sampleLen; i++) { for (int i=0; i<song.sampleLen; i++) {
DivSample* s=song.sample[i]; DivSample* s=song.sample[i];
if ((memPos&0xf00000)!=((memPos+s->adpcmRendLength)&0xf00000)) { int paddedLen=(s->lengthA+255)&(~0xff);
if ((memPos&0xf00000)!=((memPos+paddedLen)&0xf00000)) {
memPos=(memPos+0xfffff)&0xf00000; memPos=(memPos+0xfffff)&0xf00000;
} }
if (memPos>=16777216) { if (memPos>=16777216) {
logW("out of ADPCM memory for sample %d!\n",i); logW("out of ADPCM memory for sample %d!\n",i);
break; break;
} }
if (memPos+s->adpcmRendLength>=16777216) { if (memPos+paddedLen>=16777216) {
memcpy(adpcmMem+memPos,s->adpcmRendData,16777216-memPos); memcpy(adpcmAMem+memPos,s->dataA,16777216-memPos);
logW("out of ADPCM memory for sample %d!\n",i); logW("out of ADPCM memory for sample %d!\n",i);
} else { } else {
memcpy(adpcmMem+memPos,s->adpcmRendData,s->adpcmRendLength); memcpy(adpcmAMem+memPos,s->dataA,paddedLen);
} }
s->rendOff=memPos; s->offA=memPos;
memPos+=s->adpcmRendLength; memPos+=paddedLen;
} }
adpcmMemLen=memPos+256; adpcmAMemLen=memPos+256;
// step 4: allocate qsound pcm samples // step 4: allocate qsound pcm samples
if (qsoundMem==NULL) qsoundMem=new unsigned char[16777216]; if (qsoundMem==NULL) qsoundMem=new unsigned char[16777216];
memset(qsoundMem, 0, 16777216);
memPos=0; memPos=0;
for (int i=0; i<song.sampleLen; i++) { for (int i=0; i<song.sampleLen; i++) {
DivSample* s=song.sample[i]; DivSample* s=song.sample[i];
int length = s->rendLength; int length=s->length8;
if (length > 65536-16) { if (length>65536-16) {
length = 65536-16; length=65536-16;
} }
if ((memPos&0xff0000)!=((memPos+length)&0xff0000)) { if ((memPos&0xff0000)!=((memPos+length)&0xff0000)) {
memPos=(memPos+0xffff)&0xff0000; memPos=(memPos+0xffff)&0xff0000;
@ -494,19 +493,18 @@ void DivEngine::renderSamples() {
} }
if (memPos+length>=16777216) { if (memPos+length>=16777216) {
for (unsigned int i=0; i<16777216-(memPos+length); i++) { for (unsigned int i=0; i<16777216-(memPos+length); i++) {
qsoundMem[(memPos + i) ^ 0x8000] = s->rendData[i] >> ((s->depth == 16) ? 8 : 0); qsoundMem[(memPos+i)^0x8000]=s->data8[i];
} }
logW("out of QSound PCM memory for sample %d!\n",i); logW("out of QSound PCM memory for sample %d!\n",i);
} else { } else {
for (int i=0; i<length; i++) { for (int i=0; i<length; i++) {
qsoundMem[(memPos + i) ^ 0x8000] = s->rendData[i] >> ((s->depth == 16) ? 8 : 0); qsoundMem[(memPos+i)^0x8000]=s->data8[i];
} }
} }
s->rendOffQsound=memPos ^ 0x8000; s->offQSound=memPos^0x8000;
memPos+=length+16; memPos+=length+16;
} }
qsoundMemLen=memPos+256; qsoundMemLen=memPos+256;
*/
} }
void DivEngine::createNew() { void DivEngine::createNew() {

View file

@ -621,8 +621,8 @@ class DivEngine {
// terminate the engine. // terminate the engine.
bool quit(); bool quit();
unsigned char* adpcmMem; unsigned char* adpcmAMem;
size_t adpcmMemLen; size_t adpcmAMemLen;
unsigned char* adpcmBMem; unsigned char* adpcmBMem;
size_t adpcmBMemLen; size_t adpcmBMemLen;
unsigned char* qsoundMem; unsigned char* qsoundMem;
@ -680,8 +680,8 @@ class DivEngine {
totalProcessed(0), totalProcessed(0),
oscBuf{NULL,NULL}, oscBuf{NULL,NULL},
oscSize(1), oscSize(1),
adpcmMem(NULL), adpcmAMem(NULL),
adpcmMemLen(0), adpcmAMemLen(0),
adpcmBMem(NULL), adpcmBMem(NULL),
adpcmBMemLen(0), adpcmBMemLen(0),
qsoundMem(NULL), qsoundMem(NULL),

View file

@ -22,11 +22,15 @@
#include "../engine.h" #include "../engine.h"
uint8_t DivYM2610Interface::ymfm_external_read(ymfm::access_class type, uint32_t address) { uint8_t DivYM2610Interface::ymfm_external_read(ymfm::access_class type, uint32_t address) {
//printf("wants to read from %x\n",address); switch (type) {
if (type!=ymfm::ACCESS_ADPCM_A) return 0; case ymfm::ACCESS_ADPCM_A:
return parent->adpcmMem[address&0xffffff]; return parent->adpcmAMem[address&0xffffff];
/*if (12*sampleBank+(address>>16)>=parent->song.sampleLen) return 0; case ymfm::ACCESS_ADPCM_B:
return parent->song.sample[12*sampleBank+(address>>16)]->adpcmRendData[(address&0xffff)];*/ return parent->adpcmBMem[address&0xffffff];
default:
return 0;
}
return 0;
} }
void DivYM2610Interface::ymfm_external_write(ymfm::access_class type, uint32_t address, uint8_t data) { void DivYM2610Interface::ymfm_external_write(ymfm::access_class type, uint32_t address, uint8_t data) {

View file

@ -73,6 +73,7 @@ bool DivSample::save(const char* path) {
return true; return true;
} }
// 16-bit memory is padded to 512, to make things easier for ADPCM-A/B.
bool DivSample::initInternal(unsigned char d, int count) { bool DivSample::initInternal(unsigned char d, int count) {
switch (d) { switch (d) {
case 0: // 1-bit case 0: // 1-bit
@ -96,14 +97,14 @@ bool DivSample::initInternal(unsigned char d, int count) {
case 5: // ADPCM-A case 5: // ADPCM-A
if (dataA!=NULL) delete[] dataA; if (dataA!=NULL) delete[] dataA;
lengthA=(count+1)/2; lengthA=(count+1)/2;
dataA=new unsigned char[lengthA]; dataA=new unsigned char[(lengthA+255)&(~0xff)];
memset(dataA,0,lengthA); memset(dataA,0,(lengthA+255)&(~0xff));
break; break;
case 6: // ADPCM-B case 6: // ADPCM-B
if (dataB!=NULL) delete[] dataB; if (dataB!=NULL) delete[] dataB;
lengthB=(count+1)/2; lengthB=(count+1)/2;
dataB=new unsigned char[lengthB]; dataB=new unsigned char[(lengthB+255)&(~0xff)];
memset(dataB,0,lengthB); memset(dataB,0,(lengthB+255)&(~0xff));
break; break;
case 7: // X68000 ADPCM case 7: // X68000 ADPCM
if (dataX68!=NULL) delete[] dataX68; if (dataX68!=NULL) delete[] dataX68;
@ -132,8 +133,8 @@ bool DivSample::initInternal(unsigned char d, int count) {
case 16: // 16-bit case 16: // 16-bit
if (data16!=NULL) delete[] data16; if (data16!=NULL) delete[] data16;
length16=count*2; length16=count*2;
data16=new short[count]; data16=new short[(count+511)&(~0x1ff)];
memset(data16,0,count*sizeof(short)); memset(data16,0,((count+511)&(~0x1ff))*sizeof(short));
break; break;
default: default:
return false; return false;
@ -223,13 +224,14 @@ void DivSample::render() {
if (!initInternal(4,samples)) return; if (!initInternal(4,samples)) return;
bs_encode(data16,dataQSoundA,samples); bs_encode(data16,dataQSoundA,samples);
} }
// TODO: pad to 256.
if (depth!=5) { // ADPCM-A if (depth!=5) { // ADPCM-A
if (!initInternal(5,samples)) return; if (!initInternal(5,samples)) return;
yma_encode(data16,dataA,samples); yma_encode(data16,dataA,(samples+511)&(~0x1ff));
} }
if (depth!=6) { // ADPCM-B if (depth!=6) { // ADPCM-B
if (!initInternal(6,samples)) return; if (!initInternal(6,samples)) return;
ymb_encode(data16,dataB,samples); ymb_encode(data16,dataB,(samples+511)&(~0x1ff));
} }
if (depth!=7) { // X68000 ADPCM if (depth!=7) { // X68000 ADPCM
if (!initInternal(7,samples)) return; if (!initInternal(7,samples)) return;

View file

@ -928,14 +928,14 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop) {
delete[] pcmMem; delete[] pcmMem;
} }
if (writeADPCM && adpcmMemLen>0) { if (writeADPCM && adpcmAMemLen>0) {
w->writeC(0x67); w->writeC(0x67);
w->writeC(0x66); w->writeC(0x66);
w->writeC(0x82); w->writeC(0x82);
w->writeI(adpcmMemLen+8); w->writeI(adpcmAMemLen+8);
w->writeI(adpcmMemLen); w->writeI(adpcmAMemLen);
w->writeI(0); w->writeI(0);
w->write(adpcmMem,adpcmMemLen); w->write(adpcmAMem,adpcmAMemLen);
} }
if (writeQSound && qsoundMemLen>0) { if (writeQSound && qsoundMemLen>0) {

View file

@ -1898,12 +1898,12 @@ void FurnaceGUI::drawStats() {
} }
if (!statsOpen) return; if (!statsOpen) return;
if (ImGui::Begin("Statistics",&statsOpen)) { if (ImGui::Begin("Statistics",&statsOpen)) {
String adpcmUsage=fmt::sprintf("%d/16384KB",e->adpcmMemLen/1024); String adpcmAUsage=fmt::sprintf("%d/16384KB",e->adpcmAMemLen/1024);
String adpcmBUsage=fmt::sprintf("%d/16384KB",e->adpcmBMemLen/1024); String adpcmBUsage=fmt::sprintf("%d/16384KB",e->adpcmBMemLen/1024);
String qsoundUsage=fmt::sprintf("%d/16384KB",e->qsoundMemLen/1024); String qsoundUsage=fmt::sprintf("%d/16384KB",e->qsoundMemLen/1024);
ImGui::Text("ADPCM-A"); ImGui::Text("ADPCM-A");
ImGui::SameLine(); ImGui::SameLine();
ImGui::ProgressBar(((float)e->adpcmMemLen)/16777216.0f,ImVec2(-FLT_MIN,0),adpcmUsage.c_str()); ImGui::ProgressBar(((float)e->adpcmAMemLen)/16777216.0f,ImVec2(-FLT_MIN,0),adpcmAUsage.c_str());
ImGui::Text("ADPCM-B"); ImGui::Text("ADPCM-B");
ImGui::SameLine(); ImGui::SameLine();
ImGui::ProgressBar(((float)e->adpcmBMemLen)/16777216.0f,ImVec2(-FLT_MIN,0),adpcmBUsage.c_str()); ImGui::ProgressBar(((float)e->adpcmBMemLen)/16777216.0f,ImVec2(-FLT_MIN,0),adpcmBUsage.c_str());