diff --git a/src/engine/fileOps/pps.cpp b/src/engine/fileOps/pps.cpp index 37f4a8644..b69ff3eb6 100644 --- a/src/engine/fileOps/pps.cpp +++ b/src/engine/fileOps/pps.cpp @@ -92,23 +92,14 @@ void DivEngine::loadPPS(SafeReader& reader, std::vector& ret, String s->rate = PPS_SAMPLE_RATE; s->centerRate = PPS_SAMPLE_RATE; - s->depth = DIV_SAMPLE_DEPTH_8BIT; - s->init(headers[i].sample_length * 2); //byte per sample + s->depth = DIV_SAMPLE_DEPTH_4BIT; + s->init(headers[i].sample_length*2); // bytes->samples reader.seek((int)headers[i].start_pointer, SEEK_SET); - int sample_pos = 0; - for(int j = 0; j < headers[i].sample_length; j++) { - unsigned char curr_byte = (unsigned char)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++; + s->data4[j] = reader.readC(); } ret.push_back(s); diff --git a/src/engine/fileOpsSample.cpp b/src/engine/fileOpsSample.cpp index ced5bb485..5cd1d501f 100644 --- a/src/engine/fileOpsSample.cpp +++ b/src/engine/fileOpsSample.cpp @@ -524,6 +524,7 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth, case DIV_SAMPLE_DEPTH_ADPCM_B: case DIV_SAMPLE_DEPTH_ADPCM_K: case DIV_SAMPLE_DEPTH_VOX: + case DIV_SAMPLE_DEPTH_4BIT: samples=lenDivided*2; break; 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_K: case DIV_SAMPLE_DEPTH_VOX: + case DIV_SAMPLE_DEPTH_4BIT: // swap nibbles for (unsigned int i=0; igetCurBufLen(); i++) { b[i]=(b[i]<<4)|(b[i]>>4); diff --git a/src/engine/sample.cpp b/src/engine/sample.cpp index 59e97891a..c0a05f277 100644 --- a/src/engine/sample.cpp +++ b/src/engine/sample.cpp @@ -291,6 +291,9 @@ int DivSample::getSampleOffset(int offset, int length, DivSampleDepth depth) { case DIV_SAMPLE_DEPTH_16BIT: off=offset*2; break; + case DIV_SAMPLE_DEPTH_4BIT: + off=(offset+1)/2; + break; default: break; } @@ -355,6 +358,10 @@ int DivSample::getSampleOffset(int offset, int length, DivSampleDepth depth) { off=((offset*3)+1)/2; len=((length*3)+1)/2; break; + case DIV_SAMPLE_DEPTH_4BIT: + off=(offset+1)/2; + len=(length+1)/2; + break; case DIV_SAMPLE_DEPTH_16BIT: off=offset*2; len=length*2; @@ -419,6 +426,9 @@ int DivSample::getEndPosition(DivSampleDepth depth) { case DIV_SAMPLE_DEPTH_12BIT: off=length12; break; + case DIV_SAMPLE_DEPTH_4BIT: + off=length4; + break; case DIV_SAMPLE_DEPTH_16BIT: off=length16; break; @@ -622,6 +632,12 @@ bool DivSample::initInternal(DivSampleDepth d, int count) { data12=new unsigned char[length12+8]; memset(data12,0,length12+8); 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 if (data16!=NULL) delete[] data16; length16=count*2; @@ -860,6 +876,9 @@ void DivSample::convert(DivSampleDepth newDepth, unsigned int formatMask) { case DIV_SAMPLE_DEPTH_VOX: // VOX setSampleCount((samples+1)&(~1)); break; + case DIV_SAMPLE_DEPTH_4BIT: + setSampleCount((samples+1)&(~1)); + break; default: break; } @@ -1317,6 +1336,18 @@ void DivSample::render(unsigned int formatMask) { } } break; + case DIV_SAMPLE_DEPTH_4BIT: { + unsigned short nibble=0; + for (unsigned int i=0; i>1]&0xf; + } else { + nibble=data4[i>>1]>>4; + } + data16[i]=((nibble<<12)|(nibble<<8)|(nibble<<4)|nibble)^0x8000; + } + break; + } default: 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>12; + sample4=_sample<<4; + if (i+1>12; + sample4|=_sample; + } + data4[i>>1]=sample4; + } + } } void* DivSample::getCurBuf() { @@ -1550,6 +1595,8 @@ void* DivSample::getCurBuf() { return dataIMA; case DIV_SAMPLE_DEPTH_12BIT: return data12; + case DIV_SAMPLE_DEPTH_4BIT: + return data4; case DIV_SAMPLE_DEPTH_16BIT: return data16; default: @@ -1588,6 +1635,8 @@ unsigned int DivSample::getCurBufLen() { return lengthIMA; case DIV_SAMPLE_DEPTH_12BIT: return length12; + case DIV_SAMPLE_DEPTH_4BIT: + return length4; case DIV_SAMPLE_DEPTH_16BIT: return length16; default: @@ -1703,4 +1752,5 @@ DivSample::~DivSample() { if (dataC219) delete[] dataC219; if (dataIMA) delete[] dataIMA; if (data12) delete[] data12; + if (data4) delete[] data4; } diff --git a/src/engine/sample.h b/src/engine/sample.h index 988dcc317..dfd69b400 100644 --- a/src/engine/sample.h +++ b/src/engine/sample.h @@ -48,6 +48,7 @@ enum DivSampleDepth: unsigned char { DIV_SAMPLE_DEPTH_C219=12, DIV_SAMPLE_DEPTH_IMA_ADPCM=13, DIV_SAMPLE_DEPTH_12BIT=14, + DIV_SAMPLE_DEPTH_4BIT=15, DIV_SAMPLE_DEPTH_16BIT=16, DIV_SAMPLE_DEPTH_MAX // boundary for sample depth }; @@ -147,8 +148,9 @@ struct DivSample { unsigned char* dataC219; // 12 unsigned char* dataIMA; // 13 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; @@ -360,6 +362,7 @@ struct DivSample { dataC219(NULL), dataIMA(NULL), data12(NULL), + data4(NULL), length8(0), length16(0), length1(0), @@ -375,6 +378,7 @@ struct DivSample { lengthC219(0), lengthIMA(0), length12(0), + length4(0), samples(0) { for (int i=0; i(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) { statusBar2=fmt::sprintf("(%d, %d)",posX,posY); }