[IMAADP32.ACM] Sync with Wine Staging 4.0. CORE-15682
[reactos.git] / dll / win32 / imaadp32.acm / imaadp32.c
index e2c3af0..a93b5f6 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#define WIN32_NO_STATUS
-
 #include <assert.h>
 #include <stdarg.h>
-//#include <string.h>
-#include <windef.h>
-#include <winbase.h>
-#include <wingdi.h>
-#include <winuser.h>
-#include <winnls.h>
-//#include "mmsystem.h"
-//#include "mmreg.h"
-//#include "msacm.h"
-#include <msacmdrv.h>
-#include <wine/debug.h>
+#include <string.h>
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winnls.h"
+#include "mmsystem.h"
+#include "mmreg.h"
+#include "msacm.h"
+#include "msacmdrv.h"
+#include "wine/debug.h"
 
 /* see http://www.pcisys.net/~melanson/codecs/adpcm.txt for the details */
 
@@ -81,9 +79,6 @@ static const Format ADPCM_Formats[] =
     {1,  4, 22050}, {2,        4, 22050},  {1,  4, 44100}, {2,  4, 44100},
 };
 
-#define        NUM_PCM_FORMATS         (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
-#define        NUM_ADPCM_FORMATS       (sizeof(ADPCM_Formats) / sizeof(ADPCM_Formats[0]))
-
 /***********************************************************************
  *           ADPCM_GetFormatIndex
  */
@@ -95,11 +90,11 @@ static      DWORD   ADPCM_GetFormatIndex(const WAVEFORMATEX *wfx)
     switch (wfx->wFormatTag)
     {
     case WAVE_FORMAT_PCM:
-       hi = NUM_PCM_FORMATS;
+       hi = ARRAY_SIZE(PCM_Formats);
        fmts = PCM_Formats;
        break;
     case WAVE_FORMAT_IMA_ADPCM:
-       hi = NUM_ADPCM_FORMATS;
+       hi = ARRAY_SIZE(ADPCM_Formats);
        fmts = ADPCM_Formats;
        break;
     default:
@@ -156,7 +151,7 @@ static void     init_wfx_ima_adpcm(IMAADPCMWAVEFORMAT* awfx/*, DWORD nba*/)
     }
     pwfx->cbSize = sizeof(WORD);
 
-    awfx->wSamplesPerBlock = (pwfx->nBlockAlign - (4 * pwfx->nChannels) * 2) / pwfx->nChannels + 1;
+    awfx->wSamplesPerBlock = (pwfx->nBlockAlign - (4 * pwfx->nChannels)) * (2 / pwfx->nChannels) + 1;
     pwfx->nAvgBytesPerSec = (pwfx->nSamplesPerSec * pwfx->nBlockAlign) / awfx->wSamplesPerBlock;
 }
 
@@ -181,6 +176,25 @@ 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);
+}
+
+
+static inline void W8_16(unsigned char* dst, short s, int bytes)
+{
+    if(bytes == 1)
+        W8(dst, s);
+    else
+        W16(dst, s);
+}
+
 /* IMA (or DVI) APDCM codec routines */
 
 static const unsigned IMA_StepTable[89] =
@@ -341,43 +355,43 @@ static    void cvtSSima16K(PACMDRVSTREAMINSTANCE adsi,
     }
 }
 
-static void cvtMMima16K(PACMDRVSTREAMINSTANCE adsi,
-                         const unsigned char* src, LPDWORD nsrc,
-                         unsigned char* dst, LPDWORD ndst)
+static void cvtMMimaK(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;
+    int sample;
+    int stepIndex;
+    int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
+    int nsamp;
+    int bytesPerSample = adsi->pwfxDst->wBitsPerSample / 8;
     /* 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 * 2));
+    DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign, *ndst / (nsamp_blk * bytesPerSample));
 
     *nsrc = nblock * adsi->pwfxSrc->nBlockAlign;
-    *ndst = nblock * nsamp_blk * 2;
+    *ndst = nblock * nsamp_blk * bytesPerSample;
 
     nsamp_blk--; /* remove the sample in block header */
     for (; nblock > 0; nblock--)
     {
-        const unsigned char*    in_src = src;
+        const unsigned char* in_src = src;
 
-       /* handle header first */
-       sample = R16(src);
-       stepIndex = (unsigned)*(src + 2);
+        /* handle header first */
+        sample = R16(src);
+        stepIndex = (unsigned)*(src + 2);
         clamp_step_index(&stepIndex);
-       src += 4;
-       W16(dst, sample);       dst += 2;
+        src += 4;
+        W8_16(dst, sample, bytesPerSample); dst += bytesPerSample;
 
-       for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
+        for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
         {
             process_nibble(*src, &stepIndex, &sample);
-           W16(dst, sample); dst += 2;
+            W8_16(dst, sample, bytesPerSample); dst += bytesPerSample;
             process_nibble(*src++ >> 4, &stepIndex, &sample);
-           W16(dst, sample); dst += 2;
-       }
+            W8_16(dst, sample, bytesPerSample); dst += bytesPerSample;
+        }
         /* we have now to realign the source pointer on block */
         src = in_src + adsi->pwfxSrc->nBlockAlign;
     }
@@ -414,31 +428,29 @@ static    void cvtSS16imaK(PACMDRVSTREAMINSTANCE adsi,
         /* generate header */
        sampleL = R16(src);  src += 2;
        W16(dst, sampleL); dst += 2;
-       *dst = (unsigned char)(unsigned)stepIndexL;
-       dst += 2;
+       W16(dst, stepIndexL); dst += 2;
 
        sampleR = R16(src); src += 2;
        W16(dst, sampleR); dst += 2;
-       *dst = (unsigned char)(unsigned)stepIndexR;
-       dst += 2;
+       W16(dst, stepIndexR); dst += 2;
 
        for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 8)
         {
             for (i = 0; i < 4; i++)
             {
-                code1 = generate_nibble(R16(src + (2 * i + 0) * 2 + 0),
+                code1 = generate_nibble(R16(src + (4 * i + 0) * 2),
                                         &stepIndexL, &sampleL);
-                code2 = generate_nibble(R16(src + (2 * i + 1) * 2 + 0),
+                code2 = generate_nibble(R16(src + (4 * i + 2) * 2),
                                         &stepIndexL, &sampleL);
-                *dst++ = (code1 << 4) | code2;
+                *dst++ = (code2 << 4) | code1;
             }
             for (i = 0; i < 4; i++)
             {
-                code1 = generate_nibble(R16(src + (2 * i + 0) * 2 + 1),
+                code1 = generate_nibble(R16(src + (4 * i + 1) * 2),
                                         &stepIndexR, &sampleR);
-                code2 = generate_nibble(R16(src + (2 * i + 1) * 2 + 1),
+                code2 = generate_nibble(R16(src + (4 * i + 3) * 2),
                                         &stepIndexR, &sampleR);
-                *dst++ = (code1 << 4) | code2;
+                *dst++ = (code2 << 4) | code1;
             }
             src += 32;
        }
@@ -494,7 +506,7 @@ static      void cvtMM16imaK(PACMDRVSTREAMINSTANCE adsi,
             src += 2;
             code2 = generate_nibble(R16(src), &stepIndex, &sample);
             src += 2;
-            *dst++ = (code1 << 4) | code2;
+            *dst++ = (code2 << 4) | code1;
        }
        dst = in_dst + adsi->pwfxDst->nBlockAlign;
     }
@@ -509,8 +521,8 @@ static      LRESULT ADPCM_DriverDetails(PACMDRIVERDETAILSW add)
 {
     add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
     add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
-    add->wMid = 0x1;
-    add->wPid = 0x22;
+    add->wMid = MM_MICROSOFT;
+    add->wPid = MM_MSFT_ACM_IMAADPCM;
     add->vdwACM = 0x3320000;
     add->vdwDriver = 0x04000000;
     add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
@@ -518,13 +530,13 @@ static    LRESULT ADPCM_DriverDetails(PACMDRIVERDETAILSW add)
     add->cFilterTags = 0;
     add->hicon = NULL;
     MultiByteToWideChar( CP_ACP, 0, "Microsoft IMA ADPCM", -1,
-                         add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) );
+                         add->szShortName, ARRAY_SIZE(add->szShortName) );
     MultiByteToWideChar( CP_ACP, 0, "Microsoft IMA ADPCM CODEC", -1,
-                         add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) );
+                         add->szLongName, ARRAY_SIZE(add->szLongName) );
     MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
-                         add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) );
+                         add->szCopyright, ARRAY_SIZE(add->szCopyright) );
     MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
-                         add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) );
+                         add->szLicensing, ARRAY_SIZE(add->szLicensing) );
     add->szFeatures[0] = 0;
 
     return MMSYSERR_NOERROR;
@@ -570,13 +582,13 @@ static    LRESULT ADPCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
     case 0:
        aftd->dwFormatTag = WAVE_FORMAT_PCM;
        aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
-       aftd->cStandardFormats = NUM_PCM_FORMATS;
+       aftd->cStandardFormats = ARRAY_SIZE(PCM_Formats);
         lstrcpyW(aftd->szFormatTag, szPcm);
         break;
     case 1:
        aftd->dwFormatTag = WAVE_FORMAT_IMA_ADPCM;
        aftd->cbFormatSize = sizeof(IMAADPCMWAVEFORMAT);
-       aftd->cStandardFormats = NUM_ADPCM_FORMATS;
+       aftd->cStandardFormats = ARRAY_SIZE(ADPCM_Formats);
         lstrcpyW(aftd->szFormatTag, szImaAdPcm);
        break;
     }
@@ -599,7 +611,7 @@ static      LRESULT ADPCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
        switch (afd->dwFormatTag)
         {
        case WAVE_FORMAT_PCM:
-           if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE;
+           if (afd->dwFormatIndex >= ARRAY_SIZE(PCM_Formats)) return ACMERR_NOTPOSSIBLE;
            afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
            afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
            afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
@@ -612,18 +624,11 @@ static    LRESULT ADPCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
                afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
            break;
        case WAVE_FORMAT_IMA_ADPCM:
-           if (afd->dwFormatIndex >= NUM_ADPCM_FORMATS) return ACMERR_NOTPOSSIBLE;
+           if (afd->dwFormatIndex >= ARRAY_SIZE(ADPCM_Formats)) return ACMERR_NOTPOSSIBLE;
            afd->pwfx->nChannels = ADPCM_Formats[afd->dwFormatIndex].nChannels;
            afd->pwfx->nSamplesPerSec = ADPCM_Formats[afd->dwFormatIndex].rate;
            afd->pwfx->wBitsPerSample = ADPCM_Formats[afd->dwFormatIndex].nBits;
-           afd->pwfx->nBlockAlign = 1024;
-           /* we got 4 bits per sample */
-           afd->pwfx->nAvgBytesPerSec =
-               (afd->pwfx->nSamplesPerSec * 4) / 8;
-            if (afd->cbwfx >= sizeof(WAVEFORMATEX))
-                afd->pwfx->cbSize = sizeof(WORD);
-            if (afd->cbwfx >= sizeof(IMAADPCMWAVEFORMAT))
-                ((IMAADPCMWAVEFORMAT*)afd->pwfx)->wSamplesPerBlock = (1024 - 4 * afd->pwfx->nChannels) * (2 / afd->pwfx->nChannels) + 1;
+           init_wfx_ima_adpcm((IMAADPCMWAVEFORMAT *)afd->pwfx);
            break;
        default:
             WARN("Unsupported tag %08x\n", afd->dwFormatTag);
@@ -735,13 +740,14 @@ static    LRESULT ADPCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
     else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
              adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
     {
-       /* resampling or mono <=> stereo not available
+        /* 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)
-           goto theEnd;
+        if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
+            adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
+            (adsi->pwfxDst->wBitsPerSample != 16 && adsi->pwfxDst->wBitsPerSample != 8))
+            goto theEnd;
 
         nspb = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
         TRACE("spb=%u\n", nspb);
@@ -754,11 +760,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 = cvtMMimaK;
+        if (adsi->pwfxDst->wBitsPerSample == 8 && adsi->pwfxDst->nChannels == 1)
+            aad->convert = cvtMMimaK;
+        /* 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)