dev102 - new sample storage format
This commit is contained in:
parent
7bc3166ed5
commit
d004629a58
|
|
@ -816,7 +816,47 @@ size | description
|
||||||
4?? | wavetable data
|
4?? | wavetable data
|
||||||
```
|
```
|
||||||
|
|
||||||
# sample
|
# sample (>=102)
|
||||||
|
|
||||||
|
this is the new sample storage format used in Furnace dev102 and higher.
|
||||||
|
|
||||||
|
```
|
||||||
|
size | description
|
||||||
|
-----|------------------------------------
|
||||||
|
4 | "SMP2" block ID
|
||||||
|
4 | size of this block
|
||||||
|
STR | sample name
|
||||||
|
4 | length
|
||||||
|
4 | compatibility rate
|
||||||
|
4 | C-4 rate
|
||||||
|
1 | depth
|
||||||
|
| - 0: ZX Spectrum overlay drum (1-bit)
|
||||||
|
| - 1: 1-bit NES DPCM (1-bit)
|
||||||
|
| - 3: YMZ ADPCM
|
||||||
|
| - 4: QSound ADPCM
|
||||||
|
| - 5: ADPCM-A
|
||||||
|
| - 6: ADPCM-B
|
||||||
|
| - 8: 8-bit PCM
|
||||||
|
| - 9: BRR (SNES)
|
||||||
|
| - 10: VOX
|
||||||
|
| - 16: 16-bit PCM
|
||||||
|
3 | reserved
|
||||||
|
4 | loop start
|
||||||
|
| - -1 means no loop
|
||||||
|
4 | loop end
|
||||||
|
| - -1 means no loop
|
||||||
|
16 | sample presence bitfields
|
||||||
|
| - for future use.
|
||||||
|
| - indicates whether the sample should be present in the memory of a system.
|
||||||
|
| - read 4 32-bit numbers (for 4 memory banks per system, e.g. YM2610
|
||||||
|
| does ADPCM-A and ADPCM-B on separate memory banks).
|
||||||
|
??? | sample data
|
||||||
|
| - size is length
|
||||||
|
```
|
||||||
|
|
||||||
|
# old sample (<102)
|
||||||
|
|
||||||
|
this format is present when saving using previous Furnace versions.
|
||||||
|
|
||||||
```
|
```
|
||||||
size | description
|
size | description
|
||||||
|
|
@ -825,7 +865,7 @@ size | description
|
||||||
4 | size of this block
|
4 | size of this block
|
||||||
STR | sample name
|
STR | sample name
|
||||||
4 | length
|
4 | length
|
||||||
4 | rate
|
4 | compatibility rate
|
||||||
2 | volume (<58) or reserved
|
2 | volume (<58) or reserved
|
||||||
2 | pitch (<58) or reserved
|
2 | pitch (<58) or reserved
|
||||||
1 | depth
|
1 | depth
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,8 @@
|
||||||
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
|
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
|
||||||
#define BUSY_END isBusy.unlock(); softLocked=false;
|
#define BUSY_END isBusy.unlock(); softLocked=false;
|
||||||
|
|
||||||
#define DIV_VERSION "0.6pre1 (dev101)"
|
#define DIV_VERSION "0.6pre1 (dev102)"
|
||||||
#define DIV_ENGINE_VERSION 101
|
#define DIV_ENGINE_VERSION 102
|
||||||
|
|
||||||
// for imports
|
// for imports
|
||||||
#define DIV_VERSION_MOD 0xff01
|
#define DIV_VERSION_MOD 0xff01
|
||||||
|
|
|
||||||
|
|
@ -1619,51 +1619,67 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.read(magic,4);
|
reader.read(magic,4);
|
||||||
if (strcmp(magic,"SMPL")!=0) {
|
if (strcmp(magic,"SMPL")!=0 && strcmp(magic,"SMP2")!=0) {
|
||||||
logE("%d: invalid sample header!",i);
|
logE("%d: invalid sample header!",i);
|
||||||
lastError="invalid sample header!";
|
lastError="invalid sample header!";
|
||||||
ds.unload();
|
ds.unload();
|
||||||
delete[] file;
|
delete[] file;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
bool isNewSample=(strcmp(magic,"SMP2")==0);
|
||||||
reader.readI();
|
reader.readI();
|
||||||
DivSample* sample=new DivSample;
|
DivSample* sample=new DivSample;
|
||||||
logD("reading sample %d at %x...",i,samplePtr[i]);
|
logD("reading sample %d at %x...",i,samplePtr[i]);
|
||||||
|
if (!isNewSample) logV("(old sample)");
|
||||||
|
|
||||||
sample->name=reader.readString();
|
sample->name=reader.readString();
|
||||||
sample->samples=sample->loopEnd=reader.readI();
|
sample->samples=reader.readI();
|
||||||
|
if (!isNewSample) {
|
||||||
|
sample->loopEnd=sample->samples;
|
||||||
|
}
|
||||||
sample->rate=reader.readI();
|
sample->rate=reader.readI();
|
||||||
if (ds.version<58) {
|
|
||||||
vol=reader.readS();
|
|
||||||
pitch=reader.readS();
|
|
||||||
} else {
|
|
||||||
reader.readI();
|
|
||||||
}
|
|
||||||
sample->depth=(DivSampleDepth)reader.readC();
|
|
||||||
|
|
||||||
// reserved
|
if (isNewSample) {
|
||||||
reader.readC();
|
sample->centerRate=reader.readI();
|
||||||
|
sample->depth=(DivSampleDepth)reader.readC();
|
||||||
|
|
||||||
// while version 32 stored this value, it was unused.
|
// reserved
|
||||||
if (ds.version>=38) {
|
reader.readC();
|
||||||
sample->centerRate=(unsigned short) reader.readS();
|
reader.readC();
|
||||||
} else {
|
reader.readC();
|
||||||
reader.readS();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ds.version>=19) {
|
|
||||||
sample->loopStart=reader.readI();
|
sample->loopStart=reader.readI();
|
||||||
|
sample->loopEnd=reader.readI();
|
||||||
|
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
reader.readI();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
reader.readI();
|
if (ds.version<58) {
|
||||||
|
vol=reader.readS();
|
||||||
|
pitch=reader.readS();
|
||||||
|
} else {
|
||||||
|
reader.readI();
|
||||||
|
}
|
||||||
|
sample->depth=(DivSampleDepth)reader.readC();
|
||||||
|
|
||||||
|
// reserved
|
||||||
|
reader.readC();
|
||||||
|
|
||||||
|
// while version 32 stored this value, it was unused.
|
||||||
|
if (ds.version>=38) {
|
||||||
|
sample->centerRate=(unsigned short)reader.readS();
|
||||||
|
} else {
|
||||||
|
reader.readS();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ds.version>=19) {
|
||||||
|
sample->loopStart=reader.readI();
|
||||||
|
} else {
|
||||||
|
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());
|
||||||
|
|
@ -3038,19 +3054,24 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) {
|
||||||
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];
|
||||||
samplePtr.push_back(w->tell());
|
samplePtr.push_back(w->tell());
|
||||||
w->write("SMPL",4);
|
w->write("SMP2",4);
|
||||||
blockStartSeek=w->tell();
|
blockStartSeek=w->tell();
|
||||||
w->writeI(0);
|
w->writeI(0);
|
||||||
|
|
||||||
w->writeString(sample->name,false);
|
w->writeString(sample->name,false);
|
||||||
w->writeI(sample->samples);
|
w->writeI(sample->samples);
|
||||||
w->writeI(sample->rate);
|
w->writeI(sample->rate);
|
||||||
w->writeI(0); // reserved (for now)
|
w->writeI(sample->centerRate);
|
||||||
w->writeC(sample->depth);
|
w->writeC(sample->depth);
|
||||||
|
w->writeC(0); // reserved
|
||||||
|
w->writeC(0);
|
||||||
w->writeC(0);
|
w->writeC(0);
|
||||||
w->writeS(sample->centerRate);
|
|
||||||
w->writeI(sample->loopStart);
|
w->writeI(sample->loopStart);
|
||||||
//w->writeI(sample->loopEnd);
|
w->writeI(sample->loopEnd);
|
||||||
|
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
w->writeI(0xffffffff);
|
||||||
|
}
|
||||||
|
|
||||||
w->write(sample->getCurBuf(),sample->getCurBufLen());
|
w->write(sample->getCurBuf(),sample->getCurBufLen());
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue