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