From a6ef36d42e3c4940bc35562275cff5f441224ec7 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 2 May 2022 14:51:06 -0500 Subject: [PATCH] SoundUnit: PCM support --- src/engine/platform/su.cpp | 84 ++++++++++++++++++++++++++++++++++++-- src/engine/platform/su.h | 5 +++ src/engine/sample.h | 3 +- src/engine/song.h | 2 +- src/gui/debugWindow.cpp | 3 +- 5 files changed, 90 insertions(+), 7 deletions(-) diff --git a/src/engine/platform/su.cpp b/src/engine/platform/su.cpp index a75b7c0b8..284c20801 100644 --- a/src/engine/platform/su.cpp +++ b/src/engine/platform/su.cpp @@ -19,6 +19,7 @@ #include "su.h" #include "../engine.h" +#include "../../ta-log.h" #include //#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& 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; isong.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; diff --git a/src/engine/platform/su.h b/src/engine/platform/su.h index 7ff3e8709..22ea1e78d 100644 --- a/src/engine/platform/su.h +++ b/src/engine/platform/su.h @@ -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& 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(); diff --git a/src/engine/sample.h b/src/engine/sample.h index ae0c06dae..6e4de0941 100644 --- a/src/engine/sample.h +++ b/src/engine/sample.h @@ -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(); }; diff --git a/src/engine/song.h b/src/engine/song.h index 8e67cce83..c0852ea0e 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -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!"; diff --git a/src/gui/debugWindow.cpp b/src/gui/debugWindow.cpp index 7b232a9cf..566f916fa 100644 --- a/src/gui/debugWindow.cpp +++ b/src/gui/debugWindow.cpp @@ -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(); @@ -312,4 +313,4 @@ void FurnaceGUI::drawDebug() { } if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_DEBUG; ImGui::End(); -} \ No newline at end of file +}