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
30 #include <assert.h>
31 #include <stdarg.h>
32 #include <string.h>
33
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"
43
44 #include "msacmdrv.h"
45 #include "wineacm.h"
46
47 #include "wine/debug.h"
48
49 WINE_DEFAULT_DEBUG_CHANNEL(msacm);
50
51 /***********************************************************************
52 * PCM_drvOpen
53 */
PCM_drvOpen(LPCSTR str,PACMDRVOPENDESCW adod)54 static DWORD PCM_drvOpen(LPCSTR str, PACMDRVOPENDESCW adod)
55 {
56 TRACE("(%p, %p)\n", str, adod);
57
58 return (adod == NULL) ||
59 (adod->fccType == ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC &&
60 adod->fccComp == ACMDRIVERDETAILS_FCCCOMP_UNDEFINED);
61 }
62
63 /***********************************************************************
64 * PCM_drvClose
65 */
PCM_drvClose(DWORD dwDevID)66 static DWORD PCM_drvClose(DWORD dwDevID)
67 {
68 TRACE("(%d)\n", dwDevID);
69
70 return 1;
71 }
72
73 #define NUM_OF(a,b) ((a)/(b))
74
75 /* flags for fdwDriver */
76 #define PCM_RESAMPLE 1
77
78 typedef void (*PCM_CONVERT_KEEP_RATE)(const unsigned char*, int, unsigned char*);
79
80 typedef void (*PCM_CONVERT_CHANGE_RATE)(const DWORD, const unsigned char*, DWORD*, const DWORD, unsigned char*, DWORD*);
81
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;
90
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
93 */
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},
105 };
106
107 /***********************************************************************
108 * PCM_GetFormatIndex
109 */
PCM_GetFormatIndex(LPWAVEFORMATEX wfx)110 static DWORD PCM_GetFormatIndex(LPWAVEFORMATEX wfx)
111 {
112 unsigned int i;
113 TRACE("(%p)\n", wfx);
114
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;
120 }
121 return 0xFFFFFFFF;
122 }
123
124 /* PCM Conversions:
125 *
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)
131 *
132 * mono => stereo: copy the same sample on Left & Right channels
133 * stereo => mono: use the sum of Left & Right channels
134 */
135
136 /***********************************************************************
137 * C816
138 *
139 * Converts a 8 bit sample to a 16 bit one
140 */
C816(unsigned char b)141 static inline short C816(unsigned char b)
142 {
143 return (b - 128) << 8;
144 }
145
146 /***********************************************************************
147 * C168
148 *
149 * Converts a 16 bit sample to a 8 bit one (data loss !!)
150 */
C168(short s)151 static inline unsigned char C168(short s)
152 {
153 return HIBYTE(s) ^ (unsigned char)0x80;
154 }
155
156 /***********************************************************************
157 * C248
158 *
159 * Converts a 24 bit sample to a 8 bit one (data loss !!)
160 */
C248(int s)161 static inline unsigned char C248(int s)
162 {
163 return HIBYTE(HIWORD(s)) ^ (unsigned char)0x80;
164 }
165
166 /***********************************************************************
167 * C2416
168 *
169 * Converts a 24 bit sample to a 16 bit one (data loss !!)
170 */
C2416(int s)171 static inline short C2416(int s)
172 {
173 return HIWORD(s);
174 }
175
176 /***********************************************************************
177 * R16
178 *
179 * Read a 16 bit sample (correctly handles endianness)
180 */
R16(const unsigned char * src)181 static inline short R16(const unsigned char* src)
182 {
183 return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));
184 }
185
186 /***********************************************************************
187 * R24
188 *
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.
192 */
R24(const unsigned char * src)193 static inline int R24(const unsigned char* src)
194 {
195 return ((int)src[0] | (int)src[1] << 8 | (int)src[2] << 16) << 8;
196 }
197
198 /***********************************************************************
199 * W16
200 *
201 * Write a 16 bit sample (correctly handles endianness)
202 */
W16(unsigned char * dst,short s)203 static inline void W16(unsigned char* dst, short s)
204 {
205 dst[0] = LOBYTE(s);
206 dst[1] = HIBYTE(s);
207 }
208
209 /***********************************************************************
210 * W24
211 *
212 * Write a 24 bit sample (correctly handles endianness)
213 */
W24(unsigned char * dst,int s)214 static inline void W24(unsigned char* dst, int s)
215 {
216 dst[0] = HIBYTE(LOWORD(s));
217 dst[1] = LOBYTE(HIWORD(s));
218 dst[2] = HIBYTE(HIWORD(s));
219 }
220
221 /***********************************************************************
222 * M24
223 *
224 * Convert the (l,r) 24 bit stereo sample into a 24 bit mono
225 * (takes the sum of the two values)
226 */
M24(int l,int r)227 static inline int M24(int l, int r)
228 {
229 LONGLONG sum = l + r;
230
231 /* clip sum to saturation */
232 if (sum > 0x7fffff00)
233 sum = 0x7fffff00;
234 else if (sum < -0x7fffff00)
235 sum = -0x7fffff00;
236
237 return sum;
238 }
239
240 /***********************************************************************
241 * M16
242 *
243 * Convert the (l,r) 16 bit stereo sample into a 16 bit mono
244 * (takes the sum of the two values)
245 */
M16(short l,short r)246 static inline short M16(short l, short r)
247 {
248 int sum = l + r;
249
250 /* clip sum to saturation */
251 if (sum > 32767)
252 sum = 32767;
253 else if (sum < -32768)
254 sum = -32768;
255
256 return sum;
257 }
258
259 /***********************************************************************
260 * M8
261 *
262 * Convert the (l,r) 8 bit stereo sample into a 8 bit mono
263 * (takes the sum of the two values)
264 */
M8(unsigned char a,unsigned char b)265 static inline unsigned char M8(unsigned char a, unsigned char b)
266 {
267 int l = a - 128;
268 int r = b - 128;
269 int sum = (l + r) + 128;
270
271 /* clip sum to saturation */
272 if (sum > 0xff)
273 sum = 0xff;
274 else if (sum < 0)
275 sum = 0;
276
277 return sum;
278 }
279
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)
286 *
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)
289 */
290
cvtMM88K(const unsigned char * src,int ns,unsigned char * dst)291 static void cvtMM88K(const unsigned char* src, int ns, unsigned char* dst)
292 {
293 TRACE("(%p, %d, %p)\n", src, ns, dst);
294 memcpy(dst, src, ns);
295 }
296
cvtSS88K(const unsigned char * src,int ns,unsigned char * dst)297 static void cvtSS88K(const unsigned char* src, int ns, unsigned char* dst)
298 {
299 TRACE("(%p, %d, %p)\n", src, ns, dst);
300 memcpy(dst, src, ns * 2);
301 }
302
cvtMM1616K(const unsigned char * src,int ns,unsigned char * dst)303 static void cvtMM1616K(const unsigned char* src, int ns, unsigned char* dst)
304 {
305 TRACE("(%p, %d, %p)\n", src, ns, dst);
306 memcpy(dst, src, ns * 2);
307 }
308
cvtSS1616K(const unsigned char * src,int ns,unsigned char * dst)309 static void cvtSS1616K(const unsigned char* src, int ns, unsigned char* dst)
310 {
311 TRACE("(%p, %d, %p)\n", src, ns, dst);
312 memcpy(dst, src, ns * 4);
313 }
314
cvtMS88K(const unsigned char * src,int ns,unsigned char * dst)315 static void cvtMS88K(const unsigned char* src, int ns, unsigned char* dst)
316 {
317 TRACE("(%p, %d, %p)\n", src, ns, dst);
318
319 while (ns--) {
320 *dst++ = *src;
321 *dst++ = *src++;
322 }
323 }
324
cvtMS816K(const unsigned char * src,int ns,unsigned char * dst)325 static void cvtMS816K(const unsigned char* src, int ns, unsigned char* dst)
326 {
327 short v;
328 TRACE("(%p, %d, %p)\n", src, ns, dst);
329
330 while (ns--) {
331 v = C816(*src++);
332 W16(dst, v); dst += 2;
333 W16(dst, v); dst += 2;
334 }
335 }
336
cvtMS168K(const unsigned char * src,int ns,unsigned char * dst)337 static void cvtMS168K(const unsigned char* src, int ns, unsigned char* dst)
338 {
339 unsigned char v;
340 TRACE("(%p, %d, %p)\n", src, ns, dst);
341
342 while (ns--) {
343 v = C168(R16(src)); src += 2;
344 *dst++ = v;
345 *dst++ = v;
346 }
347 }
348
cvtMS1616K(const unsigned char * src,int ns,unsigned char * dst)349 static void cvtMS1616K(const unsigned char* src, int ns, unsigned char* dst)
350 {
351 short v;
352 TRACE("(%p, %d, %p)\n", src, ns, dst);
353
354 while (ns--) {
355 v = R16(src); src += 2;
356 W16(dst, v); dst += 2;
357 W16(dst, v); dst += 2;
358 }
359 }
360
cvtSM88K(const unsigned char * src,int ns,unsigned char * dst)361 static void cvtSM88K(const unsigned char* src, int ns, unsigned char* dst)
362 {
363 TRACE("(%p, %d, %p)\n", src, ns, dst);
364
365 while (ns--) {
366 *dst++ = M8(src[0], src[1]);
367 src += 2;
368 }
369 }
370
cvtSM816K(const unsigned char * src,int ns,unsigned char * dst)371 static void cvtSM816K(const unsigned char* src, int ns, unsigned char* dst)
372 {
373 short v;
374 TRACE("(%p, %d, %p)\n", src, ns, dst);
375
376 while (ns--) {
377 v = M16(C816(src[0]), C816(src[1]));
378 src += 2;
379 W16(dst, v); dst += 2;
380 }
381 }
382
cvtSM168K(const unsigned char * src,int ns,unsigned char * dst)383 static void cvtSM168K(const unsigned char* src, int ns, unsigned char* dst)
384 {
385 TRACE("(%p, %d, %p)\n", src, ns, dst);
386
387 while (ns--) {
388 *dst++ = C168(M16(R16(src), R16(src + 2)));
389 src += 4;
390 }
391 }
392
cvtSM1616K(const unsigned char * src,int ns,unsigned char * dst)393 static void cvtSM1616K(const unsigned char* src, int ns, unsigned char* dst)
394 {
395 TRACE("(%p, %d, %p)\n", src, ns, dst);
396
397 while (ns--) {
398 W16(dst, M16(R16(src),R16(src+2))); dst += 2;
399 src += 4;
400 }
401 }
402
cvtMM816K(const unsigned char * src,int ns,unsigned char * dst)403 static void cvtMM816K(const unsigned char* src, int ns, unsigned char* dst)
404 {
405 TRACE("(%p, %d, %p)\n", src, ns, dst);
406
407 while (ns--) {
408 W16(dst, C816(*src++)); dst += 2;
409 }
410 }
411
cvtSS816K(const unsigned char * src,int ns,unsigned char * dst)412 static void cvtSS816K(const unsigned char* src, int ns, unsigned char* dst)
413 {
414 TRACE("(%p, %d, %p)\n", src, ns, dst);
415
416 while (ns--) {
417 W16(dst, C816(*src++)); dst += 2;
418 W16(dst, C816(*src++)); dst += 2;
419 }
420 }
421
cvtMM168K(const unsigned char * src,int ns,unsigned char * dst)422 static void cvtMM168K(const unsigned char* src, int ns, unsigned char* dst)
423 {
424 TRACE("(%p, %d, %p)\n", src, ns, dst);
425
426 while (ns--) {
427 *dst++ = C168(R16(src)); src += 2;
428 }
429 }
430
cvtSS168K(const unsigned char * src,int ns,unsigned char * dst)431 static void cvtSS168K(const unsigned char* src, int ns, unsigned char* dst)
432 {
433 TRACE("(%p, %d, %p)\n", src, ns, dst);
434
435 while (ns--) {
436 *dst++ = C168(R16(src)); src += 2;
437 *dst++ = C168(R16(src)); src += 2;
438 }
439 }
440
cvtMS248K(const unsigned char * src,int ns,unsigned char * dst)441 static void cvtMS248K(const unsigned char* src, int ns, unsigned char* dst)
442 {
443 unsigned char v;
444 TRACE("(%p, %d, %p)\n", src, ns, dst);
445
446 while (ns--) {
447 v = C248(R24(src)); src += 3;
448 *dst++ = v;
449 *dst++ = v;
450 }
451 }
452
cvtSM248K(const unsigned char * src,int ns,unsigned char * dst)453 static void cvtSM248K(const unsigned char* src, int ns, unsigned char* dst)
454 {
455 TRACE("(%p, %d, %p)\n", src, ns, dst);
456
457 while (ns--) {
458 *dst++ = C248(M24(R24(src), R24(src + 3)));
459 src += 6;
460 }
461 }
462
cvtMM248K(const unsigned char * src,int ns,unsigned char * dst)463 static void cvtMM248K(const unsigned char* src, int ns, unsigned char* dst)
464 {
465 TRACE("(%p, %d, %p)\n", src, ns, dst);
466
467 while (ns--) {
468 *dst++ = C248(R24(src)); src += 3;
469 }
470 }
471
cvtSS248K(const unsigned char * src,int ns,unsigned char * dst)472 static void cvtSS248K(const unsigned char* src, int ns, unsigned char* dst)
473 {
474 TRACE("(%p, %d, %p)\n", src, ns, dst);
475
476 while (ns--) {
477 *dst++ = C248(R24(src)); src += 3;
478 *dst++ = C248(R24(src)); src += 3;
479 }
480 }
481
cvtMS2416K(const unsigned char * src,int ns,unsigned char * dst)482 static void cvtMS2416K(const unsigned char* src, int ns, unsigned char* dst)
483 {
484 short v;
485 TRACE("(%p, %d, %p)\n", src, ns, dst);
486
487 while (ns--) {
488 v = C2416(R24(src)); src += 3;
489 W16(dst, v); dst += 2;
490 W16(dst, v); dst += 2;
491 }
492 }
493
cvtSM2416K(const unsigned char * src,int ns,unsigned char * dst)494 static void cvtSM2416K(const unsigned char* src, int ns, unsigned char* dst)
495 {
496 TRACE("(%p, %d, %p)\n", src, ns, dst);
497
498 while (ns--) {
499 W16(dst, C2416(M24(R24(src), R24(src + 3))));
500 dst += 2;
501 src += 6;
502 }
503 }
504
cvtMM2416K(const unsigned char * src,int ns,unsigned char * dst)505 static void cvtMM2416K(const unsigned char* src, int ns, unsigned char* dst)
506 {
507 TRACE("(%p, %d, %p)\n", src, ns, dst);
508
509 while (ns--) {
510 W16(dst, C2416(R24(src))); dst += 2; src += 3;
511 }
512 }
513
cvtSS2416K(const unsigned char * src,int ns,unsigned char * dst)514 static void cvtSS2416K(const unsigned char* src, int ns, unsigned char* dst)
515 {
516 TRACE("(%p, %d, %p)\n", src, ns, dst);
517
518 while (ns--) {
519 W16(dst, C2416(R24(src))); dst += 2; src += 3;
520 W16(dst, C2416(R24(src))); dst += 2; src += 3;
521 }
522 }
523
524
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 */
535 };
536
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)
543 *
544 */
545
cvtSS88C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)546 static void cvtSS88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
547 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
548 {
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;
559
560 *dst++ = src[0];
561 *dst++ = src[1];
562 }
563 src += 2;
564 }
565 }
566
cvtSM88C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)567 static void cvtSM88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
568 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
569 {
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;
580
581 *dst++ = M8(src[0], src[1]);
582 }
583 src += 2;
584 }
585 }
586
cvtMS88C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)587 static void cvtMS88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
588 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
589 {
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;
600
601 *dst++ = src[0];
602 *dst++ = src[0];
603 }
604 src += 1;
605 }
606 }
607
cvtMM88C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)608 static void cvtMM88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
609 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
610 {
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;
621
622 *dst++ = src[0];
623 }
624 src += 1;
625 }
626 }
627
cvtSS816C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)628 static void cvtSS816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
629 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
630 {
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;
641
642 W16(dst, C816(src[0])); dst += 2;
643 W16(dst, C816(src[1])); dst += 2;
644 }
645 src += 2;
646 }
647 }
648
cvtSM816C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)649 static void cvtSM816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
650 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
651 {
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;
662
663 W16(dst, M16(C816(src[0]), C816(src[1]))); dst += 2;
664 }
665 src += 2;
666 }
667 }
668
cvtMS816C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)669 static void cvtMS816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
670 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
671 {
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;
682
683 W16(dst, C816(src[0])); dst += 2;
684 W16(dst, C816(src[0])); dst += 2;
685 }
686 src += 1;
687 }
688 }
689
cvtMM816C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)690 static void cvtMM816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
691 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
692 {
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;
703
704 W16(dst, C816(src[0])); dst += 2;
705 }
706 src += 1;
707 }
708 }
709
cvtSS168C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)710 static void cvtSS168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
711 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
712 {
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;
723
724 *dst++ = C168(R16(src));
725 *dst++ = C168(R16(src + 2));
726 }
727 src += 4;
728 }
729 }
730
cvtSM168C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)731 static void cvtSM168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
732 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
733 {
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;
744
745 *dst++ = C168(M16(R16(src), R16(src + 2)));
746 }
747 src += 4;
748 }
749 }
750
cvtMS168C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)751 static void cvtMS168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
752 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
753 {
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;
764
765 *dst++ = C168(R16(src));
766 *dst++ = C168(R16(src));
767 }
768 src += 2;
769 }
770 }
771
cvtMM168C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)772 static void cvtMM168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
773 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
774 {
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;
785
786 *dst++ = C168(R16(src));
787 }
788 src += 2;
789 }
790 }
791
cvtSS1616C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)792 static void cvtSS1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
793 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
794 {
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;
805
806 W16(dst, R16(src)); dst += 2;
807 W16(dst, R16(src + 2)); dst += 2;
808 }
809 src += 4;
810 }
811 }
812
cvtSM1616C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)813 static void cvtSM1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
814 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
815 {
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;
826
827 W16(dst, M16(R16(src), R16(src + 2))); dst += 2;
828 }
829 src += 4;
830 }
831 }
832
cvtMS1616C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)833 static void cvtMS1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
834 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
835 {
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;
846
847 W16(dst, R16(src)); dst += 2;
848 W16(dst, R16(src)); dst += 2;
849 }
850 src += 2;
851 }
852 }
853
cvtMM1616C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)854 static void cvtMM1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
855 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
856 {
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;
867
868 W16(dst, R16(src)); dst += 2;
869 }
870 src += 2;
871 }
872 }
873
cvtSS2424C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)874 static void cvtSS2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
875 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
876 {
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;
887
888 W24(dst, R24(src)); dst += 3;
889 W24(dst, R24(src + 3)); dst += 3;
890 }
891 src += 6;
892 }
893 }
894
cvtSM2424C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)895 static void cvtSM2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
896 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
897 {
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;
908
909 W24(dst, M24(R24(src), R24(src + 3))); dst += 3;
910 }
911 src += 6;
912 }
913 }
914
cvtMS2424C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)915 static void cvtMS2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
916 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
917 {
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;
928
929 W24(dst, R24(src)); dst += 3;
930 W24(dst, R24(src)); dst += 3;
931 }
932 src += 3;
933 }
934 }
935
cvtMM2424C(const DWORD srcRate,const unsigned char * src,DWORD * nsrc,const DWORD dstRate,unsigned char * dst,DWORD * ndst)936 static void cvtMM2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc,
937 const DWORD dstRate, unsigned char *dst, DWORD *ndst)
938 {
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;
949
950 W24(dst, R24(src)); dst += 3;
951 }
952 src += 3;
953 }
954 }
955
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,
966 };
967
968 /***********************************************************************
969 * PCM_DriverDetails
970 *
971 */
PCM_DriverDetails(PACMDRIVERDETAILSW add)972 static LRESULT PCM_DriverDetails(PACMDRIVERDETAILSW add)
973 {
974 TRACE("(%p)\n", add);
975
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;
994
995 return MMSYSERR_NOERROR;
996 }
997
998 /***********************************************************************
999 * PCM_FormatTagDetails
1000 *
1001 */
PCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd,DWORD dwQuery)1002 static LRESULT PCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
1003 {
1004 TRACE("(%p, %08x)\n", aftd, dwQuery);
1005
1006 switch (dwQuery) {
1007 case ACM_FORMATTAGDETAILSF_INDEX:
1008 if (aftd->dwFormatTagIndex != 0) {
1009 WARN("not possible\n");
1010 return ACMERR_NOTPOSSIBLE;
1011 }
1012 break;
1013 case ACM_FORMATTAGDETAILSF_FORMATTAG:
1014 if (aftd->dwFormatTag != WAVE_FORMAT_PCM) {
1015 WARN("not possible\n");
1016 return ACMERR_NOTPOSSIBLE;
1017 }
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;
1024 }
1025 break;
1026 default:
1027 WARN("Unsupported query %08x\n", dwQuery);
1028 return MMSYSERR_NOTSUPPORTED;
1029 }
1030
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;
1037
1038 return MMSYSERR_NOERROR;
1039 }
1040
1041 /***********************************************************************
1042 * PCM_FormatDetails
1043 *
1044 */
PCM_FormatDetails(PACMFORMATDETAILSW afd,DWORD dwQuery)1045 static LRESULT PCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
1046 {
1047 TRACE("(%p, %08x)\n", afd, dwQuery);
1048
1049 switch (dwQuery) {
1050 case ACM_FORMATDETAILSF_FORMAT:
1051 if (PCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) {
1052 WARN("not possible\n");
1053 return ACMERR_NOTPOSSIBLE;
1054 }
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;
1064 */
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 %08x\n", dwQuery);
1072 return MMSYSERR_NOTSUPPORTED;
1073 }
1074
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);
1079
1080 return MMSYSERR_NOERROR;
1081 }
1082
1083 /***********************************************************************
1084 * PCM_FormatSuggest
1085 *
1086 */
PCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs)1087 static LRESULT PCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
1088 {
1089 TRACE("(%p)\n", adfs);
1090
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;
1097 }
1098
1099 /* is no suggestion for destination, then copy source value */
1100 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS)) {
1101 adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
1102 }
1103 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC)) {
1104 adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
1105 }
1106 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE)) {
1107 adfs->pwfxDst->wBitsPerSample = adfs->pwfxSrc->wBitsPerSample;
1108 }
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;
1113 }
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;
1119 }
1120 }
1121 /* check if result is ok */
1122 if (PCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) {
1123 WARN("not possible\n");
1124 return ACMERR_NOTPOSSIBLE;
1125 }
1126
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;
1130
1131 return MMSYSERR_NOERROR;
1132 }
1133
1134 /***********************************************************************
1135 * PCM_StreamOpen
1136 *
1137 */
PCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi)1138 static LRESULT PCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
1139 {
1140 AcmPcmData* apd;
1141 int idx;
1142 DWORD flags;
1143
1144 TRACE("(%p)\n", adsi);
1145
1146 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
1147
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;
1159 }
1160 idx = 24;
1161 break;
1162 default:
1163 FIXME("Unsupported source bit depth: %u\n", adsi->pwfxSrc->wBitsPerSample);
1164 return MMSYSERR_NOTSUPPORTED;
1165 }
1166
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;
1177 }
1178 idx += 8;
1179 break;
1180 default:
1181 FIXME("Unsupported destination bit depth: %u\n", adsi->pwfxDst->wBitsPerSample);
1182 return MMSYSERR_NOTSUPPORTED;
1183 }
1184
1185 if (adsi->pwfxSrc->nChannels == 1) idx += 2;
1186
1187 if (adsi->pwfxDst->nChannels == 1) idx += 1;
1188
1189 apd = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmPcmData));
1190 if (!apd)
1191 return MMSYSERR_NOMEM;
1192
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];
1199 }
1200
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;
1207 }
1208
1209 adsi->dwDriver = (DWORD_PTR)apd;
1210 adsi->fdwDriver = flags;
1211
1212 return MMSYSERR_NOERROR;
1213 }
1214
1215 /***********************************************************************
1216 * PCM_StreamClose
1217 *
1218 */
PCM_StreamClose(PACMDRVSTREAMINSTANCE adsi)1219 static LRESULT PCM_StreamClose(PACMDRVSTREAMINSTANCE adsi)
1220 {
1221 TRACE("(%p)\n", adsi);
1222
1223 HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
1224 return MMSYSERR_NOERROR;
1225 }
1226
1227 /***********************************************************************
1228 * PCM_round
1229 *
1230 */
PCM_round(DWORD a,DWORD b,DWORD c)1231 static inline DWORD PCM_round(DWORD a, DWORD b, DWORD c)
1232 {
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;
1236 }
1237
1238 /***********************************************************************
1239 * PCM_StreamSize
1240 *
1241 */
PCM_StreamSize(PACMDRVSTREAMINSTANCE adsi,PACMDRVSTREAMSIZE adss)1242 static LRESULT PCM_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss)
1243 {
1244 DWORD srcMask = ~(adsi->pwfxSrc->nBlockAlign - 1);
1245 DWORD dstMask = ~(adsi->pwfxDst->nBlockAlign - 1);
1246
1247 TRACE("(%p, %p)\n", adsi, adss);
1248
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 %08x\n", adss->fdwSize);
1264 return MMSYSERR_NOTSUPPORTED;
1265 }
1266 return MMSYSERR_NOERROR;
1267 }
1268
1269 /***********************************************************************
1270 * PCM_StreamConvert
1271 *
1272 */
PCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi,PACMDRVSTREAMHEADER adsh)1273 static LRESULT PCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
1274 {
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);
1278
1279 TRACE("(%p, %p)\n", adsi, adsh);
1280
1281 TRACE("nsrc=%d,adsh->cbSrcLength=%d\n", nsrc, adsh->cbSrcLength);
1282 TRACE("ndst=%d,adsh->cbDstLength=%d\n", ndst, adsh->cbDstLength);
1283 TRACE("src [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%u, nAvgBytesPerSec=%u, 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=%u, nAvgBytesPerSec=%u, 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);
1289
1290 if (adsh->fdwConvert &
1291 ~(ACM_STREAMCONVERTF_BLOCKALIGN|
1292 ACM_STREAMCONVERTF_END|
1293 ACM_STREAMCONVERTF_START)) {
1294 FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert);
1295 }
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
1300 */
1301 if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START) &&
1302 (adsi->fdwDriver & PCM_RESAMPLE)) {
1303 }
1304
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;
1311
1312 /* nsrc is now equal to ndst */
1313 apd->cvt.cvtKeepRate(adsh->pbSrc, nsrc, adsh->pbDst);
1314 }
1315
1316 adsh->cbSrcLengthUsed = nsrc * adsi->pwfxSrc->nBlockAlign;
1317 adsh->cbDstLengthUsed = ndst * adsi->pwfxDst->nBlockAlign;
1318
1319 return MMSYSERR_NOERROR;
1320 }
1321
1322 /**************************************************************************
1323 * DriverProc (MSACM32.@)
1324 */
PCM_DriverProc(DWORD_PTR dwDevID,HDRVR hDriv,UINT wMsg,LPARAM dwParam1,LPARAM dwParam2)1325 LRESULT CALLBACK PCM_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
1326 LPARAM dwParam1, LPARAM dwParam2)
1327 {
1328 TRACE("(%08lx %p %u %08lx %08lx);\n",
1329 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1330
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;
1342
1343 case ACMDM_DRIVER_NOTIFY:
1344 /* no caching from other ACM drivers is done so far */
1345 return MMSYSERR_NOERROR;
1346
1347 case ACMDM_DRIVER_DETAILS:
1348 return PCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
1349
1350 case ACMDM_FORMATTAG_DETAILS:
1351 return PCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
1352
1353 case ACMDM_FORMAT_DETAILS:
1354 return PCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
1355
1356 case ACMDM_FORMAT_SUGGEST:
1357 return PCM_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
1358
1359 case ACMDM_STREAM_OPEN:
1360 return PCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
1361
1362 case ACMDM_STREAM_CLOSE:
1363 return PCM_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
1364
1365 case ACMDM_STREAM_SIZE:
1366 return PCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
1367
1368 case ACMDM_STREAM_CONVERT:
1369 return PCM_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
1370
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;
1383
1384 default:
1385 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1386 }
1387 }
1388