diff --git a/.gitmodules b/.gitmodules index c78fee42a..498a32410 100644 --- a/.gitmodules +++ b/.gitmodules @@ -15,3 +15,6 @@ [submodule "extern/portaudio"] path = extern/portaudio url = https://github.com/PortAudio/portaudio.git +[submodule "extern/adpcm-xq"] + path = extern/adpcm-xq + url = https://github.com/dbry/adpcm-xq.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 8425a78d3..2779c8b54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -485,6 +485,8 @@ extern/adpcm/yma_codec.c extern/adpcm/ymb_codec.c extern/adpcm/ymz_codec.c +extern/adpcm-xq/adpcm-lib.c + extern/opn/ym3438.c extern/Nuked-PSG/ympsg.c extern/opm/opm.c diff --git a/extern/adpcm-xq b/extern/adpcm-xq new file mode 160000 index 000000000..6220fed76 --- /dev/null +++ b/extern/adpcm-xq @@ -0,0 +1 @@ +Subproject commit 6220fed7655e86a29702b45dbc641a028ed5a4bf diff --git a/src/engine/platform/nds.cpp b/src/engine/platform/nds.cpp index 006b3f1dc..b52980198 100644 --- a/src/engine/platform/nds.cpp +++ b/src/engine/platform/nds.cpp @@ -156,7 +156,7 @@ void DivPlatformNDS::tick(bool sysTick) { if (chan[i].pcm || i<8) { DivSample* s=parent->getSample(chan[i].sample); switch (s->depth) { - //case DIV_SAMPLE_DEPTH_YMZ_ADPCM: ctrl=0x40; break; + case DIV_SAMPLE_DEPTH_IMA_ADPCM: ctrl=0x40; break; case DIV_SAMPLE_DEPTH_8BIT: ctrl=0x00; break; case DIV_SAMPLE_DEPTH_16BIT: ctrl=0x20; break; default: break; @@ -179,7 +179,7 @@ void DivPlatformNDS::tick(bool sysTick) { } if (chan[i].audPos>0) { switch (s->depth) { - //case DIV_SAMPLE_DEPTH_YMZ_ADPCM: start+=chan[i].audPos/2; end-=(chan[i].audPos/8); break; + case DIV_SAMPLE_DEPTH_IMA_ADPCM: start+=chan[i].audPos/2; end-=(chan[i].audPos/8); break; case DIV_SAMPLE_DEPTH_8BIT: start+=chan[i].audPos; end-=(chan[i].audPos/4); break; case DIV_SAMPLE_DEPTH_16BIT: start+=chan[i].audPos*2; end-=(chan[i].audPos/2); break; default: break; @@ -188,8 +188,7 @@ void DivPlatformNDS::tick(bool sysTick) { if (s->isLoopable()) { if (chan[i].audPos>0) { switch (s->depth) { - /* - case DIV_SAMPLE_DEPTH_YMZ_ADPCM: + case DIV_SAMPLE_DEPTH_IMA_ADPCM: loopStart=(s->loopStart-chan[i].audPos)/8; loopEnd=(s->loopEnd-s->loopStart)/8; if (chan[i].audPos>(unsigned int)s->loopStart) { @@ -197,7 +196,6 @@ void DivPlatformNDS::tick(bool sysTick) { loopEnd-=(chan[i].audPos-s->loopStart)/8; } break; - */ case DIV_SAMPLE_DEPTH_8BIT: loopStart=(s->loopStart-chan[i].audPos)/4; loopEnd=(s->loopEnd-s->loopStart)/4; @@ -218,7 +216,7 @@ void DivPlatformNDS::tick(bool sysTick) { } } else { switch (s->depth) { - //case DIV_SAMPLE_DEPTH_YMZ_ADPCM: loopStart=s->loopStart/8; loopEnd=(s->loopEnd-s->loopStart)/8; break; + case DIV_SAMPLE_DEPTH_IMA_ADPCM: loopStart=s->loopStart/8; loopEnd=(s->loopEnd-s->loopStart)/8; break; case DIV_SAMPLE_DEPTH_8BIT: loopStart=s->loopStart/4; loopEnd=(s->loopEnd-s->loopStart)/4; break; case DIV_SAMPLE_DEPTH_16BIT: loopStart=s->loopStart/2; loopEnd=(s->loopEnd-s->loopStart)/2; break; default: break; diff --git a/src/engine/sample.cpp b/src/engine/sample.cpp index 8ce8dd16f..17340f551 100644 --- a/src/engine/sample.cpp +++ b/src/engine/sample.cpp @@ -35,6 +35,7 @@ extern "C" { #include "../../extern/adpcm/ymb_codec.h" #include "../../extern/adpcm/ymz_codec.h" } +#include "../../extern/adpcm-xq/adpcm-lib.h" #include "brrUtils.h" DivSampleHistory::~DivSampleHistory() { @@ -599,7 +600,7 @@ bool DivSample::initInternal(DivSampleDepth d, int count) { break; case DIV_SAMPLE_DEPTH_IMA_ADPCM: // IMA ADPCM if (dataIMA!=NULL) delete[] dataIMA; - lengthIMA=(count+1)/2; + lengthIMA=4+((count+1)/2); dataIMA=new unsigned char[lengthIMA]; memset(dataIMA,0,lengthIMA); break; @@ -1288,7 +1289,7 @@ void DivSample::render(unsigned int formatMask) { } break; case DIV_SAMPLE_DEPTH_IMA_ADPCM: // IMA ADPCM - // TODO: decode + if (adpcm_decode_block(data16,dataIMA,lengthIMA,1)==0) logE("oh crap!"); break; default: return; @@ -1461,9 +1462,22 @@ void DivSample::render(unsigned int formatMask) { dataC219[i]=x|(negate?0x80:0); } } - if (NOT_IN_FORMAT(DIV_SAMPLE_DEPTH_IMA_ADPCM)) { // C219 + if (NOT_IN_FORMAT(DIV_SAMPLE_DEPTH_IMA_ADPCM)) { // IMA ADPCM if (!initInternal(DIV_SAMPLE_DEPTH_IMA_ADPCM,samples)) return; - // TODO: encode + int delta[2]; + delta[0]=0; + delta[1]=0; + + void* codec=adpcm_create_context(1,4,NOISE_SHAPING_OFF,delta); + if (codec==NULL) { + logE("oh no IMA encoder could not be created!"); + } else { + size_t whyPointer=0; + adpcm_encode_block(codec,dataIMA,&whyPointer,data16,samples); + if (whyPointer!=lengthIMA) logW("IMA length mismatch! %d -> %d!=%d",(int)samples,(int)whyPointer,(int)lengthIMA); + + adpcm_free_context(codec); + } } } diff --git a/src/gui/about.cpp b/src/gui/about.cpp index 30d891042..21ebc3873 100644 --- a/src/gui/about.cpp +++ b/src/gui/about.cpp @@ -214,6 +214,7 @@ const char* aboutLine[]={ "FFTW by Matteo Frigo and Steven G. Johnson", "backward-cpp by Google", "adpcm by superctr", + "adpcm-xq by David Bryant", "Nuked-OPL3/OPLL/OPM/OPN2/PSG by nukeykt", "YM3812-LLE, YMF262-LLE and YMF276-LLE by nukeykt", "ESFMu (modified version) by Kagamiin~", diff --git a/src/main.cpp b/src/main.cpp index 4f36135dd..a954759a7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -215,6 +215,7 @@ TAParamResult pVersion(String) { printf("- ESFMu (modified version) by Kagamiin~ (LGPLv2.1)\n"); printf("- ymfm by Aaron Giles (BSD 3-clause)\n"); printf("- adpcm by superctr (public domain)\n"); + printf("- adpcm-xq by David Bryant (BSD 3-clause)\n"); printf("- MAME SN76496 emulation core by Nicola Salmoria (BSD 3-clause)\n"); printf("- MAME AY-3-8910 emulation core by Couriersud (BSD 3-clause)\n"); printf("- MAME SAA1099 emulation core by Juergen Buchmueller and Manuel Abadia (BSD 3-clause)\n");