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:
parent
3542229448
commit
1e98f0c4a1
19 changed files with 545 additions and 390 deletions
|
|
@ -23,20 +23,24 @@
|
|||
#include <sndfile.h>
|
||||
#include <math.h>
|
||||
|
||||
extern "C" {
|
||||
#include "../../extern/adpcm/bs_codec.h"
|
||||
#include "../../extern/adpcm/oki_codec.h"
|
||||
#include "../../extern/adpcm/yma_codec.h"
|
||||
#include "../../extern/adpcm/ymb_codec.h"
|
||||
#include "../../extern/adpcm/ymz_codec.h"
|
||||
}
|
||||
|
||||
bool DivSample::save(const char* path) {
|
||||
SNDFILE* f;
|
||||
SF_INFO si;
|
||||
memset(&si,0,sizeof(SF_INFO));
|
||||
|
||||
if (length<1) return false;
|
||||
if (length16<1) return false;
|
||||
|
||||
si.channels=1;
|
||||
si.samplerate=rate;
|
||||
if (depth==16) {
|
||||
si.format=SF_FORMAT_PCM_16|SF_FORMAT_WAV;
|
||||
} else {
|
||||
si.format=SF_FORMAT_PCM_U8|SF_FORMAT_WAV;
|
||||
}
|
||||
si.format=SF_FORMAT_PCM_16|SF_FORMAT_WAV;
|
||||
|
||||
f=sf_open(path,SFM_WRITE,&si);
|
||||
|
||||
|
|
@ -58,28 +62,253 @@ bool DivSample::save(const char* path) {
|
|||
inst.loop_count = 1;
|
||||
inst.loops[0].mode = SF_LOOP_FORWARD;
|
||||
inst.loops[0].start = loopStart;
|
||||
inst.loops[0].end = length;
|
||||
inst.loops[0].end = samples;
|
||||
}
|
||||
sf_command(f, SFC_SET_INSTRUMENT, &inst, sizeof(inst));
|
||||
|
||||
if (depth==16) {
|
||||
sf_writef_short(f,data,length);
|
||||
} else {
|
||||
short* cbuf=new short[length];
|
||||
for (int i=0; i<length; i++) {
|
||||
cbuf[i]=(data[i]<<8)^0x8000;
|
||||
}
|
||||
sf_writef_short(f,cbuf,length);
|
||||
delete[] cbuf;
|
||||
}
|
||||
sf_write_short(f,data16,length16);
|
||||
|
||||
sf_close(f);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DivSample::~DivSample() {
|
||||
if (data) delete[] data;
|
||||
if (rendData) delete[] rendData;
|
||||
if (adpcmRendData) delete[] adpcmRendData;
|
||||
bool DivSample::initInternal(unsigned char d, int count) {
|
||||
switch (d) {
|
||||
case 0: // 1-bit
|
||||
if (data1!=NULL) delete[] data1;
|
||||
length1=(count+7)/8;
|
||||
data1=new unsigned char[length1];
|
||||
memset(data1,0,length1);
|
||||
break;
|
||||
case 1: // DPCM
|
||||
if (dataDPCM!=NULL) delete[] dataDPCM;
|
||||
lengthDPCM=(count+7)/8;
|
||||
dataDPCM=new unsigned char[lengthDPCM];
|
||||
memset(dataDPCM,0,lengthDPCM);
|
||||
break;
|
||||
case 4: // QSound ADPCM
|
||||
if (dataQSoundA!=NULL) delete[] dataQSoundA;
|
||||
lengthQSoundA=(count+1)/2;
|
||||
dataQSoundA=new unsigned char[lengthQSoundA];
|
||||
memset(dataQSoundA,0,lengthQSoundA);
|
||||
break;
|
||||
case 5: // ADPCM-A
|
||||
if (dataA!=NULL) delete[] dataA;
|
||||
lengthA=(count+1)/2;
|
||||
dataA=new unsigned char[lengthA];
|
||||
memset(dataA,0,lengthA);
|
||||
break;
|
||||
case 6: // ADPCM-B
|
||||
if (dataB!=NULL) delete[] dataB;
|
||||
lengthB=(count+1)/2;
|
||||
dataB=new unsigned char[lengthB];
|
||||
memset(dataB,0,lengthB);
|
||||
break;
|
||||
case 7: // X68000 ADPCM
|
||||
if (dataX68!=NULL) delete[] dataX68;
|
||||
lengthX68=(count+1)/2;
|
||||
dataX68=new unsigned char[lengthX68];
|
||||
memset(dataX68,0,lengthX68);
|
||||
break;
|
||||
case 8: // 8-bit
|
||||
if (data8!=NULL) delete[] data8;
|
||||
length8=count;
|
||||
data8=new signed char[length8];
|
||||
memset(data8,0,length8);
|
||||
break;
|
||||
case 9: // BRR
|
||||
if (dataBRR!=NULL) delete[] dataBRR;
|
||||
lengthBRR=9*((count+15)/16);
|
||||
dataBRR=new unsigned char[lengthBRR];
|
||||
memset(dataBRR,0,lengthBRR);
|
||||
break;
|
||||
case 10: // VOX
|
||||
if (dataVOX!=NULL) delete[] dataVOX;
|
||||
lengthVOX=(count+1)/2;
|
||||
dataVOX=new unsigned char[lengthVOX];
|
||||
memset(dataVOX,0,lengthVOX);
|
||||
break;
|
||||
case 16: // 16-bit
|
||||
if (data16!=NULL) delete[] data16;
|
||||
length16=count*2;
|
||||
data16=new short[count];
|
||||
memset(data16,0,count*sizeof(short));
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DivSample::init(unsigned int count) {
|
||||
if (!initInternal(depth,count)) return false;
|
||||
samples=count;
|
||||
return true;
|
||||
}
|
||||
|
||||
void DivSample::render() {
|
||||
// step 1: convert to 16-bit if needed
|
||||
if (depth!=16) {
|
||||
if (!initInternal(16,samples)) return;
|
||||
switch (depth) {
|
||||
case 0: // 1-bit
|
||||
for (unsigned int i=0; i<samples; i++) {
|
||||
data16[i]=((data1[i>>3]>>(i&7))&1)?0x7fff:-0x7fff;
|
||||
}
|
||||
break;
|
||||
case 1: { // DPCM
|
||||
int accum=0;
|
||||
for (unsigned int i=0; i<samples; i++) {
|
||||
accum+=((data1[i>>3]>>(i&7))&1)?1:-1;
|
||||
if (accum>63) accum=63;
|
||||
if (accum<-64) accum=-64;
|
||||
data16[i]=accum*512;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: // QSound ADPCM
|
||||
bs_decode(dataQSoundA,data16,samples);
|
||||
break;
|
||||
case 5: // ADPCM-A
|
||||
yma_decode(dataA,data16,samples);
|
||||
break;
|
||||
case 6: // ADPCM-B
|
||||
ymb_decode(dataB,data16,samples);
|
||||
break;
|
||||
case 7: // X6800 ADPCM
|
||||
oki6258_decode(dataX68,data16,samples);
|
||||
break;
|
||||
case 8: // 8-bit PCM
|
||||
for (unsigned int i=0; i<samples; i++) {
|
||||
data16[i]=data8[i]<<8;
|
||||
}
|
||||
break;
|
||||
case 9: // BRR
|
||||
// TODO!
|
||||
break;
|
||||
case 10: // VOX
|
||||
oki_decode(dataVOX,data16,samples);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// step 2: render to other formats
|
||||
if (depth!=0) { // 1-bit
|
||||
if (!initInternal(0,samples)) return;
|
||||
for (unsigned int i=0; i<samples; i++) {
|
||||
if (data16[i]>0) {
|
||||
data1[i>>3]|=1<<(i&7);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (depth!=1) { // DPCM
|
||||
if (!initInternal(1,samples)) return;
|
||||
int accum=63;
|
||||
for (unsigned int i=0; i<samples; i++) {
|
||||
int next=((unsigned short)(data16[i]^0x8000))>>9;
|
||||
if (next>accum) {
|
||||
dataDPCM[i>>3]|=1<<(i&7);
|
||||
accum++;
|
||||
} else {
|
||||
accum--;
|
||||
}
|
||||
if (accum<0) accum=0;
|
||||
if (accum>127) accum=127;
|
||||
}
|
||||
}
|
||||
if (depth!=4) { // QSound ADPCM
|
||||
if (!initInternal(4,samples)) return;
|
||||
bs_encode(data16,dataQSoundA,samples);
|
||||
}
|
||||
if (depth!=5) { // ADPCM-A
|
||||
if (!initInternal(5,samples)) return;
|
||||
yma_encode(data16,dataA,samples);
|
||||
}
|
||||
if (depth!=6) { // ADPCM-B
|
||||
if (!initInternal(6,samples)) return;
|
||||
ymb_encode(data16,dataB,samples);
|
||||
}
|
||||
if (depth!=7) { // X68000 ADPCM
|
||||
if (!initInternal(7,samples)) return;
|
||||
oki6258_encode(data16,dataX68,samples);
|
||||
}
|
||||
if (depth!=8) { // 8-bit PCM
|
||||
if (!initInternal(8,samples)) return;
|
||||
for (unsigned int i=0; i<samples; i++) {
|
||||
data8[i]=data16[i]>>8;
|
||||
}
|
||||
}
|
||||
// TODO: BRR!
|
||||
if (depth!=10) { // VOX
|
||||
if (!initInternal(10,samples)) return;
|
||||
oki_encode(data16,dataVOX,samples);
|
||||
}
|
||||
}
|
||||
|
||||
void* DivSample::getCurBuf() {
|
||||
switch (depth) {
|
||||
case 0:
|
||||
return data1;
|
||||
case 1:
|
||||
return dataDPCM;
|
||||
case 4:
|
||||
return dataQSoundA;
|
||||
case 5:
|
||||
return dataA;
|
||||
case 6:
|
||||
return dataB;
|
||||
case 7:
|
||||
return dataX68;
|
||||
case 8:
|
||||
return data8;
|
||||
case 9:
|
||||
return dataBRR;
|
||||
case 10:
|
||||
return dataVOX;
|
||||
case 16:
|
||||
return data16;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int DivSample::getCurBufLen() {
|
||||
switch (depth) {
|
||||
case 0:
|
||||
return length1;
|
||||
case 1:
|
||||
return lengthDPCM;
|
||||
case 4:
|
||||
return lengthQSoundA;
|
||||
case 5:
|
||||
return lengthA;
|
||||
case 6:
|
||||
return lengthB;
|
||||
case 7:
|
||||
return lengthX68;
|
||||
case 8:
|
||||
return length8;
|
||||
case 9:
|
||||
return lengthBRR;
|
||||
case 10:
|
||||
return lengthVOX;
|
||||
case 16:
|
||||
return length16;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DivSample::~DivSample() {
|
||||
if (data8) delete[] data8;
|
||||
if (data16) delete[] data16;
|
||||
if (data1) delete[] data1;
|
||||
if (dataDPCM) delete[] dataDPCM;
|
||||
if (dataQSoundA) delete[] dataQSoundA;
|
||||
if (dataA) delete[] dataA;
|
||||
if (dataB) delete[] dataB;
|
||||
if (dataX68) delete[] dataX68;
|
||||
if (dataBRR) delete[] dataBRR;
|
||||
if (dataVOX) delete[] dataVOX;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue