sample system rewrite! **PLEASE READ**

this commit mostly rewrites the sample system.
as of now samples can be ADPCM, 8-bit, BRR or 16-bit
or something...

consider this VERY EXPERIMENTAL.
if you find any issues REPORT THEM immediately.

it's nearly 4am...
This commit is contained in:
tildearrow 2022-02-24 03:57:45 -05:00
parent 3542229448
commit 1e98f0c4a1
19 changed files with 545 additions and 390 deletions

View file

@ -42,6 +42,12 @@ struct InflateBlock {
}
};
static double samplePitches[11]={
0.1666666666, 0.2, 0.25, 0.333333333, 0.5,
1,
2, 3, 4, 5, 6
};
bool DivEngine::loadDMF(unsigned char* file, size_t len) {
SafeReader reader=SafeReader(file,len);
warnings="";
@ -607,9 +613,12 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
}
for (int i=0; i<ds.sampleLen; i++) {
DivSample* sample=new DivSample;
sample->length=reader.readI();
if (sample->length<0) {
logE("invalid sample length %d. are we doing something wrong?\n",sample->length);
int length=reader.readI();
int pitch=5;
int vol=50;
short* data;
if (length<0) {
logE("invalid sample length %d. are we doing something wrong?\n",length);
lastError="file is corrupt or unreadable at samples";
delete[] file;
return false;
@ -619,31 +628,57 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
} else {
sample->name="";
}
logD("%d name %s (%d)\n",i,sample->name.c_str(),sample->length);
if (ds.version<0x0b) {
sample->rate=22050;
sample->pitch=5;
sample->vol=50;
} else {
logD("%d name %s (%d)\n",i,sample->name.c_str(),length);
sample->rate=22050;
if (ds.version>=0x0b) {
sample->rate=fileToDivRate(reader.readC());
sample->pitch=reader.readC();
sample->vol=reader.readC();
pitch=reader.readC();
vol=reader.readC();
}
logI("pitch and vol: %d %d\n",sample->pitch,sample->vol);
if (ds.version>0x15) {
sample->depth=reader.readC();
if (sample->depth!=8 && sample->depth!=16) {
logW("%d: sample depth is wrong! (%d)\n",i,sample->depth);
sample->depth=16;
}
} else {
sample->depth=16;
}
if (sample->length>0) {
if (length>0) {
if (ds.version<0x0b) {
sample->data=new short[1+(sample->length/2)];
reader.read(sample->data,sample->length);
sample->length/=2;
data=new short[1+(length/2)];
reader.read(data,length);
length/=2;
} else {
sample->data=new short[sample->length];
reader.read(sample->data,sample->length*2);
data=new short[length];
reader.read(data,length*2);
}
if (pitch!=5) {
logD("%d: scaling from %d...\n",i,pitch);
}
// render data
if (!sample->init((double)length/samplePitches[pitch])) {
logE("%d: error while initializing sample!\n",i);
}
unsigned int k=0;
float mult=(float)(vol)/50.0f;
for (double j=0; j<length; j+=samplePitches[pitch]) {
if (k>=sample->samples) {
break;
}
if (sample->depth==8) {
float next=(float)(data[(unsigned int)j]-0x80)*mult;
sample->data8[k++]=fmin(fmax(next,-128),127);
} else {
float next=(float)data[(unsigned int)j]*mult;
sample->data16[k++]=fmin(fmax(next,-32768),32767);
}
}
delete[] data;
}
ds.sample.push_back(sample);
}
@ -996,6 +1031,9 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
// read samples
for (int i=0; i<ds.sampleLen; i++) {
int vol=0;
int pitch=0;
reader.seek(samplePtr[i],SEEK_SET);
reader.read(magic,4);
if (strcmp(magic,"SMPL")!=0) {
@ -1008,10 +1046,14 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
DivSample* sample=new DivSample;
sample->name=reader.readString();
sample->length=reader.readI();
sample->samples=reader.readI();
sample->rate=reader.readI();
sample->vol=reader.readS();
sample->pitch=reader.readS();
if (ds.version<58) {
vol=reader.readS();
pitch=reader.readS();
} else {
reader.readI();
}
sample->depth=reader.readC();
// reserved
@ -1030,8 +1072,42 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
reader.readI();
}
sample->data=new short[sample->length];
reader.read(sample->data,2*sample->length);
if (ds.version>=58) { // modern sample
sample->init(sample->samples);
reader.read(sample->getCurBuf(),sample->getCurBufLen());
} else { // legacy sample
int length=sample->samples;
short* data=new short[length];
reader.read(data,2*length);
if (pitch!=5) {
logD("%d: scaling from %d...\n",i,pitch);
}
// render data
if (sample->depth!=8 && sample->depth!=16) {
logW("%d: sample depth is wrong! (%d)\n",i,sample->depth);
sample->depth=16;
}
sample->init(sample->samples);
unsigned int k=0;
float mult=(float)(vol)/50.0f;
for (double j=0; j<length; j+=samplePitches[pitch]) {
if (k>=sample->samples) {
break;
}
if (sample->depth==8) {
float next=(float)(data[(unsigned int)j]-0x80)*mult;
sample->data8[k++]=fmin(fmax(next,-128),127);
} else {
float next=(float)data[(unsigned int)j]*mult;
sample->data16[k++]=fmin(fmax(next,-32768),32767);
}
}
delete[] data;
}
ds.sample.push_back(sample);
}
@ -1390,16 +1466,15 @@ SafeWriter* DivEngine::saveFur() {
w->writeI(0);
w->writeString(sample->name,false);
w->writeI(sample->length);
w->writeI(sample->samples);
w->writeI(sample->rate);
w->writeS(sample->vol);
w->writeS(sample->pitch);
w->writeI(0); // reserved (for now)
w->writeC(sample->depth);
w->writeC(0);
w->writeS(sample->centerRate);
w->writeI(sample->loopStart);
w->write(sample->data,sample->length*2);
w->write(sample->getCurBuf(),sample->getCurBufLen());
}
/// PATTERN
@ -1728,13 +1803,14 @@ SafeWriter* DivEngine::saveDMF(unsigned char version) {
w->writeC(song.sample.size());
for (DivSample* i: song.sample) {
w->writeI(i->length);
w->writeI(i->samples);
w->writeString(i->name,true);
w->writeC(divToFileRate(i->rate));
w->writeC(i->pitch);
w->writeC(i->vol);
w->writeC(i->depth);
w->write(i->data,2*i->length);
w->writeC(5);
w->writeC(50);
// i'm too lazy to deal with .dmf's weird way of storing 8-bit samples
w->writeC(16);
w->write(i->data16,i->length16);
}
return w;