diff --git a/papers/format.md b/papers/format.md index d8e12b7bd..d5ebddbab 100644 --- a/papers/format.md +++ b/papers/format.md @@ -587,6 +587,7 @@ size | description | - 11: 8-bit μ-law PCM | - 12: C219 PCM | - 13: IMA ADPCM + | - 14: 12-bit PCM (MultiPCM) | - 16: 16-bit PCM 1 | loop direction (>=123) or reserved | - 0: forward diff --git a/src/engine/platform/opl.cpp b/src/engine/platform/opl.cpp index ef0955386..5fe422dbf 100644 --- a/src/engine/platform/opl.cpp +++ b/src/engine/platform/opl.cpp @@ -3197,6 +3197,9 @@ void DivPlatformOPL::renderSamples(int sysID) { case DIV_SAMPLE_DEPTH_8BIT: length=MIN(65535,s->getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT)); break; + case DIV_SAMPLE_DEPTH_12BIT: + length=MIN(98303,s->getLoopEndPosition(DIV_SAMPLE_DEPTH_12BIT)); + break; case DIV_SAMPLE_DEPTH_16BIT: length=MIN(131070,s->getLoopEndPosition(DIV_SAMPLE_DEPTH_16BIT)); break; @@ -3239,7 +3242,9 @@ void DivPlatformOPL::renderSamples(int sysID) { case DIV_SAMPLE_DEPTH_8BIT: bitDepth=0; break; - // TODO: 12 bit PCM + case DIV_SAMPLE_DEPTH_12BIT: + bitDepth=1; + break; case DIV_SAMPLE_DEPTH_16BIT: bitDepth=2; break; diff --git a/src/engine/sample.cpp b/src/engine/sample.cpp index 020e0dec7..670e869af 100644 --- a/src/engine/sample.cpp +++ b/src/engine/sample.cpp @@ -285,6 +285,9 @@ int DivSample::getSampleOffset(int offset, int length, DivSampleDepth depth) { case DIV_SAMPLE_DEPTH_IMA_ADPCM: off=(offset+1)/2; break; + case DIV_SAMPLE_DEPTH_12BIT: + off=((offset*3)+1)/2; + break; case DIV_SAMPLE_DEPTH_16BIT: off=offset*2; break; @@ -348,6 +351,10 @@ int DivSample::getSampleOffset(int offset, int length, DivSampleDepth depth) { off=(offset+1)/2; len=(length+1)/2; break; + case DIV_SAMPLE_DEPTH_12BIT: + off=((offset*3)+1)/2; + len=((length*3)+1)/2; + break; case DIV_SAMPLE_DEPTH_16BIT: off=offset*2; len=length*2; @@ -409,6 +416,9 @@ int DivSample::getEndPosition(DivSampleDepth depth) { case DIV_SAMPLE_DEPTH_IMA_ADPCM: off=lengthIMA; break; + case DIV_SAMPLE_DEPTH_12BIT: + off=length12; + break; case DIV_SAMPLE_DEPTH_16BIT: off=length16; break; @@ -606,6 +616,12 @@ bool DivSample::initInternal(DivSampleDepth d, int count) { dataIMA=new unsigned char[lengthIMA]; memset(dataIMA,0,lengthIMA); break; + case DIV_SAMPLE_DEPTH_12BIT: // 12-bit PCM (MultiPCM) + if (data12!=NULL) delete[] data12; + length12=((count*3)+1)/2; + data12=new unsigned char[length12]; + memset(data12,0,length12); + break; case DIV_SAMPLE_DEPTH_16BIT: // 16-bit if (data16!=NULL) delete[] data16; length16=count*2; @@ -1293,6 +1309,14 @@ void DivSample::render(unsigned int formatMask) { case DIV_SAMPLE_DEPTH_IMA_ADPCM: // IMA ADPCM if (adpcm_decode_block(data16,dataIMA,lengthIMA,samples)==0) logE("oh crap!"); break; + case DIV_SAMPLE_DEPTH_12BIT: // 12-bit PCM (MultiPCM) + for (unsigned int i=0,j=0; i>8; + data12[j+1]=((data16[i+0]>>4)&0xf)|(i+1>4)&0xf:0); + if (i+1>8; + } + } } void* DivSample::getCurBuf() { @@ -1512,6 +1545,8 @@ void* DivSample::getCurBuf() { return dataC219; case DIV_SAMPLE_DEPTH_IMA_ADPCM: return dataIMA; + case DIV_SAMPLE_DEPTH_12BIT: + return data12; case DIV_SAMPLE_DEPTH_16BIT: return data16; default: @@ -1548,6 +1583,8 @@ unsigned int DivSample::getCurBufLen() { return lengthC219; case DIV_SAMPLE_DEPTH_IMA_ADPCM: return lengthIMA; + case DIV_SAMPLE_DEPTH_12BIT: + return length12; case DIV_SAMPLE_DEPTH_16BIT: return length16; default: @@ -1662,4 +1699,5 @@ DivSample::~DivSample() { if (dataMuLaw) delete[] dataMuLaw; if (dataC219) delete[] dataC219; if (dataIMA) delete[] dataIMA; + if (data12) delete[] data12; } diff --git a/src/engine/sample.h b/src/engine/sample.h index 5fc593d23..c585c7e32 100644 --- a/src/engine/sample.h +++ b/src/engine/sample.h @@ -47,6 +47,7 @@ enum DivSampleDepth: unsigned char { DIV_SAMPLE_DEPTH_MULAW=11, DIV_SAMPLE_DEPTH_C219=12, DIV_SAMPLE_DEPTH_IMA_ADPCM=13, + DIV_SAMPLE_DEPTH_12BIT=14, DIV_SAMPLE_DEPTH_16BIT=16, DIV_SAMPLE_DEPTH_MAX // boundary for sample depth }; @@ -118,6 +119,7 @@ struct DivSample { // - 11: 8-bit µ-law PCM // - 12: C219 "µ-law" PCM // - 13: IMA ADPCM + // - 14: 12-bit PCM (MultiPCM) // - 16: 16-bit PCM DivSampleDepth depth; bool loop, brrEmphasis, brrNoFilter, dither; @@ -144,8 +146,9 @@ struct DivSample { unsigned char* dataMuLaw; // 11 unsigned char* dataC219; // 12 unsigned char* dataIMA; // 13 + unsigned char* data12; // 14 - unsigned int length8, length16, length1, lengthDPCM, lengthZ, lengthQSoundA, lengthA, lengthB, lengthK, lengthBRR, lengthVOX, lengthMuLaw, lengthC219, lengthIMA; + unsigned int length8, length16, length1, lengthDPCM, lengthZ, lengthQSoundA, lengthA, lengthB, lengthK, lengthBRR, lengthVOX, lengthMuLaw, lengthC219, lengthIMA, length12; unsigned int samples; @@ -356,6 +359,7 @@ struct DivSample { dataMuLaw(NULL), dataC219(NULL), dataIMA(NULL), + data12(NULL), length8(0), length16(0), length1(0), @@ -370,6 +374,7 @@ struct DivSample { lengthMuLaw(0), lengthC219(0), lengthIMA(0), + length12(0), samples(0) { for (int i=0; i