cmd: DIR command outputs free space for the path.
[wine.git] / dlls / msacm32 / pcmconverter.c
blob0b9724ba5e12a2e3b91f815b340466d82454c750
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
3 /*
4 * MSACM32 library
6 * Copyright 2000 Eric Pouech
7 * Copyright 2004 Robert Reif
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * FIXME / TODO list
24 * + get rid of hack for PCM_DriverProc (msacm32.dll shouldn't export
25 * a DriverProc, but this would require implementing a generic
26 * embedded driver handling scheme in msacm32.dll which isn't done yet
30 #include <assert.h>
31 #include <stdarg.h>
32 #include <string.h>
34 #include "windef.h"
35 #include "winbase.h"
36 #include "mmsystem.h"
37 #define NOBITMAP
38 #include "mmreg.h"
39 #include "msacm.h"
40 #include "wingdi.h"
41 #include "winnls.h"
42 #include "winuser.h"
44 #include "msacmdrv.h"
45 #include "wineacm.h"
47 #include "wine/debug.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(msacm);
51 /***********************************************************************
52 * PCM_drvOpen
54 static DWORD PCM_drvOpen(LPCSTR str, PACMDRVOPENDESCW adod)
56 TRACE("(%p, %p)\n", str, adod);
58 return (adod == NULL) ||
59 (adod->fccType == ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC &&
60 adod->fccComp == ACMDRIVERDETAILS_FCCCOMP_UNDEFINED);
63 /***********************************************************************
64 * PCM_drvClose
66 static DWORD PCM_drvClose(DWORD dwDevID)
68 TRACE("(%ld)\n", dwDevID);
70 return 1;
73 #define NUM_OF(a,b) ((a)/(b))
75 /* flags for fdwDriver */
76 #define PCM_RESAMPLE 1
78 typedef void (*PCM_CONVERT_KEEP_RATE)(const unsigned char*, int, unsigned char*);
80 typedef void (*PCM_CONVERT_CHANGE_RATE)(const DWORD, const unsigned char*, DWORD*, const DWORD, unsigned char*, DWORD*);
82 /* data used while converting */
83 typedef struct tagAcmPcmData {
84 /* conversion routine, depending if rate conversion is required */
85 union {
86 PCM_CONVERT_KEEP_RATE cvtKeepRate;
87 PCM_CONVERT_CHANGE_RATE cvtChangeRate;
88 } cvt;
89 } AcmPcmData;
91 /* table to list all supported formats... those are the basic ones. this
92 * also helps given a unique index to each of the supported formats
94 static const struct {
95 int nChannels;
96 int nBits;
97 int rate;
98 } PCM_Formats[] = {
99 {1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000}, {1, 24, 8000}, {2, 24, 8000},
100 {1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025}, {1, 24, 11025}, {2, 24, 11025},
101 {1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050}, {1, 24, 22050}, {2, 24, 22050},
102 {1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100}, {1, 24, 44100}, {2, 24, 44100},
103 {1, 8, 48000}, {2, 8, 48000}, {1, 16, 48000}, {2, 16, 48000}, {1, 24, 48000}, {2, 24, 48000},
104 {1, 8, 96000}, {2, 8, 96000}, {1, 16, 96000}, {2, 16, 96000}, {1, 24, 96000}, {2, 24, 96000},
107 /***********************************************************************
108 * PCM_GetFormatIndex
110 static DWORD PCM_GetFormatIndex(LPWAVEFORMATEX wfx)
112 unsigned int i;
113 TRACE("(%p)\n", wfx);
115 for (i = 0; i < ARRAY_SIZE(PCM_Formats); i++) {
116 if (wfx->nChannels == PCM_Formats[i].nChannels &&
117 wfx->nSamplesPerSec == PCM_Formats[i].rate &&
118 wfx->wBitsPerSample == PCM_Formats[i].nBits)
119 return i;
121 return 0xFFFFFFFF;
124 /* PCM Conversions:
126 * parameters:
127 * + 8 bit unsigned vs 16 bit signed
128 * + mono vs stereo (1 or 2 channels)
129 * + sampling rate (8.0, 11.025, 22.05, 44.1 kHz are defined, but algo
130 * shall work in all cases)
132 * mono => stereo: copy the same sample on Left & Right channels
133 * stereo => mono: use the sum of Left & Right channels
136 /***********************************************************************
137 * C816
139 * Converts a 8 bit sample to a 16 bit one
141 static inline short C816(unsigned char b)
143 return (b - 128) << 8;
146 /***********************************************************************
147 * C168
149 * Converts a 16 bit sample to a 8 bit one (data loss !!)
151 static inline unsigned char C168(short s)
153 return HIBYTE(s) ^ (unsigned char)0x80;
156 /***********************************************************************
157 * C248
159 * Converts a 24 bit sample to a 8 bit one (data loss !!)
161 static inline unsigned char C248(int s)
163 return HIBYTE(HIWORD(s)) ^ (unsigned char)0x80;
166 /***********************************************************************
167 * C2416
169 * Converts a 24 bit sample to a 16 bit one (data loss !!)
171 static inline short C2416(int s)
173 return HIWORD(s);
176 /***********************************************************************
177 * R16
179 * Read a 16 bit sample (correctly handles endianness)
181 static inline short R16(const unsigned char* src)
183 return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));
186 /***********************************************************************
187 * R24
189 * Read a 24 bit sample (correctly handles endianness)
190 * Note, to support signed arithmetic, the values are shifted high in the int
191 * and low 8 bytes are unused.
193 static inline int R24(const unsigned char* src)
195 return ((int)src[0] | (int)src[1] << 8 | (int)src[2] << 16) << 8;
198 /***********************************************************************
199 * W16
201 * Write a 16 bit sample (correctly handles endianness)
203 static inline void W16(unsigned char* dst, short s)
205 dst[0] = LOBYTE(s);
206 dst[1] = HIBYTE(s);
209 /***********************************************************************
210 * W24
212 * Write a 24 bit sample (correctly handles endianness)
214 static inline void W24(unsigned char* dst, int s)
216 dst[0] = HIBYTE(LOWORD(s));
217 dst[1] = LOBYTE(HIWORD(s));
218 dst[2] = HIBYTE(HIWORD(s));
221 /***********************************************************************
222 * M24
224 * Convert the (l,r) 24 bit stereo sample into a 24 bit mono
225 * (takes the sum of the two values)
227 static inline int M24(int l, int r)
229 LONGLONG sum = l + r;
231 /* clip sum to saturation */
232 if (sum > 0x7fffff00)
233 sum = 0x7fffff00;
234 else if (sum < -0x7fffff00)
235 sum = -0x7fffff00;
237 return sum;
240 /***********************************************************************
241 * M16
243 * Convert the (l,r) 16 bit stereo sample into a 16 bit mono
244 * (takes the sum of the two values)
246 static inline short M16(short l, short r)
248 int sum = l + r;
250 /* clip sum to saturation */
251 if (sum > 32767)
252 sum = 32767;
253 else if (sum < -32768)
254 sum = -32768;
256 return sum;
259 /***********************************************************************
260 * M8
262 * Convert the (l,r) 8 bit stereo sample into a 8 bit mono
263 * (takes the sum of the two values)
265 static inline unsigned char M8(unsigned char a, unsigned char b)
267 int l = a - 128;
268 int r = b - 128;
269 int sum = (l + r) + 128;
271 /* clip sum to saturation */
272 if (sum > 0xff)
273 sum = 0xff;
274 else if (sum < 0)
275 sum = 0;
277 return sum;
280 /* the conversion routines without rate conversion are labelled cvt<X><Y><N><M>K
281 * where :
282 * <X> is the (M)ono/(S)tereo configuration of input channel
283 * <Y> is the (M)ono/(S)tereo configuration of output channel
284 * <N> is the number of bits of input channel (8 or 16)
285 * <M> is the number of bits of output channel (8 or 16)
287 * in the parameters, ns is always the number of samples, so the size of input
288 * buffer (resp output buffer) is ns * (<X> == 'Mono' ? 1:2) * (<N> == 8 ? 1:2)
291 static void cvtMM88K(const unsigned char* src, int ns, unsigned char* dst)
293 TRACE("(%p, %d, %p)\n", src, ns, dst);
294 memcpy(dst, src, ns);
297 static void cvtSS88K(const unsigned char* src, int ns, unsigned char* dst)
299 TRACE("(%p, %d, %p)\n", src, ns, dst);
300 memcpy(dst, src, ns * 2);
303 static void cvtMM1616K(const unsigned char* src, int ns, unsigned char* dst)
305 TRACE("(%p, %d, %p)\n", src, ns, dst);
306 memcpy(dst, src, ns * 2);
309 static void cvtSS1616K(const unsigned char* src, int ns, unsigned char* dst)
311 TRACE("(%p, %d, %p)\n", src, ns, dst);
312 memcpy(dst, src, ns * 4);
315 static void cvtMS88K(const unsigned char* src, int ns, unsigned char* dst)
317 TRACE("(%p, %d, %p)\n", src, ns, dst);
319 while (ns--) {
320 *dst++ = *src;
321 *dst++ = *src++;
325 static void cvtMS816K(const unsigned char* src, int ns, unsigned char* dst)
327 short v;
328 TRACE("(%p, %d, %p)\n", src, ns, dst);
330 while (ns--) {
331 v = C816(*src++);
332 W16(dst, v); dst += 2;
333 W16(dst, v); dst += 2;
337 static void cvtMS168K(const unsigned char* src, int ns, unsigned char* dst)
339 unsigned char v;
340 TRACE("(%p, %d, %p)\n", src, ns, dst);
342 while (ns--) {
343 v = C168(R16(src)); src += 2;
344 *dst++ = v;
345 *dst++ = v;
349 static void cvtMS1616K(const unsigned char* src, int ns, unsigned char* dst)
351 short v;
352 TRACE("(%p, %d, %p)\n", src, ns, dst);
354 while (ns--) {
355 v = R16(src); src += 2;
356 W16(dst, v); dst += 2;
357 W16(dst, v); dst += 2;
361 static void cvtSM88K(const unsigned char* src, int ns, unsigned char* dst)
363 TRACE("(%p, %d, %p)\n", src, ns, dst);
365 while (ns--) {
366 *dst++ = M8(src[0], src[1]);
367 src += 2;
371 static void cvtSM816K(const unsigned char* src, int ns, unsigned char* dst)
373 short v;
374 TRACE("(%p, %d, %p)\n", src, ns, dst);
376 while (ns--) {
377 v = M16(C816(src[0]), C816(src[1]));
378 src += 2;
379 W16(dst, v); dst += 2;
383 static void cvtSM168K(const unsigned char* src, int ns, unsigned char* dst)
385 TRACE("(%p, %d, %p)\n", src, ns, dst);
387 while (ns--) {
388 *dst++ = C168(M16(R16(src), R16(src + 2)));
389 src += 4;
393 static void cvtSM1616K(const unsigned char* src, int ns, unsigned char* dst)
395 TRACE("(%p, %d, %p)\n", src, ns, dst);
397 while (ns--) {
398 W16(dst, M16(R16(src),R16(src+2))); dst += 2;
399 src += 4;
403 static void cvtMM816K(const unsigned char* src, int ns, unsigned char* dst)
405 TRACE("(%p, %d, %p)\n", src, ns, dst);
407 while (ns--) {
408 W16(dst, C816(*src++)); dst += 2;
412 static void cvtSS816K(const unsigned char* src, int ns, unsigned char* dst)
414 TRACE("(%p, %d, %p)\n", src, ns, dst);
416 while (ns--) {
417 W16(dst, C816(*src++)); dst += 2;
418 W16(dst, C816(*src++)); dst += 2;
422 static void cvtMM168K(const unsigned char* src, int ns, unsigned char* dst)
424 TRACE("(%p, %d, %p)\n", src, ns, dst);
426 while (ns--) {
427 *dst++ = C168(R16(src)); src += 2;
431 static void cvtSS168K(const unsigned char* src, int ns, unsigned char* dst)
433 TRACE("(%p, %d, %p)\n", src, ns, dst);
435 while (ns--) {
436 *dst++ = C168(R16(src)); src += 2;
437 *dst++ = C168(R16(src)); src += 2;
441 static void cvtMS248K(const unsigned char* src, int ns, unsigned char* dst)
443 unsigned char v;
444 TRACE("(%p, %d, %p)\n", src, ns, dst);
446 while (ns--) {
447 v = C248(R24(src)); src += 3;
448 *dst++ = v;
449 *dst++ = v;
453 static void cvtSM248K(const unsigned char* src, int ns, unsigned char* dst)
455 TRACE("(%p, %d, %p)\n", src, ns, dst);
457 while (ns--) {
458 *dst++ = C248(M24(R24(src), R24(src + 3)));
459 src += 6;
463 static void cvtMM248K(const unsigned char* src, int ns, unsigned char* dst)
465 TRACE("(%p, %d, %p)\n", src, ns, dst);
467 while (ns--) {
468 *dst++ = C248(R24(src)); src += 3;
472 static void cvtSS248K(const unsigned char* src, int ns, unsigned char* dst)
474 TRACE("(%p, %d, %p)\n", src, ns, dst);
476 while (ns--) {
477 *dst++ = C248(R24(src)); src += 3;
478 *dst++ = C248(R24(src)); src += 3;
482 static void cvtMS2416K(const unsigned char* src, int ns, unsigned char* dst)
484 short v;
485 TRACE("(%p, %d, %p)\n", src, ns, dst);
487 while (ns--) {
488 v = C2416(R24(src)); src += 3;
489 W16(dst, v); dst += 2;
490 W16(dst, v); dst += 2;
494 static void cvtSM2416K(const unsigned char* src, int ns, unsigned char* dst)
496 TRACE("(%p, %d, %p)\n", src, ns, dst);
498 while (ns--) {
499 W16(dst, C2416(M24(R24(src), R24(src + 3))));
500 dst += 2;
501 src += 6;
505 static void cvtMM2416K(const unsigned char* src, int ns, unsigned char* dst)
507 TRACE("(%p, %d, %p)\n", src, ns, dst);
509 while (ns--) {
510 W16(dst, C2416(R24(src))); dst += 2; src += 3;
514 static void cvtSS2416K(const unsigned char* src, int ns, unsigned char* dst)
516 TRACE("(%p, %d, %p)\n", src, ns, dst);
518 while (ns--) {
519 W16(dst, C2416(R24(src))); dst += 2; src += 3;
520 W16(dst, C2416(R24(src))); dst += 2; src += 3;
525 static const PCM_CONVERT_KEEP_RATE PCM_ConvertKeepRate[] = {
526 cvtSS88K, cvtSM88K, cvtMS88K, cvtMM88K,
527 cvtSS816K, cvtSM816K, cvtMS816K, cvtMM816K,
528 NULL, NULL, NULL, NULL, /* TODO: 8->24 */
529 cvtSS168K, cvtSM168K, cvtMS168K, cvtMM168K,
530 cvtSS1616K, cvtSM1616K, cvtMS1616K, cvtMM1616K,
531 NULL, NULL, NULL, NULL, /* TODO: 16->24 */
532 cvtSS248K, cvtSM248K, cvtMS248K, cvtMM248K,
533 cvtSS2416K, cvtSM2416K, cvtMS2416K, cvtMM2416K,
534 NULL, NULL, NULL, NULL, /* TODO: 24->24 */
537 /* the conversion routines with rate conversion are labelled cvt<X><Y><N><M>C
538 * where :
539 * <X> is the (M)ono/(S)tereo configuration of input channel
540 * <Y> is the (M)ono/(S)tereo configuration of output channel
541 * <N> is the number of bits of input channel (8 or 16)
542 * <M> is the number of bits of output channel (8 or 16)
546 static void cvtSS88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
547 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
549 DWORD error = srcRate / 2;
550 DWORD maxSrc = *nsrc, maxDst = *ndst;
551 *ndst = 0;
552 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
553 error += dstRate;
554 while (error > srcRate) {
555 if (*ndst == maxDst)
556 return;
557 (*ndst)++;
558 error -= srcRate;
560 *dst++ = src[0];
561 *dst++ = src[1];
563 src += 2;
567 static void cvtSM88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
568 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
570 DWORD error = srcRate / 2;
571 DWORD maxSrc = *nsrc, maxDst = *ndst;
572 *ndst = 0;
573 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
574 error += dstRate;
575 while (error > srcRate) {
576 if (*ndst == maxDst)
577 return;
578 (*ndst)++;
579 error -= srcRate;
581 *dst++ = M8(src[0], src[1]);
583 src += 2;
587 static void cvtMS88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
588 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
590 DWORD error = srcRate / 2;
591 DWORD maxSrc = *nsrc, maxDst = *ndst;
592 *ndst = 0;
593 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
594 error += dstRate;
595 while (error > srcRate) {
596 if (*ndst == maxDst)
597 return;
598 (*ndst)++;
599 error -= srcRate;
601 *dst++ = src[0];
602 *dst++ = src[0];
604 src += 1;
608 static void cvtMM88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
609 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
611 DWORD error = srcRate / 2;
612 DWORD maxSrc = *nsrc, maxDst = *ndst;
613 *ndst = 0;
614 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
615 error += dstRate;
616 while (error > srcRate) {
617 if (*ndst == maxDst)
618 return;
619 (*ndst)++;
620 error -= srcRate;
622 *dst++ = src[0];
624 src += 1;
628 static void cvtSS816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
629 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
631 DWORD error = srcRate / 2;
632 DWORD maxSrc = *nsrc, maxDst = *ndst;
633 *ndst = 0;
634 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
635 error += dstRate;
636 while (error > srcRate) {
637 if (*ndst == maxDst)
638 return;
639 (*ndst)++;
640 error -= srcRate;
642 W16(dst, C816(src[0])); dst += 2;
643 W16(dst, C816(src[1])); dst += 2;
645 src += 2;
649 static void cvtSM816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
650 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
652 DWORD error = srcRate / 2;
653 DWORD maxSrc = *nsrc, maxDst = *ndst;
654 *ndst = 0;
655 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
656 error += dstRate;
657 while (error > srcRate) {
658 if (*ndst == maxDst)
659 return;
660 (*ndst)++;
661 error -= srcRate;
663 W16(dst, M16(C816(src[0]), C816(src[1]))); dst += 2;
665 src += 2;
669 static void cvtMS816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
670 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
672 DWORD error = srcRate / 2;
673 DWORD maxSrc = *nsrc, maxDst = *ndst;
674 *ndst = 0;
675 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
676 error += dstRate;
677 while (error > srcRate) {
678 if (*ndst == maxDst)
679 return;
680 (*ndst)++;
681 error -= srcRate;
683 W16(dst, C816(src[0])); dst += 2;
684 W16(dst, C816(src[0])); dst += 2;
686 src += 1;
690 static void cvtMM816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
691 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
693 DWORD error = srcRate / 2;
694 DWORD maxSrc = *nsrc, maxDst = *ndst;
695 *ndst = 0;
696 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
697 error += dstRate;
698 while (error > srcRate) {
699 if (*ndst == maxDst)
700 return;
701 (*ndst)++;
702 error -= srcRate;
704 W16(dst, C816(src[0])); dst += 2;
706 src += 1;
710 static void cvtSS168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
711 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
713 DWORD error = srcRate / 2;
714 DWORD maxSrc = *nsrc, maxDst = *ndst;
715 *ndst = 0;
716 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
717 error += dstRate;
718 while (error > srcRate) {
719 if (*ndst == maxDst)
720 return;
721 (*ndst)++;
722 error -= srcRate;
724 *dst++ = C168(R16(src));
725 *dst++ = C168(R16(src + 2));
727 src += 4;
731 static void cvtSM168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
732 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
734 DWORD error = srcRate / 2;
735 DWORD maxSrc = *nsrc, maxDst = *ndst;
736 *ndst = 0;
737 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
738 error += dstRate;
739 while (error > srcRate) {
740 if (*ndst == maxDst)
741 return;
742 (*ndst)++;
743 error -= srcRate;
745 *dst++ = C168(M16(R16(src), R16(src + 2)));
747 src += 4;
751 static void cvtMS168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
752 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
754 DWORD error = srcRate / 2;
755 DWORD maxSrc = *nsrc, maxDst = *ndst;
756 *ndst = 0;
757 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
758 error += dstRate;
759 while (error > srcRate) {
760 if (*ndst == maxDst)
761 return;
762 (*ndst)++;
763 error -= srcRate;
765 *dst++ = C168(R16(src));
766 *dst++ = C168(R16(src));
768 src += 2;
772 static void cvtMM168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
773 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
775 DWORD error = srcRate / 2;
776 DWORD maxSrc = *nsrc, maxDst = *ndst;
777 *ndst = 0;
778 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
779 error += dstRate;
780 while (error > srcRate) {
781 if (*ndst == maxDst)
782 return;
783 (*ndst)++;
784 error -= srcRate;
786 *dst++ = C168(R16(src));
788 src += 2;
792 static void cvtSS1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
793 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
795 DWORD error = srcRate / 2;
796 DWORD maxSrc = *nsrc, maxDst = *ndst;
797 *ndst = 0;
798 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
799 error += dstRate;
800 while (error > srcRate) {
801 if (*ndst == maxDst)
802 return;
803 (*ndst)++;
804 error -= srcRate;
806 W16(dst, R16(src)); dst += 2;
807 W16(dst, R16(src + 2)); dst += 2;
809 src += 4;
813 static void cvtSM1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
814 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
816 DWORD error = srcRate / 2;
817 DWORD maxSrc = *nsrc, maxDst = *ndst;
818 *ndst = 0;
819 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
820 error += dstRate;
821 while (error > srcRate) {
822 if (*ndst == maxDst)
823 return;
824 (*ndst)++;
825 error -= srcRate;
827 W16(dst, M16(R16(src), R16(src + 2))); dst += 2;
829 src += 4;
833 static void cvtMS1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
834 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
836 DWORD error = srcRate / 2;
837 DWORD maxSrc = *nsrc, maxDst = *ndst;
838 *ndst = 0;
839 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
840 error += dstRate;
841 while (error > srcRate) {
842 if (*ndst == maxDst)
843 return;
844 (*ndst)++;
845 error -= srcRate;
847 W16(dst, R16(src)); dst += 2;
848 W16(dst, R16(src)); dst += 2;
850 src += 2;
854 static void cvtMM1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
855 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
857 DWORD error = srcRate / 2;
858 DWORD maxSrc = *nsrc, maxDst = *ndst;
859 *ndst = 0;
860 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
861 error += dstRate;
862 while (error > srcRate) {
863 if (*ndst == maxDst)
864 return;
865 (*ndst)++;
866 error -= srcRate;
868 W16(dst, R16(src)); dst += 2;
870 src += 2;
874 static void cvtSS2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
875 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
877 DWORD error = srcRate / 2;
878 DWORD maxSrc = *nsrc, maxDst = *ndst;
879 *ndst = 0;
880 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
881 error += dstRate;
882 while (error > srcRate) {
883 if (*ndst == maxDst)
884 return;
885 (*ndst)++;
886 error -= srcRate;
888 W24(dst, R24(src)); dst += 3;
889 W24(dst, R24(src + 3)); dst += 3;
891 src += 6;
895 static void cvtSM2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
896 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
898 DWORD error = srcRate / 2;
899 DWORD maxSrc = *nsrc, maxDst = *ndst;
900 *ndst = 0;
901 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
902 error += dstRate;
903 while (error > srcRate) {
904 if (*ndst == maxDst)
905 return;
906 (*ndst)++;
907 error -= srcRate;
909 W24(dst, M24(R24(src), R24(src + 3))); dst += 3;
911 src += 6;
915 static void cvtMS2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
916 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
918 DWORD error = srcRate / 2;
919 DWORD maxSrc = *nsrc, maxDst = *ndst;
920 *ndst = 0;
921 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
922 error += dstRate;
923 while (error > srcRate) {
924 if (*ndst == maxDst)
925 return;
926 (*ndst)++;
927 error -= srcRate;
929 W24(dst, R24(src)); dst += 3;
930 W24(dst, R24(src)); dst += 3;
932 src += 3;
936 static void cvtMM2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
937 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
939 DWORD error = srcRate / 2;
940 DWORD maxSrc = *nsrc, maxDst = *ndst;
941 *ndst = 0;
942 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
943 error += dstRate;
944 while (error > srcRate) {
945 if (*ndst == maxDst)
946 return;
947 (*ndst)++;
948 error -= srcRate;
950 W24(dst, R24(src)); dst += 3;
952 src += 3;
956 static const PCM_CONVERT_CHANGE_RATE PCM_ConvertChangeRate[] = {
957 cvtSS88C, cvtSM88C, cvtMS88C, cvtMM88C,
958 cvtSS816C, cvtSM816C, cvtMS816C, cvtMM816C,
959 NULL, NULL, NULL, NULL, /* TODO: 8->24 */
960 cvtSS168C, cvtSM168C, cvtMS168C, cvtMM168C,
961 cvtSS1616C, cvtSM1616C, cvtMS1616C, cvtMM1616C,
962 NULL, NULL, NULL, NULL, /* TODO: 16->24 */
963 NULL, NULL, NULL, NULL, /* TODO: 24->8 */
964 NULL, NULL, NULL, NULL, /* TODO: 24->16 */
965 cvtSS2424C, cvtSM2424C, cvtMS2424C, cvtMM2424C,
968 /***********************************************************************
969 * PCM_DriverDetails
972 static LRESULT PCM_DriverDetails(PACMDRIVERDETAILSW add)
974 TRACE("(%p)\n", add);
976 add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
977 add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
978 add->wMid = MM_MICROSOFT;
979 add->wPid = MM_MSFT_ACM_PCM;
980 add->vdwACM = 0x01000000;
981 add->vdwDriver = 0x01000000;
982 add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CONVERTER;
983 add->cFormatTags = 1;
984 add->cFilterTags = 0;
985 add->hicon = NULL;
986 MultiByteToWideChar(CP_ACP, 0, "MS-PCM", -1, add->szShortName, ARRAY_SIZE(add->szShortName));
987 MultiByteToWideChar(CP_ACP, 0, "Wine PCM converter", -1,
988 add->szLongName, ARRAY_SIZE(add->szLongName));
989 MultiByteToWideChar(CP_ACP, 0, "Brought to you by the Wine team...", -1,
990 add->szCopyright, ARRAY_SIZE(add->szCopyright));
991 MultiByteToWideChar(CP_ACP, 0, "Refer to LICENSE file", -1,
992 add->szLicensing, ARRAY_SIZE(add->szLicensing) );
993 add->szFeatures[0] = 0;
995 return MMSYSERR_NOERROR;
998 /***********************************************************************
999 * PCM_FormatTagDetails
1002 static LRESULT PCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
1004 TRACE("(%p, %08lx)\n", aftd, dwQuery);
1006 switch (dwQuery) {
1007 case ACM_FORMATTAGDETAILSF_INDEX:
1008 if (aftd->dwFormatTagIndex != 0) {
1009 WARN("not possible\n");
1010 return ACMERR_NOTPOSSIBLE;
1012 break;
1013 case ACM_FORMATTAGDETAILSF_FORMATTAG:
1014 if (aftd->dwFormatTag != WAVE_FORMAT_PCM) {
1015 WARN("not possible\n");
1016 return ACMERR_NOTPOSSIBLE;
1018 break;
1019 case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
1020 if (aftd->dwFormatTag != WAVE_FORMAT_UNKNOWN &&
1021 aftd->dwFormatTag != WAVE_FORMAT_PCM) {
1022 WARN("not possible\n");
1023 return ACMERR_NOTPOSSIBLE;
1025 break;
1026 default:
1027 WARN("Unsupported query %08lx\n", dwQuery);
1028 return MMSYSERR_NOTSUPPORTED;
1031 aftd->dwFormatTagIndex = 0;
1032 aftd->dwFormatTag = WAVE_FORMAT_PCM;
1033 aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
1034 aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CONVERTER;
1035 aftd->cStandardFormats = ARRAY_SIZE(PCM_Formats);
1036 aftd->szFormatTag[0] = 0;
1038 return MMSYSERR_NOERROR;
1041 /***********************************************************************
1042 * PCM_FormatDetails
1045 static LRESULT PCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
1047 TRACE("(%p, %08lx)\n", afd, dwQuery);
1049 switch (dwQuery) {
1050 case ACM_FORMATDETAILSF_FORMAT:
1051 if (PCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) {
1052 WARN("not possible\n");
1053 return ACMERR_NOTPOSSIBLE;
1055 break;
1056 case ACM_FORMATDETAILSF_INDEX:
1057 assert(afd->dwFormatIndex < ARRAY_SIZE(PCM_Formats));
1058 afd->pwfx->wFormatTag = WAVE_FORMAT_PCM;
1059 afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
1060 afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
1061 afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
1062 /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not
1063 * accessible afd->pwfx->cbSize = 0;
1065 afd->pwfx->nBlockAlign =
1066 (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8;
1067 afd->pwfx->nAvgBytesPerSec =
1068 afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
1069 break;
1070 default:
1071 WARN("Unsupported query %08lx\n", dwQuery);
1072 return MMSYSERR_NOTSUPPORTED;
1075 afd->dwFormatTag = WAVE_FORMAT_PCM;
1076 afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CONVERTER;
1077 afd->szFormat[0] = 0; /* let MSACM format this for us... */
1078 afd->cbwfx = sizeof(PCMWAVEFORMAT);
1080 return MMSYSERR_NOERROR;
1083 /***********************************************************************
1084 * PCM_FormatSuggest
1087 static LRESULT PCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
1089 TRACE("(%p)\n", adfs);
1091 /* some tests ... */
1092 if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
1093 adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
1094 PCM_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) {
1095 WARN("not possible\n");
1096 return ACMERR_NOTPOSSIBLE;
1099 /* is no suggestion for destination, then copy source value */
1100 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS)) {
1101 adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
1103 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC)) {
1104 adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
1106 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE)) {
1107 adfs->pwfxDst->wBitsPerSample = adfs->pwfxSrc->wBitsPerSample;
1109 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG)) {
1110 if (adfs->pwfxSrc->wFormatTag != WAVE_FORMAT_PCM) {
1111 WARN("source format 0x%x not supported\n", adfs->pwfxSrc->wFormatTag);
1112 return ACMERR_NOTPOSSIBLE;
1114 adfs->pwfxDst->wFormatTag = adfs->pwfxSrc->wFormatTag;
1115 } else {
1116 if (adfs->pwfxDst->wFormatTag != WAVE_FORMAT_PCM) {
1117 WARN("destination format 0x%x not supported\n", adfs->pwfxDst->wFormatTag);
1118 return ACMERR_NOTPOSSIBLE;
1121 /* check if result is ok */
1122 if (PCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) {
1123 WARN("not possible\n");
1124 return ACMERR_NOTPOSSIBLE;
1127 /* recompute other values */
1128 adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8;
1129 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
1131 return MMSYSERR_NOERROR;
1134 /***********************************************************************
1135 * PCM_StreamOpen
1138 static LRESULT PCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
1140 AcmPcmData* apd;
1141 int idx;
1142 DWORD flags;
1144 TRACE("(%p)\n", adsi);
1146 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
1148 switch(adsi->pwfxSrc->wBitsPerSample){
1149 case 8:
1150 idx = 0;
1151 break;
1152 case 16:
1153 idx = 12;
1154 break;
1155 case 24:
1156 if (adsi->pwfxSrc->nBlockAlign != 3 * adsi->pwfxSrc->nChannels) {
1157 FIXME("Source: 24-bit samples must be packed\n");
1158 return MMSYSERR_NOTSUPPORTED;
1160 idx = 24;
1161 break;
1162 default:
1163 FIXME("Unsupported source bit depth: %u\n", adsi->pwfxSrc->wBitsPerSample);
1164 return MMSYSERR_NOTSUPPORTED;
1167 switch(adsi->pwfxDst->wBitsPerSample){
1168 case 8:
1169 break;
1170 case 16:
1171 idx += 4;
1172 break;
1173 case 24:
1174 if (adsi->pwfxDst->nBlockAlign != 3 * adsi->pwfxDst->nChannels) {
1175 FIXME("Destination: 24-bit samples must be packed\n");
1176 return MMSYSERR_NOTSUPPORTED;
1178 idx += 8;
1179 break;
1180 default:
1181 FIXME("Unsupported destination bit depth: %u\n", adsi->pwfxDst->wBitsPerSample);
1182 return MMSYSERR_NOTSUPPORTED;
1185 if (adsi->pwfxSrc->nChannels == 1) idx += 2;
1187 if (adsi->pwfxDst->nChannels == 1) idx += 1;
1189 apd = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmPcmData));
1190 if (!apd)
1191 return MMSYSERR_NOMEM;
1193 if (adsi->pwfxSrc->nSamplesPerSec == adsi->pwfxDst->nSamplesPerSec) {
1194 flags = 0;
1195 apd->cvt.cvtKeepRate = PCM_ConvertKeepRate[idx];
1196 } else {
1197 flags = PCM_RESAMPLE;
1198 apd->cvt.cvtChangeRate = PCM_ConvertChangeRate[idx];
1201 if(!apd->cvt.cvtChangeRate && !apd->cvt.cvtKeepRate){
1202 FIXME("Unimplemented conversion from %u -> %u bps\n",
1203 adsi->pwfxSrc->wBitsPerSample,
1204 adsi->pwfxDst->wBitsPerSample);
1205 HeapFree(GetProcessHeap(), 0, apd);
1206 return MMSYSERR_NOTSUPPORTED;
1209 adsi->dwDriver = (DWORD_PTR)apd;
1210 adsi->fdwDriver = flags;
1212 return MMSYSERR_NOERROR;
1215 /***********************************************************************
1216 * PCM_StreamClose
1219 static LRESULT PCM_StreamClose(PACMDRVSTREAMINSTANCE adsi)
1221 TRACE("(%p)\n", adsi);
1223 HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
1224 return MMSYSERR_NOERROR;
1227 /***********************************************************************
1228 * PCM_round
1231 static inline DWORD PCM_round(DWORD a, DWORD b, DWORD c)
1233 assert(c);
1234 /* to be sure, always return an entire number of c... */
1235 return ((double)a * (double)b + (double)c - 1) / (double)c;
1238 /***********************************************************************
1239 * PCM_StreamSize
1242 static LRESULT PCM_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss)
1244 DWORD srcMask = ~(adsi->pwfxSrc->nBlockAlign - 1);
1245 DWORD dstMask = ~(adsi->pwfxDst->nBlockAlign - 1);
1247 TRACE("(%p, %p)\n", adsi, adss);
1249 switch (adss->fdwSize) {
1250 case ACM_STREAMSIZEF_DESTINATION:
1251 /* cbDstLength => cbSrcLength */
1252 adss->cbSrcLength = PCM_round(adss->cbDstLength & dstMask,
1253 adsi->pwfxSrc->nAvgBytesPerSec,
1254 adsi->pwfxDst->nAvgBytesPerSec) & srcMask;
1255 break;
1256 case ACM_STREAMSIZEF_SOURCE:
1257 /* cbSrcLength => cbDstLength */
1258 adss->cbDstLength = PCM_round(adss->cbSrcLength & srcMask,
1259 adsi->pwfxDst->nAvgBytesPerSec,
1260 adsi->pwfxSrc->nAvgBytesPerSec) & dstMask;
1261 break;
1262 default:
1263 WARN("Unsupported query %08lx\n", adss->fdwSize);
1264 return MMSYSERR_NOTSUPPORTED;
1266 return MMSYSERR_NOERROR;
1269 /***********************************************************************
1270 * PCM_StreamConvert
1273 static LRESULT PCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
1275 AcmPcmData* apd = (AcmPcmData*)adsi->dwDriver;
1276 DWORD nsrc = NUM_OF(adsh->cbSrcLength, adsi->pwfxSrc->nBlockAlign);
1277 DWORD ndst = NUM_OF(adsh->cbDstLength, adsi->pwfxDst->nBlockAlign);
1279 TRACE("(%p, %p)\n", adsi, adsh);
1281 TRACE("nsrc=%ld,adsh->cbSrcLength=%ld\n", nsrc, adsh->cbSrcLength);
1282 TRACE("ndst=%ld,adsh->cbDstLength=%ld\n", ndst, adsh->cbDstLength);
1283 TRACE("src [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n",
1284 adsi->pwfxSrc->wFormatTag, adsi->pwfxSrc->nChannels, adsi->pwfxSrc->nSamplesPerSec, adsi->pwfxSrc->nAvgBytesPerSec,
1285 adsi->pwfxSrc->nBlockAlign, adsi->pwfxSrc->wBitsPerSample, adsi->pwfxSrc->cbSize);
1286 TRACE("dst [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n",
1287 adsi->pwfxDst->wFormatTag, adsi->pwfxDst->nChannels, adsi->pwfxDst->nSamplesPerSec, adsi->pwfxDst->nAvgBytesPerSec,
1288 adsi->pwfxDst->nBlockAlign, adsi->pwfxDst->wBitsPerSample, adsi->pwfxDst->cbSize);
1290 if (adsh->fdwConvert &
1291 ~(ACM_STREAMCONVERTF_BLOCKALIGN|
1292 ACM_STREAMCONVERTF_END|
1293 ACM_STREAMCONVERTF_START)) {
1294 FIXME("Unsupported fdwConvert (%08lx), ignoring it\n", adsh->fdwConvert);
1296 /* ACM_STREAMCONVERTF_BLOCKALIGN
1297 * currently all conversions are block aligned, so do nothing for this flag
1298 * ACM_STREAMCONVERTF_END
1299 * no pending data, so do nothing for this flag
1301 if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START) &&
1302 (adsi->fdwDriver & PCM_RESAMPLE)) {
1305 /* do the job */
1306 if (adsi->fdwDriver & PCM_RESAMPLE) {
1307 apd->cvt.cvtChangeRate(adsi->pwfxSrc->nSamplesPerSec, adsh->pbSrc, &nsrc,
1308 adsi->pwfxDst->nSamplesPerSec, adsh->pbDst, &ndst);
1309 } else {
1310 if (nsrc < ndst) ndst = nsrc; else nsrc = ndst;
1312 /* nsrc is now equal to ndst */
1313 apd->cvt.cvtKeepRate(adsh->pbSrc, nsrc, adsh->pbDst);
1316 adsh->cbSrcLengthUsed = nsrc * adsi->pwfxSrc->nBlockAlign;
1317 adsh->cbDstLengthUsed = ndst * adsi->pwfxDst->nBlockAlign;
1319 return MMSYSERR_NOERROR;
1322 /**************************************************************************
1323 * DriverProc (MSACM32.@)
1325 LRESULT CALLBACK PCM_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
1326 LPARAM dwParam1, LPARAM dwParam2)
1328 TRACE("(%08Ix %p %u %08Ix %08Ix);\n",
1329 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1331 switch (wMsg) {
1332 case DRV_LOAD: return 1;
1333 case DRV_FREE: return 1;
1334 case DRV_OPEN: return PCM_drvOpen((LPSTR)dwParam1, (PACMDRVOPENDESCW)dwParam2);
1335 case DRV_CLOSE: return PCM_drvClose(dwDevID);
1336 case DRV_ENABLE: return 1;
1337 case DRV_DISABLE: return 1;
1338 case DRV_QUERYCONFIGURE: return 1;
1339 case DRV_CONFIGURE: MessageBoxA(0, "MSACM PCM filter !", "Wine Driver", MB_OK); return 1;
1340 case DRV_INSTALL: return DRVCNF_RESTART;
1341 case DRV_REMOVE: return DRVCNF_RESTART;
1343 case ACMDM_DRIVER_NOTIFY:
1344 /* no caching from other ACM drivers is done so far */
1345 return MMSYSERR_NOERROR;
1347 case ACMDM_DRIVER_DETAILS:
1348 return PCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
1350 case ACMDM_FORMATTAG_DETAILS:
1351 return PCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
1353 case ACMDM_FORMAT_DETAILS:
1354 return PCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
1356 case ACMDM_FORMAT_SUGGEST:
1357 return PCM_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
1359 case ACMDM_STREAM_OPEN:
1360 return PCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
1362 case ACMDM_STREAM_CLOSE:
1363 return PCM_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
1365 case ACMDM_STREAM_SIZE:
1366 return PCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
1368 case ACMDM_STREAM_CONVERT:
1369 return PCM_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
1371 case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
1372 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
1373 /* this converter is not a hardware driver */
1374 case ACMDM_FILTERTAG_DETAILS:
1375 case ACMDM_FILTER_DETAILS:
1376 /* this converter is not a filter */
1377 case ACMDM_STREAM_RESET:
1378 /* only needed for asynchronous driver... we aren't, so just say it */
1379 case ACMDM_STREAM_PREPARE:
1380 case ACMDM_STREAM_UNPREPARE:
1381 /* nothing special to do here... so don't do anything */
1382 return MMSYSERR_NOTSUPPORTED;
1384 default:
1385 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);