Implement sample loop end position, enum-ise sample depth (#557)

TODO: new sample format
This commit is contained in:
cam900 2022-07-22 13:36:42 +09:00 committed by GitHub
parent a137eefd20
commit 5127d5ef18
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 461 additions and 306 deletions

View file

@ -114,12 +114,10 @@ void DivPlatformAmiga::acquire(short* bufL, short* bufR, size_t start, size_t le
if (chan[i].audPos<s->samples) {
writeAudDat(s->data8[chan[i].audPos++]);
}
if (chan[i].audPos>=s->samples || chan[i].audPos>=131071) {
if (s->loopStart>=0 && s->loopStart<(int)s->samples) {
chan[i].audPos=s->loopStart;
} else {
chan[i].sample=-1;
}
if (s->isLoopable() && chan[i].audPos>=MIN(131071,s->getEndPosition())) {
chan[i].audPos=s->loopStart;
} else if (chan[i].audPos>=MIN(131071,s->samples)) {
chan[i].sample=-1;
}
} else {
chan[i].sample=-1;

View file

@ -153,14 +153,13 @@ void DivPlatformGenesis::processDAC() {
if (chan[i].dacPeriod>=(chipClock/576)) {
if (s->samples>0) {
while (chan[i].dacPeriod>=(chipClock/576)) {
if (++chan[i].dacPos>=s->samples) {
if (s->loopStart>=0 && s->loopStart<(int)s->samples && !chan[i].dacDirection) {
chan[i].dacPos=s->loopStart;
} else {
chan[i].dacSample=-1;
chan[i].dacPeriod=0;
break;
}
++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) {
chan[i].dacSample=-1;
chan[i].dacPeriod=0;
break;
}
chan[i].dacPeriod-=(chipClock/576);
}
@ -200,14 +199,13 @@ void DivPlatformGenesis::processDAC() {
chan[5].dacReady=false;
}
}
if (++chan[5].dacPos>=s->samples) {
if (s->loopStart>=0 && s->loopStart<(int)s->samples && !chan[5].dacDirection) {
chan[5].dacPos=s->loopStart;
} else {
chan[5].dacSample=-1;
if (parent->song.brokenDACMode) {
rWrite(0x2b,0);
}
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) {
chan[5].dacSample=-1;
if (parent->song.brokenDACMode) {
rWrite(0x2b,0);
}
}
while (chan[5].dacPeriod>=rate) chan[5].dacPeriod-=rate;

View file

@ -158,12 +158,10 @@ 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 (chan[i].samplePos>=(int)s->samples) {
if (s->loopStart>=0 && s->loopStart<(int)s->samples) {
chan[i].samplePos=s->loopStart;
} else {
chan[i].sample=-1;
}
if (s->isLoopable() && chan[i].samplePos>=(int)s->getEndPosition()) {
chan[i].samplePos=s->loopStart;
} else if (chan[i].samplePos>=(int)s->samples) {
chan[i].sample=-1;
}
}
}

View file

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

View file

@ -108,12 +108,11 @@ void DivPlatformNES::doWrite(unsigned short addr, unsigned char data) {
rWrite(0x4011,next); \
} \
} \
if (++dacPos>=s->samples) { \
if (s->loopStart>=0 && s->loopStart<(int)s->samples) { \
dacPos=s->loopStart; \
} else { \
dacSample=-1; \
} \
dacPos++; \
if (s->isLoopable() && dacPos>=s->getEndPosition()) { \
dacPos=s->loopStart; \
} else if (dacPos>=s->samples) { \
dacSample=-1; \
} \
dacPeriod-=rate; \
} else { \

View file

@ -771,7 +771,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
int end=s->offB+s->lengthB-1;
immWrite(11,(end>>2)&0xff);
immWrite(12,(end>>10)&0xff);
immWrite(7,(s->loopStart>=0)?0xb0:0xa0); // start/repeat
immWrite(7,(s->isLoopable())?0xb0:0xa0); // start/repeat
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value;
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
@ -807,7 +807,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
int end=s->offB+s->lengthB-1;
immWrite(11,(end>>2)&0xff);
immWrite(12,(end>>10)&0xff);
immWrite(7,(s->loopStart>=0)?0xb0:0xa0); // start/repeat
immWrite(7,(s->isLoopable())?0xb0:0xa0); // start/repeat
int freq=(65536.0*(double)s->rate)/(double)chipRateBase;
immWrite(16,freq&0xff);
immWrite(17,(freq>>8)&0xff);

View file

@ -90,12 +90,10 @@ 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 (chan[i].dacPos>=s->samples) {
if (s->loopStart>=0 && s->loopStart<(int)s->samples) {
chan[i].dacPos=s->loopStart;
} else {
chan[i].dacSample=-1;
}
if (s->isLoopable() && chan[i].dacPos>=s->getEndPosition()) {
chan[i].dacPos=s->loopStart;
} else if (chan[i].dacPos>=s->samples) {
chan[i].dacSample=-1;
}
chan[i].dacPeriod-=rate;
}

View file

@ -301,7 +301,7 @@ void DivPlatformQSound::tick(bool sysTick) {
qsound_bank = 0x8000 | (s->offQSound >> 16);
qsound_addr = s->offQSound & 0xffff;
int length = s->samples;
int length = s->getEndPosition();
if (length > 65536 - 16) {
length = 65536 - 16;
}

View file

@ -142,7 +142,7 @@ void DivPlatformRF5C68::tick(bool sysTick) {
if (chan[i].audPos>0) {
start=start+MIN(chan[i].audPos,s->length8);
}
if (s->loopStart>=0) {
if (s->isLoopable()) {
loop=start+s->loopStart;
}
start=MIN(start,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->length8;
int length=s->getEndPosition(DIV_SAMPLE_DEPTH_8BIT);
int actualLength=MIN((int)(getSampleMemCapacity()-memPos)-31,length);
if (actualLength>0) {
s->offRF5C68=memPos;

View file

@ -56,12 +56,10 @@ 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 (chan[i].pcm.pos>=(s->samples<<8)) {
if (s->loopStart>=0 && s->loopStart<(int)s->samples) {
chan[i].pcm.pos=s->loopStart<<8;
} else {
chan[i].pcm.sample=-1;
}
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)) {
chan[i].pcm.sample=-1;
}
} else {
oscBuf[i]->data[oscBuf[i]->needle++]=0;
@ -202,7 +200,7 @@ 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->length8;
int actualLength=(int)(s->getEndPosition(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);
@ -235,7 +233,7 @@ 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->length8;
int actualLength=(int)(s->getEndPosition(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);

View file

@ -213,7 +213,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->samples;
unsigned int sampleEnd=sample->offSU+(sample->getEndPosition());
unsigned int off=sample->offSU+chan[i].hasOffset;
chan[i].hasOffset=0;
if (sampleEnd>=getSampleMemCapacity(0)) sampleEnd=getSampleMemCapacity(0)-1;
@ -221,7 +221,7 @@ void DivPlatformSoundUnit::tick(bool sysTick) {
chWrite(i,0x0b,off>>8);
chWrite(i,0x0c,sampleEnd&0xff);
chWrite(i,0x0d,sampleEnd>>8);
if (sample->loopStart>=0 && sample->loopStart<(int)sample->samples) {
if (sample->isLoopable()) {
unsigned int sampleLoop=sample->offSU+sample->loopStart;
if (sampleLoop>=getSampleMemCapacity(0)) sampleLoop=getSampleMemCapacity(0)-1;
chWrite(i,0x0e,sampleLoop&0xff);

View file

@ -83,12 +83,10 @@ void DivPlatformSwan::acquire(short* bufL, short* bufR, size_t start, size_t len
continue;
}
rWrite(0x09,(unsigned char)s->data8[dacPos++]+0x80);
if (dacPos>=s->samples) {
if (s->loopStart>=0 && s->loopStart<(int)s->samples) {
dacPos=s->loopStart;
} else {
dacSample=-1;
}
if (s->isLoopable() && dacPos>=s->getEndPosition()) {
dacPos=s->loopStart;
} else if (dacPos>=s->samples) {
dacSample=-1;
}
dacPeriod-=rate;
}

View file

@ -96,13 +96,11 @@ void DivPlatformVERA::acquire(short* bufL, short* bufR, size_t start, size_t len
rWritePCMData(tmp_r&0xff);
}
chan[16].pcm.pos++;
if (chan[16].pcm.pos>=s->samples) {
if (s->loopStart>=0 && s->loopStart<(int)s->samples) {
chan[16].pcm.pos=s->loopStart;
} else {
chan[16].pcm.sample=-1;
break;
}
if (s->isLoopable() && chan[16].pcm.pos>=s->getEndPosition()) {
chan[16].pcm.pos=s->loopStart;
} else if (chan[16].pcm.pos>=s->samples) {
chan[16].pcm.sample=-1;
break;
}
}
} else {
@ -267,12 +265,12 @@ int DivPlatformVERA::dispatch(DivCommand c) {
chan[16].pcm.pos=0;
DivSample* s=parent->getSample(chan[16].pcm.sample);
unsigned char ctrl=0x90|chan[16].vol; // always stereo
if (s->depth==16) {
if (s->depth==DIV_SAMPLE_DEPTH_16BIT) {
chan[16].pcm.depth16=true;
ctrl|=0x20;
} else {
chan[16].pcm.depth16=false;
if (s->depth!=8) chan[16].pcm.sample=-1;
if (s->depth!=DIV_SAMPLE_DEPTH_8BIT) chan[16].pcm.sample=-1;
}
rWritePCMCtrl(ctrl);
}

View file

@ -77,13 +77,11 @@ void DivPlatformVRC6::acquire(short* bufL, short* bufR, size_t start, size_t len
chWrite(i,0,0x80|chan[i].dacOut);
}
chan[i].dacPos++;
if (chan[i].dacPos>=s->samples) {
if (s->loopStart>=0 && s->loopStart<(int)s->samples) {
chan[i].dacPos=s->loopStart;
} else {
chan[i].dacSample=-1;
chWrite(i,0,0);
}
if (s->isLoopable() && chan[i].dacPos>=s->getEndPosition()) {
chan[i].dacPos=s->loopStart;
} else if (chan[i].dacPos>=s->samples) {
chan[i].dacSample=-1;
chWrite(i,0,0);
}
chan[i].dacPeriod-=rate;
}

View file

@ -761,7 +761,7 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
immWrite(0x104,(end>>5)&0xff);
immWrite(0x105,(end>>13)&0xff);
immWrite(0x101,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|2);
immWrite(0x100,(s->loopStart>=0)?0xb0:0xa0); // start/repeat
immWrite(0x100,(s->isLoopable())?0xb0:0xa0); // start/repeat
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value;
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
@ -796,7 +796,7 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
immWrite(0x104,(end>>5)&0xff);
immWrite(0x105,(end>>13)&0xff);
immWrite(0x101,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|2);
immWrite(0x100,(s->loopStart>=0)?0xb0:0xa0); // start/repeat
immWrite(0x100,(s->isLoopable())?0xb0:0xa0); // start/repeat
int freq=(65536.0*(double)s->rate)/((double)chipClock/144.0);
immWrite(0x109,freq&0xff);
immWrite(0x10a,(freq>>8)&0xff);

View file

@ -793,7 +793,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
immWrite(0x14,(end>>8)&0xff);
immWrite(0x15,end>>16);
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
immWrite(0x10,(s->loopStart>=0)?0x90:0x80); // start/repeat
immWrite(0x10,(s->isLoopable())?0x90:0x80); // start/repeat
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value;
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
@ -828,7 +828,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
immWrite(0x14,(end>>8)&0xff);
immWrite(0x15,end>>16);
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
immWrite(0x10,(s->loopStart>=0)?0x90:0x80); // start/repeat
immWrite(0x10,(s->isLoopable())?0x90:0x80); // start/repeat
int freq=(65536.0*(double)s->rate)/((double)chipClock/144.0);
immWrite(0x19,freq&0xff);
immWrite(0x1a,(freq>>8)&0xff);

View file

@ -775,7 +775,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
immWrite(0x14,(end>>8)&0xff);
immWrite(0x15,end>>16);
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
immWrite(0x10,(s->loopStart>=0)?0x90:0x80); // start/repeat
immWrite(0x10,(s->isLoopable())?0x90:0x80); // start/repeat
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value;
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
@ -810,7 +810,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
immWrite(0x14,(end>>8)&0xff);
immWrite(0x15,end>>16);
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
immWrite(0x10,(s->loopStart>=0)?0x90:0x80); // start/repeat
immWrite(0x10,(s->isLoopable())?0x90:0x80); // start/repeat
int freq=(65536.0*(double)s->rate)/((double)chipClock/144.0);
immWrite(0x19,freq&0xff);
immWrite(0x1a,(freq>>8)&0xff);

View file

@ -136,9 +136,9 @@ void DivPlatformYMZ280B::tick(bool sysTick) {
DivSample* s=parent->getSample(chan[i].sample);
unsigned char ctrl;
switch (s->depth) {
case 3: ctrl=0x20; break;
case 8: ctrl=0x40; break;
case 16: ctrl=0x60; break;
case DIV_SAMPLE_DEPTH_YMZ_ADPCM: ctrl=0x20; break;
case DIV_SAMPLE_DEPTH_8BIT: ctrl=0x40; break;
case DIV_SAMPLE_DEPTH_16BIT: ctrl=0x60; break;
default: ctrl=0;
}
double off=(s->centerRate>=1)?((double)s->centerRate/8363.0):1.0;
@ -146,40 +146,44 @@ void DivPlatformYMZ280B::tick(bool sysTick) {
if (chan[i].freq<0) chan[i].freq=0;
if (chan[i].freq>511) chan[i].freq=511;
// ADPCM has half the range
if (s->depth==3 && chan[i].freq>255) chan[i].freq=255;
ctrl|=(chan[i].active?0x80:0)|((s->loopStart>=0)?0x10:0)|(chan[i].freq>>8);
if (s->depth==DIV_SAMPLE_DEPTH_YMZ_ADPCM && chan[i].freq>255) chan[i].freq=255;
ctrl|=(chan[i].active?0x80:0)|((s->isLoopable())?0x10:0)|(chan[i].freq>>8);
if (chan[i].keyOn) {
unsigned int start=s->offYMZ280B;
unsigned int loop=0;
unsigned int loopStart=0;
unsigned int loopEnd=0;
unsigned int end=MIN(start+s->getCurBufLen(),getSampleMemCapacity()-1);
if (chan[i].audPos>0) {
switch (s->depth) {
case 3: start+=chan[i].audPos/2; break;
case 8: start+=chan[i].audPos; break;
case 16: start+=chan[i].audPos*2; break;
case DIV_SAMPLE_DEPTH_YMZ_ADPCM: start+=chan[i].audPos/2; break;
case DIV_SAMPLE_DEPTH_8BIT: start+=chan[i].audPos; break;
case DIV_SAMPLE_DEPTH_16BIT: start+=chan[i].audPos*2; break;
default: break;
}
start=MIN(start,end);
}
if (s->loopStart>=0) {
if (s->isLoopable()) {
switch (s->depth) {
case 3: loop=start+s->loopStart/2; break;
case 8: loop=start+s->loopStart; break;
case 16: loop=start+s->loopStart*2; break;
case DIV_SAMPLE_DEPTH_YMZ_ADPCM: loopStart=start+s->loopStart/2; loopEnd=start+s->loopEnd/2; break;
case DIV_SAMPLE_DEPTH_8BIT: loopStart=start+s->loopStart; loopEnd=start+s->loopEnd; break;
case DIV_SAMPLE_DEPTH_16BIT: loopStart=start+s->loopStart*2; loopEnd=start+s->loopEnd*2; break;
default: break;
}
loop=MIN(loop,end);
loopEnd=MIN(loopEnd,end);
loopStart=MIN(loopStart,loopEnd);
}
rWrite(0x01+i*4,ctrl&~0x80); // force keyoff first
rWrite(0x20+i*4,(start>>16)&0xff);
rWrite(0x21+i*4,(loop>>16)&0xff);
rWrite(0x22+i*4,(end>>16)&0xff);
rWrite(0x21+i*4,(loopStart>>16)&0xff);
rWrite(0x22+i*4,(loopEnd>>16)&0xff);
rWrite(0x23+i*4,(end>>16)&0xff);
rWrite(0x40+i*4,(start>>8)&0xff);
rWrite(0x41+i*4,(loop>>8)&0xff);
rWrite(0x42+i*4,(end>>8)&0xff);
rWrite(0x41+i*4,(loopStart>>8)&0xff);
rWrite(0x42+i*4,(loopEnd>>8)&0xff);
rWrite(0x43+i*4,(end>>8)&0xff);
rWrite(0x60+i*4,start&0xff);
rWrite(0x61+i*4,loop&0xff);
rWrite(0x62+i*4,end&0xff);
rWrite(0x61+i*4,loopStart&0xff);
rWrite(0x62+i*4,loopEnd&0xff);
rWrite(0x63+i*4,end&0xff);
if (!chan[i].std.vol.had) {
chan[i].outVol=chan[i].vol;