From: Fabian Maurer Subject: [PATCH] msacm32: Added converter for ADPCM to PCM 8 bit mono. Message-Id: <1463705641-8659-1-git-send-email-dark.shadow4@web.de> Date: Fri, 20 May 2016 02:54:01 +0200 Fixes https://bugs.winehq.org/show_bug.cgi?id=25396 Added a simple converter from ADPCM to PCM with 8 bit samples since the API seems to allow that. Signed-off-by: Fabian Maurer --- dlls/imaadp32.acm/imaadp32.c | 80 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 6 deletions(-) diff --git a/dlls/imaadp32.acm/imaadp32.c b/dlls/imaadp32.acm/imaadp32.c index c5c65f6..b74c7c5 100644 --- a/dlls/imaadp32.acm/imaadp32.c +++ b/dlls/imaadp32.acm/imaadp32.c @@ -179,6 +179,26 @@ static inline void W16(unsigned char* dst, short s) dst[1] = HIBYTE(s); } +/*********************************************************************** + * W8 + * + * Write a 8 bit sample + */ +static inline void W8(unsigned char* dst, short s) +{ + dst[0] = (unsigned char)((s + 32768) >> 8); +} + +/*********************************************************************** + * R8 + * + * Read a 8 bit sample + */ +static inline short R8(const unsigned char* src) +{ + return *src; +} + /* IMA (or DVI) APDCM codec routines */ static const unsigned IMA_StepTable[89] = @@ -381,6 +401,48 @@ static void cvtMMima16K(PACMDRVSTREAMINSTANCE adsi, } } +static void cvtMMima8K(PACMDRVSTREAMINSTANCE adsi, + const unsigned char* src, LPDWORD nsrc, + unsigned char* dst, LPDWORD ndst) +{ + int sample; + int stepIndex; + int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock; + int nsamp; + /* compute the number of entire blocks we can decode... + * it's the min of the number of entire blocks in source buffer and the number + * of entire blocks in destination buffer + */ + DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign, + *ndst / (nsamp_blk)); + + *nsrc = nblock * adsi->pwfxSrc->nBlockAlign; + *ndst = nblock * nsamp_blk; + + nsamp_blk--; /* remove the sample in block header */ + for (; nblock > 0; nblock--) + { + const unsigned char* in_src = src; + + /* handle header first */ + sample = R16(src); + stepIndex = (unsigned)*(src + 2); + clamp_step_index(&stepIndex); + src += 4; + W8(dst, sample); dst += 1; + + for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2) + { + process_nibble(*src, &stepIndex, &sample); + W8(dst, sample); dst += 1; + process_nibble(*src++ >> 4, &stepIndex, &sample); + W8(dst, sample); dst += 1; + } + /* we have now to realign the source pointer on block */ + src = in_src + adsi->pwfxSrc->nBlockAlign; + } +} + static void cvtSS16imaK(PACMDRVSTREAMINSTANCE adsi, const unsigned char* src, LPDWORD nsrc, unsigned char* dst, LPDWORD ndst) @@ -735,10 +797,11 @@ static LRESULT ADPCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi) { /* resampling or mono <=> stereo not available * ADPCM algo only define 16 bit per sample output + * (The API seems to still allow 8 bit per sample output) */ if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels || - adsi->pwfxDst->wBitsPerSample != 16) + (adsi->pwfxDst->wBitsPerSample != 16 && adsi->pwfxDst->wBitsPerSample != 8)) goto theEnd; nspb = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock; @@ -752,11 +815,16 @@ static LRESULT ADPCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi) if ((((nspb - 1) / 2) + 4) * adsi->pwfxSrc->nChannels < adsi->pwfxSrc->nBlockAlign) goto theEnd; - /* adpcm decoding... */ - if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 2) - aad->convert = cvtSSima16K; - if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 1) - aad->convert = cvtMMima16K; + /* adpcm decoding... */ + if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 2) + aad->convert = cvtSSima16K; + if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 1) + aad->convert = cvtMMima16K; + if (adsi->pwfxDst->wBitsPerSample == 8 && adsi->pwfxDst->nChannels == 1) + aad->convert = cvtMMima8K; + /* FIXME: Stereo support for 8bit samples*/ + if (adsi->pwfxDst->wBitsPerSample == 8 && adsi->pwfxDst->nChannels == 2) + goto theEnd; } else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM) -- 2.8.2