[MSACM32] Sync with Wine Staging 4.0. CORE-15682
[reactos.git] / dll / win32 / msacm32 / pcmconverter.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2
3 /*
4 * MSACM32 library
5 *
6 * Copyright 2000 Eric Pouech
7 * Copyright 2004 Robert Reif
8 *
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.
13 *
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.
18 *
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
22 *
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
27 */
28
29 #include "config.h"
30
31 #include <assert.h>
32 #include <stdarg.h>
33 #include <string.h>
34
35 #include "windef.h"
36 #include "winbase.h"
37 #include "mmsystem.h"
38 #define NOBITMAP
39 #include "mmreg.h"
40 #include "msacm.h"
41 #include "wingdi.h"
42 #include "winnls.h"
43 #include "winuser.h"
44
45 #include "msacmdrv.h"
46 #include "wineacm.h"
47
48 #include "wine/debug.h"
49
50 WINE_DEFAULT_DEBUG_CHANNEL(msacm);
51
52 /***********************************************************************
53 * PCM_drvOpen
54 */
55 static DWORD PCM_drvOpen(LPCSTR str, PACMDRVOPENDESCW adod)
56 {
57 TRACE("(%p, %p)\n", str, adod);
58
59 return (adod == NULL) ||
60 (adod->fccType == ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC &&
61 adod->fccComp == ACMDRIVERDETAILS_FCCCOMP_UNDEFINED);
62 }
63
64 /***********************************************************************
65 * PCM_drvClose
66 */
67 static DWORD PCM_drvClose(DWORD dwDevID)
68 {
69 TRACE("(%d)\n", dwDevID);
70
71 return 1;
72 }
73
74 #define NUM_OF(a,b) ((a)/(b))
75
76 /* flags for fdwDriver */
77 #define PCM_RESAMPLE 1
78
79 typedef void (*PCM_CONVERT_KEEP_RATE)(const unsigned char*, int, unsigned char*);
80
81 typedef void (*PCM_CONVERT_CHANGE_RATE)(const DWORD, const unsigned char*, DWORD*, const DWORD, unsigned char*, DWORD*);
82
83 /* data used while converting */
84 typedef struct tagAcmPcmData {
85 /* conversion routine, depending if rate conversion is required */
86 union {
87 PCM_CONVERT_KEEP_RATE cvtKeepRate;
88 PCM_CONVERT_CHANGE_RATE cvtChangeRate;
89 } cvt;
90 } AcmPcmData;
91
92 /* table to list all supported formats... those are the basic ones. this
93 * also helps given a unique index to each of the supported formats
94 */
95 static const struct {
96 int nChannels;
97 int nBits;
98 int rate;
99 } PCM_Formats[] = {
100 {1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000}, {1, 24, 8000}, {2, 24, 8000},
101 {1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025}, {1, 24, 11025}, {2, 24, 11025},
102 {1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050}, {1, 24, 22050}, {2, 24, 22050},
103 {1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100}, {1, 24, 44100}, {2, 24, 44100},
104 {1, 8, 48000}, {2, 8, 48000}, {1, 16, 48000}, {2, 16, 48000}, {1, 24, 48000}, {2, 24, 48000},
105 {1, 8, 96000}, {2, 8, 96000}, {1, 16, 96000}, {2, 16, 96000}, {1, 24, 96000}, {2, 24, 96000},
106 };
107
108 /***********************************************************************
109 * PCM_GetFormatIndex
110 */
111 static DWORD PCM_GetFormatIndex(LPWAVEFORMATEX wfx)
112 {
113 unsigned int i;
114 TRACE("(%p)\n", wfx);
115
116 for (i = 0; i < ARRAY_SIZE(PCM_Formats); i++) {
117 if (wfx->nChannels == PCM_Formats[i].nChannels &&
118 wfx->nSamplesPerSec == PCM_Formats[i].rate &&
119 wfx->wBitsPerSample == PCM_Formats[i].nBits)
120 return i;
121 }
122 return 0xFFFFFFFF;
123 }
124
125 /* PCM Conversions:
126 *
127 * parameters:
128 * + 8 bit unsigned vs 16 bit signed
129 * + mono vs stereo (1 or 2 channels)
130 * + sampling rate (8.0, 11.025, 22.05, 44.1 kHz are defined, but algo
131 * shall work in all cases)
132 *
133 * mono => stereo: copy the same sample on Left & Right channels
134 * stereo => mono: use the sum of Left & Right channels
135 */
136
137 /***********************************************************************
138 * C816
139 *
140 * Converts a 8 bit sample to a 16 bit one
141 */
142 static inline short C816(unsigned char b)
143 {
144 return (b - 128) << 8;
145 }
146
147 /***********************************************************************
148 * C168
149 *
150 * Converts a 16 bit sample to a 8 bit one (data loss !!)
151 */
152 static inline unsigned char C168(short s)
153 {
154 return HIBYTE(s) ^ (unsigned char)0x80;
155 }
156
157 /***********************************************************************
158 * C248
159 *
160 * Converts a 24 bit sample to a 8 bit one (data loss !!)
161 */
162 static inline unsigned char C248(int s)
163 {
164 return HIBYTE(HIWORD(s)) ^ (unsigned char)0x80;
165 }
166
167 /***********************************************************************
168 * C2416
169 *
170 * Converts a 24 bit sample to a 16 bit one (data loss !!)
171 */
172 static inline short C2416(int s)
173 {
174 return HIWORD(s);
175 }
176
177 /***********************************************************************
178 * R16
179 *
180 * Read a 16 bit sample (correctly handles endianness)
181 */
182 static inline short R16(const unsigned char* src)
183 {
184 return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));
185 }
186
187 /***********************************************************************
188 * R24
189 *
190 * Read a 24 bit sample (correctly handles endianness)
191 * Note, to support signed arithmetic, the values are shifted high in the int
192 * and low 8 bytes are unused.
193 */
194 static inline int R24(const unsigned char* src)
195 {
196 return ((int)src[0] | (int)src[1] << 8 | (int)src[2] << 16) << 8;
197 }
198
199 /***********************************************************************
200 * W16
201 *
202 * Write a 16 bit sample (correctly handles endianness)
203 */
204 static inline void W16(unsigned char* dst, short s)
205 {
206 dst[0] = LOBYTE(s);
207 dst[1] = HIBYTE(s);
208 }
209
210 /***********************************************************************
211 * W24
212 *
213 * Write a 24 bit sample (correctly handles endianness)
214 */
215 static inline void W24(unsigned char* dst, int s)
216 {
217 dst[0] = HIBYTE(LOWORD(s));
218 dst[1] = LOBYTE(HIWORD(s));
219 dst[2] = HIBYTE(HIWORD(s));
220 }
221
222 /***********************************************************************
223 * M24
224 *
225 * Convert the (l,r) 24 bit stereo sample into a 24 bit mono
226 * (takes the sum of the two values)
227 */
228 static inline int M24(int l, int r)
229 {
230 LONGLONG sum = l + r;
231
232 /* clip sum to saturation */
233 if (sum > 0x7fffff00)
234 sum = 0x7fffff00;
235 else if (sum < -0x7fffff00)
236 sum = -0x7fffff00;
237
238 return sum;
239 }
240
241 /***********************************************************************
242 * M16
243 *
244 * Convert the (l,r) 16 bit stereo sample into a 16 bit mono
245 * (takes the sum of the two values)
246 */
247 static inline short M16(short l, short r)
248 {
249 int sum = l + r;
250
251 /* clip sum to saturation */
252 if (sum > 32767)
253 sum = 32767;
254 else if (sum < -32768)
255 sum = -32768;
256
257 return sum;
258 }
259
260 /***********************************************************************
261 * M8
262 *
263 * Convert the (l,r) 8 bit stereo sample into a 8 bit mono
264 * (takes the sum of the two values)
265 */
266 static inline unsigned char M8(unsigned char a, unsigned char b)
267 {
268 int l = a - 128;
269 int r = b - 128;
270 int sum = (l + r) + 128;
271
272 /* clip sum to saturation */
273 if (sum > 0xff)
274 sum = 0xff;
275 else if (sum < 0)
276 sum = 0;
277
278 return sum;
279 }
280
281 /* the conversion routines without rate conversion are labelled cvt<X><Y><N><M>K
282 * where :
283 * <X> is the (M)ono/(S)tereo configuration of input channel
284 * <Y> is the (M)ono/(S)tereo configuration of output channel
285 * <N> is the number of bits of input channel (8 or 16)
286 * <M> is the number of bits of output channel (8 or 16)
287 *
288 * in the parameters, ns is always the number of samples, so the size of input
289 * buffer (resp output buffer) is ns * (<X> == 'Mono' ? 1:2) * (<N> == 8 ? 1:2)
290 */
291
292 static void cvtMM88K(const unsigned char* src, int ns, unsigned char* dst)
293 {
294 TRACE("(%p, %d, %p)\n", src, ns, dst);
295 memcpy(dst, src, ns);
296 }
297
298 static void cvtSS88K(const unsigned char* src, int ns, unsigned char* dst)
299 {
300 TRACE("(%p, %d, %p)\n", src, ns, dst);
301 memcpy(dst, src, ns * 2);
302 }
303
304 static void cvtMM1616K(const unsigned char* src, int ns, unsigned char* dst)
305 {
306 TRACE("(%p, %d, %p)\n", src, ns, dst);
307 memcpy(dst, src, ns * 2);
308 }
309
310 static void cvtSS1616K(const unsigned char* src, int ns, unsigned char* dst)
311 {
312 TRACE("(%p, %d, %p)\n", src, ns, dst);
313 memcpy(dst, src, ns * 4);
314 }
315
316 static void cvtMS88K(const unsigned char* src, int ns, unsigned char* dst)
317 {
318 TRACE("(%p, %d, %p)\n", src, ns, dst);
319
320 while (ns--) {
321 *dst++ = *src;
322 *dst++ = *src++;
323 }
324 }
325
326 static void cvtMS816K(const unsigned char* src, int ns, unsigned char* dst)
327 {
328 short v;
329 TRACE("(%p, %d, %p)\n", src, ns, dst);
330
331 while (ns--) {
332 v = C816(*src++);
333 W16(dst, v); dst += 2;
334 W16(dst, v); dst += 2;
335 }
336 }
337
338 static void cvtMS168K(const unsigned char* src, int ns, unsigned char* dst)
339 {
340 unsigned char v;
341 TRACE("(%p, %d, %p)\n", src, ns, dst);
342
343 while (ns--) {
344 v = C168(R16(src)); src += 2;
345 *dst++ = v;
346 *dst++ = v;
347 }
348 }
349
350 static void cvtMS1616K(const unsigned char* src, int ns, unsigned char* dst)
351 {
352 short v;
353 TRACE("(%p, %d, %p)\n", src, ns, dst);
354
355 while (ns--) {
356 v = R16(src); src += 2;
357 W16(dst, v); dst += 2;
358 W16(dst, v); dst += 2;
359 }
360 }
361
362 static void cvtSM88K(const unsigned char* src, int ns, unsigned char* dst)
363 {
364 TRACE("(%p, %d, %p)\n", src, ns, dst);
365
366 while (ns--) {
367 *dst++ = M8(src[0], src[1]);
368 src += 2;
369 }
370 }
371
372 static void cvtSM816K(const unsigned char* src, int ns, unsigned char* dst)
373 {
374 short v;
375 TRACE("(%p, %d, %p)\n", src, ns, dst);
376
377 while (ns--) {
378 v = M16(C816(src[0]), C816(src[1]));
379 src += 2;
380 W16(dst, v); dst += 2;
381 }
382 }
383
384 static void cvtSM168K(const unsigned char* src, int ns, unsigned char* dst)
385 {
386 TRACE("(%p, %d, %p)\n", src, ns, dst);
387
388 while (ns--) {
389 *dst++ = C168(M16(R16(src), R16(src + 2)));
390 src += 4;
391 }
392 }
393
394 static void cvtSM1616K(const unsigned char* src, int ns, unsigned char* dst)
395 {
396 TRACE("(%p, %d, %p)\n", src, ns, dst);
397
398 while (ns--) {
399 W16(dst, M16(R16(src),R16(src+2))); dst += 2;
400 src += 4;
401 }
402 }
403
404 static void cvtMM816K(const unsigned char* src, int ns, unsigned char* dst)
405 {
406 TRACE("(%p, %d, %p)\n", src, ns, dst);
407
408 while (ns--) {
409 W16(dst, C816(*src++)); dst += 2;
410 }
411 }
412
413 static void cvtSS816K(const unsigned char* src, int ns, unsigned char* dst)
414 {
415 TRACE("(%p, %d, %p)\n", src, ns, dst);
416
417 while (ns--) {
418 W16(dst, C816(*src++)); dst += 2;
419 W16(dst, C816(*src++)); dst += 2;
420 }
421 }
422
423 static void cvtMM168K(const unsigned char* src, int ns, unsigned char* dst)
424 {
425 TRACE("(%p, %d, %p)\n", src, ns, dst);
426
427 while (ns--) {
428 *dst++ = C168(R16(src)); src += 2;
429 }
430 }
431
432 static void cvtSS168K(const unsigned char* src, int ns, unsigned char* dst)
433 {
434 TRACE("(%p, %d, %p)\n", src, ns, dst);
435
436 while (ns--) {
437 *dst++ = C168(R16(src)); src += 2;
438 *dst++ = C168(R16(src)); src += 2;
439 }
440 }
441
442 static void cvtMS248K(const unsigned char* src, int ns, unsigned char* dst)
443 {
444 unsigned char v;
445 TRACE("(%p, %d, %p)\n", src, ns, dst);
446
447 while (ns--) {
448 v = C248(R24(src)); src += 3;
449 *dst++ = v;
450 *dst++ = v;
451 }
452 }
453
454 static void cvtSM248K(const unsigned char* src, int ns, unsigned char* dst)
455 {
456 TRACE("(%p, %d, %p)\n", src, ns, dst);
457
458 while (ns--) {
459 *dst++ = C248(M24(R24(src), R24(src + 3)));
460 src += 6;
461 }
462 }
463
464 static void cvtMM248K(const unsigned char* src, int ns, unsigned char* dst)
465 {
466 TRACE("(%p, %d, %p)\n", src, ns, dst);
467
468 while (ns--) {
469 *dst++ = C248(R24(src)); src += 3;
470 }
471 }
472
473 static void cvtSS248K(const unsigned char* src, int ns, unsigned char* dst)
474 {
475 TRACE("(%p, %d, %p)\n", src, ns, dst);
476
477 while (ns--) {
478 *dst++ = C248(R24(src)); src += 3;
479 *dst++ = C248(R24(src)); src += 3;
480 }
481 }
482
483 static void cvtMS2416K(const unsigned char* src, int ns, unsigned char* dst)
484 {
485 short v;
486 TRACE("(%p, %d, %p)\n", src, ns, dst);
487
488 while (ns--) {
489 v = C2416(R24(src)); src += 3;
490 W16(dst, v); dst += 2;
491 W16(dst, v); dst += 2;
492 }
493 }
494
495 static void cvtSM2416K(const unsigned char* src, int ns, unsigned char* dst)
496 {
497 TRACE("(%p, %d, %p)\n", src, ns, dst);
498
499 while (ns--) {
500 W16(dst, C2416(M24(R24(src), R24(src + 3))));
501 dst += 2;
502 src += 6;
503 }
504 }
505
506 static void cvtMM2416K(const unsigned char* src, int ns, unsigned char* dst)
507 {
508 TRACE("(%p, %d, %p)\n", src, ns, dst);
509
510 while (ns--) {
511 W16(dst, C2416(R24(src))); dst += 2; src += 3;
512 }
513 }
514
515 static void cvtSS2416K(const unsigned char* src, int ns, unsigned char* dst)
516 {
517 TRACE("(%p, %d, %p)\n", src, ns, dst);
518
519 while (ns--) {
520 W16(dst, C2416(R24(src))); dst += 2; src += 3;
521 W16(dst, C2416(R24(src))); dst += 2; src += 3;
522 }
523 }
524
525
526 static const PCM_CONVERT_KEEP_RATE PCM_ConvertKeepRate[] = {
527 cvtSS88K, cvtSM88K, cvtMS88K, cvtMM88K,
528 cvtSS816K, cvtSM816K, cvtMS816K, cvtMM816K,
529 NULL, NULL, NULL, NULL, /* TODO: 8->24 */
530 cvtSS168K, cvtSM168K, cvtMS168K, cvtMM168K,
531 cvtSS1616K, cvtSM1616K, cvtMS1616K, cvtMM1616K,
532 NULL, NULL, NULL, NULL, /* TODO: 16->24 */
533 cvtSS248K, cvtSM248K, cvtMS248K, cvtMM248K,
534 cvtSS2416K, cvtSM2416K, cvtMS2416K, cvtMM2416K,
535 NULL, NULL, NULL, NULL, /* TODO: 24->24 */
536 };
537
538 /* the conversion routines with rate conversion are labelled cvt<X><Y><N><M>C
539 * where :
540 * <X> is the (M)ono/(S)tereo configuration of input channel
541 * <Y> is the (M)ono/(S)tereo configuration of output channel
542 * <N> is the number of bits of input channel (8 or 16)
543 * <M> is the number of bits of output channel (8 or 16)
544 *
545 */
546
547 static void cvtSS88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
548 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
549 {
550 DWORD error = srcRate / 2;
551 DWORD maxSrc = *nsrc, maxDst = *ndst;
552 *ndst = 0;
553 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
554 error += dstRate;
555 while (error > srcRate) {
556 if (*ndst == maxDst)
557 return;
558 (*ndst)++;
559 error -= srcRate;
560
561 *dst++ = src[0];
562 *dst++ = src[1];
563 }
564 src += 2;
565 }
566 }
567
568 static void cvtSM88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
569 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
570 {
571 DWORD error = srcRate / 2;
572 DWORD maxSrc = *nsrc, maxDst = *ndst;
573 *ndst = 0;
574 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
575 error += dstRate;
576 while (error > srcRate) {
577 if (*ndst == maxDst)
578 return;
579 (*ndst)++;
580 error -= srcRate;
581
582 *dst++ = M8(src[0], src[1]);
583 }
584 src += 2;
585 }
586 }
587
588 static void cvtMS88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
589 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
590 {
591 DWORD error = srcRate / 2;
592 DWORD maxSrc = *nsrc, maxDst = *ndst;
593 *ndst = 0;
594 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
595 error += dstRate;
596 while (error > srcRate) {
597 if (*ndst == maxDst)
598 return;
599 (*ndst)++;
600 error -= srcRate;
601
602 *dst++ = src[0];
603 *dst++ = src[0];
604 }
605 src += 1;
606 }
607 }
608
609 static void cvtMM88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
610 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
611 {
612 DWORD error = srcRate / 2;
613 DWORD maxSrc = *nsrc, maxDst = *ndst;
614 *ndst = 0;
615 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
616 error += dstRate;
617 while (error > srcRate) {
618 if (*ndst == maxDst)
619 return;
620 (*ndst)++;
621 error -= srcRate;
622
623 *dst++ = src[0];
624 }
625 src += 1;
626 }
627 }
628
629 static void cvtSS816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
630 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
631 {
632 DWORD error = srcRate / 2;
633 DWORD maxSrc = *nsrc, maxDst = *ndst;
634 *ndst = 0;
635 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
636 error += dstRate;
637 while (error > srcRate) {
638 if (*ndst == maxDst)
639 return;
640 (*ndst)++;
641 error -= srcRate;
642
643 W16(dst, C816(src[0])); dst += 2;
644 W16(dst, C816(src[1])); dst += 2;
645 }
646 src += 2;
647 }
648 }
649
650 static void cvtSM816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
651 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
652 {
653 DWORD error = srcRate / 2;
654 DWORD maxSrc = *nsrc, maxDst = *ndst;
655 *ndst = 0;
656 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
657 error += dstRate;
658 while (error > srcRate) {
659 if (*ndst == maxDst)
660 return;
661 (*ndst)++;
662 error -= srcRate;
663
664 W16(dst, M16(C816(src[0]), C816(src[1]))); dst += 2;
665 }
666 src += 2;
667 }
668 }
669
670 static void cvtMS816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
671 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
672 {
673 DWORD error = srcRate / 2;
674 DWORD maxSrc = *nsrc, maxDst = *ndst;
675 *ndst = 0;
676 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
677 error += dstRate;
678 while (error > srcRate) {
679 if (*ndst == maxDst)
680 return;
681 (*ndst)++;
682 error -= srcRate;
683
684 W16(dst, C816(src[0])); dst += 2;
685 W16(dst, C816(src[0])); dst += 2;
686 }
687 src += 1;
688 }
689 }
690
691 static void cvtMM816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
692 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
693 {
694 DWORD error = srcRate / 2;
695 DWORD maxSrc = *nsrc, maxDst = *ndst;
696 *ndst = 0;
697 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
698 error += dstRate;
699 while (error > srcRate) {
700 if (*ndst == maxDst)
701 return;
702 (*ndst)++;
703 error -= srcRate;
704
705 W16(dst, C816(src[0])); dst += 2;
706 }
707 src += 1;
708 }
709 }
710
711 static void cvtSS168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
712 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
713 {
714 DWORD error = srcRate / 2;
715 DWORD maxSrc = *nsrc, maxDst = *ndst;
716 *ndst = 0;
717 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
718 error += dstRate;
719 while (error > srcRate) {
720 if (*ndst == maxDst)
721 return;
722 (*ndst)++;
723 error -= srcRate;
724
725 *dst++ = C168(R16(src));
726 *dst++ = C168(R16(src + 2));
727 }
728 src += 4;
729 }
730 }
731
732 static void cvtSM168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
733 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
734 {
735 DWORD error = srcRate / 2;
736 DWORD maxSrc = *nsrc, maxDst = *ndst;
737 *ndst = 0;
738 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
739 error += dstRate;
740 while (error > srcRate) {
741 if (*ndst == maxDst)
742 return;
743 (*ndst)++;
744 error -= srcRate;
745
746 *dst++ = C168(M16(R16(src), R16(src + 2)));
747 }
748 src += 4;
749 }
750 }
751
752 static void cvtMS168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
753 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
754 {
755 DWORD error = srcRate / 2;
756 DWORD maxSrc = *nsrc, maxDst = *ndst;
757 *ndst = 0;
758 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
759 error += dstRate;
760 while (error > srcRate) {
761 if (*ndst == maxDst)
762 return;
763 (*ndst)++;
764 error -= srcRate;
765
766 *dst++ = C168(R16(src));
767 *dst++ = C168(R16(src));
768 }
769 src += 2;
770 }
771 }
772
773 static void cvtMM168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
774 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
775 {
776 DWORD error = srcRate / 2;
777 DWORD maxSrc = *nsrc, maxDst = *ndst;
778 *ndst = 0;
779 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
780 error += dstRate;
781 while (error > srcRate) {
782 if (*ndst == maxDst)
783 return;
784 (*ndst)++;
785 error -= srcRate;
786
787 *dst++ = C168(R16(src));
788 }
789 src += 2;
790 }
791 }
792
793 static void cvtSS1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
794 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
795 {
796 DWORD error = srcRate / 2;
797 DWORD maxSrc = *nsrc, maxDst = *ndst;
798 *ndst = 0;
799 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
800 error += dstRate;
801 while (error > srcRate) {
802 if (*ndst == maxDst)
803 return;
804 (*ndst)++;
805 error -= srcRate;
806
807 W16(dst, R16(src)); dst += 2;
808 W16(dst, R16(src + 2)); dst += 2;
809 }
810 src += 4;
811 }
812 }
813
814 static void cvtSM1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
815 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
816 {
817 DWORD error = srcRate / 2;
818 DWORD maxSrc = *nsrc, maxDst = *ndst;
819 *ndst = 0;
820 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
821 error += dstRate;
822 while (error > srcRate) {
823 if (*ndst == maxDst)
824 return;
825 (*ndst)++;
826 error -= srcRate;
827
828 W16(dst, M16(R16(src), R16(src + 2))); dst += 2;
829 }
830 src += 4;
831 }
832 }
833
834 static void cvtMS1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
835 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
836 {
837 DWORD error = srcRate / 2;
838 DWORD maxSrc = *nsrc, maxDst = *ndst;
839 *ndst = 0;
840 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
841 error += dstRate;
842 while (error > srcRate) {
843 if (*ndst == maxDst)
844 return;
845 (*ndst)++;
846 error -= srcRate;
847
848 W16(dst, R16(src)); dst += 2;
849 W16(dst, R16(src)); dst += 2;
850 }
851 src += 2;
852 }
853 }
854
855 static void cvtMM1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
856 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
857 {
858 DWORD error = srcRate / 2;
859 DWORD maxSrc = *nsrc, maxDst = *ndst;
860 *ndst = 0;
861 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
862 error += dstRate;
863 while (error > srcRate) {
864 if (*ndst == maxDst)
865 return;
866 (*ndst)++;
867 error -= srcRate;
868
869 W16(dst, R16(src)); dst += 2;
870 }
871 src += 2;
872 }
873 }
874
875 static void cvtSS2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
876 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
877 {
878 DWORD error = srcRate / 2;
879 DWORD maxSrc = *nsrc, maxDst = *ndst;
880 *ndst = 0;
881 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
882 error += dstRate;
883 while (error > srcRate) {
884 if (*ndst == maxDst)
885 return;
886 (*ndst)++;
887 error -= srcRate;
888
889 W24(dst, R24(src)); dst += 3;
890 W24(dst, R24(src + 3)); dst += 3;
891 }
892 src += 6;
893 }
894 }
895
896 static void cvtSM2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
897 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
898 {
899 DWORD error = srcRate / 2;
900 DWORD maxSrc = *nsrc, maxDst = *ndst;
901 *ndst = 0;
902 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
903 error += dstRate;
904 while (error > srcRate) {
905 if (*ndst == maxDst)
906 return;
907 (*ndst)++;
908 error -= srcRate;
909
910 W24(dst, M24(R24(src), R24(src + 3))); dst += 3;
911 }
912 src += 6;
913 }
914 }
915
916 static void cvtMS2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
917 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
918 {
919 DWORD error = srcRate / 2;
920 DWORD maxSrc = *nsrc, maxDst = *ndst;
921 *ndst = 0;
922 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
923 error += dstRate;
924 while (error > srcRate) {
925 if (*ndst == maxDst)
926 return;
927 (*ndst)++;
928 error -= srcRate;
929
930 W24(dst, R24(src)); dst += 3;
931 W24(dst, R24(src)); dst += 3;
932 }
933 src += 3;
934 }
935 }
936
937 static void cvtMM2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
938 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
939 {
940 DWORD error = srcRate / 2;
941 DWORD maxSrc = *nsrc, maxDst = *ndst;
942 *ndst = 0;
943 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) {
944 error += dstRate;
945 while (error > srcRate) {
946 if (*ndst == maxDst)
947 return;
948 (*ndst)++;
949 error -= srcRate;
950
951 W24(dst, R24(src)); dst += 3;
952 }
953 src += 3;
954 }
955 }
956
957 static const PCM_CONVERT_CHANGE_RATE PCM_ConvertChangeRate[] = {
958 cvtSS88C, cvtSM88C, cvtMS88C, cvtMM88C,
959 cvtSS816C, cvtSM816C, cvtMS816C, cvtMM816C,
960 NULL, NULL, NULL, NULL, /* TODO: 8->24 */
961 cvtSS168C, cvtSM168C, cvtMS168C, cvtMM168C,
962 cvtSS1616C, cvtSM1616C, cvtMS1616C, cvtMM1616C,
963 NULL, NULL, NULL, NULL, /* TODO: 16->24 */
964 NULL, NULL, NULL, NULL, /* TODO: 24->8 */
965 NULL, NULL, NULL, NULL, /* TODO: 24->16 */
966 cvtSS2424C, cvtSM2424C, cvtMS2424C, cvtMM2424C,
967 };
968
969 /***********************************************************************
970 * PCM_DriverDetails
971 *
972 */
973 static LRESULT PCM_DriverDetails(PACMDRIVERDETAILSW add)
974 {
975 TRACE("(%p)\n", add);
976
977 add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
978 add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
979 add->wMid = MM_MICROSOFT;
980 add->wPid = MM_MSFT_ACM_PCM;
981 add->vdwACM = 0x01000000;
982 add->vdwDriver = 0x01000000;
983 add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CONVERTER;
984 add->cFormatTags = 1;
985 add->cFilterTags = 0;
986 add->hicon = NULL;
987 MultiByteToWideChar(CP_ACP, 0, "MS-PCM", -1, add->szShortName, ARRAY_SIZE(add->szShortName));
988 MultiByteToWideChar(CP_ACP, 0, "Wine PCM converter", -1,
989 add->szLongName, ARRAY_SIZE(add->szLongName));
990 MultiByteToWideChar(CP_ACP, 0, "Brought to you by the Wine team...", -1,
991 add->szCopyright, ARRAY_SIZE(add->szCopyright));
992 MultiByteToWideChar(CP_ACP, 0, "Refer to LICENSE file", -1,
993 add->szLicensing, ARRAY_SIZE(add->szLicensing) );
994 add->szFeatures[0] = 0;
995
996 return MMSYSERR_NOERROR;
997 }
998
999 /***********************************************************************
1000 * PCM_FormatTagDetails
1001 *
1002 */
1003 static LRESULT PCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
1004 {
1005 TRACE("(%p, %08x)\n", aftd, dwQuery);
1006
1007 switch (dwQuery) {
1008 case ACM_FORMATTAGDETAILSF_INDEX:
1009 if (aftd->dwFormatTagIndex != 0) {
1010 WARN("not possible\n");
1011 return ACMERR_NOTPOSSIBLE;
1012 }
1013 break;
1014 case ACM_FORMATTAGDETAILSF_FORMATTAG:
1015 if (aftd->dwFormatTag != WAVE_FORMAT_PCM) {
1016 WARN("not possible\n");
1017 return ACMERR_NOTPOSSIBLE;
1018 }
1019 break;
1020 case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
1021 if (aftd->dwFormatTag != WAVE_FORMAT_UNKNOWN &&
1022 aftd->dwFormatTag != WAVE_FORMAT_PCM) {
1023 WARN("not possible\n");
1024 return ACMERR_NOTPOSSIBLE;
1025 }
1026 break;
1027 default:
1028 WARN("Unsupported query %08x\n", dwQuery);
1029 return MMSYSERR_NOTSUPPORTED;
1030 }
1031
1032 aftd->dwFormatTagIndex = 0;
1033 aftd->dwFormatTag = WAVE_FORMAT_PCM;
1034 aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
1035 aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CONVERTER;
1036 aftd->cStandardFormats = ARRAY_SIZE(PCM_Formats);
1037 aftd->szFormatTag[0] = 0;
1038
1039 return MMSYSERR_NOERROR;
1040 }
1041
1042 /***********************************************************************
1043 * PCM_FormatDetails
1044 *
1045 */
1046 static LRESULT PCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
1047 {
1048 TRACE("(%p, %08x)\n", afd, dwQuery);
1049
1050 switch (dwQuery) {
1051 case ACM_FORMATDETAILSF_FORMAT:
1052 if (PCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) {
1053 WARN("not possible\n");
1054 return ACMERR_NOTPOSSIBLE;
1055 }
1056 break;
1057 case ACM_FORMATDETAILSF_INDEX:
1058 assert(afd->dwFormatIndex < ARRAY_SIZE(PCM_Formats));
1059 afd->pwfx->wFormatTag = WAVE_FORMAT_PCM;
1060 afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
1061 afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
1062 afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
1063 /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not
1064 * accessible afd->pwfx->cbSize = 0;
1065 */
1066 afd->pwfx->nBlockAlign =
1067 (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8;
1068 afd->pwfx->nAvgBytesPerSec =
1069 afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
1070 break;
1071 default:
1072 WARN("Unsupported query %08x\n", dwQuery);
1073 return MMSYSERR_NOTSUPPORTED;
1074 }
1075
1076 afd->dwFormatTag = WAVE_FORMAT_PCM;
1077 afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CONVERTER;
1078 afd->szFormat[0] = 0; /* let MSACM format this for us... */
1079 afd->cbwfx = sizeof(PCMWAVEFORMAT);
1080
1081 return MMSYSERR_NOERROR;
1082 }
1083
1084 /***********************************************************************
1085 * PCM_FormatSuggest
1086 *
1087 */
1088 static LRESULT PCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
1089 {
1090 TRACE("(%p)\n", adfs);
1091
1092 /* some tests ... */
1093 if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
1094 adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
1095 PCM_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) {
1096 WARN("not possible\n");
1097 return ACMERR_NOTPOSSIBLE;
1098 }
1099
1100 /* is no suggestion for destination, then copy source value */
1101 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS)) {
1102 adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
1103 }
1104 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC)) {
1105 adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
1106 }
1107 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE)) {
1108 adfs->pwfxDst->wBitsPerSample = adfs->pwfxSrc->wBitsPerSample;
1109 }
1110 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG)) {
1111 if (adfs->pwfxSrc->wFormatTag != WAVE_FORMAT_PCM) {
1112 WARN("source format 0x%x not supported\n", adfs->pwfxSrc->wFormatTag);
1113 return ACMERR_NOTPOSSIBLE;
1114 }
1115 adfs->pwfxDst->wFormatTag = adfs->pwfxSrc->wFormatTag;
1116 } else {
1117 if (adfs->pwfxDst->wFormatTag != WAVE_FORMAT_PCM) {
1118 WARN("destination format 0x%x not supported\n", adfs->pwfxDst->wFormatTag);
1119 return ACMERR_NOTPOSSIBLE;
1120 }
1121 }
1122 /* check if result is ok */
1123 if (PCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) {
1124 WARN("not possible\n");
1125 return ACMERR_NOTPOSSIBLE;
1126 }
1127
1128 /* recompute other values */
1129 adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8;
1130 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
1131
1132 return MMSYSERR_NOERROR;
1133 }
1134
1135 /***********************************************************************
1136 * PCM_StreamOpen
1137 *
1138 */
1139 static LRESULT PCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
1140 {
1141 AcmPcmData* apd;
1142 int idx;
1143 DWORD flags;
1144
1145 TRACE("(%p)\n", adsi);
1146
1147 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
1148
1149 switch(adsi->pwfxSrc->wBitsPerSample){
1150 case 8:
1151 idx = 0;
1152 break;
1153 case 16:
1154 idx = 12;
1155 break;
1156 case 24:
1157 if (adsi->pwfxSrc->nBlockAlign != 3 * adsi->pwfxSrc->nChannels) {
1158 FIXME("Source: 24-bit samples must be packed\n");
1159 return MMSYSERR_NOTSUPPORTED;
1160 }
1161 idx = 24;
1162 break;
1163 default:
1164 FIXME("Unsupported source bit depth: %u\n", adsi->pwfxSrc->wBitsPerSample);
1165 return MMSYSERR_NOTSUPPORTED;
1166 }
1167
1168 switch(adsi->pwfxDst->wBitsPerSample){
1169 case 8:
1170 break;
1171 case 16:
1172 idx += 4;
1173 break;
1174 case 24:
1175 if (adsi->pwfxDst->nBlockAlign != 3 * adsi->pwfxDst->nChannels) {
1176 FIXME("Destination: 24-bit samples must be packed\n");
1177 return MMSYSERR_NOTSUPPORTED;
1178 }
1179 idx += 8;
1180 break;
1181 default:
1182 FIXME("Unsupported destination bit depth: %u\n", adsi->pwfxDst->wBitsPerSample);
1183 return MMSYSERR_NOTSUPPORTED;
1184 }
1185
1186 if (adsi->pwfxSrc->nChannels == 1) idx += 2;
1187
1188 if (adsi->pwfxDst->nChannels == 1) idx += 1;
1189
1190 apd = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmPcmData));
1191 if (!apd)
1192 return MMSYSERR_NOMEM;
1193
1194 if (adsi->pwfxSrc->nSamplesPerSec == adsi->pwfxDst->nSamplesPerSec) {
1195 flags = 0;
1196 apd->cvt.cvtKeepRate = PCM_ConvertKeepRate[idx];
1197 } else {
1198 flags = PCM_RESAMPLE;
1199 apd->cvt.cvtChangeRate = PCM_ConvertChangeRate[idx];
1200 }
1201
1202 if(!apd->cvt.cvtChangeRate && !apd->cvt.cvtKeepRate){
1203 FIXME("Unimplemented conversion from %u -> %u bps\n",
1204 adsi->pwfxSrc->wBitsPerSample,
1205 adsi->pwfxDst->wBitsPerSample);
1206 HeapFree(GetProcessHeap(), 0, apd);
1207 return MMSYSERR_NOTSUPPORTED;
1208 }
1209
1210 adsi->dwDriver = (DWORD_PTR)apd;
1211 adsi->fdwDriver = flags;
1212
1213 return MMSYSERR_NOERROR;
1214 }
1215
1216 /***********************************************************************
1217 * PCM_StreamClose
1218 *
1219 */
1220 static LRESULT PCM_StreamClose(PACMDRVSTREAMINSTANCE adsi)
1221 {
1222 TRACE("(%p)\n", adsi);
1223
1224 HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
1225 return MMSYSERR_NOERROR;
1226 }
1227
1228 /***********************************************************************
1229 * PCM_round
1230 *
1231 */
1232 static inline DWORD PCM_round(DWORD a, DWORD b, DWORD c)
1233 {
1234 assert(c);
1235 /* to be sure, always return an entire number of c... */
1236 return ((double)a * (double)b + (double)c - 1) / (double)c;
1237 }
1238
1239 /***********************************************************************
1240 * PCM_StreamSize
1241 *
1242 */
1243 static LRESULT PCM_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss)
1244 {
1245 DWORD srcMask = ~(adsi->pwfxSrc->nBlockAlign - 1);
1246 DWORD dstMask = ~(adsi->pwfxDst->nBlockAlign - 1);
1247
1248 TRACE("(%p, %p)\n", adsi, adss);
1249
1250 switch (adss->fdwSize) {
1251 case ACM_STREAMSIZEF_DESTINATION:
1252 /* cbDstLength => cbSrcLength */
1253 adss->cbSrcLength = PCM_round(adss->cbDstLength & dstMask,
1254 adsi->pwfxSrc->nAvgBytesPerSec,
1255 adsi->pwfxDst->nAvgBytesPerSec) & srcMask;
1256 break;
1257 case ACM_STREAMSIZEF_SOURCE:
1258 /* cbSrcLength => cbDstLength */
1259 adss->cbDstLength = PCM_round(adss->cbSrcLength & srcMask,
1260 adsi->pwfxDst->nAvgBytesPerSec,
1261 adsi->pwfxSrc->nAvgBytesPerSec) & dstMask;
1262 break;
1263 default:
1264 WARN("Unsupported query %08x\n", adss->fdwSize);
1265 return MMSYSERR_NOTSUPPORTED;
1266 }
1267 return MMSYSERR_NOERROR;
1268 }
1269
1270 /***********************************************************************
1271 * PCM_StreamConvert
1272 *
1273 */
1274 static LRESULT PCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
1275 {
1276 AcmPcmData* apd = (AcmPcmData*)adsi->dwDriver;
1277 DWORD nsrc = NUM_OF(adsh->cbSrcLength, adsi->pwfxSrc->nBlockAlign);
1278 DWORD ndst = NUM_OF(adsh->cbDstLength, adsi->pwfxDst->nBlockAlign);
1279
1280 TRACE("(%p, %p)\n", adsi, adsh);
1281
1282 TRACE("nsrc=%d,adsh->cbSrcLength=%d\n", nsrc, adsh->cbSrcLength);
1283 TRACE("ndst=%d,adsh->cbDstLength=%d\n", ndst, adsh->cbDstLength);
1284 TRACE("src [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%u, nAvgBytesPerSec=%u, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n",
1285 adsi->pwfxSrc->wFormatTag, adsi->pwfxSrc->nChannels, adsi->pwfxSrc->nSamplesPerSec, adsi->pwfxSrc->nAvgBytesPerSec,
1286 adsi->pwfxSrc->nBlockAlign, adsi->pwfxSrc->wBitsPerSample, adsi->pwfxSrc->cbSize);
1287 TRACE("dst [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%u, nAvgBytesPerSec=%u, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n",
1288 adsi->pwfxDst->wFormatTag, adsi->pwfxDst->nChannels, adsi->pwfxDst->nSamplesPerSec, adsi->pwfxDst->nAvgBytesPerSec,
1289 adsi->pwfxDst->nBlockAlign, adsi->pwfxDst->wBitsPerSample, adsi->pwfxDst->cbSize);
1290
1291 if (adsh->fdwConvert &
1292 ~(ACM_STREAMCONVERTF_BLOCKALIGN|
1293 ACM_STREAMCONVERTF_END|
1294 ACM_STREAMCONVERTF_START)) {
1295 FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert);
1296 }
1297 /* ACM_STREAMCONVERTF_BLOCKALIGN
1298 * currently all conversions are block aligned, so do nothing for this flag
1299 * ACM_STREAMCONVERTF_END
1300 * no pending data, so do nothing for this flag
1301 */
1302 if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START) &&
1303 (adsi->fdwDriver & PCM_RESAMPLE)) {
1304 }
1305
1306 /* do the job */
1307 if (adsi->fdwDriver & PCM_RESAMPLE) {
1308 apd->cvt.cvtChangeRate(adsi->pwfxSrc->nSamplesPerSec, adsh->pbSrc, &nsrc,
1309 adsi->pwfxDst->nSamplesPerSec, adsh->pbDst, &ndst);
1310 } else {
1311 if (nsrc < ndst) ndst = nsrc; else nsrc = ndst;
1312
1313 /* nsrc is now equal to ndst */
1314 apd->cvt.cvtKeepRate(adsh->pbSrc, nsrc, adsh->pbDst);
1315 }
1316
1317 adsh->cbSrcLengthUsed = nsrc * adsi->pwfxSrc->nBlockAlign;
1318 adsh->cbDstLengthUsed = ndst * adsi->pwfxDst->nBlockAlign;
1319
1320 return MMSYSERR_NOERROR;
1321 }
1322
1323 /**************************************************************************
1324 * DriverProc (MSACM32.@)
1325 */
1326 LRESULT CALLBACK PCM_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
1327 LPARAM dwParam1, LPARAM dwParam2)
1328 {
1329 TRACE("(%08lx %p %u %08lx %08lx);\n",
1330 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1331
1332 switch (wMsg) {
1333 case DRV_LOAD: return 1;
1334 case DRV_FREE: return 1;
1335 case DRV_OPEN: return PCM_drvOpen((LPSTR)dwParam1, (PACMDRVOPENDESCW)dwParam2);
1336 case DRV_CLOSE: return PCM_drvClose(dwDevID);
1337 case DRV_ENABLE: return 1;
1338 case DRV_DISABLE: return 1;
1339 case DRV_QUERYCONFIGURE: return 1;
1340 case DRV_CONFIGURE: MessageBoxA(0, "MSACM PCM filter !", "Wine Driver", MB_OK); return 1;
1341 case DRV_INSTALL: return DRVCNF_RESTART;
1342 case DRV_REMOVE: return DRVCNF_RESTART;
1343
1344 case ACMDM_DRIVER_NOTIFY:
1345 /* no caching from other ACM drivers is done so far */
1346 return MMSYSERR_NOERROR;
1347
1348 case ACMDM_DRIVER_DETAILS:
1349 return PCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
1350
1351 case ACMDM_FORMATTAG_DETAILS:
1352 return PCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
1353
1354 case ACMDM_FORMAT_DETAILS:
1355 return PCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
1356
1357 case ACMDM_FORMAT_SUGGEST:
1358 return PCM_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
1359
1360 case ACMDM_STREAM_OPEN:
1361 return PCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
1362
1363 case ACMDM_STREAM_CLOSE:
1364 return PCM_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
1365
1366 case ACMDM_STREAM_SIZE:
1367 return PCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
1368
1369 case ACMDM_STREAM_CONVERT:
1370 return PCM_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
1371
1372 case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
1373 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
1374 /* this converter is not a hardware driver */
1375 case ACMDM_FILTERTAG_DETAILS:
1376 case ACMDM_FILTER_DETAILS:
1377 /* this converter is not a filter */
1378 case ACMDM_STREAM_RESET:
1379 /* only needed for asynchronous driver... we aren't, so just say it */
1380 case ACMDM_STREAM_PREPARE:
1381 case ACMDM_STREAM_UNPREPARE:
1382 /* nothing special to do here... so don't do anything */
1383 return MMSYSERR_NOTSUPPORTED;
1384
1385 default:
1386 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1387 }
1388 }