Prepare for backward and bi-directional loop

This commit is contained in:
cam900 2022-08-11 22:21:54 +09:00
parent da8f7dabd5
commit d44f5f0b2b
27 changed files with 418 additions and 123 deletions

View file

@ -110,13 +110,13 @@ void DivPlatformAmiga::acquire(short* bufL, short* bufR, size_t start, size_t le
}
} else {
DivSample* s=parent->getSample(chan[i].sample);
if (s->samples>0) {
if (chan[i].audPos<s->samples) {
if (s->getEndPosition()>0) {
if (chan[i].audPos<(unsigned int)s->getEndPosition()) {
writeAudDat(s->data8[chan[i].audPos++]);
}
if (s->isLoopable() && chan[i].audPos>=MIN(131071,s->getEndPosition())) {
chan[i].audPos=s->loopStart;
} else if (chan[i].audPos>=MIN(131071,s->samples)) {
if (s->isLoopable() && chan[i].audPos>=MIN(131071,(unsigned int)s->getLoopEndPosition())) {
chan[i].audPos=s->getLoopStartPosition();
} else if (chan[i].audPos>=MIN(131071,(unsigned int)s->getEndPosition())) {
chan[i].sample=-1;
}
} else {

View file

@ -154,9 +154,9 @@ void DivPlatformGenesis::processDAC() {
if (s->samples>0) {
while (chan[i].dacPeriod>=(chipClock/576)) {
++chan[i].dacPos;
if (!chan[i].dacDirection && (s->isLoopable() && chan[i].dacPos>=s->getEndPosition())) {
chan[i].dacPos=s->loopStart;
} else if (chan[i].dacPos>=s->samples) {
if (!chan[i].dacDirection && (s->isLoopable() && chan[i].dacPos>=(unsigned int)s->getLoopEndPosition())) {
chan[i].dacPos=s->getLoopStartPosition();
} else if (chan[i].dacPos>=(unsigned int)s->getEndPosition()) {
chan[i].dacSample=-1;
chan[i].dacPeriod=0;
break;
@ -200,9 +200,9 @@ void DivPlatformGenesis::processDAC() {
}
}
chan[5].dacPos++;
if (!chan[5].dacDirection && (s->isLoopable() && chan[5].dacPos>=s->getEndPosition())) {
chan[5].dacPos=s->loopStart;
} else if (chan[5].dacPos>=s->samples) {
if (!chan[5].dacDirection && (s->isLoopable() && chan[5].dacPos>=(unsigned int)s->getLoopEndPosition())) {
chan[5].dacPos=s->getLoopStartPosition();
} else if (chan[5].dacPos>=(unsigned int)s->getEndPosition()) {
chan[5].dacSample=-1;
if (parent->song.brokenDACMode) {
rWrite(0x2b,0);

View file

@ -158,9 +158,9 @@ void DivPlatformLynx::acquire(short* bufL, short* bufR, size_t start, size_t len
WRITE_OUTPUT(i,(s->data8[chan[i].samplePos++]*chan[i].outVol)>>7);
}
if (s->isLoopable() && chan[i].samplePos>=(int)s->getEndPosition()) {
chan[i].samplePos=s->loopStart;
} else if (chan[i].samplePos>=(int)s->samples) {
if (s->isLoopable() && chan[i].samplePos>=s->getLoopEndPosition()) {
chan[i].samplePos=s->getLoopStartPosition();
} else if (chan[i].samplePos>=s->getEndPosition()) {
chan[i].sample=-1;
}
}

View file

@ -58,14 +58,14 @@ void DivPlatformMMC5::acquire(short* bufL, short* bufR, size_t start, size_t len
dacPeriod+=dacRate;
if (dacPeriod>=rate) {
DivSample* s=parent->getSample(dacSample);
if (s->samples>0) {
if (s->getEndPosition()>0) {
if (!isMuted[2]) {
rWrite(0x5011,((unsigned char)s->data8[dacPos]+0x80));
}
dacPos++;
if (s->isLoopable() && dacPos>=s->getEndPosition()) {
dacPos=s->loopStart;
} else if (dacPos>=s->samples) {
if (s->isLoopable() && dacPos>=(unsigned int)s->getLoopEndPosition()) {
dacPos=s->getLoopStartPosition();
} else if (dacPos>=(unsigned int)s->getEndPosition()) {
dacSample=-1;
}
dacPeriod-=rate;

View file

@ -97,7 +97,7 @@ void DivPlatformNES::doWrite(unsigned short addr, unsigned char data) {
dacPeriod+=dacRate; \
if (dacPeriod>=rate) { \
DivSample* s=parent->getSample(dacSample); \
if (s->samples>0) { \
if (s->getEndPosition()>0) { \
if (!isMuted[4]) { \
unsigned char next=((unsigned char)s->data8[dacPos]+0x80)>>1; \
if (dacAntiClickOn && dacAntiClick<next) { \
@ -109,9 +109,9 @@ void DivPlatformNES::doWrite(unsigned short addr, unsigned char data) {
} \
} \
dacPos++; \
if (s->isLoopable() && dacPos>=s->getEndPosition()) { \
dacPos=s->loopStart; \
} else if (dacPos>=s->samples) { \
if (s->isLoopable() && dacPos>=(unsigned int)s->getLoopEndPosition()) { \
dacPos=s->getLoopStartPosition(); \
} else if (dacPos>=(unsigned int)s->getEndPosition()) { \
dacSample=-1; \
} \
dacPeriod-=rate; \

View file

@ -82,7 +82,7 @@ void DivPlatformPCE::acquire(short* bufL, short* bufR, size_t start, size_t len)
chan[i].dacPeriod+=chan[i].dacRate;
if (chan[i].dacPeriod>rate) {
DivSample* s=parent->getSample(chan[i].dacSample);
if (s->samples<=0) {
if (s->getEndPosition()<=0) {
chan[i].dacSample=-1;
continue;
}
@ -90,9 +90,9 @@ void DivPlatformPCE::acquire(short* bufL, short* bufR, size_t start, size_t len)
chWrite(i,0x04,0xdf);
chWrite(i,0x06,(((unsigned char)s->data8[chan[i].dacPos]+0x80)>>3));
chan[i].dacPos++;
if (s->isLoopable() && chan[i].dacPos>=s->getEndPosition()) {
chan[i].dacPos=s->loopStart;
} else if (chan[i].dacPos>=s->samples) {
if (s->isLoopable() && chan[i].dacPos>=(unsigned int)s->getLoopEndPosition()) {
chan[i].dacPos=s->getLoopStartPosition();
} else if (chan[i].dacPos>=(unsigned int)s->getEndPosition()) {
chan[i].dacSample=-1;
}
chan[i].dacPeriod-=rate;

View file

@ -49,13 +49,13 @@ void DivPlatformPCMDAC::acquire(short* bufL, short* bufR, size_t start, size_t l
output=(chan.ws.output[chan.audPos]^0x80)<<8;
} else {
DivSample* s=parent->getSample(chan.sample);
if (s->samples>0) {
if (s->isLoopable() && chan.audPos>=s->getEndPosition()) {
chan.audPos=s->loopStart;
} else if (chan.audPos>=s->samples) {
if (s->getEndPosition()>0) {
if (s->isLoopable() && chan.audPos>=(unsigned int)s->getLoopEndPosition()) {
chan.audPos=s->getLoopStartPosition();
} else if (chan.audPos>=(unsigned int)s->getEndPosition()) {
chan.sample=-1;
}
if (chan.audPos<s->samples) {
if (chan.audPos<(unsigned int)s->getEndPosition()) {
output=s->data16[chan.audPos];
}
} else {

View file

@ -301,16 +301,17 @@ void DivPlatformQSound::tick(bool sysTick) {
qsound_bank = 0x8000 | (s->offQSound >> 16);
qsound_addr = s->offQSound & 0xffff;
int length = s->getEndPosition();
int loopStart=s->getLoopStartPosition();
int length = s->getLoopEndPosition();
if (length > 65536 - 16) {
length = 65536 - 16;
}
if (s->loopStart == -1 || s->loopStart >= length) {
if (loopStart == -1 || loopStart >= length) {
qsound_end = s->offQSound + length + 15;
qsound_loop = 15;
} else {
qsound_end = s->offQSound + length;
qsound_loop = length - s->loopStart;
qsound_loop = length - loopStart;
}
}
if (chan[i].std.arp.had) {

View file

@ -143,7 +143,7 @@ void DivPlatformRF5C68::tick(bool sysTick) {
start=start+MIN(chan[i].audPos,s->length8);
}
if (s->isLoopable()) {
loop=start+s->loopStart;
loop=start+s->getLoopStartPosition();
}
start=MIN(start,getSampleMemCapacity()-31);
loop=MIN(loop,getSampleMemCapacity()-31);
@ -393,7 +393,7 @@ void DivPlatformRF5C68::renderSamples() {
size_t memPos=0;
for (int i=0; i<parent->song.sampleLen; i++) {
DivSample* s=parent->song.sample[i];
int length=s->getEndPosition(DIV_SAMPLE_DEPTH_8BIT);
int length=s->getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT);
int actualLength=MIN((int)(getSampleMemCapacity()-memPos)-31,length);
if (actualLength>0) {
s->offRF5C68=memPos;

View file

@ -45,7 +45,7 @@ void DivPlatformSegaPCM::acquire(short* bufL, short* bufR, size_t start, size_t
for (int i=0; i<16; i++) {
if (chan[i].pcm.sample>=0 && chan[i].pcm.sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[i].pcm.sample);
if (s->samples<=0) {
if (s->getEndPosition()<=0) {
chan[i].pcm.sample=-1;
oscBuf[i]->data[oscBuf[i]->needle++]=0;
continue;
@ -56,9 +56,9 @@ void DivPlatformSegaPCM::acquire(short* bufL, short* bufR, size_t start, size_t
pcmR+=(s->data8[chan[i].pcm.pos>>8]*chan[i].chVolR);
}
chan[i].pcm.pos+=chan[i].pcm.freq;
if (s->isLoopable() && chan[i].pcm.pos>=(s->getEndPosition()<<8)) {
chan[i].pcm.pos=s->loopStart<<8;
} else if (chan[i].pcm.pos>=(s->samples<<8)) {
if (s->isLoopable() && chan[i].pcm.pos>=((unsigned int)s->getLoopEndPosition()<<8)) {
chan[i].pcm.pos=s->getLoopStartPosition()<<8;
} else if (chan[i].pcm.pos>=((unsigned int)s->getEndPosition()<<8)) {
chan[i].pcm.sample=-1;
}
} else {
@ -200,16 +200,17 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) {
chan[c.chan].macroInit(ins);
if (dumpWrites) { // Sega PCM writes
DivSample* s=parent->getSample(chan[c.chan].pcm.sample);
int actualLength=(int)(s->getEndPosition(DIV_SAMPLE_DEPTH_8BIT));
int loopStart=s->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT);
int actualLength=(s->getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT));
if (actualLength>0xfeff) actualLength=0xfeff;
addWrite(0x10086+(c.chan<<3),3+((s->offSegaPCM>>16)<<3));
addWrite(0x10084+(c.chan<<3),(s->offSegaPCM)&0xff);
addWrite(0x10085+(c.chan<<3),(s->offSegaPCM>>8)&0xff);
addWrite(0x10006+(c.chan<<3),MIN(255,((s->offSegaPCM&0xffff)+actualLength-1)>>8));
if (s->loopStart<0 || s->loopStart>=actualLength) {
if (loopStart<0 || loopStart>=actualLength) {
addWrite(0x10086+(c.chan<<3),2+((s->offSegaPCM>>16)<<3));
} else {
int loopPos=(s->offSegaPCM&0xffff)+s->loopStart+s->loopOffP;
int loopPos=(s->offSegaPCM&0xffff)+loopStart+s->loopOffP;
addWrite(0x10004+(c.chan<<3),loopPos&0xff);
addWrite(0x10005+(c.chan<<3),(loopPos>>8)&0xff);
addWrite(0x10086+(c.chan<<3),((s->offSegaPCM>>16)<<3));
@ -233,16 +234,17 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) {
chan[c.chan].furnacePCM=false;
if (dumpWrites) { // Sega PCM writes
DivSample* s=parent->getSample(chan[c.chan].pcm.sample);
int actualLength=(int)(s->getEndPosition(DIV_SAMPLE_DEPTH_8BIT));
int loopStart=s->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT);
int actualLength=(s->getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT));
if (actualLength>65536) actualLength=65536;
addWrite(0x10086+(c.chan<<3),3+((s->offSegaPCM>>16)<<3));
addWrite(0x10084+(c.chan<<3),(s->offSegaPCM)&0xff);
addWrite(0x10085+(c.chan<<3),(s->offSegaPCM>>8)&0xff);
addWrite(0x10006+(c.chan<<3),MIN(255,((s->offSegaPCM&0xffff)+actualLength-1)>>8));
if (s->loopStart<0 || s->loopStart>=actualLength) {
if (loopStart<0 || loopStart>=actualLength) {
addWrite(0x10086+(c.chan<<3),2+((s->offSegaPCM>>16)<<3));
} else {
int loopPos=(s->offSegaPCM&0xffff)+s->loopStart+s->loopOffP;
int loopPos=(s->offSegaPCM&0xffff)+loopStart+s->loopOffP;
addWrite(0x10004+(c.chan<<3),loopPos&0xff);
addWrite(0x10005+(c.chan<<3),(loopPos>>8)&0xff);
addWrite(0x10086+(c.chan<<3),((s->offSegaPCM>>16)<<3));

View file

@ -220,7 +220,7 @@ void DivPlatformSoundUnit::tick(bool sysTick) {
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SU);
DivSample* sample=parent->getSample(ins->amiga.getSample(chan[i].note));
if (sample!=NULL) {
unsigned int sampleEnd=sample->offSU+(sample->getEndPosition());
unsigned int sampleEnd=sample->offSU+(sample->getLoopEndPosition());
unsigned int off=sample->offSU+chan[i].hasOffset;
chan[i].hasOffset=0;
if (sampleEnd>=getSampleMemCapacity(0)) sampleEnd=getSampleMemCapacity(0)-1;
@ -229,7 +229,7 @@ void DivPlatformSoundUnit::tick(bool sysTick) {
chWrite(i,0x0c,sampleEnd&0xff);
chWrite(i,0x0d,sampleEnd>>8);
if (sample->isLoopable()) {
unsigned int sampleLoop=sample->offSU+sample->loopStart;
unsigned int sampleLoop=sample->offSU+sample->getLoopStartPosition();
if (sampleLoop>=getSampleMemCapacity(0)) sampleLoop=getSampleMemCapacity(0)-1;
chWrite(i,0x0e,sampleLoop&0xff);
chWrite(i,0x0f,sampleLoop>>8);
@ -603,7 +603,7 @@ void DivPlatformSoundUnit::renderSamples() {
for (int i=0; i<parent->song.sampleLen; i++) {
DivSample* s=parent->song.sample[i];
if (s->data8==NULL) continue;
int paddedLen=s->samples;
int paddedLen=s->getEndPosition();
if (memPos>=getSampleMemCapacity(0)) {
logW("out of PCM memory for sample %d!",i);
break;

View file

@ -78,14 +78,14 @@ void DivPlatformSwan::acquire(short* bufL, short* bufR, size_t start, size_t len
dacPeriod+=dacRate;
while (dacPeriod>rate) {
DivSample* s=parent->getSample(dacSample);
if (s->samples<=0) {
if (s->getEndPosition()<=0) {
dacSample=-1;
continue;
}
rWrite(0x09,(unsigned char)s->data8[dacPos++]+0x80);
if (s->isLoopable() && dacPos>=s->getEndPosition()) {
dacPos=s->loopStart;
} else if (dacPos>=s->samples) {
if (s->isLoopable() && dacPos>=(unsigned int)s->getLoopEndPosition()) {
dacPos=s->getLoopStartPosition();
} else if (dacPos>=(unsigned int)s->getEndPosition()) {
dacSample=-1;
}
dacPeriod-=rate;

View file

@ -70,7 +70,7 @@ void DivPlatformVERA::acquire(short* bufL, short* bufR, size_t start, size_t len
size_t pos=start;
DivSample* s=parent->getSample(chan[16].pcm.sample);
while (len>0) {
if (s->samples>0) {
if (s->getEndPosition()>0) {
while (pcm_is_fifo_almost_empty(pcm)) {
short tmp_l=0;
short tmp_r=0;
@ -96,9 +96,9 @@ void DivPlatformVERA::acquire(short* bufL, short* bufR, size_t start, size_t len
rWritePCMData(tmp_r&0xff);
}
chan[16].pcm.pos++;
if (s->isLoopable() && chan[16].pcm.pos>=s->getEndPosition()) {
chan[16].pcm.pos=s->loopStart;
} else if (chan[16].pcm.pos>=s->samples) {
if (s->isLoopable() && chan[16].pcm.pos>=(unsigned int)s->getLoopEndPosition()) {
chan[16].pcm.pos=s->getLoopStartPosition();
} else if (chan[16].pcm.pos>=(unsigned int)s->getEndPosition()) {
chan[16].pcm.sample=-1;
break;
}

View file

@ -66,7 +66,7 @@ void DivPlatformVRC6::acquire(short* bufL, short* bufR, size_t start, size_t len
chan[i].dacPeriod+=chan[i].dacRate;
if (chan[i].dacPeriod>rate) {
DivSample* s=parent->getSample(chan[i].dacSample);
if (s->samples<=0) {
if (s->getEndPosition()<=0) {
chan[i].dacSample=-1;
chWrite(i,0,0);
continue;
@ -77,9 +77,9 @@ void DivPlatformVRC6::acquire(short* bufL, short* bufR, size_t start, size_t len
chWrite(i,0,0x80|chan[i].dacOut);
}
chan[i].dacPos++;
if (s->isLoopable() && chan[i].dacPos>=s->getEndPosition()) {
chan[i].dacPos=s->loopStart;
} else if (chan[i].dacPos>=s->samples) {
if (s->isLoopable() && chan[i].dacPos>=(unsigned int)s->getLoopEndPosition()) {
chan[i].dacPos=s->getLoopStartPosition();
} else if (chan[i].dacPos>=(unsigned int)s->getEndPosition()) {
chan[i].dacSample=-1;
chWrite(i,0,0);
}

View file

@ -46,9 +46,9 @@ void DivPlatformZXBeeper::acquire(short* bufL, short* bufR, size_t start, size_t
if (curSample>=0 && curSample<parent->song.sampleLen) {
if (--curSamplePeriod<0) {
DivSample* s=parent->getSample(curSample);
if (s->samples>0) {
if (s->getEndPosition()>0) {
sampleOut=(s->data8[curSamplePos++]>0);
if (curSamplePos>=s->samples) curSample=-1;
if (curSamplePos>=(unsigned int)s->getEndPosition()) curSample=-1;
// 256 bits
if (curSamplePos>2047) curSample=-1;