Implement sample loop end position, enum-ise sample depth (#557)
TODO: new sample format
This commit is contained in:
parent
a137eefd20
commit
5127d5ef18
|
@ -2226,7 +2226,7 @@ int DivEngine::addSampleFromFile(const char* path) {
|
||||||
|
|
||||||
sample->rate=33144;
|
sample->rate=33144;
|
||||||
sample->centerRate=33144;
|
sample->centerRate=33144;
|
||||||
sample->depth=1;
|
sample->depth=DIV_SAMPLE_DEPTH_1BIT_DPCM;
|
||||||
sample->init(len*8);
|
sample->init(len*8);
|
||||||
|
|
||||||
if (fread(sample->dataDPCM,1,len,f)==0) {
|
if (fread(sample->dataDPCM,1,len,f)==0) {
|
||||||
|
@ -2301,9 +2301,9 @@ int DivEngine::addSampleFromFile(const char* path) {
|
||||||
|
|
||||||
int index=0;
|
int index=0;
|
||||||
if ((si.format&SF_FORMAT_SUBMASK)==SF_FORMAT_PCM_U8) {
|
if ((si.format&SF_FORMAT_SUBMASK)==SF_FORMAT_PCM_U8) {
|
||||||
sample->depth=8;
|
sample->depth=DIV_SAMPLE_DEPTH_8BIT;
|
||||||
} else {
|
} else {
|
||||||
sample->depth=16;
|
sample->depth=DIV_SAMPLE_DEPTH_16BIT;
|
||||||
}
|
}
|
||||||
sample->init(si.frames);
|
sample->init(si.frames);
|
||||||
if ((si.format&SF_FORMAT_SUBMASK)==SF_FORMAT_PCM_U8) {
|
if ((si.format&SF_FORMAT_SUBMASK)==SF_FORMAT_PCM_U8) {
|
||||||
|
@ -2358,6 +2358,7 @@ int DivEngine::addSampleFromFile(const char* path) {
|
||||||
if(inst.loop_count && inst.loops[0].mode == SF_LOOP_FORWARD)
|
if(inst.loop_count && inst.loops[0].mode == SF_LOOP_FORWARD)
|
||||||
{
|
{
|
||||||
sample->loopStart=inst.loops[0].start;
|
sample->loopStart=inst.loops[0].start;
|
||||||
|
sample->loopEnd=inst.loops[0].end;
|
||||||
if(inst.loops[0].end < (unsigned int)sampleCount)
|
if(inst.loops[0].end < (unsigned int)sampleCount)
|
||||||
sampleCount=inst.loops[0].end;
|
sampleCount=inst.loops[0].end;
|
||||||
}
|
}
|
||||||
|
|
|
@ -799,17 +799,17 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
|
||||||
sample->rate=ymuSampleRate*400;
|
sample->rate=ymuSampleRate*400;
|
||||||
}
|
}
|
||||||
if (ds.version>0x15) {
|
if (ds.version>0x15) {
|
||||||
sample->depth=reader.readC();
|
sample->depth=(DivSampleDepth)reader.readC();
|
||||||
if (sample->depth!=8 && sample->depth!=16) {
|
if (sample->depth!=DIV_SAMPLE_DEPTH_8BIT && sample->depth!=DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
logW("%d: sample depth is wrong! (%d)",i,sample->depth);
|
logW("%d: sample depth is wrong! (%d)",i,sample->depth);
|
||||||
sample->depth=16;
|
sample->depth=DIV_SAMPLE_DEPTH_16BIT;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (ds.version>0x08) {
|
if (ds.version>0x08) {
|
||||||
sample->depth=16;
|
sample->depth=DIV_SAMPLE_DEPTH_16BIT;
|
||||||
} else {
|
} else {
|
||||||
// it appears samples were stored as ADPCM back then
|
// it appears samples were stored as ADPCM back then
|
||||||
sample->depth=3;
|
sample->depth=DIV_SAMPLE_DEPTH_YMZ_ADPCM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (length>0) {
|
if (length>0) {
|
||||||
|
@ -838,7 +838,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
|
||||||
if (k>=sample->samples) {
|
if (k>=sample->samples) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (sample->depth==8) {
|
if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
float next=(float)(data[(unsigned int)j]-0x80)*mult;
|
float next=(float)(data[(unsigned int)j]-0x80)*mult;
|
||||||
sample->data8[k++]=fmin(fmax(next,-128),127);
|
sample->data8[k++]=fmin(fmax(next,-128),127);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1631,7 +1631,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
logD("reading sample %d at %x...",i,samplePtr[i]);
|
logD("reading sample %d at %x...",i,samplePtr[i]);
|
||||||
|
|
||||||
sample->name=reader.readString();
|
sample->name=reader.readString();
|
||||||
sample->samples=reader.readI();
|
sample->samples=sample->loopEnd=reader.readI();
|
||||||
sample->rate=reader.readI();
|
sample->rate=reader.readI();
|
||||||
if (ds.version<58) {
|
if (ds.version<58) {
|
||||||
vol=reader.readS();
|
vol=reader.readS();
|
||||||
|
@ -1639,7 +1639,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
} else {
|
} else {
|
||||||
reader.readI();
|
reader.readI();
|
||||||
}
|
}
|
||||||
sample->depth=reader.readC();
|
sample->depth=(DivSampleDepth)reader.readC();
|
||||||
|
|
||||||
// reserved
|
// reserved
|
||||||
reader.readC();
|
reader.readC();
|
||||||
|
@ -1657,6 +1657,13 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
reader.readI();
|
reader.readI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (ds.version>=100) {
|
||||||
|
sample->loopEnd=reader.readI();
|
||||||
|
} else {
|
||||||
|
reader.readI();
|
||||||
|
}
|
||||||
|
*/
|
||||||
if (ds.version>=58) { // modern sample
|
if (ds.version>=58) { // modern sample
|
||||||
sample->init(sample->samples);
|
sample->init(sample->samples);
|
||||||
reader.read(sample->getCurBuf(),sample->getCurBufLen());
|
reader.read(sample->getCurBuf(),sample->getCurBufLen());
|
||||||
|
@ -1670,9 +1677,9 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// render data
|
// render data
|
||||||
if (sample->depth!=8 && sample->depth!=16) {
|
if (sample->depth!=DIV_SAMPLE_DEPTH_8BIT && sample->depth!=DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
logW("%d: sample depth is wrong! (%d)",i,sample->depth);
|
logW("%d: sample depth is wrong! (%d)",i,sample->depth);
|
||||||
sample->depth=16;
|
sample->depth=DIV_SAMPLE_DEPTH_16BIT;
|
||||||
}
|
}
|
||||||
sample->samples=(double)sample->samples/samplePitches[pitch];
|
sample->samples=(double)sample->samples/samplePitches[pitch];
|
||||||
sample->init(sample->samples);
|
sample->init(sample->samples);
|
||||||
|
@ -1683,7 +1690,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
if (k>=sample->samples) {
|
if (k>=sample->samples) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (sample->depth==8) {
|
if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
float next=(float)(data[(unsigned int)j]-0x80)*mult;
|
float next=(float)(data[(unsigned int)j]-0x80)*mult;
|
||||||
sample->data8[k++]=fmin(fmax(next,-128),127);
|
sample->data8[k++]=fmin(fmax(next,-128),127);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1877,7 +1884,7 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) {
|
||||||
logD("reading samples... (%d)",insCount);
|
logD("reading samples... (%d)",insCount);
|
||||||
for (int i=0; i<insCount; i++) {
|
for (int i=0; i<insCount; i++) {
|
||||||
DivSample* sample=new DivSample;
|
DivSample* sample=new DivSample;
|
||||||
sample->depth=8;
|
sample->depth=DIV_SAMPLE_DEPTH_8BIT;
|
||||||
sample->name=reader.readString(22);
|
sample->name=reader.readString(22);
|
||||||
logD("%d: %s",i+1,sample->name);
|
logD("%d: %s",i+1,sample->name);
|
||||||
int slen=((unsigned short)reader.readS_BE())*2;
|
int slen=((unsigned short)reader.readS_BE())*2;
|
||||||
|
@ -1897,8 +1904,8 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) {
|
||||||
loopLen=0;
|
loopLen=0;
|
||||||
}
|
}
|
||||||
if (loopLen>=2) {
|
if (loopLen>=2) {
|
||||||
if (loopEnd<slen) slen=loopEnd;
|
|
||||||
sample->loopStart=loopStart;
|
sample->loopStart=loopStart;
|
||||||
|
sample->loopEnd=loopEnd;
|
||||||
}
|
}
|
||||||
sample->init(slen);
|
sample->init(slen);
|
||||||
ds.sample.push_back(sample);
|
ds.sample.push_back(sample);
|
||||||
|
@ -3043,6 +3050,7 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) {
|
||||||
w->writeC(0);
|
w->writeC(0);
|
||||||
w->writeS(sample->centerRate);
|
w->writeS(sample->centerRate);
|
||||||
w->writeI(sample->loopStart);
|
w->writeI(sample->loopStart);
|
||||||
|
//w->writeI(sample->loopEnd);
|
||||||
|
|
||||||
w->write(sample->getCurBuf(),sample->getCurBufLen());
|
w->write(sample->getCurBuf(),sample->getCurBufLen());
|
||||||
|
|
||||||
|
|
|
@ -114,13 +114,11 @@ void DivPlatformAmiga::acquire(short* bufL, short* bufR, size_t start, size_t le
|
||||||
if (chan[i].audPos<s->samples) {
|
if (chan[i].audPos<s->samples) {
|
||||||
writeAudDat(s->data8[chan[i].audPos++]);
|
writeAudDat(s->data8[chan[i].audPos++]);
|
||||||
}
|
}
|
||||||
if (chan[i].audPos>=s->samples || chan[i].audPos>=131071) {
|
if (s->isLoopable() && chan[i].audPos>=MIN(131071,s->getEndPosition())) {
|
||||||
if (s->loopStart>=0 && s->loopStart<(int)s->samples) {
|
|
||||||
chan[i].audPos=s->loopStart;
|
chan[i].audPos=s->loopStart;
|
||||||
} else {
|
} else if (chan[i].audPos>=MIN(131071,s->samples)) {
|
||||||
chan[i].sample=-1;
|
chan[i].sample=-1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
chan[i].sample=-1;
|
chan[i].sample=-1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,15 +153,14 @@ void DivPlatformGenesis::processDAC() {
|
||||||
if (chan[i].dacPeriod>=(chipClock/576)) {
|
if (chan[i].dacPeriod>=(chipClock/576)) {
|
||||||
if (s->samples>0) {
|
if (s->samples>0) {
|
||||||
while (chan[i].dacPeriod>=(chipClock/576)) {
|
while (chan[i].dacPeriod>=(chipClock/576)) {
|
||||||
if (++chan[i].dacPos>=s->samples) {
|
++chan[i].dacPos;
|
||||||
if (s->loopStart>=0 && s->loopStart<(int)s->samples && !chan[i].dacDirection) {
|
if (!chan[i].dacDirection && (s->isLoopable() && chan[i].dacPos>=s->getEndPosition())) {
|
||||||
chan[i].dacPos=s->loopStart;
|
chan[i].dacPos=s->loopStart;
|
||||||
} else {
|
} else if (chan[i].dacPos>=s->samples) {
|
||||||
chan[i].dacSample=-1;
|
chan[i].dacSample=-1;
|
||||||
chan[i].dacPeriod=0;
|
chan[i].dacPeriod=0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
chan[i].dacPeriod-=(chipClock/576);
|
chan[i].dacPeriod-=(chipClock/576);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -200,16 +199,15 @@ void DivPlatformGenesis::processDAC() {
|
||||||
chan[5].dacReady=false;
|
chan[5].dacReady=false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (++chan[5].dacPos>=s->samples) {
|
chan[5].dacPos++;
|
||||||
if (s->loopStart>=0 && s->loopStart<(int)s->samples && !chan[5].dacDirection) {
|
if (!chan[5].dacDirection && (s->isLoopable() && chan[5].dacPos>=s->getEndPosition())) {
|
||||||
chan[5].dacPos=s->loopStart;
|
chan[5].dacPos=s->loopStart;
|
||||||
} else {
|
} else if (chan[5].dacPos>=s->samples) {
|
||||||
chan[5].dacSample=-1;
|
chan[5].dacSample=-1;
|
||||||
if (parent->song.brokenDACMode) {
|
if (parent->song.brokenDACMode) {
|
||||||
rWrite(0x2b,0);
|
rWrite(0x2b,0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
while (chan[5].dacPeriod>=rate) chan[5].dacPeriod-=rate;
|
while (chan[5].dacPeriod>=rate) chan[5].dacPeriod-=rate;
|
||||||
} else {
|
} else {
|
||||||
chan[5].dacSample=-1;
|
chan[5].dacSample=-1;
|
||||||
|
|
|
@ -158,17 +158,15 @@ 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);
|
WRITE_OUTPUT(i,(s->data8[chan[i].samplePos++]*chan[i].outVol)>>7);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chan[i].samplePos>=(int)s->samples) {
|
if (s->isLoopable() && chan[i].samplePos>=(int)s->getEndPosition()) {
|
||||||
if (s->loopStart>=0 && s->loopStart<(int)s->samples) {
|
|
||||||
chan[i].samplePos=s->loopStart;
|
chan[i].samplePos=s->loopStart;
|
||||||
} else {
|
} else if (chan[i].samplePos>=(int)s->samples) {
|
||||||
chan[i].sample=-1;
|
chan[i].sample=-1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mikey->sampleAudio( bufL + h, bufR + h, 1, oscBuf );
|
mikey->sampleAudio( bufL + h, bufR + h, 1, oscBuf );
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,13 +62,12 @@ void DivPlatformMMC5::acquire(short* bufL, short* bufR, size_t start, size_t len
|
||||||
if (!isMuted[2]) {
|
if (!isMuted[2]) {
|
||||||
rWrite(0x5011,((unsigned char)s->data8[dacPos]+0x80));
|
rWrite(0x5011,((unsigned char)s->data8[dacPos]+0x80));
|
||||||
}
|
}
|
||||||
if (++dacPos>=s->samples) {
|
dacPos++;
|
||||||
if (s->loopStart>=0 && s->loopStart<(int)s->samples) {
|
if (s->isLoopable() && dacPos>=s->getEndPosition()) {
|
||||||
dacPos=s->loopStart;
|
dacPos=s->loopStart;
|
||||||
} else {
|
} else if (dacPos>=s->samples) {
|
||||||
dacSample=-1;
|
dacSample=-1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
dacPeriod-=rate;
|
dacPeriod-=rate;
|
||||||
} else {
|
} else {
|
||||||
dacSample=-1;
|
dacSample=-1;
|
||||||
|
|
|
@ -108,13 +108,12 @@ void DivPlatformNES::doWrite(unsigned short addr, unsigned char data) {
|
||||||
rWrite(0x4011,next); \
|
rWrite(0x4011,next); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
if (++dacPos>=s->samples) { \
|
dacPos++; \
|
||||||
if (s->loopStart>=0 && s->loopStart<(int)s->samples) { \
|
if (s->isLoopable() && dacPos>=s->getEndPosition()) { \
|
||||||
dacPos=s->loopStart; \
|
dacPos=s->loopStart; \
|
||||||
} else { \
|
} else if (dacPos>=s->samples) { \
|
||||||
dacSample=-1; \
|
dacSample=-1; \
|
||||||
} \
|
} \
|
||||||
} \
|
|
||||||
dacPeriod-=rate; \
|
dacPeriod-=rate; \
|
||||||
} else { \
|
} else { \
|
||||||
dacSample=-1; \
|
dacSample=-1; \
|
||||||
|
|
|
@ -771,7 +771,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
int end=s->offB+s->lengthB-1;
|
int end=s->offB+s->lengthB-1;
|
||||||
immWrite(11,(end>>2)&0xff);
|
immWrite(11,(end>>2)&0xff);
|
||||||
immWrite(12,(end>>10)&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) {
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
chan[c.chan].note=c.value;
|
chan[c.chan].note=c.value;
|
||||||
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
|
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;
|
int end=s->offB+s->lengthB-1;
|
||||||
immWrite(11,(end>>2)&0xff);
|
immWrite(11,(end>>2)&0xff);
|
||||||
immWrite(12,(end>>10)&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;
|
int freq=(65536.0*(double)s->rate)/(double)chipRateBase;
|
||||||
immWrite(16,freq&0xff);
|
immWrite(16,freq&0xff);
|
||||||
immWrite(17,(freq>>8)&0xff);
|
immWrite(17,(freq>>8)&0xff);
|
||||||
|
|
|
@ -90,13 +90,11 @@ void DivPlatformPCE::acquire(short* bufL, short* bufR, size_t start, size_t len)
|
||||||
chWrite(i,0x04,0xdf);
|
chWrite(i,0x04,0xdf);
|
||||||
chWrite(i,0x06,(((unsigned char)s->data8[chan[i].dacPos]+0x80)>>3));
|
chWrite(i,0x06,(((unsigned char)s->data8[chan[i].dacPos]+0x80)>>3));
|
||||||
chan[i].dacPos++;
|
chan[i].dacPos++;
|
||||||
if (chan[i].dacPos>=s->samples) {
|
if (s->isLoopable() && chan[i].dacPos>=s->getEndPosition()) {
|
||||||
if (s->loopStart>=0 && s->loopStart<(int)s->samples) {
|
|
||||||
chan[i].dacPos=s->loopStart;
|
chan[i].dacPos=s->loopStart;
|
||||||
} else {
|
} else if (chan[i].dacPos>=s->samples) {
|
||||||
chan[i].dacSample=-1;
|
chan[i].dacSample=-1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
chan[i].dacPeriod-=rate;
|
chan[i].dacPeriod-=rate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -301,7 +301,7 @@ void DivPlatformQSound::tick(bool sysTick) {
|
||||||
qsound_bank = 0x8000 | (s->offQSound >> 16);
|
qsound_bank = 0x8000 | (s->offQSound >> 16);
|
||||||
qsound_addr = s->offQSound & 0xffff;
|
qsound_addr = s->offQSound & 0xffff;
|
||||||
|
|
||||||
int length = s->samples;
|
int length = s->getEndPosition();
|
||||||
if (length > 65536 - 16) {
|
if (length > 65536 - 16) {
|
||||||
length = 65536 - 16;
|
length = 65536 - 16;
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,7 +142,7 @@ void DivPlatformRF5C68::tick(bool sysTick) {
|
||||||
if (chan[i].audPos>0) {
|
if (chan[i].audPos>0) {
|
||||||
start=start+MIN(chan[i].audPos,s->length8);
|
start=start+MIN(chan[i].audPos,s->length8);
|
||||||
}
|
}
|
||||||
if (s->loopStart>=0) {
|
if (s->isLoopable()) {
|
||||||
loop=start+s->loopStart;
|
loop=start+s->loopStart;
|
||||||
}
|
}
|
||||||
start=MIN(start,getSampleMemCapacity()-31);
|
start=MIN(start,getSampleMemCapacity()-31);
|
||||||
|
@ -393,7 +393,7 @@ void DivPlatformRF5C68::renderSamples() {
|
||||||
size_t memPos=0;
|
size_t memPos=0;
|
||||||
for (int i=0; i<parent->song.sampleLen; i++) {
|
for (int i=0; i<parent->song.sampleLen; i++) {
|
||||||
DivSample* s=parent->song.sample[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);
|
int actualLength=MIN((int)(getSampleMemCapacity()-memPos)-31,length);
|
||||||
if (actualLength>0) {
|
if (actualLength>0) {
|
||||||
s->offRF5C68=memPos;
|
s->offRF5C68=memPos;
|
||||||
|
|
|
@ -56,13 +56,11 @@ void DivPlatformSegaPCM::acquire(short* bufL, short* bufR, size_t start, size_t
|
||||||
pcmR+=(s->data8[chan[i].pcm.pos>>8]*chan[i].chVolR);
|
pcmR+=(s->data8[chan[i].pcm.pos>>8]*chan[i].chVolR);
|
||||||
}
|
}
|
||||||
chan[i].pcm.pos+=chan[i].pcm.freq;
|
chan[i].pcm.pos+=chan[i].pcm.freq;
|
||||||
if (chan[i].pcm.pos>=(s->samples<<8)) {
|
if (s->isLoopable() && chan[i].pcm.pos>=(s->getEndPosition()<<8)) {
|
||||||
if (s->loopStart>=0 && s->loopStart<(int)s->samples) {
|
|
||||||
chan[i].pcm.pos=s->loopStart<<8;
|
chan[i].pcm.pos=s->loopStart<<8;
|
||||||
} else {
|
} else if (chan[i].pcm.pos>=(s->samples<<8)) {
|
||||||
chan[i].pcm.sample=-1;
|
chan[i].pcm.sample=-1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
oscBuf[i]->data[oscBuf[i]->needle++]=0;
|
oscBuf[i]->data[oscBuf[i]->needle++]=0;
|
||||||
}
|
}
|
||||||
|
@ -202,7 +200,7 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) {
|
||||||
chan[c.chan].macroInit(ins);
|
chan[c.chan].macroInit(ins);
|
||||||
if (dumpWrites) { // Sega PCM writes
|
if (dumpWrites) { // Sega PCM writes
|
||||||
DivSample* s=parent->getSample(chan[c.chan].pcm.sample);
|
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;
|
if (actualLength>0xfeff) actualLength=0xfeff;
|
||||||
addWrite(0x10086+(c.chan<<3),3+((s->offSegaPCM>>16)<<3));
|
addWrite(0x10086+(c.chan<<3),3+((s->offSegaPCM>>16)<<3));
|
||||||
addWrite(0x10084+(c.chan<<3),(s->offSegaPCM)&0xff);
|
addWrite(0x10084+(c.chan<<3),(s->offSegaPCM)&0xff);
|
||||||
|
@ -235,7 +233,7 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) {
|
||||||
chan[c.chan].furnacePCM=false;
|
chan[c.chan].furnacePCM=false;
|
||||||
if (dumpWrites) { // Sega PCM writes
|
if (dumpWrites) { // Sega PCM writes
|
||||||
DivSample* s=parent->getSample(chan[c.chan].pcm.sample);
|
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;
|
if (actualLength>65536) actualLength=65536;
|
||||||
addWrite(0x10086+(c.chan<<3),3+((s->offSegaPCM>>16)<<3));
|
addWrite(0x10086+(c.chan<<3),3+((s->offSegaPCM>>16)<<3));
|
||||||
addWrite(0x10084+(c.chan<<3),(s->offSegaPCM)&0xff);
|
addWrite(0x10084+(c.chan<<3),(s->offSegaPCM)&0xff);
|
||||||
|
|
|
@ -213,7 +213,7 @@ void DivPlatformSoundUnit::tick(bool sysTick) {
|
||||||
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SU);
|
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SU);
|
||||||
DivSample* sample=parent->getSample(ins->amiga.getSample(chan[i].note));
|
DivSample* sample=parent->getSample(ins->amiga.getSample(chan[i].note));
|
||||||
if (sample!=NULL) {
|
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;
|
unsigned int off=sample->offSU+chan[i].hasOffset;
|
||||||
chan[i].hasOffset=0;
|
chan[i].hasOffset=0;
|
||||||
if (sampleEnd>=getSampleMemCapacity(0)) sampleEnd=getSampleMemCapacity(0)-1;
|
if (sampleEnd>=getSampleMemCapacity(0)) sampleEnd=getSampleMemCapacity(0)-1;
|
||||||
|
@ -221,7 +221,7 @@ void DivPlatformSoundUnit::tick(bool sysTick) {
|
||||||
chWrite(i,0x0b,off>>8);
|
chWrite(i,0x0b,off>>8);
|
||||||
chWrite(i,0x0c,sampleEnd&0xff);
|
chWrite(i,0x0c,sampleEnd&0xff);
|
||||||
chWrite(i,0x0d,sampleEnd>>8);
|
chWrite(i,0x0d,sampleEnd>>8);
|
||||||
if (sample->loopStart>=0 && sample->loopStart<(int)sample->samples) {
|
if (sample->isLoopable()) {
|
||||||
unsigned int sampleLoop=sample->offSU+sample->loopStart;
|
unsigned int sampleLoop=sample->offSU+sample->loopStart;
|
||||||
if (sampleLoop>=getSampleMemCapacity(0)) sampleLoop=getSampleMemCapacity(0)-1;
|
if (sampleLoop>=getSampleMemCapacity(0)) sampleLoop=getSampleMemCapacity(0)-1;
|
||||||
chWrite(i,0x0e,sampleLoop&0xff);
|
chWrite(i,0x0e,sampleLoop&0xff);
|
||||||
|
|
|
@ -83,13 +83,11 @@ void DivPlatformSwan::acquire(short* bufL, short* bufR, size_t start, size_t len
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
rWrite(0x09,(unsigned char)s->data8[dacPos++]+0x80);
|
rWrite(0x09,(unsigned char)s->data8[dacPos++]+0x80);
|
||||||
if (dacPos>=s->samples) {
|
if (s->isLoopable() && dacPos>=s->getEndPosition()) {
|
||||||
if (s->loopStart>=0 && s->loopStart<(int)s->samples) {
|
|
||||||
dacPos=s->loopStart;
|
dacPos=s->loopStart;
|
||||||
} else {
|
} else if (dacPos>=s->samples) {
|
||||||
dacSample=-1;
|
dacSample=-1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
dacPeriod-=rate;
|
dacPeriod-=rate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,15 +96,13 @@ void DivPlatformVERA::acquire(short* bufL, short* bufR, size_t start, size_t len
|
||||||
rWritePCMData(tmp_r&0xff);
|
rWritePCMData(tmp_r&0xff);
|
||||||
}
|
}
|
||||||
chan[16].pcm.pos++;
|
chan[16].pcm.pos++;
|
||||||
if (chan[16].pcm.pos>=s->samples) {
|
if (s->isLoopable() && chan[16].pcm.pos>=s->getEndPosition()) {
|
||||||
if (s->loopStart>=0 && s->loopStart<(int)s->samples) {
|
|
||||||
chan[16].pcm.pos=s->loopStart;
|
chan[16].pcm.pos=s->loopStart;
|
||||||
} else {
|
} else if (chan[16].pcm.pos>=s->samples) {
|
||||||
chan[16].pcm.sample=-1;
|
chan[16].pcm.sample=-1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// just let the buffer run out
|
// just let the buffer run out
|
||||||
chan[16].pcm.sample=-1;
|
chan[16].pcm.sample=-1;
|
||||||
|
@ -267,12 +265,12 @@ int DivPlatformVERA::dispatch(DivCommand c) {
|
||||||
chan[16].pcm.pos=0;
|
chan[16].pcm.pos=0;
|
||||||
DivSample* s=parent->getSample(chan[16].pcm.sample);
|
DivSample* s=parent->getSample(chan[16].pcm.sample);
|
||||||
unsigned char ctrl=0x90|chan[16].vol; // always stereo
|
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;
|
chan[16].pcm.depth16=true;
|
||||||
ctrl|=0x20;
|
ctrl|=0x20;
|
||||||
} else {
|
} else {
|
||||||
chan[16].pcm.depth16=false;
|
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);
|
rWritePCMCtrl(ctrl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,14 +77,12 @@ void DivPlatformVRC6::acquire(short* bufL, short* bufR, size_t start, size_t len
|
||||||
chWrite(i,0,0x80|chan[i].dacOut);
|
chWrite(i,0,0x80|chan[i].dacOut);
|
||||||
}
|
}
|
||||||
chan[i].dacPos++;
|
chan[i].dacPos++;
|
||||||
if (chan[i].dacPos>=s->samples) {
|
if (s->isLoopable() && chan[i].dacPos>=s->getEndPosition()) {
|
||||||
if (s->loopStart>=0 && s->loopStart<(int)s->samples) {
|
|
||||||
chan[i].dacPos=s->loopStart;
|
chan[i].dacPos=s->loopStart;
|
||||||
} else {
|
} else if (chan[i].dacPos>=s->samples) {
|
||||||
chan[i].dacSample=-1;
|
chan[i].dacSample=-1;
|
||||||
chWrite(i,0,0);
|
chWrite(i,0,0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
chan[i].dacPeriod-=rate;
|
chan[i].dacPeriod-=rate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -761,7 +761,7 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
|
||||||
immWrite(0x104,(end>>5)&0xff);
|
immWrite(0x104,(end>>5)&0xff);
|
||||||
immWrite(0x105,(end>>13)&0xff);
|
immWrite(0x105,(end>>13)&0xff);
|
||||||
immWrite(0x101,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|2);
|
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) {
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
chan[c.chan].note=c.value;
|
chan[c.chan].note=c.value;
|
||||||
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
|
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(0x104,(end>>5)&0xff);
|
||||||
immWrite(0x105,(end>>13)&0xff);
|
immWrite(0x105,(end>>13)&0xff);
|
||||||
immWrite(0x101,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|2);
|
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);
|
int freq=(65536.0*(double)s->rate)/((double)chipClock/144.0);
|
||||||
immWrite(0x109,freq&0xff);
|
immWrite(0x109,freq&0xff);
|
||||||
immWrite(0x10a,(freq>>8)&0xff);
|
immWrite(0x10a,(freq>>8)&0xff);
|
||||||
|
|
|
@ -793,7 +793,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
||||||
immWrite(0x14,(end>>8)&0xff);
|
immWrite(0x14,(end>>8)&0xff);
|
||||||
immWrite(0x15,end>>16);
|
immWrite(0x15,end>>16);
|
||||||
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
|
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) {
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
chan[c.chan].note=c.value;
|
chan[c.chan].note=c.value;
|
||||||
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
|
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(0x14,(end>>8)&0xff);
|
||||||
immWrite(0x15,end>>16);
|
immWrite(0x15,end>>16);
|
||||||
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
|
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);
|
int freq=(65536.0*(double)s->rate)/((double)chipClock/144.0);
|
||||||
immWrite(0x19,freq&0xff);
|
immWrite(0x19,freq&0xff);
|
||||||
immWrite(0x1a,(freq>>8)&0xff);
|
immWrite(0x1a,(freq>>8)&0xff);
|
||||||
|
|
|
@ -775,7 +775,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
immWrite(0x14,(end>>8)&0xff);
|
immWrite(0x14,(end>>8)&0xff);
|
||||||
immWrite(0x15,end>>16);
|
immWrite(0x15,end>>16);
|
||||||
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
|
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) {
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
chan[c.chan].note=c.value;
|
chan[c.chan].note=c.value;
|
||||||
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
|
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(0x14,(end>>8)&0xff);
|
||||||
immWrite(0x15,end>>16);
|
immWrite(0x15,end>>16);
|
||||||
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
|
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);
|
int freq=(65536.0*(double)s->rate)/((double)chipClock/144.0);
|
||||||
immWrite(0x19,freq&0xff);
|
immWrite(0x19,freq&0xff);
|
||||||
immWrite(0x1a,(freq>>8)&0xff);
|
immWrite(0x1a,(freq>>8)&0xff);
|
||||||
|
|
|
@ -136,9 +136,9 @@ void DivPlatformYMZ280B::tick(bool sysTick) {
|
||||||
DivSample* s=parent->getSample(chan[i].sample);
|
DivSample* s=parent->getSample(chan[i].sample);
|
||||||
unsigned char ctrl;
|
unsigned char ctrl;
|
||||||
switch (s->depth) {
|
switch (s->depth) {
|
||||||
case 3: ctrl=0x20; break;
|
case DIV_SAMPLE_DEPTH_YMZ_ADPCM: ctrl=0x20; break;
|
||||||
case 8: ctrl=0x40; break;
|
case DIV_SAMPLE_DEPTH_8BIT: ctrl=0x40; break;
|
||||||
case 16: ctrl=0x60; break;
|
case DIV_SAMPLE_DEPTH_16BIT: ctrl=0x60; break;
|
||||||
default: ctrl=0;
|
default: ctrl=0;
|
||||||
}
|
}
|
||||||
double off=(s->centerRate>=1)?((double)s->centerRate/8363.0):1.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<0) chan[i].freq=0;
|
||||||
if (chan[i].freq>511) chan[i].freq=511;
|
if (chan[i].freq>511) chan[i].freq=511;
|
||||||
// ADPCM has half the range
|
// ADPCM has half the range
|
||||||
if (s->depth==3 && chan[i].freq>255) chan[i].freq=255;
|
if (s->depth==DIV_SAMPLE_DEPTH_YMZ_ADPCM && chan[i].freq>255) chan[i].freq=255;
|
||||||
ctrl|=(chan[i].active?0x80:0)|((s->loopStart>=0)?0x10:0)|(chan[i].freq>>8);
|
ctrl|=(chan[i].active?0x80:0)|((s->isLoopable())?0x10:0)|(chan[i].freq>>8);
|
||||||
if (chan[i].keyOn) {
|
if (chan[i].keyOn) {
|
||||||
unsigned int start=s->offYMZ280B;
|
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);
|
unsigned int end=MIN(start+s->getCurBufLen(),getSampleMemCapacity()-1);
|
||||||
if (chan[i].audPos>0) {
|
if (chan[i].audPos>0) {
|
||||||
switch (s->depth) {
|
switch (s->depth) {
|
||||||
case 3: start+=chan[i].audPos/2; break;
|
case DIV_SAMPLE_DEPTH_YMZ_ADPCM: start+=chan[i].audPos/2; break;
|
||||||
case 8: start+=chan[i].audPos; break;
|
case DIV_SAMPLE_DEPTH_8BIT: start+=chan[i].audPos; break;
|
||||||
case 16: start+=chan[i].audPos*2; break;
|
case DIV_SAMPLE_DEPTH_16BIT: start+=chan[i].audPos*2; break;
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
start=MIN(start,end);
|
start=MIN(start,end);
|
||||||
}
|
}
|
||||||
if (s->loopStart>=0) {
|
if (s->isLoopable()) {
|
||||||
switch (s->depth) {
|
switch (s->depth) {
|
||||||
case 3: loop=start+s->loopStart/2; break;
|
case DIV_SAMPLE_DEPTH_YMZ_ADPCM: loopStart=start+s->loopStart/2; loopEnd=start+s->loopEnd/2; break;
|
||||||
case 8: loop=start+s->loopStart; break;
|
case DIV_SAMPLE_DEPTH_8BIT: loopStart=start+s->loopStart; loopEnd=start+s->loopEnd; break;
|
||||||
case 16: loop=start+s->loopStart*2; 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(0x01+i*4,ctrl&~0x80); // force keyoff first
|
||||||
rWrite(0x20+i*4,(start>>16)&0xff);
|
rWrite(0x20+i*4,(start>>16)&0xff);
|
||||||
rWrite(0x21+i*4,(loop>>16)&0xff);
|
rWrite(0x21+i*4,(loopStart>>16)&0xff);
|
||||||
rWrite(0x22+i*4,(end>>16)&0xff);
|
rWrite(0x22+i*4,(loopEnd>>16)&0xff);
|
||||||
rWrite(0x23+i*4,(end>>16)&0xff);
|
rWrite(0x23+i*4,(end>>16)&0xff);
|
||||||
rWrite(0x40+i*4,(start>>8)&0xff);
|
rWrite(0x40+i*4,(start>>8)&0xff);
|
||||||
rWrite(0x41+i*4,(loop>>8)&0xff);
|
rWrite(0x41+i*4,(loopStart>>8)&0xff);
|
||||||
rWrite(0x42+i*4,(end>>8)&0xff);
|
rWrite(0x42+i*4,(loopEnd>>8)&0xff);
|
||||||
rWrite(0x43+i*4,(end>>8)&0xff);
|
rWrite(0x43+i*4,(end>>8)&0xff);
|
||||||
rWrite(0x60+i*4,start&0xff);
|
rWrite(0x60+i*4,start&0xff);
|
||||||
rWrite(0x61+i*4,loop&0xff);
|
rWrite(0x61+i*4,loopStart&0xff);
|
||||||
rWrite(0x62+i*4,end&0xff);
|
rWrite(0x62+i*4,loopEnd&0xff);
|
||||||
rWrite(0x63+i*4,end&0xff);
|
rWrite(0x63+i*4,end&0xff);
|
||||||
if (!chan[i].std.vol.had) {
|
if (!chan[i].std.vol.had) {
|
||||||
chan[i].outVol=chan[i].vol;
|
chan[i].outVol=chan[i].vol;
|
||||||
|
|
|
@ -1204,17 +1204,17 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
||||||
blip_add_delta(samp_bb,i,samp_temp-samp_prevSample);
|
blip_add_delta(samp_bb,i,samp_temp-samp_prevSample);
|
||||||
samp_prevSample=samp_temp;
|
samp_prevSample=samp_temp;
|
||||||
|
|
||||||
if (sPreview.pos>=s->samples || (sPreview.pEnd>=0 && (int)sPreview.pos>=sPreview.pEnd)) {
|
if (sPreview.pos>=s->getEndPosition() || (sPreview.pEnd>=0 && (int)sPreview.pos>=sPreview.pEnd)) {
|
||||||
if (s->loopStart>=0 && s->loopStart<(int)s->samples && (int)sPreview.pos>=s->loopStart) {
|
if (s->isLoopable() && (int)sPreview.pos>=s->loopStart) {
|
||||||
sPreview.pos=s->loopStart;
|
sPreview.pos=s->loopStart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sPreview.pos>=s->samples || (sPreview.pEnd>=0 && (int)sPreview.pos>=sPreview.pEnd)) {
|
if (sPreview.pos>=s->getEndPosition() || (sPreview.pEnd>=0 && (int)sPreview.pos>=sPreview.pEnd)) {
|
||||||
if (s->loopStart>=0 && s->loopStart<(int)s->samples && (int)sPreview.pos>=s->loopStart) {
|
if (s->isLoopable() && (int)sPreview.pos>=s->loopStart) {
|
||||||
sPreview.pos=s->loopStart;
|
sPreview.pos=s->loopStart;
|
||||||
} else {
|
} else if (sPreview.pos>=s->samples) {
|
||||||
sPreview.sample=-1;
|
sPreview.sample=-1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,65 @@ DivSampleHistory::~DivSampleHistory() {
|
||||||
if (data!=NULL) delete[] data;
|
if (data!=NULL) delete[] data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DivSample::isLoopable() {
|
||||||
|
return (loopStart>=0 && loopStart<loopEnd) && (loopEnd>loopStart && loopEnd<=(int)samples);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int DivSample::getEndPosition(DivSampleDepth depth) {
|
||||||
|
int end=loopEnd;
|
||||||
|
unsigned int len=samples;
|
||||||
|
switch (depth) {
|
||||||
|
case DIV_SAMPLE_DEPTH_1BIT:
|
||||||
|
end=(loopEnd+7)/8;
|
||||||
|
len=length1;
|
||||||
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_1BIT_DPCM:
|
||||||
|
end=(loopEnd+7)/8;
|
||||||
|
len=lengthDPCM;
|
||||||
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_YMZ_ADPCM:
|
||||||
|
end=(loopEnd+1)/2;
|
||||||
|
len=lengthZ;
|
||||||
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_QSOUND_ADPCM:
|
||||||
|
end=(loopEnd+1)/2;
|
||||||
|
len=lengthQSoundA;
|
||||||
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_ADPCM_A:
|
||||||
|
end=(loopEnd+1)/2;
|
||||||
|
len=lengthA;
|
||||||
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_ADPCM_B:
|
||||||
|
end=(loopEnd+1)/2;
|
||||||
|
len=lengthB;
|
||||||
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_8BIT:
|
||||||
|
end=loopEnd;
|
||||||
|
len=length8;
|
||||||
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_BRR:
|
||||||
|
end=9*((loopEnd+15)/16);
|
||||||
|
len=lengthBRR;
|
||||||
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_VOX:
|
||||||
|
end=(loopEnd+1)/2;
|
||||||
|
len=lengthVOX;
|
||||||
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_16BIT:
|
||||||
|
end=loopEnd*2;
|
||||||
|
len=length16;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return isLoopable()?end:len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivSample::setSampleCount(unsigned int count) {
|
||||||
|
samples=count;
|
||||||
|
if ((!isLoopable()) || loopEnd<0 || loopEnd>(int)samples) loopEnd=samples;
|
||||||
|
}
|
||||||
|
|
||||||
bool DivSample::save(const char* path) {
|
bool DivSample::save(const char* path) {
|
||||||
#ifndef HAVE_SNDFILE
|
#ifndef HAVE_SNDFILE
|
||||||
logE("Furnace was not compiled with libsndfile!");
|
logE("Furnace was not compiled with libsndfile!");
|
||||||
|
@ -53,7 +112,7 @@ bool DivSample::save(const char* path) {
|
||||||
si.channels=1;
|
si.channels=1;
|
||||||
si.samplerate=rate;
|
si.samplerate=rate;
|
||||||
switch (depth) {
|
switch (depth) {
|
||||||
case 8: // 8-bit
|
case DIV_SAMPLE_DEPTH_8BIT: // 8-bit
|
||||||
si.format=SF_FORMAT_PCM_U8|SF_FORMAT_WAV;
|
si.format=SF_FORMAT_PCM_U8|SF_FORMAT_WAV;
|
||||||
break;
|
break;
|
||||||
default: // 16-bit
|
default: // 16-bit
|
||||||
|
@ -76,17 +135,17 @@ bool DivSample::save(const char* path) {
|
||||||
inst.detune = 50 - (pitch % 100);
|
inst.detune = 50 - (pitch % 100);
|
||||||
inst.velocity_hi = 0x7f;
|
inst.velocity_hi = 0x7f;
|
||||||
inst.key_hi = 0x7f;
|
inst.key_hi = 0x7f;
|
||||||
if(loopStart != -1)
|
if(isLoopable())
|
||||||
{
|
{
|
||||||
inst.loop_count = 1;
|
inst.loop_count = 1;
|
||||||
inst.loops[0].mode = SF_LOOP_FORWARD;
|
inst.loops[0].mode = SF_LOOP_FORWARD;
|
||||||
inst.loops[0].start = loopStart;
|
inst.loops[0].start = loopStart;
|
||||||
inst.loops[0].end = samples;
|
inst.loops[0].end = loopEnd;
|
||||||
}
|
}
|
||||||
sf_command(f, SFC_SET_INSTRUMENT, &inst, sizeof(inst));
|
sf_command(f, SFC_SET_INSTRUMENT, &inst, sizeof(inst));
|
||||||
|
|
||||||
switch (depth) {
|
switch (depth) {
|
||||||
case 8: {
|
case DIV_SAMPLE_DEPTH_8BIT: {
|
||||||
// convert from signed to unsigned
|
// convert from signed to unsigned
|
||||||
unsigned char* buf=new unsigned char[length8];
|
unsigned char* buf=new unsigned char[length8];
|
||||||
for (size_t i=0; i<length8; i++) {
|
for (size_t i=0; i<length8; i++) {
|
||||||
|
@ -108,65 +167,65 @@ bool DivSample::save(const char* path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 16-bit memory is padded to 512, to make things easier for ADPCM-A/B.
|
// 16-bit memory is padded to 512, to make things easier for ADPCM-A/B.
|
||||||
bool DivSample::initInternal(unsigned char d, int count) {
|
bool DivSample::initInternal(DivSampleDepth d, int count) {
|
||||||
switch (d) {
|
switch (d) {
|
||||||
case 0: // 1-bit
|
case DIV_SAMPLE_DEPTH_1BIT: // 1-bit
|
||||||
if (data1!=NULL) delete[] data1;
|
if (data1!=NULL) delete[] data1;
|
||||||
length1=(count+7)/8;
|
length1=(count+7)/8;
|
||||||
data1=new unsigned char[length1];
|
data1=new unsigned char[length1];
|
||||||
memset(data1,0,length1);
|
memset(data1,0,length1);
|
||||||
break;
|
break;
|
||||||
case 1: // DPCM
|
case DIV_SAMPLE_DEPTH_1BIT_DPCM: // DPCM
|
||||||
if (dataDPCM!=NULL) delete[] dataDPCM;
|
if (dataDPCM!=NULL) delete[] dataDPCM;
|
||||||
lengthDPCM=(count+7)/8;
|
lengthDPCM=(count+7)/8;
|
||||||
dataDPCM=new unsigned char[lengthDPCM];
|
dataDPCM=new unsigned char[lengthDPCM];
|
||||||
memset(dataDPCM,0,lengthDPCM);
|
memset(dataDPCM,0,lengthDPCM);
|
||||||
break;
|
break;
|
||||||
case 3: // YMZ ADPCM
|
case DIV_SAMPLE_DEPTH_YMZ_ADPCM: // YMZ ADPCM
|
||||||
if (dataZ!=NULL) delete[] dataZ;
|
if (dataZ!=NULL) delete[] dataZ;
|
||||||
lengthZ=(count+1)/2;
|
lengthZ=(count+1)/2;
|
||||||
// for padding AICA sample
|
// for padding AICA sample
|
||||||
dataZ=new unsigned char[(lengthZ+3)&(~0x03)];
|
dataZ=new unsigned char[(lengthZ+3)&(~0x03)];
|
||||||
memset(dataZ,0,(lengthZ+3)&(~0x03));
|
memset(dataZ,0,(lengthZ+3)&(~0x03));
|
||||||
break;
|
break;
|
||||||
case 4: // QSound ADPCM
|
case DIV_SAMPLE_DEPTH_QSOUND_ADPCM: // QSound ADPCM
|
||||||
if (dataQSoundA!=NULL) delete[] dataQSoundA;
|
if (dataQSoundA!=NULL) delete[] dataQSoundA;
|
||||||
lengthQSoundA=(count+1)/2;
|
lengthQSoundA=(count+1)/2;
|
||||||
dataQSoundA=new unsigned char[lengthQSoundA];
|
dataQSoundA=new unsigned char[lengthQSoundA];
|
||||||
memset(dataQSoundA,0,lengthQSoundA);
|
memset(dataQSoundA,0,lengthQSoundA);
|
||||||
break;
|
break;
|
||||||
case 5: // ADPCM-A
|
case DIV_SAMPLE_DEPTH_ADPCM_A: // ADPCM-A
|
||||||
if (dataA!=NULL) delete[] dataA;
|
if (dataA!=NULL) delete[] dataA;
|
||||||
lengthA=(count+1)/2;
|
lengthA=(count+1)/2;
|
||||||
dataA=new unsigned char[(lengthA+255)&(~0xff)];
|
dataA=new unsigned char[(lengthA+255)&(~0xff)];
|
||||||
memset(dataA,0,(lengthA+255)&(~0xff));
|
memset(dataA,0,(lengthA+255)&(~0xff));
|
||||||
break;
|
break;
|
||||||
case 6: // ADPCM-B
|
case DIV_SAMPLE_DEPTH_ADPCM_B: // ADPCM-B
|
||||||
if (dataB!=NULL) delete[] dataB;
|
if (dataB!=NULL) delete[] dataB;
|
||||||
lengthB=(count+1)/2;
|
lengthB=(count+1)/2;
|
||||||
dataB=new unsigned char[(lengthB+255)&(~0xff)];
|
dataB=new unsigned char[(lengthB+255)&(~0xff)];
|
||||||
memset(dataB,0,(lengthB+255)&(~0xff));
|
memset(dataB,0,(lengthB+255)&(~0xff));
|
||||||
break;
|
break;
|
||||||
case 8: // 8-bit
|
case DIV_SAMPLE_DEPTH_8BIT: // 8-bit
|
||||||
if (data8!=NULL) delete[] data8;
|
if (data8!=NULL) delete[] data8;
|
||||||
length8=count;
|
length8=count;
|
||||||
// for padding X1-010 sample
|
// for padding X1-010 sample
|
||||||
data8=new signed char[(count+4095)&(~0xfff)];
|
data8=new signed char[(count+4095)&(~0xfff)];
|
||||||
memset(data8,0,(count+4095)&(~0xfff));
|
memset(data8,0,(count+4095)&(~0xfff));
|
||||||
break;
|
break;
|
||||||
case 9: // BRR
|
case DIV_SAMPLE_DEPTH_BRR: // BRR
|
||||||
if (dataBRR!=NULL) delete[] dataBRR;
|
if (dataBRR!=NULL) delete[] dataBRR;
|
||||||
lengthBRR=9*((count+15)/16);
|
lengthBRR=9*((count+15)/16);
|
||||||
dataBRR=new unsigned char[lengthBRR];
|
dataBRR=new unsigned char[lengthBRR];
|
||||||
memset(dataBRR,0,lengthBRR);
|
memset(dataBRR,0,lengthBRR);
|
||||||
break;
|
break;
|
||||||
case 10: // VOX
|
case DIV_SAMPLE_DEPTH_VOX: // VOX
|
||||||
if (dataVOX!=NULL) delete[] dataVOX;
|
if (dataVOX!=NULL) delete[] dataVOX;
|
||||||
lengthVOX=(count+1)/2;
|
lengthVOX=(count+1)/2;
|
||||||
dataVOX=new unsigned char[lengthVOX];
|
dataVOX=new unsigned char[lengthVOX];
|
||||||
memset(dataVOX,0,lengthVOX);
|
memset(dataVOX,0,lengthVOX);
|
||||||
break;
|
break;
|
||||||
case 16: // 16-bit
|
case DIV_SAMPLE_DEPTH_16BIT: // 16-bit
|
||||||
if (data16!=NULL) delete[] data16;
|
if (data16!=NULL) delete[] data16;
|
||||||
length16=count*2;
|
length16=count*2;
|
||||||
data16=new short[(count+511)&(~0x1ff)];
|
data16=new short[(count+511)&(~0x1ff)];
|
||||||
|
@ -180,34 +239,34 @@ bool DivSample::initInternal(unsigned char d, int count) {
|
||||||
|
|
||||||
bool DivSample::init(unsigned int count) {
|
bool DivSample::init(unsigned int count) {
|
||||||
if (!initInternal(depth,count)) return false;
|
if (!initInternal(depth,count)) return false;
|
||||||
samples=count;
|
setSampleCount(count);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DivSample::resize(unsigned int count) {
|
bool DivSample::resize(unsigned int count) {
|
||||||
if (depth==8) {
|
if (depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
if (data8!=NULL) {
|
if (data8!=NULL) {
|
||||||
signed char* oldData8=data8;
|
signed char* oldData8=data8;
|
||||||
data8=NULL;
|
data8=NULL;
|
||||||
initInternal(8,count);
|
initInternal(DIV_SAMPLE_DEPTH_8BIT,count);
|
||||||
memcpy(data8,oldData8,MIN(count,samples));
|
memcpy(data8,oldData8,MIN(count,samples));
|
||||||
delete[] oldData8;
|
delete[] oldData8;
|
||||||
} else {
|
} else {
|
||||||
initInternal(8,count);
|
initInternal(DIV_SAMPLE_DEPTH_8BIT,count);
|
||||||
}
|
}
|
||||||
samples=count;
|
setSampleCount(count);
|
||||||
return true;
|
return true;
|
||||||
} else if (depth==16) {
|
} else if (depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
if (data16!=NULL) {
|
if (data16!=NULL) {
|
||||||
short* oldData16=data16;
|
short* oldData16=data16;
|
||||||
data16=NULL;
|
data16=NULL;
|
||||||
initInternal(16,count);
|
initInternal(DIV_SAMPLE_DEPTH_16BIT,count);
|
||||||
memcpy(data16,oldData16,sizeof(short)*MIN(count,samples));
|
memcpy(data16,oldData16,sizeof(short)*MIN(count,samples));
|
||||||
delete[] oldData16;
|
delete[] oldData16;
|
||||||
} else {
|
} else {
|
||||||
initInternal(16,count);
|
initInternal(DIV_SAMPLE_DEPTH_16BIT,count);
|
||||||
}
|
}
|
||||||
samples=count;
|
setSampleCount(count);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -218,11 +277,11 @@ bool DivSample::strip(unsigned int begin, unsigned int end) {
|
||||||
if (end>samples) end=samples;
|
if (end>samples) end=samples;
|
||||||
int count=samples-(end-begin);
|
int count=samples-(end-begin);
|
||||||
if (count<=0) return resize(0);
|
if (count<=0) return resize(0);
|
||||||
if (depth==8) {
|
if (depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
if (data8!=NULL) {
|
if (data8!=NULL) {
|
||||||
signed char* oldData8=data8;
|
signed char* oldData8=data8;
|
||||||
data8=NULL;
|
data8=NULL;
|
||||||
initInternal(8,count);
|
initInternal(DIV_SAMPLE_DEPTH_8BIT,count);
|
||||||
if (begin>0) {
|
if (begin>0) {
|
||||||
memcpy(data8,oldData8,begin);
|
memcpy(data8,oldData8,begin);
|
||||||
}
|
}
|
||||||
|
@ -234,13 +293,13 @@ bool DivSample::strip(unsigned int begin, unsigned int end) {
|
||||||
// do nothing
|
// do nothing
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
samples=count;
|
setSampleCount(count);
|
||||||
return true;
|
return true;
|
||||||
} else if (depth==16) {
|
} else if (depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
if (data16!=NULL) {
|
if (data16!=NULL) {
|
||||||
short* oldData16=data16;
|
short* oldData16=data16;
|
||||||
data16=NULL;
|
data16=NULL;
|
||||||
initInternal(16,count);
|
initInternal(DIV_SAMPLE_DEPTH_16BIT,count);
|
||||||
if (begin>0) {
|
if (begin>0) {
|
||||||
memcpy(data16,oldData16,sizeof(short)*begin);
|
memcpy(data16,oldData16,sizeof(short)*begin);
|
||||||
}
|
}
|
||||||
|
@ -252,7 +311,7 @@ bool DivSample::strip(unsigned int begin, unsigned int end) {
|
||||||
// do nothing
|
// do nothing
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
samples=count;
|
setSampleCount(count);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -262,31 +321,31 @@ bool DivSample::trim(unsigned int begin, unsigned int end) {
|
||||||
int count=end-begin;
|
int count=end-begin;
|
||||||
if (count==0) return true;
|
if (count==0) return true;
|
||||||
if (begin==0 && end==samples) return true;
|
if (begin==0 && end==samples) return true;
|
||||||
if (depth==8) {
|
if (depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
if (data8!=NULL) {
|
if (data8!=NULL) {
|
||||||
signed char* oldData8=data8;
|
signed char* oldData8=data8;
|
||||||
data8=NULL;
|
data8=NULL;
|
||||||
initInternal(8,count);
|
initInternal(DIV_SAMPLE_DEPTH_8BIT,count);
|
||||||
memcpy(data8,oldData8+begin,count);
|
memcpy(data8,oldData8+begin,count);
|
||||||
delete[] oldData8;
|
delete[] oldData8;
|
||||||
} else {
|
} else {
|
||||||
// do nothing
|
// do nothing
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
samples=count;
|
setSampleCount(count);
|
||||||
return true;
|
return true;
|
||||||
} else if (depth==16) {
|
} else if (depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
if (data16!=NULL) {
|
if (data16!=NULL) {
|
||||||
short* oldData16=data16;
|
short* oldData16=data16;
|
||||||
data16=NULL;
|
data16=NULL;
|
||||||
initInternal(16,count);
|
initInternal(DIV_SAMPLE_DEPTH_16BIT,count);
|
||||||
memcpy(data16,&(oldData16[begin]),sizeof(short)*count);
|
memcpy(data16,&(oldData16[begin]),sizeof(short)*count);
|
||||||
delete[] oldData16;
|
delete[] oldData16;
|
||||||
} else {
|
} else {
|
||||||
// do nothing
|
// do nothing
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
samples=count;
|
setSampleCount(count);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -294,11 +353,11 @@ bool DivSample::trim(unsigned int begin, unsigned int end) {
|
||||||
|
|
||||||
bool DivSample::insert(unsigned int pos, unsigned int length) {
|
bool DivSample::insert(unsigned int pos, unsigned int length) {
|
||||||
unsigned int count=samples+length;
|
unsigned int count=samples+length;
|
||||||
if (depth==8) {
|
if (depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
if (data8!=NULL) {
|
if (data8!=NULL) {
|
||||||
signed char* oldData8=data8;
|
signed char* oldData8=data8;
|
||||||
data8=NULL;
|
data8=NULL;
|
||||||
initInternal(8,count);
|
initInternal(DIV_SAMPLE_DEPTH_8BIT,count);
|
||||||
if (pos>0) {
|
if (pos>0) {
|
||||||
memcpy(data8,oldData8,pos);
|
memcpy(data8,oldData8,pos);
|
||||||
}
|
}
|
||||||
|
@ -307,15 +366,15 @@ bool DivSample::insert(unsigned int pos, unsigned int length) {
|
||||||
}
|
}
|
||||||
delete[] oldData8;
|
delete[] oldData8;
|
||||||
} else {
|
} else {
|
||||||
initInternal(8,count);
|
initInternal(DIV_SAMPLE_DEPTH_8BIT,count);
|
||||||
}
|
}
|
||||||
samples=count;
|
setSampleCount(count);
|
||||||
return true;
|
return true;
|
||||||
} else if (depth==16) {
|
} else if (depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
if (data16!=NULL) {
|
if (data16!=NULL) {
|
||||||
short* oldData16=data16;
|
short* oldData16=data16;
|
||||||
data16=NULL;
|
data16=NULL;
|
||||||
initInternal(16,count);
|
initInternal(DIV_SAMPLE_DEPTH_16BIT,count);
|
||||||
if (pos>0) {
|
if (pos>0) {
|
||||||
memcpy(data16,oldData16,sizeof(short)*pos);
|
memcpy(data16,oldData16,sizeof(short)*pos);
|
||||||
}
|
}
|
||||||
|
@ -324,9 +383,9 @@ bool DivSample::insert(unsigned int pos, unsigned int length) {
|
||||||
}
|
}
|
||||||
delete[] oldData16;
|
delete[] oldData16;
|
||||||
} else {
|
} else {
|
||||||
initInternal(16,count);
|
initInternal(DIV_SAMPLE_DEPTH_16BIT,count);
|
||||||
}
|
}
|
||||||
samples=count;
|
setSampleCount(count);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -337,15 +396,15 @@ bool DivSample::insert(unsigned int pos, unsigned int length) {
|
||||||
int finalCount=(double)samples*(r/(double)rate); \
|
int finalCount=(double)samples*(r/(double)rate); \
|
||||||
signed char* oldData8=data8; \
|
signed char* oldData8=data8; \
|
||||||
short* oldData16=data16; \
|
short* oldData16=data16; \
|
||||||
if (depth==16) { \
|
if (depth==DIV_SAMPLE_DEPTH_16BIT) { \
|
||||||
if (data16!=NULL) { \
|
if (data16!=NULL) { \
|
||||||
data16=NULL; \
|
data16=NULL; \
|
||||||
initInternal(16,finalCount); \
|
initInternal(DIV_SAMPLE_DEPTH_16BIT,finalCount); \
|
||||||
} \
|
} \
|
||||||
} else if (depth==8) { \
|
} else if (depth==DIV_SAMPLE_DEPTH_8BIT) { \
|
||||||
if (data8!=NULL) { \
|
if (data8!=NULL) { \
|
||||||
data8=NULL; \
|
data8=NULL; \
|
||||||
initInternal(8,finalCount); \
|
initInternal(DIV_SAMPLE_DEPTH_8BIT,finalCount); \
|
||||||
} \
|
} \
|
||||||
} else { \
|
} else { \
|
||||||
return false; \
|
return false; \
|
||||||
|
@ -353,19 +412,20 @@ bool DivSample::insert(unsigned int pos, unsigned int length) {
|
||||||
|
|
||||||
#define RESAMPLE_END \
|
#define RESAMPLE_END \
|
||||||
if (loopStart>=0) loopStart=(double)loopStart*(r/(double)rate); \
|
if (loopStart>=0) loopStart=(double)loopStart*(r/(double)rate); \
|
||||||
|
if (loopEnd>=0) loopEnd=(double)loopEnd*(r/(double)rate); \
|
||||||
centerRate=(int)((double)centerRate*(r/(double)rate)); \
|
centerRate=(int)((double)centerRate*(r/(double)rate)); \
|
||||||
rate=r; \
|
rate=r; \
|
||||||
samples=finalCount; \
|
samples=finalCount; \
|
||||||
if (depth==16) { \
|
if (depth==DIV_SAMPLE_DEPTH_16BIT) { \
|
||||||
delete[] oldData16; \
|
delete[] oldData16; \
|
||||||
} else if (depth==8) { \
|
} else if (depth==DIV_SAMPLE_DEPTH_8BIT) { \
|
||||||
delete[] oldData8; \
|
delete[] oldData8; \
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DivSample::resampleNone(double r) {
|
bool DivSample::resampleNone(double r) {
|
||||||
RESAMPLE_BEGIN;
|
RESAMPLE_BEGIN;
|
||||||
|
|
||||||
if (depth==16) {
|
if (depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
for (int i=0; i<finalCount; i++) {
|
for (int i=0; i<finalCount; i++) {
|
||||||
unsigned int pos=(unsigned int)((double)i*((double)rate/r));
|
unsigned int pos=(unsigned int)((double)i*((double)rate/r));
|
||||||
if (pos>=samples) {
|
if (pos>=samples) {
|
||||||
|
@ -374,7 +434,7 @@ bool DivSample::resampleNone(double r) {
|
||||||
data16[i]=oldData16[pos];
|
data16[i]=oldData16[pos];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (depth==8) {
|
} else if (depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
for (int i=0; i<finalCount; i++) {
|
for (int i=0; i<finalCount; i++) {
|
||||||
unsigned int pos=(unsigned int)((double)i*((double)rate/r));
|
unsigned int pos=(unsigned int)((double)i*((double)rate/r));
|
||||||
if (pos>=samples) {
|
if (pos>=samples) {
|
||||||
|
@ -396,7 +456,7 @@ bool DivSample::resampleLinear(double r) {
|
||||||
unsigned int posInt=0;
|
unsigned int posInt=0;
|
||||||
double factor=(double)rate/r;
|
double factor=(double)rate/r;
|
||||||
|
|
||||||
if (depth==16) {
|
if (depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
for (int i=0; i<finalCount; i++) {
|
for (int i=0; i<finalCount; i++) {
|
||||||
short s1=(posInt>=samples)?0:oldData16[posInt];
|
short s1=(posInt>=samples)?0:oldData16[posInt];
|
||||||
short s2=(posInt+1>=samples)?((loopStart>=0 && loopStart<(int)samples)?oldData16[loopStart]:0):oldData16[posInt+1];
|
short s2=(posInt+1>=samples)?((loopStart>=0 && loopStart<(int)samples)?oldData16[loopStart]:0):oldData16[posInt+1];
|
||||||
|
@ -409,7 +469,7 @@ bool DivSample::resampleLinear(double r) {
|
||||||
posInt++;
|
posInt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (depth==8) {
|
} else if (depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
for (int i=0; i<finalCount; i++) {
|
for (int i=0; i<finalCount; i++) {
|
||||||
short s1=(posInt>=samples)?0:oldData8[posInt];
|
short s1=(posInt>=samples)?0:oldData8[posInt];
|
||||||
short s2=(posInt+1>=samples)?((loopStart>=0 && loopStart<(int)samples)?oldData8[loopStart]:0):oldData8[posInt+1];
|
short s2=(posInt+1>=samples)?((loopStart>=0 && loopStart<(int)samples)?oldData8[loopStart]:0):oldData8[posInt+1];
|
||||||
|
@ -436,7 +496,7 @@ bool DivSample::resampleCubic(double r) {
|
||||||
double factor=(double)rate/r;
|
double factor=(double)rate/r;
|
||||||
float* cubicTable=DivFilterTables::getCubicTable();
|
float* cubicTable=DivFilterTables::getCubicTable();
|
||||||
|
|
||||||
if (depth==16) {
|
if (depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
for (int i=0; i<finalCount; i++) {
|
for (int i=0; i<finalCount; i++) {
|
||||||
unsigned int n=((unsigned int)(posFrac*1024.0))&1023;
|
unsigned int n=((unsigned int)(posFrac*1024.0))&1023;
|
||||||
float* t=&cubicTable[n<<2];
|
float* t=&cubicTable[n<<2];
|
||||||
|
@ -456,7 +516,7 @@ bool DivSample::resampleCubic(double r) {
|
||||||
posInt++;
|
posInt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (depth==8) {
|
} else if (depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
for (int i=0; i<finalCount; i++) {
|
for (int i=0; i<finalCount; i++) {
|
||||||
unsigned int n=((unsigned int)(posFrac*1024.0))&1023;
|
unsigned int n=((unsigned int)(posFrac*1024.0))&1023;
|
||||||
float* t=&cubicTable[n<<2];
|
float* t=&cubicTable[n<<2];
|
||||||
|
@ -493,7 +553,7 @@ bool DivSample::resampleBlep(double r) {
|
||||||
|
|
||||||
memset(s,0,16*sizeof(float));
|
memset(s,0,16*sizeof(float));
|
||||||
|
|
||||||
if (depth==16) {
|
if (depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
memset(data16,0,finalCount*sizeof(short));
|
memset(data16,0,finalCount*sizeof(short));
|
||||||
for (int i=0; i<finalCount; i++) {
|
for (int i=0; i<finalCount; i++) {
|
||||||
if (posInt<samples) {
|
if (posInt<samples) {
|
||||||
|
@ -529,7 +589,7 @@ bool DivSample::resampleBlep(double r) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (depth==8) {
|
} else if (depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
memset(data8,0,finalCount);
|
memset(data8,0,finalCount);
|
||||||
for (int i=0; i<finalCount; i++) {
|
for (int i=0; i<finalCount; i++) {
|
||||||
if (posInt<samples) {
|
if (posInt<samples) {
|
||||||
|
@ -582,7 +642,7 @@ bool DivSample::resampleSinc(double r) {
|
||||||
|
|
||||||
memset(s,0,16*sizeof(float));
|
memset(s,0,16*sizeof(float));
|
||||||
|
|
||||||
if (depth==16) {
|
if (depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
for (int i=0; i<finalCount+8; i++) {
|
for (int i=0; i<finalCount+8; i++) {
|
||||||
unsigned int n=((unsigned int)(posFrac*8192.0))&8191;
|
unsigned int n=((unsigned int)(posFrac*8192.0))&8191;
|
||||||
float result=0;
|
float result=0;
|
||||||
|
@ -607,7 +667,7 @@ bool DivSample::resampleSinc(double r) {
|
||||||
s[15]=(posInt>=samples)?0:oldData16[posInt];
|
s[15]=(posInt>=samples)?0:oldData16[posInt];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (depth==8) {
|
} else if (depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
for (int i=0; i<finalCount+8; i++) {
|
for (int i=0; i<finalCount+8; i++) {
|
||||||
unsigned int n=((unsigned int)(posFrac*8192.0))&8191;
|
unsigned int n=((unsigned int)(posFrac*8192.0))&8191;
|
||||||
float result=0;
|
float result=0;
|
||||||
|
@ -639,7 +699,7 @@ bool DivSample::resampleSinc(double r) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DivSample::resample(double r, int filter) {
|
bool DivSample::resample(double r, int filter) {
|
||||||
if (depth!=8 && depth!=16) return false;
|
if (depth!=DIV_SAMPLE_DEPTH_8BIT && depth!=DIV_SAMPLE_DEPTH_16BIT) return false;
|
||||||
switch (filter) {
|
switch (filter) {
|
||||||
case DIV_RESAMPLE_NONE:
|
case DIV_RESAMPLE_NONE:
|
||||||
return resampleNone(r);
|
return resampleNone(r);
|
||||||
|
@ -669,15 +729,15 @@ bool DivSample::resample(double r, int filter) {
|
||||||
|
|
||||||
void DivSample::render() {
|
void DivSample::render() {
|
||||||
// step 1: convert to 16-bit if needed
|
// step 1: convert to 16-bit if needed
|
||||||
if (depth!=16) {
|
if (depth!=DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
if (!initInternal(16,samples)) return;
|
if (!initInternal(DIV_SAMPLE_DEPTH_16BIT,samples)) return;
|
||||||
switch (depth) {
|
switch (depth) {
|
||||||
case 0: // 1-bit
|
case DIV_SAMPLE_DEPTH_1BIT: // 1-bit
|
||||||
for (unsigned int i=0; i<samples; i++) {
|
for (unsigned int i=0; i<samples; i++) {
|
||||||
data16[i]=((data1[i>>3]>>(i&7))&1)?0x7fff:-0x7fff;
|
data16[i]=((data1[i>>3]>>(i&7))&1)?0x7fff:-0x7fff;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1: { // DPCM
|
case DIV_SAMPLE_DEPTH_1BIT_DPCM: { // DPCM
|
||||||
int accum=0;
|
int accum=0;
|
||||||
for (unsigned int i=0; i<samples; i++) {
|
for (unsigned int i=0; i<samples; i++) {
|
||||||
accum+=((dataDPCM[i>>3]>>(i&7))&1)?1:-1;
|
accum+=((dataDPCM[i>>3]>>(i&7))&1)?1:-1;
|
||||||
|
@ -687,27 +747,27 @@ void DivSample::render() {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3: // YMZ ADPCM
|
case DIV_SAMPLE_DEPTH_YMZ_ADPCM: // YMZ ADPCM
|
||||||
ymz_decode(dataZ,data16,samples);
|
ymz_decode(dataZ,data16,samples);
|
||||||
break;
|
break;
|
||||||
case 4: // QSound ADPCM
|
case DIV_SAMPLE_DEPTH_QSOUND_ADPCM: // QSound ADPCM
|
||||||
bs_decode(dataQSoundA,data16,samples);
|
bs_decode(dataQSoundA,data16,samples);
|
||||||
break;
|
break;
|
||||||
case 5: // ADPCM-A
|
case DIV_SAMPLE_DEPTH_ADPCM_A: // ADPCM-A
|
||||||
yma_decode(dataA,data16,samples);
|
yma_decode(dataA,data16,samples);
|
||||||
break;
|
break;
|
||||||
case 6: // ADPCM-B
|
case DIV_SAMPLE_DEPTH_ADPCM_B: // ADPCM-B
|
||||||
ymb_decode(dataB,data16,samples);
|
ymb_decode(dataB,data16,samples);
|
||||||
break;
|
break;
|
||||||
case 8: // 8-bit PCM
|
case DIV_SAMPLE_DEPTH_8BIT: // 8-bit PCM
|
||||||
for (unsigned int i=0; i<samples; i++) {
|
for (unsigned int i=0; i<samples; i++) {
|
||||||
data16[i]=data8[i]<<8;
|
data16[i]=data8[i]<<8;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 9: // BRR
|
case DIV_SAMPLE_DEPTH_BRR: // BRR
|
||||||
// TODO!
|
// TODO!
|
||||||
break;
|
break;
|
||||||
case 10: // VOX
|
case DIV_SAMPLE_DEPTH_VOX: // VOX
|
||||||
oki_decode(dataVOX,data16,samples);
|
oki_decode(dataVOX,data16,samples);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -716,16 +776,16 @@ void DivSample::render() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// step 2: render to other formats
|
// step 2: render to other formats
|
||||||
if (depth!=0) { // 1-bit
|
if (depth!=DIV_SAMPLE_DEPTH_1BIT) { // 1-bit
|
||||||
if (!initInternal(0,samples)) return;
|
if (!initInternal(DIV_SAMPLE_DEPTH_1BIT,samples)) return;
|
||||||
for (unsigned int i=0; i<samples; i++) {
|
for (unsigned int i=0; i<samples; i++) {
|
||||||
if (data16[i]>0) {
|
if (data16[i]>0) {
|
||||||
data1[i>>3]|=1<<(i&7);
|
data1[i>>3]|=1<<(i&7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (depth!=1) { // DPCM
|
if (depth!=DIV_SAMPLE_DEPTH_1BIT_DPCM) { // DPCM
|
||||||
if (!initInternal(1,samples)) return;
|
if (!initInternal(DIV_SAMPLE_DEPTH_1BIT_DPCM,samples)) return;
|
||||||
int accum=63;
|
int accum=63;
|
||||||
for (unsigned int i=0; i<samples; i++) {
|
for (unsigned int i=0; i<samples; i++) {
|
||||||
int next=((unsigned short)(data16[i]^0x8000))>>9;
|
int next=((unsigned short)(data16[i]^0x8000))>>9;
|
||||||
|
@ -739,84 +799,88 @@ void DivSample::render() {
|
||||||
if (accum>127) accum=127;
|
if (accum>127) accum=127;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (depth!=3) { // YMZ ADPCM
|
if (depth!=DIV_SAMPLE_DEPTH_YMZ_ADPCM) { // YMZ ADPCM
|
||||||
if (!initInternal(3,samples)) return;
|
if (!initInternal(DIV_SAMPLE_DEPTH_YMZ_ADPCM,samples)) return;
|
||||||
ymz_encode(data16,dataZ,(samples+7)&(~0x7));
|
ymz_encode(data16,dataZ,(samples+7)&(~0x7));
|
||||||
}
|
}
|
||||||
if (depth!=4) { // QSound ADPCM
|
if (depth!=DIV_SAMPLE_DEPTH_QSOUND_ADPCM) { // QSound ADPCM
|
||||||
if (!initInternal(4,samples)) return;
|
if (!initInternal(DIV_SAMPLE_DEPTH_QSOUND_ADPCM,samples)) return;
|
||||||
bs_encode(data16,dataQSoundA,samples);
|
bs_encode(data16,dataQSoundA,samples);
|
||||||
}
|
}
|
||||||
// TODO: pad to 256.
|
// TODO: pad to 256.
|
||||||
if (depth!=5) { // ADPCM-A
|
if (depth!=DIV_SAMPLE_DEPTH_ADPCM_A) { // ADPCM-A
|
||||||
if (!initInternal(5,samples)) return;
|
if (!initInternal(DIV_SAMPLE_DEPTH_ADPCM_A,samples)) return;
|
||||||
yma_encode(data16,dataA,(samples+511)&(~0x1ff));
|
yma_encode(data16,dataA,(samples+511)&(~0x1ff));
|
||||||
}
|
}
|
||||||
if (depth!=6) { // ADPCM-B
|
if (depth!=DIV_SAMPLE_DEPTH_ADPCM_B) { // ADPCM-B
|
||||||
if (!initInternal(6,samples)) return;
|
if (!initInternal(DIV_SAMPLE_DEPTH_ADPCM_B,samples)) return;
|
||||||
ymb_encode(data16,dataB,(samples+511)&(~0x1ff));
|
ymb_encode(data16,dataB,(samples+511)&(~0x1ff));
|
||||||
}
|
}
|
||||||
if (depth!=8) { // 8-bit PCM
|
if (depth!=DIV_SAMPLE_DEPTH_8BIT) { // 8-bit PCM
|
||||||
if (!initInternal(8,samples)) return;
|
if (!initInternal(DIV_SAMPLE_DEPTH_8BIT,samples)) return;
|
||||||
for (unsigned int i=0; i<samples; i++) {
|
for (unsigned int i=0; i<samples; i++) {
|
||||||
data8[i]=data16[i]>>8;
|
data8[i]=data16[i]>>8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: BRR!
|
// TODO: BRR!
|
||||||
if (depth!=10) { // VOX
|
if (depth!=DIV_SAMPLE_DEPTH_VOX) { // VOX
|
||||||
if (!initInternal(10,samples)) return;
|
if (!initInternal(DIV_SAMPLE_DEPTH_VOX,samples)) return;
|
||||||
oki_encode(data16,dataVOX,samples);
|
oki_encode(data16,dataVOX,samples);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void* DivSample::getCurBuf() {
|
void* DivSample::getCurBuf() {
|
||||||
switch (depth) {
|
switch (depth) {
|
||||||
case 0:
|
case DIV_SAMPLE_DEPTH_1BIT:
|
||||||
return data1;
|
return data1;
|
||||||
case 1:
|
case DIV_SAMPLE_DEPTH_1BIT_DPCM:
|
||||||
return dataDPCM;
|
return dataDPCM;
|
||||||
case 3:
|
case DIV_SAMPLE_DEPTH_YMZ_ADPCM:
|
||||||
return dataZ;
|
return dataZ;
|
||||||
case 4:
|
case DIV_SAMPLE_DEPTH_QSOUND_ADPCM:
|
||||||
return dataQSoundA;
|
return dataQSoundA;
|
||||||
case 5:
|
case DIV_SAMPLE_DEPTH_ADPCM_A:
|
||||||
return dataA;
|
return dataA;
|
||||||
case 6:
|
case DIV_SAMPLE_DEPTH_ADPCM_B:
|
||||||
return dataB;
|
return dataB;
|
||||||
case 8:
|
case DIV_SAMPLE_DEPTH_8BIT:
|
||||||
return data8;
|
return data8;
|
||||||
case 9:
|
case DIV_SAMPLE_DEPTH_BRR:
|
||||||
return dataBRR;
|
return dataBRR;
|
||||||
case 10:
|
case DIV_SAMPLE_DEPTH_VOX:
|
||||||
return dataVOX;
|
return dataVOX;
|
||||||
case 16:
|
case DIV_SAMPLE_DEPTH_16BIT:
|
||||||
return data16;
|
return data16;
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int DivSample::getCurBufLen() {
|
unsigned int DivSample::getCurBufLen() {
|
||||||
switch (depth) {
|
switch (depth) {
|
||||||
case 0:
|
case DIV_SAMPLE_DEPTH_1BIT:
|
||||||
return length1;
|
return length1;
|
||||||
case 1:
|
case DIV_SAMPLE_DEPTH_1BIT_DPCM:
|
||||||
return lengthDPCM;
|
return lengthDPCM;
|
||||||
case 3:
|
case DIV_SAMPLE_DEPTH_YMZ_ADPCM:
|
||||||
return lengthZ;
|
return lengthZ;
|
||||||
case 4:
|
case DIV_SAMPLE_DEPTH_QSOUND_ADPCM:
|
||||||
return lengthQSoundA;
|
return lengthQSoundA;
|
||||||
case 5:
|
case DIV_SAMPLE_DEPTH_ADPCM_A:
|
||||||
return lengthA;
|
return lengthA;
|
||||||
case 6:
|
case DIV_SAMPLE_DEPTH_ADPCM_B:
|
||||||
return lengthB;
|
return lengthB;
|
||||||
case 8:
|
case DIV_SAMPLE_DEPTH_8BIT:
|
||||||
return length8;
|
return length8;
|
||||||
case 9:
|
case DIV_SAMPLE_DEPTH_BRR:
|
||||||
return lengthBRR;
|
return lengthBRR;
|
||||||
case 10:
|
case DIV_SAMPLE_DEPTH_VOX:
|
||||||
return lengthVOX;
|
return lengthVOX;
|
||||||
case 16:
|
case DIV_SAMPLE_DEPTH_16BIT:
|
||||||
return length16;
|
return length16;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -831,9 +895,9 @@ DivSampleHistory* DivSample::prepareUndo(bool data, bool doNotPush) {
|
||||||
duplicate=new unsigned char[getCurBufLen()];
|
duplicate=new unsigned char[getCurBufLen()];
|
||||||
memcpy(duplicate,getCurBuf(),getCurBufLen());
|
memcpy(duplicate,getCurBuf(),getCurBufLen());
|
||||||
}
|
}
|
||||||
h=new DivSampleHistory(duplicate,getCurBufLen(),samples,depth,rate,centerRate,loopStart);
|
h=new DivSampleHistory(duplicate,getCurBufLen(),samples,depth,rate,centerRate,loopStart,loopEnd);
|
||||||
} else {
|
} else {
|
||||||
h=new DivSampleHistory(depth,rate,centerRate,loopStart);
|
h=new DivSampleHistory(depth,rate,centerRate,loopStart,loopEnd);
|
||||||
}
|
}
|
||||||
if (!doNotPush) {
|
if (!doNotPush) {
|
||||||
while (!redoHist.empty()) {
|
while (!redoHist.empty()) {
|
||||||
|
@ -863,7 +927,8 @@ DivSampleHistory* DivSample::prepareUndo(bool data, bool doNotPush) {
|
||||||
} \
|
} \
|
||||||
rate=h->rate; \
|
rate=h->rate; \
|
||||||
centerRate=h->centerRate; \
|
centerRate=h->centerRate; \
|
||||||
loopStart=h->loopStart;
|
loopStart=h->loopStart; \
|
||||||
|
loopEnd=h->loopEnd;
|
||||||
|
|
||||||
|
|
||||||
int DivSample::undo() {
|
int DivSample::undo() {
|
||||||
|
|
|
@ -17,9 +17,28 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _SAMPLE_H
|
||||||
|
#define _SAMPLE_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include "../ta-utils.h"
|
#include "../ta-utils.h"
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
|
enum DivSampleDepth: unsigned char {
|
||||||
|
DIV_SAMPLE_DEPTH_1BIT=0,
|
||||||
|
DIV_SAMPLE_DEPTH_1BIT_DPCM=1,
|
||||||
|
DIV_SAMPLE_DEPTH_YMZ_ADPCM=3,
|
||||||
|
DIV_SAMPLE_DEPTH_QSOUND_ADPCM=4,
|
||||||
|
DIV_SAMPLE_DEPTH_ADPCM_A=5,
|
||||||
|
DIV_SAMPLE_DEPTH_ADPCM_B=6,
|
||||||
|
DIV_SAMPLE_DEPTH_8BIT=8,
|
||||||
|
DIV_SAMPLE_DEPTH_BRR=9,
|
||||||
|
DIV_SAMPLE_DEPTH_VOX=10,
|
||||||
|
DIV_SAMPLE_DEPTH_16BIT=16,
|
||||||
|
DIV_SAMPLE_DEPTH_MAX // boundary for sample depth
|
||||||
|
};
|
||||||
|
|
||||||
enum DivResampleFilters {
|
enum DivResampleFilters {
|
||||||
DIV_RESAMPLE_NONE=0,
|
DIV_RESAMPLE_NONE=0,
|
||||||
DIV_RESAMPLE_LINEAR,
|
DIV_RESAMPLE_LINEAR,
|
||||||
|
@ -32,10 +51,10 @@ enum DivResampleFilters {
|
||||||
struct DivSampleHistory {
|
struct DivSampleHistory {
|
||||||
unsigned char* data;
|
unsigned char* data;
|
||||||
unsigned int length, samples;
|
unsigned int length, samples;
|
||||||
unsigned char depth;
|
DivSampleDepth depth;
|
||||||
int rate, centerRate, loopStart;
|
int rate, centerRate, loopStart, loopEnd;
|
||||||
bool hasSample;
|
bool hasSample;
|
||||||
DivSampleHistory(void* d, unsigned int l, unsigned int s, unsigned char de, int r, int cr, int ls):
|
DivSampleHistory(void* d, unsigned int l, unsigned int s, DivSampleDepth de, int r, int cr, int ls, int le):
|
||||||
data((unsigned char*)d),
|
data((unsigned char*)d),
|
||||||
length(l),
|
length(l),
|
||||||
samples(s),
|
samples(s),
|
||||||
|
@ -43,8 +62,9 @@ struct DivSampleHistory {
|
||||||
rate(r),
|
rate(r),
|
||||||
centerRate(cr),
|
centerRate(cr),
|
||||||
loopStart(ls),
|
loopStart(ls),
|
||||||
|
loopEnd(le),
|
||||||
hasSample(true) {}
|
hasSample(true) {}
|
||||||
DivSampleHistory(unsigned char de, int r, int cr, int ls):
|
DivSampleHistory(DivSampleDepth de, int r, int cr, int ls, int le):
|
||||||
data(NULL),
|
data(NULL),
|
||||||
length(0),
|
length(0),
|
||||||
samples(0),
|
samples(0),
|
||||||
|
@ -52,13 +72,14 @@ struct DivSampleHistory {
|
||||||
rate(r),
|
rate(r),
|
||||||
centerRate(cr),
|
centerRate(cr),
|
||||||
loopStart(ls),
|
loopStart(ls),
|
||||||
|
loopEnd(le),
|
||||||
hasSample(false) {}
|
hasSample(false) {}
|
||||||
~DivSampleHistory();
|
~DivSampleHistory();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DivSample {
|
struct DivSample {
|
||||||
String name;
|
String name;
|
||||||
int rate, centerRate, loopStart, loopOffP;
|
int rate, centerRate, loopStart, loopEnd, loopOffP;
|
||||||
// valid values are:
|
// valid values are:
|
||||||
// - 0: ZX Spectrum overlay drum (1-bit)
|
// - 0: ZX Spectrum overlay drum (1-bit)
|
||||||
// - 1: 1-bit NES DPCM (1-bit)
|
// - 1: 1-bit NES DPCM (1-bit)
|
||||||
|
@ -70,7 +91,7 @@ struct DivSample {
|
||||||
// - 9: BRR (SNES)
|
// - 9: BRR (SNES)
|
||||||
// - 10: VOX ADPCM
|
// - 10: VOX ADPCM
|
||||||
// - 16: 16-bit PCM
|
// - 16: 16-bit PCM
|
||||||
unsigned char depth;
|
DivSampleDepth depth;
|
||||||
|
|
||||||
// these are the new data structures.
|
// these are the new data structures.
|
||||||
signed char* data8; // 8
|
signed char* data8; // 8
|
||||||
|
@ -93,6 +114,23 @@ struct DivSample {
|
||||||
std::deque<DivSampleHistory*> undoHist;
|
std::deque<DivSampleHistory*> undoHist;
|
||||||
std::deque<DivSampleHistory*> redoHist;
|
std::deque<DivSampleHistory*> redoHist;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if sample is loopable.
|
||||||
|
* @return whether it is loopable.
|
||||||
|
*/
|
||||||
|
bool isLoopable();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get sample end position
|
||||||
|
* @return the samples end position.
|
||||||
|
*/
|
||||||
|
unsigned int getEndPosition(DivSampleDepth depth=DIV_SAMPLE_DEPTH_MAX);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @warning DO NOT USE - internal functions
|
||||||
|
*/
|
||||||
|
void setSampleCount(unsigned int count);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @warning DO NOT USE - internal functions
|
* @warning DO NOT USE - internal functions
|
||||||
*/
|
*/
|
||||||
|
@ -116,7 +154,7 @@ struct DivSample {
|
||||||
* @param count number of samples.
|
* @param count number of samples.
|
||||||
* @return whether it was successful.
|
* @return whether it was successful.
|
||||||
*/
|
*/
|
||||||
bool initInternal(unsigned char d, int count);
|
bool initInternal(DivSampleDepth d, int count);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* initialize sample data. make sure you have set `depth` before doing so.
|
* initialize sample data. make sure you have set `depth` before doing so.
|
||||||
|
@ -212,8 +250,9 @@ struct DivSample {
|
||||||
rate(32000),
|
rate(32000),
|
||||||
centerRate(8363),
|
centerRate(8363),
|
||||||
loopStart(-1),
|
loopStart(-1),
|
||||||
|
loopEnd(-1),
|
||||||
loopOffP(0),
|
loopOffP(0),
|
||||||
depth(16),
|
depth(DIV_SAMPLE_DEPTH_16BIT),
|
||||||
data8(NULL),
|
data8(NULL),
|
||||||
data16(NULL),
|
data16(NULL),
|
||||||
data1(NULL),
|
data1(NULL),
|
||||||
|
@ -253,3 +292,5 @@ struct DivSample {
|
||||||
samples(0) {}
|
samples(0) {}
|
||||||
~DivSample();
|
~DivSample();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -512,7 +512,7 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
|
||||||
w->writeC(streamID);
|
w->writeC(streamID);
|
||||||
w->writeS(write.val); // sample number
|
w->writeS(write.val); // sample number
|
||||||
w->writeC((sample->loopStart==0)|(sampleDir[streamID]?0x10:0)); // flags
|
w->writeC((sample->loopStart==0)|(sampleDir[streamID]?0x10:0)); // flags
|
||||||
if (sample->loopStart>0 && !sampleDir[streamID]) {
|
if (sample->isLoopable() && !sampleDir[streamID]) {
|
||||||
loopTimer[streamID]=sample->length8;
|
loopTimer[streamID]=sample->length8;
|
||||||
loopSample[streamID]=write.val;
|
loopSample[streamID]=write.val;
|
||||||
}
|
}
|
||||||
|
@ -1549,7 +1549,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version) {
|
||||||
size_t memPos=0;
|
size_t memPos=0;
|
||||||
for (int i=0; i<song.sampleLen; i++) {
|
for (int i=0; i<song.sampleLen; i++) {
|
||||||
DivSample* sample=song.sample[i];
|
DivSample* sample=song.sample[i];
|
||||||
unsigned int alignedSize=(sample->length8+0xff)&(~0xff);
|
unsigned int alignedSize=(sample->getEndPosition(DIV_SAMPLE_DEPTH_8BIT)+0xff)&(~0xff);
|
||||||
if (alignedSize>65536) alignedSize=65536;
|
if (alignedSize>65536) alignedSize=65536;
|
||||||
if ((memPos&0xff0000)!=((memPos+alignedSize)&0xff0000)) {
|
if ((memPos&0xff0000)!=((memPos+alignedSize)&0xff0000)) {
|
||||||
memPos=(memPos+0xffff)&0xff0000;
|
memPos=(memPos+0xffff)&0xff0000;
|
||||||
|
@ -1559,8 +1559,8 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version) {
|
||||||
sample->offSegaPCM=memPos;
|
sample->offSegaPCM=memPos;
|
||||||
unsigned int readPos=0;
|
unsigned int readPos=0;
|
||||||
for (unsigned int j=0; j<alignedSize; j++) {
|
for (unsigned int j=0; j<alignedSize; j++) {
|
||||||
if (readPos>=sample->length8) {
|
if (readPos>=sample->getEndPosition(DIV_SAMPLE_DEPTH_8BIT)) {
|
||||||
if (sample->loopStart>=0 && sample->loopStart<(int)sample->length8) {
|
if (sample->isLoopable()) {
|
||||||
readPos=sample->loopStart;
|
readPos=sample->loopStart;
|
||||||
pcmMem[memPos++]=((unsigned char)sample->data8[readPos]+0x80);
|
pcmMem[memPos++]=((unsigned char)sample->data8[readPos]+0x80);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1663,7 +1663,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version) {
|
||||||
memcpy(sampleMem,writeZ280[i]->getSampleMem(),sampleMemLen);
|
memcpy(sampleMem,writeZ280[i]->getSampleMem(),sampleMemLen);
|
||||||
for (int i=0; i<song.sampleLen; i++) {
|
for (int i=0; i<song.sampleLen; i++) {
|
||||||
DivSample* s=song.sample[i];
|
DivSample* s=song.sample[i];
|
||||||
if (s->depth==16) {
|
if (s->depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
unsigned int pos=s->offYMZ280B;
|
unsigned int pos=s->offYMZ280B;
|
||||||
for (unsigned int j=0; j<s->samples; j++) {
|
for (unsigned int j=0; j<s->samples; j++) {
|
||||||
unsigned char lo=sampleMem[pos+j*2];
|
unsigned char lo=sampleMem[pos+j*2];
|
||||||
|
@ -1871,12 +1871,12 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version) {
|
||||||
if (loopSample[nextToTouch]<song.sampleLen) {
|
if (loopSample[nextToTouch]<song.sampleLen) {
|
||||||
DivSample* sample=song.sample[loopSample[nextToTouch]];
|
DivSample* sample=song.sample[loopSample[nextToTouch]];
|
||||||
// insert loop
|
// insert loop
|
||||||
if (sample->loopStart<(int)sample->length8) {
|
if (sample->loopStart<(int)sample->getEndPosition(DIV_SAMPLE_DEPTH_8BIT)) {
|
||||||
w->writeC(0x93);
|
w->writeC(0x93);
|
||||||
w->writeC(nextToTouch);
|
w->writeC(nextToTouch);
|
||||||
w->writeI(sample->off8+sample->loopStart);
|
w->writeI(sample->off8+sample->loopStart);
|
||||||
w->writeC(0x81);
|
w->writeC(0x81);
|
||||||
w->writeI(sample->length8-sample->loopStart);
|
w->writeI(sample->getEndPosition(DIV_SAMPLE_DEPTH_8BIT)-sample->loopStart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loopSample[nextToTouch]=-1;
|
loopSample[nextToTouch]=-1;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
|
#include "guiConst.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "IconsFontAwesome4.h"
|
#include "IconsFontAwesome4.h"
|
||||||
#include <SDL_timer.h>
|
#include <SDL_timer.h>
|
||||||
|
@ -154,12 +155,19 @@ void FurnaceGUI::drawDebug() {
|
||||||
ImGui::Text("rate: %d",sample->rate);
|
ImGui::Text("rate: %d",sample->rate);
|
||||||
ImGui::Text("centerRate: %d",sample->centerRate);
|
ImGui::Text("centerRate: %d",sample->centerRate);
|
||||||
ImGui::Text("loopStart: %d",sample->loopStart);
|
ImGui::Text("loopStart: %d",sample->loopStart);
|
||||||
|
ImGui::Text("loopEnd: %d", sample->loopEnd);
|
||||||
ImGui::Text("loopOffP: %d",sample->loopOffP);
|
ImGui::Text("loopOffP: %d",sample->loopOffP);
|
||||||
ImGui::Text("depth: %d",sample->depth);
|
if (sampleDepths[sample->depth]!=NULL) {
|
||||||
|
ImGui::Text("depth: %d (%s)",(unsigned char)sample->depth,sampleDepths[sample->depth]);
|
||||||
|
} else {
|
||||||
|
ImGui::Text("depth: %d (<NULL!>)",(unsigned char)sample->depth);
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::Text("length8: %d",sample->length8);
|
ImGui::Text("length8: %d",sample->length8);
|
||||||
ImGui::Text("length16: %d",sample->length16);
|
ImGui::Text("length16: %d",sample->length16);
|
||||||
ImGui::Text("length1: %d",sample->length1);
|
ImGui::Text("length1: %d",sample->length1);
|
||||||
ImGui::Text("lengthDPCM: %d",sample->lengthDPCM);
|
ImGui::Text("lengthDPCM: %d",sample->lengthDPCM);
|
||||||
|
ImGui::Text("lengthZ: %d",sample->lengthZ);
|
||||||
ImGui::Text("lengthQSoundA: %d",sample->lengthQSoundA);
|
ImGui::Text("lengthQSoundA: %d",sample->lengthQSoundA);
|
||||||
ImGui::Text("lengthA: %d",sample->lengthA);
|
ImGui::Text("lengthA: %d",sample->lengthA);
|
||||||
ImGui::Text("lengthB: %d",sample->lengthB);
|
ImGui::Text("lengthB: %d",sample->lengthB);
|
||||||
|
@ -170,6 +178,7 @@ void FurnaceGUI::drawDebug() {
|
||||||
ImGui::Text("off16: %x",sample->off16);
|
ImGui::Text("off16: %x",sample->off16);
|
||||||
ImGui::Text("off1: %x",sample->off1);
|
ImGui::Text("off1: %x",sample->off1);
|
||||||
ImGui::Text("offDPCM: %x",sample->offDPCM);
|
ImGui::Text("offDPCM: %x",sample->offDPCM);
|
||||||
|
ImGui::Text("offZ: %x",sample->offZ);
|
||||||
ImGui::Text("offQSoundA: %x",sample->offQSoundA);
|
ImGui::Text("offQSoundA: %x",sample->offQSoundA);
|
||||||
ImGui::Text("offA: %x",sample->offA);
|
ImGui::Text("offA: %x",sample->offA);
|
||||||
ImGui::Text("offB: %x",sample->offB);
|
ImGui::Text("offB: %x",sample->offB);
|
||||||
|
@ -179,6 +188,8 @@ void FurnaceGUI::drawDebug() {
|
||||||
ImGui::Text("offQSound: %x",sample->offQSound);
|
ImGui::Text("offQSound: %x",sample->offQSound);
|
||||||
ImGui::Text("offX1_010: %x",sample->offX1_010);
|
ImGui::Text("offX1_010: %x",sample->offX1_010);
|
||||||
ImGui::Text("offSU: %x",sample->offSU);
|
ImGui::Text("offSU: %x",sample->offSU);
|
||||||
|
ImGui::Text("offYMZ280B: %x",sample->offYMZ280B);
|
||||||
|
ImGui::Text("offRF5C68: %x",sample->offRF5C68);
|
||||||
|
|
||||||
ImGui::Text("samples: %d",sample->samples);
|
ImGui::Text("samples: %d",sample->samples);
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
|
|
|
@ -709,6 +709,7 @@ void FurnaceGUI::doAction(int what) {
|
||||||
sample->centerRate=prevSample->centerRate;
|
sample->centerRate=prevSample->centerRate;
|
||||||
sample->name=prevSample->name;
|
sample->name=prevSample->name;
|
||||||
sample->loopStart=prevSample->loopStart;
|
sample->loopStart=prevSample->loopStart;
|
||||||
|
sample->loopEnd=prevSample->loopEnd;
|
||||||
sample->depth=prevSample->depth;
|
sample->depth=prevSample->depth;
|
||||||
if (sample->init(prevSample->samples)) {
|
if (sample->init(prevSample->samples)) {
|
||||||
if (prevSample->getCurBuf()!=NULL) {
|
if (prevSample->getCurBuf()!=NULL) {
|
||||||
|
@ -838,7 +839,7 @@ void FurnaceGUI::doAction(int what) {
|
||||||
if (!sample->insert(pos,sampleClipboardLen)) {
|
if (!sample->insert(pos,sampleClipboardLen)) {
|
||||||
showError("couldn't paste! make sure your sample is 8 or 16-bit.");
|
showError("couldn't paste! make sure your sample is 8 or 16-bit.");
|
||||||
} else {
|
} else {
|
||||||
if (sample->depth==8) {
|
if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
for (size_t i=0; i<sampleClipboardLen; i++) {
|
for (size_t i=0; i<sampleClipboardLen; i++) {
|
||||||
sample->data8[pos+i]=sampleClipboard[i]>>8;
|
sample->data8[pos+i]=sampleClipboard[i]>>8;
|
||||||
}
|
}
|
||||||
|
@ -864,7 +865,7 @@ void FurnaceGUI::doAction(int what) {
|
||||||
if (pos<0) pos=0;
|
if (pos<0) pos=0;
|
||||||
|
|
||||||
e->lockEngine([this,sample,pos]() {
|
e->lockEngine([this,sample,pos]() {
|
||||||
if (sample->depth==8) {
|
if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
for (size_t i=0; i<sampleClipboardLen; i++) {
|
for (size_t i=0; i<sampleClipboardLen; i++) {
|
||||||
if (pos+i>=sample->samples) break;
|
if (pos+i>=sample->samples) break;
|
||||||
sample->data8[pos+i]=sampleClipboard[i]>>8;
|
sample->data8[pos+i]=sampleClipboard[i]>>8;
|
||||||
|
@ -894,7 +895,7 @@ void FurnaceGUI::doAction(int what) {
|
||||||
if (pos<0) pos=0;
|
if (pos<0) pos=0;
|
||||||
|
|
||||||
e->lockEngine([this,sample,pos]() {
|
e->lockEngine([this,sample,pos]() {
|
||||||
if (sample->depth==8) {
|
if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
for (size_t i=0; i<sampleClipboardLen; i++) {
|
for (size_t i=0; i<sampleClipboardLen; i++) {
|
||||||
if (pos+i>=sample->samples) break;
|
if (pos+i>=sample->samples) break;
|
||||||
int val=sample->data8[pos+i]+(sampleClipboard[i]>>8);
|
int val=sample->data8[pos+i]+(sampleClipboard[i]>>8);
|
||||||
|
@ -948,7 +949,7 @@ void FurnaceGUI::doAction(int what) {
|
||||||
SAMPLE_OP_BEGIN;
|
SAMPLE_OP_BEGIN;
|
||||||
float maxVal=0.0f;
|
float maxVal=0.0f;
|
||||||
|
|
||||||
if (sample->depth==16) {
|
if (sample->depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
float val=fabs((float)sample->data16[i]/32767.0f);
|
float val=fabs((float)sample->data16[i]/32767.0f);
|
||||||
if (val>maxVal) maxVal=val;
|
if (val>maxVal) maxVal=val;
|
||||||
|
@ -963,7 +964,7 @@ void FurnaceGUI::doAction(int what) {
|
||||||
sample->data16[i]=val;
|
sample->data16[i]=val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (sample->depth==8) {
|
} else if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
float val=fabs((float)sample->data8[i]/127.0f);
|
float val=fabs((float)sample->data8[i]/127.0f);
|
||||||
if (val>maxVal) maxVal=val;
|
if (val>maxVal) maxVal=val;
|
||||||
|
@ -994,14 +995,14 @@ void FurnaceGUI::doAction(int what) {
|
||||||
e->lockEngine([this,sample]() {
|
e->lockEngine([this,sample]() {
|
||||||
SAMPLE_OP_BEGIN;
|
SAMPLE_OP_BEGIN;
|
||||||
|
|
||||||
if (sample->depth==16) {
|
if (sample->depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
float val=sample->data16[i]*float(i-start)/float(end-start);
|
float val=sample->data16[i]*float(i-start)/float(end-start);
|
||||||
if (val<-32768) val=-32768;
|
if (val<-32768) val=-32768;
|
||||||
if (val>32767) val=32767;
|
if (val>32767) val=32767;
|
||||||
sample->data16[i]=val;
|
sample->data16[i]=val;
|
||||||
}
|
}
|
||||||
} else if (sample->depth==8) {
|
} else if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
float val=sample->data8[i]*float(i-start)/float(end-start);
|
float val=sample->data8[i]*float(i-start)/float(end-start);
|
||||||
if (val<-128) val=-128;
|
if (val<-128) val=-128;
|
||||||
|
@ -1024,14 +1025,14 @@ void FurnaceGUI::doAction(int what) {
|
||||||
e->lockEngine([this,sample]() {
|
e->lockEngine([this,sample]() {
|
||||||
SAMPLE_OP_BEGIN;
|
SAMPLE_OP_BEGIN;
|
||||||
|
|
||||||
if (sample->depth==16) {
|
if (sample->depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
float val=sample->data16[i]*float(end-i)/float(end-start);
|
float val=sample->data16[i]*float(end-i)/float(end-start);
|
||||||
if (val<-32768) val=-32768;
|
if (val<-32768) val=-32768;
|
||||||
if (val>32767) val=32767;
|
if (val>32767) val=32767;
|
||||||
sample->data16[i]=val;
|
sample->data16[i]=val;
|
||||||
}
|
}
|
||||||
} else if (sample->depth==8) {
|
} else if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
float val=sample->data8[i]*float(end-i)/float(end-start);
|
float val=sample->data8[i]*float(end-i)/float(end-start);
|
||||||
if (val<-128) val=-128;
|
if (val<-128) val=-128;
|
||||||
|
@ -1058,11 +1059,11 @@ void FurnaceGUI::doAction(int what) {
|
||||||
e->lockEngine([this,sample]() {
|
e->lockEngine([this,sample]() {
|
||||||
SAMPLE_OP_BEGIN;
|
SAMPLE_OP_BEGIN;
|
||||||
|
|
||||||
if (sample->depth==16) {
|
if (sample->depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
sample->data16[i]=0;
|
sample->data16[i]=0;
|
||||||
}
|
}
|
||||||
} else if (sample->depth==8) {
|
} else if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
sample->data8[i]=0;
|
sample->data8[i]=0;
|
||||||
}
|
}
|
||||||
|
@ -1116,7 +1117,7 @@ void FurnaceGUI::doAction(int what) {
|
||||||
e->lockEngine([this,sample]() {
|
e->lockEngine([this,sample]() {
|
||||||
SAMPLE_OP_BEGIN;
|
SAMPLE_OP_BEGIN;
|
||||||
|
|
||||||
if (sample->depth==16) {
|
if (sample->depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
unsigned int ri=end-i-1+start;
|
unsigned int ri=end-i-1+start;
|
||||||
if (ri<=i) break;
|
if (ri<=i) break;
|
||||||
|
@ -1124,7 +1125,7 @@ void FurnaceGUI::doAction(int what) {
|
||||||
sample->data16[ri]^=sample->data16[i];
|
sample->data16[ri]^=sample->data16[i];
|
||||||
sample->data16[i]^=sample->data16[ri];
|
sample->data16[i]^=sample->data16[ri];
|
||||||
}
|
}
|
||||||
} else if (sample->depth==8) {
|
} else if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
unsigned int ri=end-i-1+start;
|
unsigned int ri=end-i-1+start;
|
||||||
if (ri<=i) break;
|
if (ri<=i) break;
|
||||||
|
@ -1148,12 +1149,12 @@ void FurnaceGUI::doAction(int what) {
|
||||||
e->lockEngine([this,sample]() {
|
e->lockEngine([this,sample]() {
|
||||||
SAMPLE_OP_BEGIN;
|
SAMPLE_OP_BEGIN;
|
||||||
|
|
||||||
if (sample->depth==16) {
|
if (sample->depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
sample->data16[i]=-sample->data16[i];
|
sample->data16[i]=-sample->data16[i];
|
||||||
if (sample->data16[i]==-32768) sample->data16[i]=32767;
|
if (sample->data16[i]==-32768) sample->data16[i]=32767;
|
||||||
}
|
}
|
||||||
} else if (sample->depth==8) {
|
} else if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
sample->data8[i]=-sample->data8[i];
|
sample->data8[i]=-sample->data8[i];
|
||||||
if (sample->data16[i]==-128) sample->data16[i]=127;
|
if (sample->data16[i]==-128) sample->data16[i]=127;
|
||||||
|
@ -1174,11 +1175,11 @@ void FurnaceGUI::doAction(int what) {
|
||||||
e->lockEngine([this,sample]() {
|
e->lockEngine([this,sample]() {
|
||||||
SAMPLE_OP_BEGIN;
|
SAMPLE_OP_BEGIN;
|
||||||
|
|
||||||
if (sample->depth==16) {
|
if (sample->depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
sample->data16[i]^=0x8000;
|
sample->data16[i]^=0x8000;
|
||||||
}
|
}
|
||||||
} else if (sample->depth==8) {
|
} else if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
sample->data8[i]^=0x80;
|
sample->data8[i]^=0x80;
|
||||||
}
|
}
|
||||||
|
@ -1261,8 +1262,8 @@ void FurnaceGUI::doAction(int what) {
|
||||||
e->lockEngine([this,sample]() {
|
e->lockEngine([this,sample]() {
|
||||||
SAMPLE_OP_BEGIN;
|
SAMPLE_OP_BEGIN;
|
||||||
|
|
||||||
sample->trim(0,end);
|
|
||||||
sample->loopStart=start;
|
sample->loopStart=start;
|
||||||
|
sample->loopEnd=end;
|
||||||
updateSampleTex=true;
|
updateSampleTex=true;
|
||||||
|
|
||||||
e->renderSamples();
|
e->renderSamples();
|
||||||
|
|
|
@ -116,7 +116,7 @@ const char* insTypes[DIV_INS_MAX+1]={
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* sampleDepths[17]={
|
const char* sampleDepths[DIV_SAMPLE_DEPTH_MAX]={
|
||||||
"1-bit PCM",
|
"1-bit PCM",
|
||||||
"1-bit DPCM",
|
"1-bit DPCM",
|
||||||
NULL,
|
NULL,
|
||||||
|
|
|
@ -40,7 +40,7 @@ extern const char* noteNames[180];
|
||||||
extern const char* noteNamesG[180];
|
extern const char* noteNamesG[180];
|
||||||
extern const char* pitchLabel[11];
|
extern const char* pitchLabel[11];
|
||||||
extern const char* insTypes[];
|
extern const char* insTypes[];
|
||||||
extern const char* sampleDepths[17];
|
extern const char* sampleDepths[];
|
||||||
extern const char* resampleStrats[];
|
extern const char* resampleStrats[];
|
||||||
extern const int availableSystems[];
|
extern const int availableSystems[];
|
||||||
extern const FurnaceGUIActionDef guiActions[];
|
extern const FurnaceGUIActionDef guiActions[];
|
||||||
|
|
|
@ -41,7 +41,7 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
} else {
|
} else {
|
||||||
DivSample* sample=e->song.sample[curSample];
|
DivSample* sample=e->song.sample[curSample];
|
||||||
String sampleType="Invalid";
|
String sampleType="Invalid";
|
||||||
if (sample->depth<17) {
|
if (sample->depth<DIV_SAMPLE_DEPTH_MAX) {
|
||||||
if (sampleDepths[sample->depth]!=NULL) {
|
if (sampleDepths[sample->depth]!=NULL) {
|
||||||
sampleType=sampleDepths[sample->depth];
|
sampleType=sampleDepths[sample->depth];
|
||||||
}
|
}
|
||||||
|
@ -61,11 +61,11 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
if (ImGui::BeginCombo("##SampleType",sampleType.c_str())) {
|
if (ImGui::BeginCombo("##SampleType",sampleType.c_str())) {
|
||||||
for (int i=0; i<17; i++) {
|
for (int i=0; i<DIV_SAMPLE_DEPTH_MAX; i++) {
|
||||||
if (sampleDepths[i]==NULL) continue;
|
if (sampleDepths[i]==NULL) continue;
|
||||||
if (ImGui::Selectable(sampleDepths[i])) {
|
if (ImGui::Selectable(sampleDepths[i])) {
|
||||||
sample->prepareUndo(true);
|
sample->prepareUndo(true);
|
||||||
sample->depth=i;
|
sample->depth=(DivSampleDepth)i;
|
||||||
e->renderSamplesP();
|
e->renderSamplesP();
|
||||||
updateSampleTex=true;
|
updateSampleTex=true;
|
||||||
MARK_MODIFIED;
|
MARK_MODIFIED;
|
||||||
|
@ -93,22 +93,43 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
bool doLoop=(sample->loopStart>=0);
|
bool doLoop=(sample->isLoopable());
|
||||||
if (ImGui::Checkbox("Loop",&doLoop)) { MARK_MODIFIED
|
if (ImGui::Checkbox("Loop",&doLoop)) { MARK_MODIFIED
|
||||||
if (doLoop) {
|
if (doLoop) {
|
||||||
sample->loopStart=0;
|
sample->loopStart=0;
|
||||||
|
sample->loopEnd=sample->samples;
|
||||||
} else {
|
} else {
|
||||||
sample->loopStart=-1;
|
sample->loopStart=-1;
|
||||||
|
sample->loopEnd=sample->samples;
|
||||||
}
|
}
|
||||||
updateSampleTex=true;
|
updateSampleTex=true;
|
||||||
}
|
}
|
||||||
if (doLoop) {
|
if (doLoop) {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("Loop Start");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
if (ImGui::InputInt("##LoopPosition",&sample->loopStart,1,10)) { MARK_MODIFIED
|
if (ImGui::InputInt("##LoopStartPosition",&sample->loopStart,1,10)) { MARK_MODIFIED
|
||||||
if (sample->loopStart<0 || sample->loopStart>=(int)sample->samples) {
|
if (sample->loopStart<0) {
|
||||||
sample->loopStart=0;
|
sample->loopStart=0;
|
||||||
}
|
}
|
||||||
|
if (sample->loopStart>sample->loopEnd) {
|
||||||
|
sample->loopStart=sample->loopEnd;
|
||||||
|
}
|
||||||
|
updateSampleTex=true;
|
||||||
|
}
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("Loop End");
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
|
if (ImGui::InputInt("##LoopEndPosition",&sample->loopEnd,1,10)) { MARK_MODIFIED
|
||||||
|
if (sample->loopEnd<sample->loopStart) {
|
||||||
|
sample->loopEnd=sample->loopStart;
|
||||||
|
}
|
||||||
|
if (sample->loopEnd>=(int)sample->samples) {
|
||||||
|
sample->loopEnd=sample->samples;
|
||||||
|
}
|
||||||
updateSampleTex=true;
|
updateSampleTex=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,7 +144,7 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
*/
|
*/
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
ImGui::BeginDisabled(sample->depth!=8 && sample->depth!=16);
|
ImGui::BeginDisabled(sample->depth!=DIV_SAMPLE_DEPTH_8BIT && sample->depth!=DIV_SAMPLE_DEPTH_16BIT);
|
||||||
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Button,TOGGLE_COLOR(!sampleDragMode));
|
ImGui::PushStyleColor(ImGuiCol_Button,TOGGLE_COLOR(!sampleDragMode));
|
||||||
if (ImGui::Button(ICON_FA_I_CURSOR "##SSelect")) {
|
if (ImGui::Button(ICON_FA_I_CURSOR "##SSelect")) {
|
||||||
|
@ -275,14 +296,14 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
SAMPLE_OP_BEGIN;
|
SAMPLE_OP_BEGIN;
|
||||||
float vol=amplifyVol/100.0f;
|
float vol=amplifyVol/100.0f;
|
||||||
|
|
||||||
if (sample->depth==16) {
|
if (sample->depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
float val=sample->data16[i]*vol;
|
float val=sample->data16[i]*vol;
|
||||||
if (val<-32768) val=-32768;
|
if (val<-32768) val=-32768;
|
||||||
if (val>32767) val=32767;
|
if (val>32767) val=32767;
|
||||||
sample->data16[i]=val;
|
sample->data16[i]=val;
|
||||||
}
|
}
|
||||||
} else if (sample->depth==8) {
|
} else if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
float val=sample->data8[i]*vol;
|
float val=sample->data8[i]*vol;
|
||||||
if (val<-128) val=-128;
|
if (val<-128) val=-128;
|
||||||
|
@ -466,7 +487,7 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
|
|
||||||
double power=(sampleFilterCutStart>sampleFilterCutEnd)?0.5:2.0;
|
double power=(sampleFilterCutStart>sampleFilterCutEnd)?0.5:2.0;
|
||||||
|
|
||||||
if (sample->depth==16) {
|
if (sample->depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
double freq=sampleFilterCutStart+(sampleFilterCutEnd-sampleFilterCutStart)*pow(double(i-start)/double(end-start),power);
|
double freq=sampleFilterCutStart+(sampleFilterCutEnd-sampleFilterCutStart)*pow(double(i-start)/double(end-start),power);
|
||||||
double cut=sin((freq/double(sample->rate))*M_PI);
|
double cut=sin((freq/double(sample->rate))*M_PI);
|
||||||
|
@ -482,7 +503,7 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
if (val>32767) val=32767;
|
if (val>32767) val=32767;
|
||||||
sample->data16[i]=val;
|
sample->data16[i]=val;
|
||||||
}
|
}
|
||||||
} else if (sample->depth==8) {
|
} else if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
double freq=sampleFilterCutStart+(sampleFilterCutEnd-sampleFilterCutStart)*pow(double(i-start)/double(end-start),power);
|
double freq=sampleFilterCutStart+(sampleFilterCutEnd-sampleFilterCutStart)*pow(double(i-start)/double(end-start),power);
|
||||||
double cut=sin((freq/double(sample->rate))*M_PI);
|
double cut=sin((freq/double(sample->rate))*M_PI);
|
||||||
|
@ -574,11 +595,11 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
if (ImGui::BeginCombo("##SampleType",sampleType.c_str())) {
|
if (ImGui::BeginCombo("##SampleType",sampleType.c_str())) {
|
||||||
for (int i=0; i<17; i++) {
|
for (int i=0; i<DIV_SAMPLE_DEPTH_MAX; i++) {
|
||||||
if (sampleDepths[i]==NULL) continue;
|
if (sampleDepths[i]==NULL) continue;
|
||||||
if (ImGui::Selectable(sampleDepths[i])) {
|
if (ImGui::Selectable(sampleDepths[i])) {
|
||||||
sample->prepareUndo(true);
|
sample->prepareUndo(true);
|
||||||
sample->depth=i;
|
sample->depth=(DivSampleDepth)i;
|
||||||
e->renderSamplesP();
|
e->renderSamplesP();
|
||||||
updateSampleTex=true;
|
updateSampleTex=true;
|
||||||
MARK_MODIFIED;
|
MARK_MODIFIED;
|
||||||
|
@ -607,22 +628,43 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
bool doLoop=(sample->loopStart>=0);
|
bool doLoop=(sample->isLoopable());
|
||||||
if (ImGui::Checkbox("Loop",&doLoop)) { MARK_MODIFIED
|
if (ImGui::Checkbox("Loop",&doLoop)) { MARK_MODIFIED
|
||||||
if (doLoop) {
|
if (doLoop) {
|
||||||
sample->loopStart=0;
|
sample->loopStart=0;
|
||||||
|
sample->loopEnd=sample->samples;
|
||||||
} else {
|
} else {
|
||||||
sample->loopStart=-1;
|
sample->loopStart=-1;
|
||||||
|
sample->loopEnd=sample->samples;
|
||||||
}
|
}
|
||||||
updateSampleTex=true;
|
updateSampleTex=true;
|
||||||
}
|
}
|
||||||
if (doLoop) {
|
if (doLoop) {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("Loop Start");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
if (ImGui::InputInt("##LoopPosition",&sample->loopStart,1,10)) { MARK_MODIFIED
|
if (ImGui::InputInt("##LoopStartPosition",&sample->loopStart,1,10)) { MARK_MODIFIED
|
||||||
if (sample->loopStart<0 || sample->loopStart>=(int)sample->samples) {
|
if (sample->loopStart<0) {
|
||||||
sample->loopStart=0;
|
sample->loopStart=0;
|
||||||
}
|
}
|
||||||
|
if (sample->loopStart>sample->loopEnd) {
|
||||||
|
sample->loopStart=sample->loopEnd;
|
||||||
|
}
|
||||||
|
updateSampleTex=true;
|
||||||
|
}
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("Loop End");
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
|
if (ImGui::InputInt("##LoopEndPosition",&sample->loopEnd,1,10)) { MARK_MODIFIED
|
||||||
|
if (sample->loopEnd<sample->loopStart) {
|
||||||
|
sample->loopEnd=sample->loopStart;
|
||||||
|
}
|
||||||
|
if (sample->loopEnd>=(int)sample->samples) {
|
||||||
|
sample->loopEnd=sample->samples;
|
||||||
|
}
|
||||||
updateSampleTex=true;
|
updateSampleTex=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -637,7 +679,7 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
*/
|
*/
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
ImGui::BeginDisabled(sample->depth!=8 && sample->depth!=16);
|
ImGui::BeginDisabled(sample->depth!=DIV_SAMPLE_DEPTH_8BIT && sample->depth!=DIV_SAMPLE_DEPTH_16BIT);
|
||||||
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Button,TOGGLE_COLOR(!sampleDragMode));
|
ImGui::PushStyleColor(ImGuiCol_Button,TOGGLE_COLOR(!sampleDragMode));
|
||||||
if (ImGui::Button(ICON_FA_I_CURSOR "##SSelect")) {
|
if (ImGui::Button(ICON_FA_I_CURSOR "##SSelect")) {
|
||||||
|
@ -820,7 +862,7 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
|
|
||||||
double power=(sampleFilterCutStart>sampleFilterCutEnd)?0.5:2.0;
|
double power=(sampleFilterCutStart>sampleFilterCutEnd)?0.5:2.0;
|
||||||
|
|
||||||
if (sample->depth==16) {
|
if (sample->depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
double freq=sampleFilterCutStart+(sampleFilterCutEnd-sampleFilterCutStart)*pow(double(i-start)/double(end-start),power);
|
double freq=sampleFilterCutStart+(sampleFilterCutEnd-sampleFilterCutStart)*pow(double(i-start)/double(end-start),power);
|
||||||
double cut=sin((freq/double(sample->rate))*M_PI);
|
double cut=sin((freq/double(sample->rate))*M_PI);
|
||||||
|
@ -836,7 +878,7 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
if (val>32767) val=32767;
|
if (val>32767) val=32767;
|
||||||
sample->data16[i]=val;
|
sample->data16[i]=val;
|
||||||
}
|
}
|
||||||
} else if (sample->depth==8) {
|
} else if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
double freq=sampleFilterCutStart+(sampleFilterCutEnd-sampleFilterCutStart)*pow(double(i-start)/double(end-start),power);
|
double freq=sampleFilterCutStart+(sampleFilterCutEnd-sampleFilterCutStart)*pow(double(i-start)/double(end-start),power);
|
||||||
double cut=sin((freq/double(sample->rate))*M_PI);
|
double cut=sin((freq/double(sample->rate))*M_PI);
|
||||||
|
@ -890,14 +932,14 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
SAMPLE_OP_BEGIN;
|
SAMPLE_OP_BEGIN;
|
||||||
float vol=amplifyVol/100.0f;
|
float vol=amplifyVol/100.0f;
|
||||||
|
|
||||||
if (sample->depth==16) {
|
if (sample->depth==DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
float val=sample->data16[i]*vol;
|
float val=sample->data16[i]*vol;
|
||||||
if (val<-32768) val=-32768;
|
if (val<-32768) val=-32768;
|
||||||
if (val>32767) val=32767;
|
if (val>32767) val=32767;
|
||||||
sample->data16[i]=val;
|
sample->data16[i]=val;
|
||||||
}
|
}
|
||||||
} else if (sample->depth==8) {
|
} else if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
for (unsigned int i=start; i<end; i++) {
|
for (unsigned int i=start; i<end; i++) {
|
||||||
float val=sample->data8[i]*vol;
|
float val=sample->data8[i]*vol;
|
||||||
if (val<-128) val=-128;
|
if (val<-128) val=-128;
|
||||||
|
@ -1138,7 +1180,7 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
for (int i=0; i<availY; i++) {
|
for (int i=0; i<availY; i++) {
|
||||||
for (int j=0; j<availX; j++) {
|
for (int j=0; j<availX; j++) {
|
||||||
int scaledPos=samplePos+(j*sampleZoom);
|
int scaledPos=samplePos+(j*sampleZoom);
|
||||||
if (sample->loopStart>=0 && sample->loopStart<(int)sample->samples && scaledPos>=sample->loopStart) {
|
if (sample->isLoopable() && (scaledPos>=sample->loopStart && scaledPos<=sample->loopEnd)) {
|
||||||
data[i*availX+j]=bgColorLoop;
|
data[i*availX+j]=bgColorLoop;
|
||||||
} else {
|
} else {
|
||||||
data[i*availX+j]=bgColor;
|
data[i*availX+j]=bgColor;
|
||||||
|
@ -1158,7 +1200,7 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
if (xCoarse>=sample->samples) break;
|
if (xCoarse>=sample->samples) break;
|
||||||
int y1, y2;
|
int y1, y2;
|
||||||
int totalAdvance=0;
|
int totalAdvance=0;
|
||||||
if (sample->depth==8) {
|
if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
y1=((unsigned char)sample->data8[xCoarse]^0x80)*availY/256;
|
y1=((unsigned char)sample->data8[xCoarse]^0x80)*availY/256;
|
||||||
} else {
|
} else {
|
||||||
y1=((unsigned short)sample->data16[xCoarse]^0x8000)*availY/65536;
|
y1=((unsigned short)sample->data16[xCoarse]^0x8000)*availY/65536;
|
||||||
|
@ -1171,7 +1213,7 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
totalAdvance+=xAdvanceCoarse;
|
totalAdvance+=xAdvanceCoarse;
|
||||||
if (xCoarse>=sample->samples) break;
|
if (xCoarse>=sample->samples) break;
|
||||||
do {
|
do {
|
||||||
if (sample->depth==8) {
|
if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||||
y2=((unsigned char)sample->data8[xCoarse]^0x80)*availY/256;
|
y2=((unsigned char)sample->data8[xCoarse]^0x80)*availY/256;
|
||||||
} else {
|
} else {
|
||||||
y2=((unsigned short)sample->data16[xCoarse]^0x8000)*availY/65536;
|
y2=((unsigned short)sample->data16[xCoarse]^0x8000)*availY/65536;
|
||||||
|
@ -1209,11 +1251,11 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
sampleSelStart=0;
|
sampleSelStart=0;
|
||||||
sampleSelEnd=sample->samples;
|
sampleSelEnd=sample->samples;
|
||||||
} else {
|
} else {
|
||||||
if (sample->samples>0 && (sample->depth==16 || sample->depth==8)) {
|
if (sample->samples>0 && (sample->depth==DIV_SAMPLE_DEPTH_16BIT || sample->depth==DIV_SAMPLE_DEPTH_8BIT)) {
|
||||||
sampleDragStart=rectMin;
|
sampleDragStart=rectMin;
|
||||||
sampleDragAreaSize=rectSize;
|
sampleDragAreaSize=rectSize;
|
||||||
sampleDrag16=(sample->depth==16);
|
sampleDrag16=(sample->depth==DIV_SAMPLE_DEPTH_16BIT);
|
||||||
sampleDragTarget=(sample->depth==16)?((void*)sample->data16):((void*)sample->data8);
|
sampleDragTarget=(sample->depth==DIV_SAMPLE_DEPTH_16BIT)?((void*)sample->data16):((void*)sample->data8);
|
||||||
sampleDragLen=sample->samples;
|
sampleDragLen=sample->samples;
|
||||||
sampleDragActive=true;
|
sampleDragActive=true;
|
||||||
sampleSelStart=-1;
|
sampleSelStart=-1;
|
||||||
|
@ -1312,7 +1354,7 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
posX=samplePos+pos.x*sampleZoom;
|
posX=samplePos+pos.x*sampleZoom;
|
||||||
if (posX>(int)sample->samples) posX=-1;
|
if (posX>(int)sample->samples) posX=-1;
|
||||||
}
|
}
|
||||||
posY=(0.5-pos.y/rectSize.y)*((sample->depth==8)?255:32767);
|
posY=(0.5-pos.y/rectSize.y)*((sample->depth==DIV_SAMPLE_DEPTH_8BIT)?255:32767);
|
||||||
if (posX>=0) {
|
if (posX>=0) {
|
||||||
statusBar+=fmt::sprintf(" | (%d, %d)",posX,posY);
|
statusBar+=fmt::sprintf(" | (%d, %d)",posX,posY);
|
||||||
}
|
}
|
||||||
|
@ -1362,7 +1404,7 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sample->depth!=8 && sample->depth!=16) {
|
if (sample->depth!=DIV_SAMPLE_DEPTH_8BIT && sample->depth!=DIV_SAMPLE_DEPTH_16BIT) {
|
||||||
statusBar="Non-8/16-bit samples cannot be edited without prior conversion.";
|
statusBar="Non-8/16-bit samples cannot be edited without prior conversion.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue