SoundUnit: PCM support

This commit is contained in:
tildearrow 2022-05-02 14:51:06 -05:00
parent 66f6ab4307
commit a6ef36d42e
5 changed files with 90 additions and 7 deletions

View file

@ -19,6 +19,7 @@
#include "su.h"
#include "../engine.h"
#include "../../ta-log.h"
#include <math.h>
//#define rWrite(a,v) pendingWrites[a]=v;
@ -178,12 +179,47 @@ void DivPlatformSoundUnit::tick(bool sysTick) {
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SU);
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].pitch2);
if (chan[i].pcm) {
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SU);
DivSample* sample=parent->getSample(ins->amiga.initSample);
if (sample!=NULL) {
double off=1.0;
if (sample->centerRate<1) {
off=1.0;
} else {
off=(double)sample->centerRate/8363.0;
}
chan[i].freq=(double)chan[i].freq*off;
}
}
if (chan[i].freq<0) chan[i].freq=0;
if (chan[i].freq>65535) chan[i].freq=65535;
chWrite(i,0x00,chan[i].freq&0xff);
chWrite(i,0x01,chan[i].freq>>8);
if (chan[i].freq>65535) chan[i].freq=65535;
if (chan[i].keyOn) {
//rWrite(16+i*5,0x80);
//chWrite(i,0x04,0x80|chan[i].vol);
if (chan[i].pcm) {
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SU);
DivSample* sample=parent->getSample(ins->amiga.initSample);
if (sample!=NULL) {
unsigned int sampleEnd=sample->offSU+sample->samples;
if (sampleEnd>=getSampleMemCapacity(0)) sampleEnd=getSampleMemCapacity(0)-1;
chWrite(i,0x0a,sample->offSU&0xff);
chWrite(i,0x0b,sample->offSU>>8);
chWrite(i,0x0c,sampleEnd&0xff);
chWrite(i,0x0d,sampleEnd>>8);
if (sample->loopStart>=0 && sample->loopStart<(int)sample->samples) {
unsigned int sampleLoop=sample->offSU+sample->loopStart;
if (sampleLoop>=getSampleMemCapacity(0)) sampleLoop=getSampleMemCapacity(0)-1;
chWrite(i,0x0e,sampleLoop&0xff);
chWrite(i,0x0f,sampleLoop>>8);
chan[i].pcmLoop=true;
} else {
chan[i].pcmLoop=false;
}
writeControl(i);
writeControlUpper(i);
}
}
}
if (chan[i].keyOff) {
chWrite(i,0x02,0);
@ -199,6 +235,11 @@ int DivPlatformSoundUnit::dispatch(DivCommand c) {
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_SU);
if (chan[c.chan].pcm && ins->type!=DIV_INS_AMIGA) {
writeControl(c.chan);
writeControlUpper(c.chan);
}
chan[c.chan].pcm=(ins->type==DIV_INS_AMIGA);
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
chan[c.chan].freqChanged=true;
@ -247,7 +288,6 @@ int DivPlatformSoundUnit::dispatch(DivCommand c) {
break;
case DIV_CMD_WAVE:
chan[c.chan].wave=c.value;
chan[c.chan].keyOn=true;
break;
case DIV_CMD_NOTE_PORTA: {
int destFreq=NOTE_FREQUENCY(c.value2);
@ -385,6 +425,42 @@ void DivPlatformSoundUnit::poke(std::vector<DivRegWrite>& wlist) {
for (DivRegWrite& i: wlist) rWrite(i.addr,i.val);
}
const void* DivPlatformSoundUnit::getSampleMem(int index) {
return (index==0)?su->pcm:NULL;
}
size_t DivPlatformSoundUnit::getSampleMemCapacity(int index) {
return (index==0)?8192:0;
}
size_t DivPlatformSoundUnit::getSampleMemUsage(int index) {
return (index==0)?sampleMemLen:0;
}
void DivPlatformSoundUnit::renderSamples() {
memset(su->pcm,0,getSampleMemCapacity(0));
size_t memPos=0;
for (int i=0; i<parent->song.sampleLen; i++) {
DivSample* s=parent->song.sample[i];
int paddedLen=s->samples;
if (memPos>=getSampleMemCapacity(0)) {
logW("out of PCM memory for sample %d!",i);
break;
}
if (memPos+paddedLen>=getSampleMemCapacity(0)) {
memcpy(su->pcm+memPos,s->data8,getSampleMemCapacity(0)-memPos);
logW("out of PCM memory for sample %d!",i);
} else {
memcpy(su->pcm+memPos,s->data8,paddedLen);
}
s->offSU=memPos;
memPos+=paddedLen;
}
sampleMemLen=memPos;
}
int DivPlatformSoundUnit::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
parent=p;
dumpWrites=false;

View file

@ -86,6 +86,7 @@ class DivPlatformSoundUnit: public DivDispatch {
short tempR;
unsigned char sampleBank, lfoMode, lfoSpeed;
SoundUnit* su;
size_t sampleMemLen;
unsigned char regPool[128];
void writeControl(int ch);
void writeControlUpper(int ch);
@ -110,6 +111,10 @@ class DivPlatformSoundUnit: public DivDispatch {
void poke(std::vector<DivRegWrite>& wlist);
const char** getRegisterSheet();
const char* getEffectName(unsigned char effect);
const void* getSampleMem(int index);
size_t getSampleMemCapacity(int index);
size_t getSampleMemUsage(int index);
void renderSamples();
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
void quit();
~DivPlatformSoundUnit();

View file

@ -86,7 +86,7 @@ struct DivSample {
unsigned int length8, length16, length1, lengthDPCM, lengthQSoundA, lengthA, lengthB, lengthX68, lengthBRR, lengthVOX;
unsigned int off8, off16, off1, offDPCM, offQSoundA, offA, offB, offX68, offBRR, offVOX;
unsigned int offSegaPCM, offQSound, offX1_010;
unsigned int offSegaPCM, offQSound, offX1_010, offSU;
unsigned int samples;
@ -247,6 +247,7 @@ struct DivSample {
offSegaPCM(0),
offQSound(0),
offX1_010(0),
offSU(0),
samples(0) {}
~DivSample();
};

View file

@ -457,7 +457,7 @@ struct DivSong {
system[0]=DIV_SYSTEM_YM2612;
system[1]=DIV_SYSTEM_SMS;
nullInsOPLL.fm.opllPreset=7;
nullInsOPLL.fm.opllPreset=0;
nullInsOPLL.fm.op[1].tl=0;
nullInsOPLL.name="This is a bug! Report!";

View file

@ -180,6 +180,7 @@ void FurnaceGUI::drawDebug() {
ImGui::Text("offSegaPCM: %x",sample->offSegaPCM);
ImGui::Text("offQSound: %x",sample->offQSound);
ImGui::Text("offX1_010: %x",sample->offX1_010);
ImGui::Text("offSU: %x",sample->offSU);
ImGui::Text("samples: %d",sample->samples);
ImGui::Unindent();