* embedded driver handling scheme in msacm32.dll which isn't done yet
*/
-#include "wineacm.h"
+#include "config.h"
#include <assert.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "mmsystem.h"
+#define NOBITMAP
+#include "mmreg.h"
+#include "msacm.h"
+#include "wingdi.h"
+#include "winnls.h"
+#include "winuser.h"
+
+#include "msacmdrv.h"
+#include "wineacm.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msacm);
/***********************************************************************
* PCM_drvOpen
/* flags for fdwDriver */
#define PCM_RESAMPLE 1
+typedef void (*PCM_CONVERT_KEEP_RATE)(const unsigned char*, int, unsigned char*);
+
+typedef void (*PCM_CONVERT_CHANGE_RATE)(const DWORD, const unsigned char*, DWORD*, const DWORD, unsigned char*, DWORD*);
+
/* data used while converting */
typedef struct tagAcmPcmData {
/* conversion routine, depending if rate conversion is required */
union {
- void (*cvtKeepRate)(const unsigned char*, int, unsigned char*);
- void (*cvtChangeRate)(DWORD, const unsigned char*, LPDWORD,
- DWORD, unsigned char*, LPDWORD);
+ PCM_CONVERT_KEEP_RATE cvtKeepRate;
+ PCM_CONVERT_CHANGE_RATE cvtChangeRate;
} cvt;
} AcmPcmData;
int nBits;
int rate;
} PCM_Formats[] = {
- {1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000},
- {1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025},
- {1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050},
- {1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100},
- {1, 8, 48000}, {2, 8, 48000}, {1, 16, 48000}, {2, 16, 48000},
- {1, 8, 96000}, {2, 8, 96000}, {1, 16, 96000}, {2, 16, 96000}
+ {1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000}, {1, 24, 8000}, {2, 24, 8000},
+ {1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025}, {1, 24, 11025}, {2, 24, 11025},
+ {1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050}, {1, 24, 22050}, {2, 24, 22050},
+ {1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100}, {1, 24, 44100}, {2, 24, 44100},
+ {1, 8, 48000}, {2, 8, 48000}, {1, 16, 48000}, {2, 16, 48000}, {1, 24, 48000}, {2, 24, 48000},
+ {1, 8, 96000}, {2, 8, 96000}, {1, 16, 96000}, {2, 16, 96000}, {1, 24, 96000}, {2, 24, 96000},
};
/***********************************************************************
return HIBYTE(s) ^ (unsigned char)0x80;
}
+/***********************************************************************
+ * C248
+ *
+ * Converts a 24 bit sample to a 8 bit one (data loss !!)
+ */
+static inline unsigned char C248(int s)
+{
+ return HIBYTE(HIWORD(s)) ^ (unsigned char)0x80;
+}
+
+/***********************************************************************
+ * C2416
+ *
+ * Converts a 24 bit sample to a 16 bit one (data loss !!)
+ */
+static inline short C2416(int s)
+{
+ return HIWORD(s);
+}
+
/***********************************************************************
* R16
*
return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));
}
+/***********************************************************************
+ * R24
+ *
+ * Read a 24 bit sample (correctly handles endianness)
+ * Note, to support signed arithmetic, the values are shifted high in the int
+ * and low 8 bytes are unused.
+ */
+static inline int R24(const unsigned char* src)
+{
+ return ((int)src[0] | (int)src[1] << 8 | (int)src[2] << 16) << 8;
+}
+
/***********************************************************************
* W16
*
dst[1] = HIBYTE(s);
}
+/***********************************************************************
+ * W24
+ *
+ * Write a 24 bit sample (correctly handles endianness)
+ */
+static inline void W24(unsigned char* dst, int s)
+{
+ dst[0] = HIBYTE(LOWORD(s));
+ dst[1] = LOBYTE(HIWORD(s));
+ dst[2] = HIBYTE(HIWORD(s));
+}
+
+/***********************************************************************
+ * M24
+ *
+ * Convert the (l,r) 24 bit stereo sample into a 24 bit mono
+ * (takes the sum of the two values)
+ */
+static inline int M24(int l, int r)
+{
+ LONGLONG sum = l + r;
+
+ /* clip sum to saturation */
+ if (sum > 0x7fffff00)
+ sum = 0x7fffff00;
+ else if (sum < -0x7fffff00)
+ sum = -0x7fffff00;
+
+ return sum;
+}
+
/***********************************************************************
* M16
*
}
}
+static void cvtMS248K(const unsigned char* src, int ns, unsigned char* dst)
+{
+ unsigned char v;
+ TRACE("(%p, %d, %p)\n", src, ns, dst);
+
+ while (ns--) {
+ v = C248(R24(src)); src += 3;
+ *dst++ = v;
+ *dst++ = v;
+ }
+}
+
+static void cvtSM248K(const unsigned char* src, int ns, unsigned char* dst)
+{
+ TRACE("(%p, %d, %p)\n", src, ns, dst);
+
+ while (ns--) {
+ *dst++ = C248(M24(R24(src), R24(src + 3)));
+ src += 6;
+ }
+}
+
+static void cvtMM248K(const unsigned char* src, int ns, unsigned char* dst)
+{
+ TRACE("(%p, %d, %p)\n", src, ns, dst);
+
+ while (ns--) {
+ *dst++ = C248(R24(src)); src += 3;
+ }
+}
+
+static void cvtSS248K(const unsigned char* src, int ns, unsigned char* dst)
+{
+ TRACE("(%p, %d, %p)\n", src, ns, dst);
+
+ while (ns--) {
+ *dst++ = C248(R24(src)); src += 3;
+ *dst++ = C248(R24(src)); src += 3;
+ }
+}
+
+static void cvtMS2416K(const unsigned char* src, int ns, unsigned char* dst)
+{
+ short v;
+ TRACE("(%p, %d, %p)\n", src, ns, dst);
+
+ while (ns--) {
+ v = C2416(R24(src)); src += 3;
+ W16(dst, v); dst += 2;
+ W16(dst, v); dst += 2;
+ }
+}
+
+static void cvtSM2416K(const unsigned char* src, int ns, unsigned char* dst)
+{
+ TRACE("(%p, %d, %p)\n", src, ns, dst);
+
+ while (ns--) {
+ W16(dst, C2416(M24(R24(src), R24(src + 3))));
+ dst += 2;
+ src += 6;
+ }
+}
+
+static void cvtMM2416K(const unsigned char* src, int ns, unsigned char* dst)
+{
+ TRACE("(%p, %d, %p)\n", src, ns, dst);
+
+ while (ns--) {
+ W16(dst, C2416(R24(src))); dst += 2; src += 3;
+ }
+}
+
+static void cvtSS2416K(const unsigned char* src, int ns, unsigned char* dst)
+{
+ TRACE("(%p, %d, %p)\n", src, ns, dst);
+
+ while (ns--) {
+ W16(dst, C2416(R24(src))); dst += 2; src += 3;
+ W16(dst, C2416(R24(src))); dst += 2; src += 3;
+ }
+}
-typedef void (*PCM_CONVERT_KEEP_RATE)(const unsigned char*, int, unsigned char*);
-static const PCM_CONVERT_KEEP_RATE PCM_ConvertKeepRate[16] = {
+static const PCM_CONVERT_KEEP_RATE PCM_ConvertKeepRate[] = {
cvtSS88K, cvtSM88K, cvtMS88K, cvtMM88K,
cvtSS816K, cvtSM816K, cvtMS816K, cvtMM816K,
+ NULL, NULL, NULL, NULL, /* TODO: 8->24 */
cvtSS168K, cvtSM168K, cvtMS168K, cvtMM168K,
cvtSS1616K, cvtSM1616K, cvtMS1616K, cvtMM1616K,
+ NULL, NULL, NULL, NULL, /* TODO: 16->24 */
+ cvtSS248K, cvtSM248K, cvtMS248K, cvtMM248K,
+ cvtSS2416K, cvtSM2416K, cvtMS2416K, cvtMM2416K,
+ NULL, NULL, NULL, NULL, /* TODO: 24->24 */
};
/* the conversion routines with rate conversion are labelled cvt<X><Y><N><M>C
* <M> is the number of bits of output channel (8 or 16)
*
*/
-static void cvtSS88C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
- DWORD dstRate, unsigned char* dst, LPDWORD ndst)
-{
- DWORD error = dstRate / 2;
- TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
-
- while ((*ndst)--) {
- *dst++ = *src;
- *dst++ = *src;
- error = error + srcRate;
- while (error > dstRate) {
- src += 2;
- (*nsrc)--;
- if (*nsrc == 0)
+
+static void cvtSS88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
+{
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
return;
- error = error - dstRate;
+ (*ndst)++;
+ error -= srcRate;
+
+ *dst++ = src[0];
+ *dst++ = src[1];
}
+ src += 2;
}
}
-static void cvtSM88C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
- DWORD dstRate, unsigned char* dst, LPDWORD ndst)
+static void cvtSM88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
{
- DWORD error = dstRate / 2;
- TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
-
- while ((*ndst)--) {
- *dst++ = M8(src[0], src[1]);
- error = error + srcRate;
- while (error > dstRate) {
- src += 2;
- (*nsrc)--;
- if (*nsrc == 0)
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
return;
- error = error - dstRate;
+ (*ndst)++;
+ error -= srcRate;
+
+ *dst++ = M8(src[0], src[1]);
}
+ src += 2;
}
}
-static void cvtMS88C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
- DWORD dstRate, unsigned char* dst, LPDWORD ndst)
+static void cvtMS88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
{
- DWORD error = dstRate / 2;
- TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
-
- while ((*ndst)--) {
- *dst++ = *src;
- *dst++ = *src;
- error = error + srcRate;
- while (error > dstRate) {
- src++;
- (*nsrc)--;
- if (*nsrc == 0)
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
return;
- error = error - dstRate;
+ (*ndst)++;
+ error -= srcRate;
+
+ *dst++ = src[0];
+ *dst++ = src[0];
}
+ src += 1;
}
}
-static void cvtMM88C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
- DWORD dstRate, unsigned char* dst, LPDWORD ndst)
+static void cvtMM88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
{
- DWORD error = dstRate / 2;
- TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
-
- while ((*ndst)--) {
- *dst++ = *src;
- error = error + srcRate;
- while (error > dstRate) {
- src++;
- (*nsrc)--;
- if (*nsrc==0)
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
return;
- error = error - dstRate;
+ (*ndst)++;
+ error -= srcRate;
+
+ *dst++ = src[0];
}
+ src += 1;
}
}
-static void cvtSS816C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
- DWORD dstRate, unsigned char* dst, LPDWORD ndst)
+static void cvtSS816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
{
- DWORD error = dstRate / 2;
- TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
-
- while ((*ndst)--) {
- W16(dst, C816(src[0])); dst += 2;
- W16(dst, C816(src[1])); dst += 2;
- error = error + srcRate;
- while (error > dstRate) {
- src += 2;
- (*nsrc)--;
- if (*nsrc==0)
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
return;
- error = error - dstRate;
+ (*ndst)++;
+ error -= srcRate;
+
+ W16(dst, C816(src[0])); dst += 2;
+ W16(dst, C816(src[1])); dst += 2;
}
+ src += 2;
}
}
-static void cvtSM816C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
- DWORD dstRate, unsigned char* dst, LPDWORD ndst)
+static void cvtSM816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
{
- DWORD error = dstRate / 2;
- TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
-
- while ((*ndst)--) {
- W16(dst, M16(C816(src[0]), C816(src[1]))); dst += 2;
- error = error + srcRate;
- while (error > dstRate) {
- src += 2;
- (*nsrc)--;
- if (*nsrc==0)
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
return;
- error = error - dstRate;
+ (*ndst)++;
+ error -= srcRate;
+
+ W16(dst, M16(C816(src[0]), C816(src[1]))); dst += 2;
}
+ src += 2;
}
}
-static void cvtMS816C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
- DWORD dstRate, unsigned char* dst, LPDWORD ndst)
+static void cvtMS816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
{
- DWORD error = dstRate / 2;
- TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
-
- while ((*ndst)--) {
- W16(dst, C816(*src)); dst += 2;
- W16(dst, C816(*src)); dst += 2;
- error = error + srcRate;
- while (error > dstRate) {
- src++;
- (*nsrc)--;
- if (*nsrc==0)
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
return;
- error = error - dstRate;
+ (*ndst)++;
+ error -= srcRate;
+
+ W16(dst, C816(src[0])); dst += 2;
+ W16(dst, C816(src[0])); dst += 2;
}
+ src += 1;
}
}
-static void cvtMM816C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
- DWORD dstRate, unsigned char* dst, LPDWORD ndst)
+static void cvtMM816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
{
- DWORD error = dstRate / 2;
- TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
-
- while ((*ndst)--) {
- W16(dst, C816(*src)); dst += 2;
- error = error + srcRate;
- while (error > dstRate) {
- src++;
- (*nsrc)--;
- if (*nsrc==0)
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
return;
- error = error - dstRate;
+ (*ndst)++;
+ error -= srcRate;
+
+ W16(dst, C816(src[0])); dst += 2;
}
+ src += 1;
}
}
-static void cvtSS168C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
- DWORD dstRate, unsigned char* dst, LPDWORD ndst)
+static void cvtSS168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
{
- DWORD error = dstRate / 2;
- TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
-
- while ((*ndst)--) {
- *dst++ = C168(R16(src));
- *dst++ = C168(R16(src + 2));
- error = error + srcRate;
- while (error > dstRate) {
- src += 4;
- (*nsrc)--;
- if (*nsrc==0)
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
return;
- error = error - dstRate;
+ (*ndst)++;
+ error -= srcRate;
+
+ *dst++ = C168(R16(src));
+ *dst++ = C168(R16(src + 2));
}
+ src += 4;
}
}
-static void cvtSM168C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
- DWORD dstRate, unsigned char* dst, LPDWORD ndst)
+static void cvtSM168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
{
- DWORD error = dstRate / 2;
- TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
-
- while ((*ndst)--) {
- *dst++ = C168(M16(R16(src), R16(src + 2)));
- error = error + srcRate;
- while (error > dstRate) {
- src += 4;
- (*nsrc)--;
- if (*nsrc==0)
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
return;
- error = error - dstRate;
+ (*ndst)++;
+ error -= srcRate;
+
+ *dst++ = C168(M16(R16(src), R16(src + 2)));
}
+ src += 4;
}
}
-static void cvtMS168C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
- DWORD dstRate, unsigned char* dst, LPDWORD ndst)
+static void cvtMS168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
{
- DWORD error = dstRate / 2;
- TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
-
- while ((*ndst)--) {
- *dst++ = C168(R16(src));
- *dst++ = C168(R16(src));
- error = error + srcRate;
- while (error > dstRate) {
- src += 2;
- (*nsrc)--;
- if (*nsrc==0)
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
return;
- error = error - dstRate;
+ (*ndst)++;
+ error -= srcRate;
+
+ *dst++ = C168(R16(src));
+ *dst++ = C168(R16(src));
}
+ src += 2;
}
}
-static void cvtMM168C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
- DWORD dstRate, unsigned char* dst, LPDWORD ndst)
+static void cvtMM168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
{
- DWORD error = dstRate / 2;
- TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
-
- while ((*ndst)--) {
- *dst++ = C168(R16(src));
- error = error + srcRate;
- while (error > dstRate) {
- src += 2;
- (*nsrc)--;
- if (*nsrc == 0)
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
return;
- error = error - dstRate;
+ (*ndst)++;
+ error -= srcRate;
+
+ *dst++ = C168(R16(src));
}
+ src += 2;
}
}
-static void cvtSS1616C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
- DWORD dstRate, unsigned char* dst, LPDWORD ndst)
+static void cvtSS1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
{
- DWORD error = dstRate / 2;
- TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
-
- while ((*ndst)--) {
- W16(dst, R16(src)); dst += 2;
- W16(dst, R16(src)); dst += 2;
- error = error + srcRate;
- while (error > dstRate) {
- src += 4;
- (*nsrc)--;
- if (*nsrc == 0)
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
return;
- error = error - dstRate;
+ (*ndst)++;
+ error -= srcRate;
+
+ W16(dst, R16(src)); dst += 2;
+ W16(dst, R16(src + 2)); dst += 2;
}
+ src += 4;
}
}
-static void cvtSM1616C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
- DWORD dstRate, unsigned char* dst, LPDWORD ndst)
+static void cvtSM1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
{
- DWORD error = dstRate / 2;
- TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
+ return;
+ (*ndst)++;
+ error -= srcRate;
+
+ W16(dst, M16(R16(src), R16(src + 2))); dst += 2;
+ }
+ src += 4;
+ }
+}
- while ((*ndst)--) {
- W16(dst, M16(R16(src), R16(src + 2))); dst += 2;
- error = error + srcRate;
- while (error > dstRate) {
- src += 4;
- (*nsrc)--;
- if (*nsrc == 0)
+static void cvtMS1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
+{
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
return;
- error = error - dstRate;
+ (*ndst)++;
+ error -= srcRate;
+
+ W16(dst, R16(src)); dst += 2;
+ W16(dst, R16(src)); dst += 2;
}
+ src += 2;
}
}
-static void cvtMS1616C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
- DWORD dstRate, unsigned char* dst, LPDWORD ndst)
+static void cvtMM1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
{
- DWORD error = dstRate / 2;
- TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
+ return;
+ (*ndst)++;
+ error -= srcRate;
- while((*ndst)--) {
- W16(dst, R16(src)); dst += 2;
- W16(dst, R16(src)); dst += 2;
- error = error + srcRate;
- while (error > dstRate) {
- src += 2;
- (*nsrc)--;
- if (*nsrc == 0)
+ W16(dst, R16(src)); dst += 2;
+ }
+ src += 2;
+ }
+}
+
+static void cvtSS2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
+{
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
return;
- error = error - dstRate;
+ (*ndst)++;
+ error -= srcRate;
+
+ W24(dst, R24(src)); dst += 3;
+ W24(dst, R24(src + 3)); dst += 3;
}
+ src += 6;
}
}
-static void cvtMM1616C(DWORD srcRate, const unsigned char* src, LPDWORD nsrc,
- DWORD dstRate, unsigned char* dst, LPDWORD ndst)
+static void cvtSM2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
{
- DWORD error = dstRate / 2;
- TRACE("(%d, %p, %p, %d, %p, %p)\n", srcRate, src, nsrc, dstRate, dst, ndst);
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
+ return;
+ (*ndst)++;
+ error -= srcRate;
+
+ W24(dst, M24(R24(src), R24(src + 3))); dst += 3;
+ }
+ src += 6;
+ }
+}
- while ((*ndst)--) {
- W16(dst, R16(src)); dst += 2;
- error = error + srcRate;
- while (error > dstRate) {
- src += 2;
- (*nsrc)--;
- if (*nsrc == 0)
+static void cvtMS2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
+{
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
return;
- error = error - dstRate;
+ (*ndst)++;
+ error -= srcRate;
+
+ W24(dst, R24(src)); dst += 3;
+ W24(dst, R24(src)); dst += 3;
}
+ src += 3;
}
}
-typedef void (*PCM_CONVERT_CHANGE_RATE)(DWORD, const unsigned char*, LPDWORD, DWORD, unsigned char*, LPDWORD);
+static void cvtMM2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
+ const DWORD dstRate, unsigned char *dst, DWORD *ndst)
+{
+ DWORD error = srcRate / 2;
+ DWORD maxSrc = *nsrc, maxDst = *ndst;
+ *ndst = 0;
+ for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
+ error += dstRate;
+ while (error > srcRate) {
+ if (*ndst == maxDst)
+ return;
+ (*ndst)++;
+ error -= srcRate;
+
+ W24(dst, R24(src)); dst += 3;
+ }
+ src += 3;
+ }
+}
-static const PCM_CONVERT_CHANGE_RATE PCM_ConvertChangeRate[16] = {
+static const PCM_CONVERT_CHANGE_RATE PCM_ConvertChangeRate[] = {
cvtSS88C, cvtSM88C, cvtMS88C, cvtMM88C,
cvtSS816C, cvtSM816C, cvtMS816C, cvtMM816C,
+ NULL, NULL, NULL, NULL, /* TODO: 8->24 */
cvtSS168C, cvtSM168C, cvtMS168C, cvtMM168C,
cvtSS1616C, cvtSM1616C, cvtMS1616C, cvtMM1616C,
+ NULL, NULL, NULL, NULL, /* TODO: 16->24 */
+ NULL, NULL, NULL, NULL, /* TODO: 24->8 */
+ NULL, NULL, NULL, NULL, /* TODO: 24->16 */
+ cvtSS2424C, cvtSM2424C, cvtMS2424C, cvtMM2424C,
};
/***********************************************************************
add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
- add->wMid = 0xFF;
- add->wPid = 0x00;
+ add->wMid = MM_MICROSOFT;
+ add->wPid = MM_MSFT_ACM_PCM;
add->vdwACM = 0x01000000;
add->vdwDriver = 0x01000000;
add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CONVERTER;
add->cFormatTags = 1;
add->cFilterTags = 0;
add->hicon = NULL;
- MultiByteToWideChar( CP_ACP, 0, "WINE-PCM", -1,
+ MultiByteToWideChar( CP_ACP, 0, "MS-PCM", -1,
add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, "Wine PCM converter", -1,
add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) );
/* some tests ... */
if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
- adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
- PCM_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) {
+ adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
+ PCM_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) {
WARN("not possible\n");
return ACMERR_NOTPOSSIBLE;
}
/* is no suggestion for destination, then copy source value */
if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS)) {
- adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
+ adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
}
if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC)) {
- adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
+ adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
}
if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE)) {
- adfs->pwfxDst->wBitsPerSample = adfs->pwfxSrc->wBitsPerSample;
+ adfs->pwfxDst->wBitsPerSample = adfs->pwfxSrc->wBitsPerSample;
}
if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG)) {
- if (adfs->pwfxSrc->wFormatTag != WAVE_FORMAT_PCM) {
- WARN("not possible\n");
+ if (adfs->pwfxSrc->wFormatTag != WAVE_FORMAT_PCM) {
+ WARN("source format 0x%x not supported\n", adfs->pwfxSrc->wFormatTag);
+ return ACMERR_NOTPOSSIBLE;
+ }
+ adfs->pwfxDst->wFormatTag = adfs->pwfxSrc->wFormatTag;
+ } else {
+ if (adfs->pwfxDst->wFormatTag != WAVE_FORMAT_PCM) {
+ WARN("destination format 0x%x not supported\n", adfs->pwfxDst->wFormatTag);
return ACMERR_NOTPOSSIBLE;
}
- adfs->pwfxDst->wFormatTag = adfs->pwfxSrc->wFormatTag;
}
/* check if result is ok */
if (PCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) {
*/
static LRESULT PCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
{
- AcmPcmData* apd;
- int idx = 0;
+ AcmPcmData* apd;
+ int idx;
+ DWORD flags;
TRACE("(%p)\n", adsi);
assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
- apd = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmPcmData));
- if (apd == 0) {
- WARN("no memory\n");
- return MMSYSERR_NOMEM;
+ switch(adsi->pwfxSrc->wBitsPerSample){
+ case 8:
+ idx = 0;
+ break;
+ case 16:
+ idx = 12;
+ break;
+ case 24:
+ if (adsi->pwfxSrc->nBlockAlign != 3 * adsi->pwfxSrc->nChannels) {
+ FIXME("Source: 24-bit samples must be packed\n");
+ return MMSYSERR_NOTSUPPORTED;
+ }
+ idx = 24;
+ break;
+ default:
+ FIXME("Unsupported source bit depth: %u\n", adsi->pwfxSrc->wBitsPerSample);
+ return MMSYSERR_NOTSUPPORTED;
}
- adsi->dwDriver = (DWORD_PTR)apd;
- adsi->fdwDriver = 0;
+ switch(adsi->pwfxDst->wBitsPerSample){
+ case 8:
+ break;
+ case 16:
+ idx += 4;
+ break;
+ case 24:
+ if (adsi->pwfxDst->nBlockAlign != 3 * adsi->pwfxDst->nChannels) {
+ FIXME("Destination: 24-bit samples must be packed\n");
+ return MMSYSERR_NOTSUPPORTED;
+ }
+ idx += 8;
+ break;
+ default:
+ FIXME("Unsupported destination bit depth: %u\n", adsi->pwfxDst->wBitsPerSample);
+ return MMSYSERR_NOTSUPPORTED;
+ }
- if (adsi->pwfxSrc->wBitsPerSample == 16) idx += 8;
- if (adsi->pwfxDst->wBitsPerSample == 16) idx += 4;
if (adsi->pwfxSrc->nChannels == 1) idx += 2;
+
if (adsi->pwfxDst->nChannels == 1) idx += 1;
+ apd = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmPcmData));
+ if (!apd)
+ return MMSYSERR_NOMEM;
+
if (adsi->pwfxSrc->nSamplesPerSec == adsi->pwfxDst->nSamplesPerSec) {
- apd->cvt.cvtKeepRate = PCM_ConvertKeepRate[idx];
+ flags = 0;
+ apd->cvt.cvtKeepRate = PCM_ConvertKeepRate[idx];
} else {
- adsi->fdwDriver |= PCM_RESAMPLE;
- apd->cvt.cvtChangeRate = PCM_ConvertChangeRate[idx];
+ flags = PCM_RESAMPLE;
+ apd->cvt.cvtChangeRate = PCM_ConvertChangeRate[idx];
+ }
+
+ if(!apd->cvt.cvtChangeRate && !apd->cvt.cvtKeepRate){
+ FIXME("Unimplemented conversion from %u -> %u bps\n",
+ adsi->pwfxSrc->wBitsPerSample,
+ adsi->pwfxDst->wBitsPerSample);
+ HeapFree(GetProcessHeap(), 0, apd);
+ return MMSYSERR_NOTSUPPORTED;
}
+ adsi->dwDriver = (DWORD_PTR)apd;
+ adsi->fdwDriver = flags;
+
return MMSYSERR_NOERROR;
}
/* do the job */
if (adsi->fdwDriver & PCM_RESAMPLE) {
- DWORD nsrc2 = nsrc;
- DWORD ndst2 = ndst;
- apd->cvt.cvtChangeRate(adsi->pwfxSrc->nSamplesPerSec, adsh->pbSrc, &nsrc2,
- adsi->pwfxDst->nSamplesPerSec, adsh->pbDst, &ndst2);
- nsrc -= nsrc2;
- ndst -= ndst2;
+ apd->cvt.cvtChangeRate(adsi->pwfxSrc->nSamplesPerSec, adsh->pbSrc, &nsrc,
+ adsi->pwfxDst->nSamplesPerSec, adsh->pbDst, &ndst);
} else {
if (nsrc < ndst) ndst = nsrc; else nsrc = ndst;