[PATCH] msacm32: Added converter for ADPCM to PCM 8 bit mono.

Fabian Maurer dark.shadow4 at web.de
Thu May 19 19:54:01 CDT 2016


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 <dark.shadow4 at web.de>
---
 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




More information about the wine-patches mailing list