mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-30 00:13:03 +00:00
GBA DMA: implement sample memory
This commit is contained in:
parent
2b9dd1caff
commit
67253245ab
2 changed files with 86 additions and 14 deletions
|
@ -33,13 +33,12 @@ void DivPlatformGBADMA::acquire(short** buf, size_t len) {
|
||||||
// internal mixing is always 10-bit
|
// internal mixing is always 10-bit
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i<2; i++) {
|
||||||
bool newSamp=h==0;
|
bool newSamp=h==0;
|
||||||
|
chan[i].audDat=0;
|
||||||
if (chan[i].active && (chan[i].useWave || (chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen))) {
|
if (chan[i].active && (chan[i].useWave || (chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen))) {
|
||||||
chan[i].audSub+=(1<<outDepth);
|
chan[i].audSub+=(1<<outDepth);
|
||||||
if (chan[i].useWave) {
|
if (chan[i].useWave) {
|
||||||
if (chan[i].audPos<(int)chan[i].audLen) {
|
if (chan[i].audPos<(int)chan[i].audLen) {
|
||||||
chan[i].audDat=chan[i].ws.output[chan[i].audPos]-0x80;
|
chan[i].audDat=wtMem[i*256+chan[i].audPos];
|
||||||
} else {
|
|
||||||
chan[i].audDat=0;
|
|
||||||
}
|
}
|
||||||
newSamp=true;
|
newSamp=true;
|
||||||
if (chan[i].audSub>=chan[i].freq) {
|
if (chan[i].audSub>=chan[i].freq) {
|
||||||
|
@ -52,13 +51,12 @@ void DivPlatformGBADMA::acquire(short** buf, size_t len) {
|
||||||
}
|
}
|
||||||
chan[i].dmaCount&=15;
|
chan[i].dmaCount&=15;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (sampleLoaded[chan[i].sample]) {
|
||||||
DivSample* s=parent->getSample(chan[i].sample);
|
DivSample* s=parent->getSample(chan[i].sample);
|
||||||
if (s->samples>0) {
|
if (s->samples>0) {
|
||||||
if (chan[i].audPos>=0 && chan[i].audPos<(int)s->samples) {
|
if (chan[i].audPos>=0) {
|
||||||
chan[i].audDat=s->data8[chan[i].audPos];
|
unsigned int pos=(sampleOff[chan[i].sample]+chan[i].audPos)&0x01ffffff;
|
||||||
} else {
|
chan[i].audDat=sampleMem[pos];
|
||||||
chan[i].audDat=0;
|
|
||||||
}
|
}
|
||||||
newSamp=true;
|
newSamp=true;
|
||||||
if (chan[i].audSub>=chan[i].freq) {
|
if (chan[i].audSub>=chan[i].freq) {
|
||||||
|
@ -68,8 +66,9 @@ void DivPlatformGBADMA::acquire(short** buf, size_t len) {
|
||||||
chan[i].dmaCount+=posInc;
|
chan[i].dmaCount+=posInc;
|
||||||
if (s->isLoopable()) {
|
if (s->isLoopable()) {
|
||||||
if (chan[i].dmaCount>=16 && chan[i].audPos>=s->loopEnd) {
|
if (chan[i].dmaCount>=16 && chan[i].audPos>=s->loopEnd) {
|
||||||
int loopPos=chan[i].audPos-s->loopStart;
|
int loopStart=s->loopStart&~3;
|
||||||
chan[i].audPos=(loopPos%(s->loopEnd-s->loopStart))+s->loopStart;
|
int loopPos=chan[i].audPos-loopStart;
|
||||||
|
chan[i].audPos=(loopPos%(s->loopEnd-s->loopStart))+loopStart;
|
||||||
}
|
}
|
||||||
} else if (chan[i].audPos>=(int)s->samples) {
|
} else if (chan[i].audPos>=(int)s->samples) {
|
||||||
chan[i].sample=-1;
|
chan[i].sample=-1;
|
||||||
|
@ -82,8 +81,6 @@ void DivPlatformGBADMA::acquire(short** buf, size_t len) {
|
||||||
chan[i].audPos=0;
|
chan[i].audPos=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
chan[i].audDat=0;
|
|
||||||
}
|
}
|
||||||
if (!isMuted[i] && newSamp) {
|
if (!isMuted[i] && newSamp) {
|
||||||
int out=chan[i].audDat*(chan[i].vol*chan[i].envVol/2)<<1;
|
int out=chan[i].audDat*(chan[i].vol*chan[i].envVol/2)<<1;
|
||||||
|
@ -112,6 +109,7 @@ void DivPlatformGBADMA::tick(bool sysTick) {
|
||||||
if (chan[i].std.vol.had) {
|
if (chan[i].std.vol.had) {
|
||||||
chan[i].envVol=chan[i].std.vol.val;
|
chan[i].envVol=chan[i].std.vol.val;
|
||||||
if (ins->type==DIV_INS_AMIGA) chan[i].envVol/=32;
|
if (ins->type==DIV_INS_AMIGA) chan[i].envVol/=32;
|
||||||
|
else if (chan[i].envVol>2) chan[i].envVol=2;
|
||||||
}
|
}
|
||||||
if (NEW_ARP_STRAT) {
|
if (NEW_ARP_STRAT) {
|
||||||
chan[i].handleArp();
|
chan[i].handleArp();
|
||||||
|
@ -129,7 +127,9 @@ void DivPlatformGBADMA::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (chan[i].useWave && chan[i].active) {
|
if (chan[i].useWave && chan[i].active) {
|
||||||
chan[i].ws.tick();
|
if (chan[i].ws.tick()) {
|
||||||
|
updateWave(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (chan[i].std.pitch.had) {
|
if (chan[i].std.pitch.had) {
|
||||||
if (chan[i].std.pitch.mode) {
|
if (chan[i].std.pitch.mode) {
|
||||||
|
@ -257,7 +257,7 @@ int DivPlatformGBADMA::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_VOLUME:
|
case DIV_CMD_VOLUME:
|
||||||
if (chan[c.chan].vol!=c.value) {
|
if (chan[c.chan].vol!=c.value) {
|
||||||
chan[c.chan].vol=c.value;
|
chan[c.chan].vol=MIN(c.value,2);
|
||||||
if (!chan[c.chan].std.vol.has) {
|
if (!chan[c.chan].std.vol.has) {
|
||||||
chan[c.chan].envVol=2;
|
chan[c.chan].envVol=2;
|
||||||
}
|
}
|
||||||
|
@ -341,6 +341,13 @@ int DivPlatformGBADMA::dispatch(DivCommand c) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformGBADMA::updateWave(int ch) {
|
||||||
|
int addr=ch*256;
|
||||||
|
for (unsigned int i=0; i<chan[ch].audLen; i++) {
|
||||||
|
wtMem[addr+i]=(signed char)(chan[ch].ws.output[i]-128);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DivPlatformGBADMA::muteChannel(int ch, bool mute) {
|
void DivPlatformGBADMA::muteChannel(int ch, bool mute) {
|
||||||
isMuted[ch]=mute;
|
isMuted[ch]=mute;
|
||||||
}
|
}
|
||||||
|
@ -405,6 +412,7 @@ void DivPlatformGBADMA::notifyWaveChange(int wave) {
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i<2; i++) {
|
||||||
if (chan[i].useWave && chan[i].wave==wave) {
|
if (chan[i].useWave && chan[i].wave==wave) {
|
||||||
chan[i].ws.changeWave1(wave);
|
chan[i].ws.changeWave1(wave);
|
||||||
|
updateWave(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -415,6 +423,53 @@ void DivPlatformGBADMA::notifyInsDeletion(void* ins) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const void* DivPlatformGBADMA::getSampleMem(int index) {
|
||||||
|
return index == 0 ? sampleMem : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t DivPlatformGBADMA::getSampleMemCapacity(int index) {
|
||||||
|
return index == 0 ? 33554432 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t DivPlatformGBADMA::getSampleMemUsage(int index) {
|
||||||
|
return index == 0 ? sampleMemLen : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DivPlatformGBADMA::isSampleLoaded(int index, int sample) {
|
||||||
|
if (index!=0) return false;
|
||||||
|
if (sample<0 || sample>255) return false;
|
||||||
|
return sampleLoaded[sample];
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformGBADMA::renderSamples(int sysID) {
|
||||||
|
size_t maxPos=getSampleMemCapacity();
|
||||||
|
memset(sampleMem,0,maxPos);
|
||||||
|
|
||||||
|
size_t memPos=0;
|
||||||
|
for (int i=0; i<parent->song.sampleLen; i++) {
|
||||||
|
DivSample* s=parent->song.sample[i];
|
||||||
|
if (!s->renderOn[0][sysID]) {
|
||||||
|
sampleOff[i]=0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int length=s->length8;
|
||||||
|
int actualLength=MIN((int)(maxPos-memPos),length);
|
||||||
|
if (actualLength>0) {
|
||||||
|
sampleOff[i]=memPos;
|
||||||
|
memcpy(&sampleMem[memPos],s->data8,actualLength);
|
||||||
|
memPos+=actualLength;
|
||||||
|
}
|
||||||
|
if (actualLength<length) {
|
||||||
|
logW("out of GBA DMA PCM memory for sample %d!",i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sampleLoaded[i]=true;
|
||||||
|
// pad to multiple of 16 bytes
|
||||||
|
memPos=(memPos+15)&~15;
|
||||||
|
}
|
||||||
|
sampleMemLen=memPos;
|
||||||
|
}
|
||||||
|
|
||||||
void DivPlatformGBADMA::setFlags(const DivConfig& flags) {
|
void DivPlatformGBADMA::setFlags(const DivConfig& flags) {
|
||||||
outDepth=flags.getInt("dacDepth",9);
|
outDepth=flags.getInt("dacDepth",9);
|
||||||
chipClock=1<<24;
|
chipClock=1<<24;
|
||||||
|
@ -433,12 +488,15 @@ int DivPlatformGBADMA::init(DivEngine* p, int channels, int sugRate, const DivCo
|
||||||
isMuted[i]=false;
|
isMuted[i]=false;
|
||||||
oscBuf[i]=new DivDispatchOscBuffer;
|
oscBuf[i]=new DivDispatchOscBuffer;
|
||||||
}
|
}
|
||||||
|
sampleMem=new signed char[getSampleMemCapacity()];
|
||||||
|
sampleMemLen=0;
|
||||||
setFlags(flags);
|
setFlags(flags);
|
||||||
reset();
|
reset();
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformGBADMA::quit() {
|
void DivPlatformGBADMA::quit() {
|
||||||
|
delete[] sampleMem;
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i<2; i++) {
|
||||||
delete oscBuf[i];
|
delete oscBuf[i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,8 +54,14 @@ class DivPlatformGBADMA: public DivDispatch {
|
||||||
Channel chan[2];
|
Channel chan[2];
|
||||||
DivDispatchOscBuffer* oscBuf[2];
|
DivDispatchOscBuffer* oscBuf[2];
|
||||||
bool isMuted[2];
|
bool isMuted[2];
|
||||||
|
unsigned int sampleOff[256];
|
||||||
|
bool sampleLoaded[256];
|
||||||
int outDepth;
|
int outDepth;
|
||||||
|
|
||||||
|
signed char* sampleMem;
|
||||||
|
size_t sampleMemLen;
|
||||||
|
// maximum wavetable length is currently hardcoded to 256
|
||||||
|
signed char wtMem[256*2];
|
||||||
friend void putDispatchChip(void*,int);
|
friend void putDispatchChip(void*,int);
|
||||||
friend void putDispatchChan(void*,int,int);
|
friend void putDispatchChan(void*,int,int);
|
||||||
|
|
||||||
|
@ -76,8 +82,16 @@ class DivPlatformGBADMA: public DivDispatch {
|
||||||
void notifyInsChange(int ins);
|
void notifyInsChange(int ins);
|
||||||
void notifyWaveChange(int wave);
|
void notifyWaveChange(int wave);
|
||||||
void notifyInsDeletion(void* ins);
|
void notifyInsDeletion(void* ins);
|
||||||
|
const void* getSampleMem(int index = 0);
|
||||||
|
size_t getSampleMemCapacity(int index = 0);
|
||||||
|
size_t getSampleMemUsage(int index = 0);
|
||||||
|
bool isSampleLoaded(int index, int sample);
|
||||||
|
void renderSamples(int chipID);
|
||||||
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
|
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
|
||||||
void quit();
|
void quit();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateWave(int ch);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue