Merge remote-tracking branch 'Eknous-P/4bitpcm' (#2550)
This commit is contained in:
commit
13ac388ae5
|
@ -92,23 +92,14 @@ void DivEngine::loadPPS(SafeReader& reader, std::vector<DivSample*>& ret, String
|
||||||
|
|
||||||
s->rate = PPS_SAMPLE_RATE;
|
s->rate = PPS_SAMPLE_RATE;
|
||||||
s->centerRate = PPS_SAMPLE_RATE;
|
s->centerRate = PPS_SAMPLE_RATE;
|
||||||
s->depth = DIV_SAMPLE_DEPTH_8BIT;
|
s->depth = DIV_SAMPLE_DEPTH_4BIT;
|
||||||
s->init(headers[i].sample_length * 2); //byte per sample
|
s->init(headers[i].sample_length*2); // bytes->samples
|
||||||
|
|
||||||
reader.seek((int)headers[i].start_pointer, SEEK_SET);
|
reader.seek((int)headers[i].start_pointer, SEEK_SET);
|
||||||
|
|
||||||
int sample_pos = 0;
|
|
||||||
|
|
||||||
for(int j = 0; j < headers[i].sample_length; j++)
|
for(int j = 0; j < headers[i].sample_length; j++)
|
||||||
{
|
{
|
||||||
unsigned char curr_byte = (unsigned char)reader.readC();
|
s->data4[j] = reader.readC();
|
||||||
|
|
||||||
s->data8[sample_pos] = (curr_byte >> 4) | (curr_byte & 0xf0);
|
|
||||||
s->data8[sample_pos] += 0x80;
|
|
||||||
sample_pos++;
|
|
||||||
s->data8[sample_pos] = (curr_byte << 4) | (curr_byte & 0xf);
|
|
||||||
s->data8[sample_pos] += 0x80;
|
|
||||||
sample_pos++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.push_back(s);
|
ret.push_back(s);
|
||||||
|
|
|
@ -524,6 +524,7 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth,
|
||||||
case DIV_SAMPLE_DEPTH_ADPCM_B:
|
case DIV_SAMPLE_DEPTH_ADPCM_B:
|
||||||
case DIV_SAMPLE_DEPTH_ADPCM_K:
|
case DIV_SAMPLE_DEPTH_ADPCM_K:
|
||||||
case DIV_SAMPLE_DEPTH_VOX:
|
case DIV_SAMPLE_DEPTH_VOX:
|
||||||
|
case DIV_SAMPLE_DEPTH_4BIT:
|
||||||
samples=lenDivided*2;
|
samples=lenDivided*2;
|
||||||
break;
|
break;
|
||||||
case DIV_SAMPLE_DEPTH_IMA_ADPCM:
|
case DIV_SAMPLE_DEPTH_IMA_ADPCM:
|
||||||
|
@ -636,6 +637,7 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth,
|
||||||
case DIV_SAMPLE_DEPTH_ADPCM_B:
|
case DIV_SAMPLE_DEPTH_ADPCM_B:
|
||||||
case DIV_SAMPLE_DEPTH_ADPCM_K:
|
case DIV_SAMPLE_DEPTH_ADPCM_K:
|
||||||
case DIV_SAMPLE_DEPTH_VOX:
|
case DIV_SAMPLE_DEPTH_VOX:
|
||||||
|
case DIV_SAMPLE_DEPTH_4BIT:
|
||||||
// swap nibbles
|
// swap nibbles
|
||||||
for (unsigned int i=0; i<sample->getCurBufLen(); i++) {
|
for (unsigned int i=0; i<sample->getCurBufLen(); i++) {
|
||||||
b[i]=(b[i]<<4)|(b[i]>>4);
|
b[i]=(b[i]<<4)|(b[i]>>4);
|
||||||
|
|
|
@ -291,6 +291,9 @@ int DivSample::getSampleOffset(int offset, int length, DivSampleDepth depth) {
|
||||||
case DIV_SAMPLE_DEPTH_16BIT:
|
case DIV_SAMPLE_DEPTH_16BIT:
|
||||||
off=offset*2;
|
off=offset*2;
|
||||||
break;
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_4BIT:
|
||||||
|
off=(offset+1)/2;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -355,6 +358,10 @@ int DivSample::getSampleOffset(int offset, int length, DivSampleDepth depth) {
|
||||||
off=((offset*3)+1)/2;
|
off=((offset*3)+1)/2;
|
||||||
len=((length*3)+1)/2;
|
len=((length*3)+1)/2;
|
||||||
break;
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_4BIT:
|
||||||
|
off=(offset+1)/2;
|
||||||
|
len=(length+1)/2;
|
||||||
|
break;
|
||||||
case DIV_SAMPLE_DEPTH_16BIT:
|
case DIV_SAMPLE_DEPTH_16BIT:
|
||||||
off=offset*2;
|
off=offset*2;
|
||||||
len=length*2;
|
len=length*2;
|
||||||
|
@ -419,6 +426,9 @@ int DivSample::getEndPosition(DivSampleDepth depth) {
|
||||||
case DIV_SAMPLE_DEPTH_12BIT:
|
case DIV_SAMPLE_DEPTH_12BIT:
|
||||||
off=length12;
|
off=length12;
|
||||||
break;
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_4BIT:
|
||||||
|
off=length4;
|
||||||
|
break;
|
||||||
case DIV_SAMPLE_DEPTH_16BIT:
|
case DIV_SAMPLE_DEPTH_16BIT:
|
||||||
off=length16;
|
off=length16;
|
||||||
break;
|
break;
|
||||||
|
@ -622,6 +632,12 @@ bool DivSample::initInternal(DivSampleDepth d, int count) {
|
||||||
data12=new unsigned char[length12+8];
|
data12=new unsigned char[length12+8];
|
||||||
memset(data12,0,length12+8);
|
memset(data12,0,length12+8);
|
||||||
break;
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_4BIT:
|
||||||
|
if (data4!=NULL) delete[] data4;
|
||||||
|
length4=(count+1)/2;
|
||||||
|
data4=new unsigned char[length4];
|
||||||
|
memset(data4,0,length4);
|
||||||
|
break;
|
||||||
case DIV_SAMPLE_DEPTH_16BIT: // 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;
|
||||||
|
@ -860,6 +876,9 @@ void DivSample::convert(DivSampleDepth newDepth, unsigned int formatMask) {
|
||||||
case DIV_SAMPLE_DEPTH_VOX: // VOX
|
case DIV_SAMPLE_DEPTH_VOX: // VOX
|
||||||
setSampleCount((samples+1)&(~1));
|
setSampleCount((samples+1)&(~1));
|
||||||
break;
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_4BIT:
|
||||||
|
setSampleCount((samples+1)&(~1));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1317,6 +1336,18 @@ void DivSample::render(unsigned int formatMask) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_4BIT: {
|
||||||
|
unsigned short nibble=0;
|
||||||
|
for (unsigned int i=0; i<samples; i++) {
|
||||||
|
if (i&1) {
|
||||||
|
nibble=data4[i>>1]&0xf;
|
||||||
|
} else {
|
||||||
|
nibble=data4[i>>1]>>4;
|
||||||
|
}
|
||||||
|
data16[i]=((nibble<<12)|(nibble<<8)|(nibble<<4)|nibble)^0x8000;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1518,6 +1549,20 @@ void DivSample::render(unsigned int formatMask) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (NOT_IN_FORMAT(DIV_SAMPLE_DEPTH_4BIT)) {
|
||||||
|
if (!initInternal(DIV_SAMPLE_DEPTH_4BIT,samples)) return;
|
||||||
|
unsigned char _sample=0, sample4=0;
|
||||||
|
unsigned short* samplePtr = (unsigned short*)data16;
|
||||||
|
for (unsigned int i=0; i<samples; i+=2) {
|
||||||
|
_sample=(*samplePtr++^0x8000)>>12;
|
||||||
|
sample4=_sample<<4;
|
||||||
|
if (i+1<samples) {
|
||||||
|
_sample=(*samplePtr++^0x8000)>>12;
|
||||||
|
sample4|=_sample;
|
||||||
|
}
|
||||||
|
data4[i>>1]=sample4;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void* DivSample::getCurBuf() {
|
void* DivSample::getCurBuf() {
|
||||||
|
@ -1550,6 +1595,8 @@ void* DivSample::getCurBuf() {
|
||||||
return dataIMA;
|
return dataIMA;
|
||||||
case DIV_SAMPLE_DEPTH_12BIT:
|
case DIV_SAMPLE_DEPTH_12BIT:
|
||||||
return data12;
|
return data12;
|
||||||
|
case DIV_SAMPLE_DEPTH_4BIT:
|
||||||
|
return data4;
|
||||||
case DIV_SAMPLE_DEPTH_16BIT:
|
case DIV_SAMPLE_DEPTH_16BIT:
|
||||||
return data16;
|
return data16;
|
||||||
default:
|
default:
|
||||||
|
@ -1588,6 +1635,8 @@ unsigned int DivSample::getCurBufLen() {
|
||||||
return lengthIMA;
|
return lengthIMA;
|
||||||
case DIV_SAMPLE_DEPTH_12BIT:
|
case DIV_SAMPLE_DEPTH_12BIT:
|
||||||
return length12;
|
return length12;
|
||||||
|
case DIV_SAMPLE_DEPTH_4BIT:
|
||||||
|
return length4;
|
||||||
case DIV_SAMPLE_DEPTH_16BIT:
|
case DIV_SAMPLE_DEPTH_16BIT:
|
||||||
return length16;
|
return length16;
|
||||||
default:
|
default:
|
||||||
|
@ -1703,4 +1752,5 @@ DivSample::~DivSample() {
|
||||||
if (dataC219) delete[] dataC219;
|
if (dataC219) delete[] dataC219;
|
||||||
if (dataIMA) delete[] dataIMA;
|
if (dataIMA) delete[] dataIMA;
|
||||||
if (data12) delete[] data12;
|
if (data12) delete[] data12;
|
||||||
|
if (data4) delete[] data4;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ enum DivSampleDepth: unsigned char {
|
||||||
DIV_SAMPLE_DEPTH_C219=12,
|
DIV_SAMPLE_DEPTH_C219=12,
|
||||||
DIV_SAMPLE_DEPTH_IMA_ADPCM=13,
|
DIV_SAMPLE_DEPTH_IMA_ADPCM=13,
|
||||||
DIV_SAMPLE_DEPTH_12BIT=14,
|
DIV_SAMPLE_DEPTH_12BIT=14,
|
||||||
|
DIV_SAMPLE_DEPTH_4BIT=15,
|
||||||
DIV_SAMPLE_DEPTH_16BIT=16,
|
DIV_SAMPLE_DEPTH_16BIT=16,
|
||||||
DIV_SAMPLE_DEPTH_MAX // boundary for sample depth
|
DIV_SAMPLE_DEPTH_MAX // boundary for sample depth
|
||||||
};
|
};
|
||||||
|
@ -147,8 +148,9 @@ struct DivSample {
|
||||||
unsigned char* dataC219; // 12
|
unsigned char* dataC219; // 12
|
||||||
unsigned char* dataIMA; // 13
|
unsigned char* dataIMA; // 13
|
||||||
unsigned char* data12; // 14
|
unsigned char* data12; // 14
|
||||||
|
unsigned char* data4; // 15
|
||||||
|
|
||||||
unsigned int length8, length16, length1, lengthDPCM, lengthZ, lengthQSoundA, lengthA, lengthB, lengthK, lengthBRR, lengthVOX, lengthMuLaw, lengthC219, lengthIMA, length12;
|
unsigned int length8, length16, length1, lengthDPCM, lengthZ, lengthQSoundA, lengthA, lengthB, lengthK, lengthBRR, lengthVOX, lengthMuLaw, lengthC219, lengthIMA, length12, length4;
|
||||||
|
|
||||||
unsigned int samples;
|
unsigned int samples;
|
||||||
|
|
||||||
|
@ -360,6 +362,7 @@ struct DivSample {
|
||||||
dataC219(NULL),
|
dataC219(NULL),
|
||||||
dataIMA(NULL),
|
dataIMA(NULL),
|
||||||
data12(NULL),
|
data12(NULL),
|
||||||
|
data4(NULL),
|
||||||
length8(0),
|
length8(0),
|
||||||
length16(0),
|
length16(0),
|
||||||
length1(0),
|
length1(0),
|
||||||
|
@ -375,6 +378,7 @@ struct DivSample {
|
||||||
lengthC219(0),
|
lengthC219(0),
|
||||||
lengthIMA(0),
|
lengthIMA(0),
|
||||||
length12(0),
|
length12(0),
|
||||||
|
length4(0),
|
||||||
samples(0) {
|
samples(0) {
|
||||||
for (int i=0; i<DIV_MAX_CHIPS; i++) {
|
for (int i=0; i<DIV_MAX_CHIPS; i++) {
|
||||||
for (int j=0; j<DIV_MAX_SAMPLE_TYPE; j++) {
|
for (int j=0; j<DIV_MAX_SAMPLE_TYPE; j++) {
|
||||||
|
|
|
@ -7039,6 +7039,7 @@ bool FurnaceGUI::loop() {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetNextItemWidth(120.0f*dpiScale);
|
ImGui::SetNextItemWidth(120.0f*dpiScale);
|
||||||
if (ImGui::InputInt("##RSChans",&pendingRawSampleChannels,1,2)) {
|
if (ImGui::InputInt("##RSChans",&pendingRawSampleChannels,1,2)) {
|
||||||
|
if (pendingRawSampleChannels<1) pendingRawSampleChannels=1;
|
||||||
}
|
}
|
||||||
ImGui::Text(_("(will be mixed down to mono)"));
|
ImGui::Text(_("(will be mixed down to mono)"));
|
||||||
ImGui::Checkbox(_("Unsigned"),&pendingRawSampleUnsigned);
|
ImGui::Checkbox(_("Unsigned"),&pendingRawSampleUnsigned);
|
||||||
|
@ -7052,7 +7053,8 @@ bool FurnaceGUI::loop() {
|
||||||
pendingRawSampleDepth==DIV_SAMPLE_DEPTH_QSOUND_ADPCM ||
|
pendingRawSampleDepth==DIV_SAMPLE_DEPTH_QSOUND_ADPCM ||
|
||||||
pendingRawSampleDepth==DIV_SAMPLE_DEPTH_ADPCM_A ||
|
pendingRawSampleDepth==DIV_SAMPLE_DEPTH_ADPCM_A ||
|
||||||
pendingRawSampleDepth==DIV_SAMPLE_DEPTH_ADPCM_B ||
|
pendingRawSampleDepth==DIV_SAMPLE_DEPTH_ADPCM_B ||
|
||||||
pendingRawSampleDepth==DIV_SAMPLE_DEPTH_VOX) {
|
pendingRawSampleDepth==DIV_SAMPLE_DEPTH_VOX ||
|
||||||
|
pendingRawSampleDepth==DIV_SAMPLE_DEPTH_4BIT) {
|
||||||
ImGui::Checkbox(_("Swap nibbles"),&pendingRawSampleSwapNibbles);
|
ImGui::Checkbox(_("Swap nibbles"),&pendingRawSampleSwapNibbles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -212,7 +212,7 @@ const char* sampleDepths[DIV_SAMPLE_DEPTH_MAX]={
|
||||||
"C219 PCM",
|
"C219 PCM",
|
||||||
"IMA ADPCM",
|
"IMA ADPCM",
|
||||||
"12-bit PCM",
|
"12-bit PCM",
|
||||||
NULL,
|
"4-bit PCM",
|
||||||
"16-bit PCM"
|
"16-bit PCM"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1929,7 +1929,18 @@ 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==DIV_SAMPLE_DEPTH_8BIT)?255:65535);
|
switch (sample->depth) {
|
||||||
|
case DIV_SAMPLE_DEPTH_8BIT:
|
||||||
|
posY=(0.5-pos.y/rectSize.y)*255;
|
||||||
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_4BIT:
|
||||||
|
posY=(1-pos.y/rectSize.y)*15;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
posY=(0.5-pos.y/rectSize.y)*65535;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (posX>=0) {
|
if (posX>=0) {
|
||||||
statusBar2=fmt::sprintf("(%d, %d)",posX,posY);
|
statusBar2=fmt::sprintf("(%d, %d)",posX,posY);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue