mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-27 06:53:01 +00:00
SoundUnit: PCM support
This commit is contained in:
parent
66f6ab4307
commit
a6ef36d42e
5 changed files with 90 additions and 7 deletions
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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!";
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue