ReactOS  0.4.14-dev-52-g6116262
pcmconverter.c
Go to the documentation of this file.
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 
51 
52 /***********************************************************************
53  * PCM_drvOpen
54  */
56 {
57  TRACE("(%p, %p)\n", str, adod);
58 
59  return (adod == NULL) ||
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 {
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  */
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 
529  NULL, NULL, NULL, NULL, /* TODO: 8->24 */
532  NULL, NULL, NULL, NULL, /* TODO: 16->24 */
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 
960  NULL, NULL, NULL, NULL, /* TODO: 8->24 */
963  NULL, NULL, NULL, NULL, /* TODO: 16->24 */
964  NULL, NULL, NULL, NULL, /* TODO: 24->8 */
965  NULL, NULL, NULL, NULL, /* TODO: 24->16 */
967 };
968 
969 /***********************************************************************
970  * PCM_DriverDetails
971  *
972  */
974 {
975  TRACE("(%p)\n", add);
976 
979  add->wMid = MM_MICROSOFT;
980  add->wPid = MM_MSFT_ACM_PCM;
981  add->vdwACM = 0x01000000;
982  add->vdwDriver = 0x01000000;
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  */
1004 {
1005  TRACE("(%p, %08x)\n", aftd, dwQuery);
1006 
1007  switch (dwQuery) {
1009  if (aftd->dwFormatTagIndex != 0) {
1010  WARN("not possible\n");
1011  return ACMERR_NOTPOSSIBLE;
1012  }
1013  break;
1015  if (aftd->dwFormatTag != WAVE_FORMAT_PCM) {
1016  WARN("not possible\n");
1017  return ACMERR_NOTPOSSIBLE;
1018  }
1019  break;
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);
1037  aftd->szFormatTag[0] = 0;
1038 
1039  return MMSYSERR_NOERROR;
1040 }
1041 
1042 /***********************************************************************
1043  * PCM_FormatDetails
1044  *
1045  */
1047 {
1048  TRACE("(%p, %08x)\n", afd, dwQuery);
1049 
1050  switch (dwQuery) {
1052  if (PCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) {
1053  WARN("not possible\n");
1054  return ACMERR_NOTPOSSIBLE;
1055  }
1056  break;
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 
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  */
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  }
1105  adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
1106  }
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;
1131 
1132  return MMSYSERR_NOERROR;
1133 }
1134 
1135 /***********************************************************************
1136  * PCM_StreamOpen
1137  *
1138  */
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;
1197  } else {
1198  flags = PCM_RESAMPLE;
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  */
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  */
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) {
1252  /* cbDstLength => cbSrcLength */
1253  adss->cbSrcLength = PCM_round(adss->cbDstLength & dstMask,
1254  adsi->pwfxSrc->nAvgBytesPerSec,
1255  adsi->pwfxDst->nAvgBytesPerSec) & srcMask;
1256  break;
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  */
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",
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",
1289  adsi->pwfxDst->nBlockAlign, adsi->pwfxDst->wBitsPerSample, adsi->pwfxDst->cbSize);
1290 
1291  if (adsh->fdwConvert &
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 
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 
1374  /* this converter is not a hardware driver */
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:
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 }
PWAVEFORMATEX pwfx
Definition: msacm.h:507
#define DRV_DISABLE
Definition: mmsystem.h:123
#define WAVE_FORMAT_UNKNOWN
Definition: mmreg.h:95
int add
Definition: i386-dis.c:3122
PCM_CONVERT_KEEP_RATE cvtKeepRate
Definition: pcmconverter.c:87
static void cvtMS816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:670
static void cvtSS248K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:473
static void cvtMM816K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:404
static short C816(unsigned char b)
Definition: pcmconverter.c:142
#define ACM_STREAMSIZEF_DESTINATION
Definition: msacm.h:218
static void cvtSS88K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:298
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
#define ACM_FORMATSUGGESTF_NSAMPLESPERSEC
Definition: msacm.h:176
static void cvtMM248K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:464
static unsigned char M8(unsigned char a, unsigned char b)
Definition: pcmconverter.c:266
#define DWORD_PTR
Definition: treelist.c:76
#define error(str)
Definition: mkdosfs.c:1605
#define ACM_STREAMCONVERTF_BLOCKALIGN
Definition: msacm.h:205
#define LOBYTE(W)
Definition: jmemdos.c:487
static LRESULT PCM_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss)
static void cvtSS816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:629
static void cvtMS816K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:326
static void cvtMS88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:588
void(* PCM_CONVERT_CHANGE_RATE)(const DWORD, const unsigned char *, DWORD *, const DWORD, unsigned char *, DWORD *)
Definition: pcmconverter.c:81
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
PWAVEFORMATEX pwfxDst
Definition: msacmdrv.h:153
#define CP_ACP
Definition: compat.h:99
static void cvtMS248K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:442
DWORD nAvgBytesPerSec
Definition: mmreg.h:81
static void cvtSS168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:711
WORD nChannels
Definition: mmreg.h:79
#define WARN(fmt,...)
Definition: debug.h:111
static void cvtMS1616K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:350
#define ACMDM_STREAM_RESET
Definition: msacmdrv.h:62
#define CALLBACK
Definition: compat.h:27
#define HIBYTE(W)
Definition: jmemdos.c:486
#define ACM_FORMATSUGGESTF_WFORMATTAG
Definition: msacm.h:174
static void cvtMM88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:609
static LRESULT PCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
static void cvtSM168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:732
#define assert(x)
Definition: debug.h:53
#define DRV_CLOSE
Definition: mmsystem.h:122
static unsigned char C168(short s)
Definition: pcmconverter.c:152
int rate
Definition: pcmconverter.c:98
#define ACMDM_STREAM_OPEN
Definition: msacmdrv.h:58
#define ACMDM_FORMATTAG_DETAILS
Definition: msacmdrv.h:51
char * LPSTR
Definition: xmlstorage.h:182
#define ACMDM_STREAM_PREPARE
Definition: msacmdrv.h:63
struct pcmwaveformat_tag PCMWAVEFORMAT
static void cvtSS2416K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:515
int nChannels
Definition: pcmconverter.c:96
static LRESULT PCM_StreamClose(PACMDRVSTREAMINSTANCE adsi)
#define DWORD
Definition: nt_native.h:44
#define ACM_STREAMCONVERTF_END
Definition: msacm.h:207
void(* PCM_CONVERT_KEEP_RATE)(const unsigned char *, int, unsigned char *)
Definition: pcmconverter.c:79
static void cvtMS168K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:338
static const struct @455 PCM_Formats[]
static void cvtMM816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:691
#define ACMDM_STREAM_CLOSE
Definition: msacmdrv.h:59
#define DRV_QUERYCONFIGURE
Definition: mmsystem.h:126
#define DRV_OPEN
Definition: mmsystem.h:121
static void cvtSM1616K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:394
int WINAPI MessageBoxA(_In_opt_ HWND, _In_opt_ LPCSTR, _In_opt_ LPCSTR, _In_ UINT)
#define ACMDM_DRIVER_NOTIFY
Definition: msacmdrv.h:45
#define ACMDM_FORMAT_SUGGEST
Definition: msacmdrv.h:53
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:93
#define MMSYSERR_NOMEM
Definition: mmsystem.h:103
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define WAVE_FORMAT_PCM
Definition: constants.h:425
static short R16(const unsigned char *src)
Definition: pcmconverter.c:182
LRESULT CALLBACK PCM_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg, LPARAM dwParam1, LPARAM dwParam2)
static short C2416(int s)
Definition: pcmconverter.c:172
#define ACM_FORMATDETAILSF_FORMAT
Definition: msacm.h:161
static LRESULT PCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
static int R24(const unsigned char *src)
Definition: pcmconverter.c:194
#define ACMDM_DRIVER_DETAILS
Definition: msacmdrv.h:46
union tagAcmPcmData::@456 cvt
struct tagAcmPcmData AcmPcmData
#define ACMDM_STREAM_CONVERT
Definition: msacmdrv.h:61
static void cvtMM168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:773
#define FIXME(fmt,...)
Definition: debug.h:110
static LRESULT PCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
static void cvtMM88K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:292
static void cvtSM88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:568
unsigned int idx
Definition: utils.c:41
static void cvtSM2416K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:495
static const char mbstate_t *static wchar_t const char mbstate_t *static const wchar_t int *static double
Definition: string.c:80
static DWORD PCM_GetFormatIndex(LPWAVEFORMATEX wfx)
Definition: pcmconverter.c:111
DWORD cStandardFormats
Definition: msacm.h:534
static void cvtSM248K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:454
#define ACMDRIVERDETAILS_FCCCOMP_UNDEFINED
Definition: msacm.h:59
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
static LRESULT PCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
unsigned char
Definition: typeof.h:29
#define NUM_OF(a, b)
Definition: pcmconverter.c:74
FOURCC fccType
Definition: msacmdrv.h:87
static void cvtSM1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:814
LONG_PTR LPARAM
Definition: windef.h:208
#define ACM_FORMATSUGGESTF_NCHANNELS
Definition: msacm.h:175
#define DRV_LOAD(x)
int nBits
Definition: pcmconverter.c:97
const char * LPCSTR
Definition: xmlstorage.h:183
#define DRVCNF_RESTART
Definition: mmsystem.h:135
#define DRV_REMOVE
Definition: mmsystem.h:128
static int sum(int x_, int y_)
Definition: ptr2_test.cpp:35
#define ACMDM_HARDWARE_WAVE_CAPS_OUTPUT
Definition: msacmdrv.h:49
#define ACMDM_HARDWARE_WAVE_CAPS_INPUT
Definition: msacmdrv.h:48
r l[0]
Definition: byte_order.h:167
PWAVEFORMATEX pwfxDst
Definition: msacmdrv.h:101
int64_t LONGLONG
Definition: typedefs.h:66
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define TRACE(s)
Definition: solgame.cpp:4
#define ACM_FORMATTAGDETAILSF_FORMATTAG
Definition: msacm.h:183
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
static const PCM_CONVERT_KEEP_RATE PCM_ConvertKeepRate[]
Definition: pcmconverter.c:526
#define DRV_CONFIGURE
Definition: mmsystem.h:125
#define ACM_STREAMSIZEF_SOURCE
Definition: msacm.h:217
#define ACM_FORMATTAGDETAILSF_INDEX
Definition: msacm.h:182
PCM_CONVERT_CHANGE_RATE cvtChangeRate
Definition: pcmconverter.c:88
const GLubyte * c
Definition: glext.h:8905
unsigned long DWORD
Definition: ntddk_ex.h:95
WCHAR szFormat[ACMFORMATDETAILS_FORMAT_CHARS]
Definition: msacm.h:509
static void cvtSS816K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:413
#define ACM_STREAMOPENF_ASYNC
Definition: msacm.h:214
#define ACMDRIVERDETAILS_SUPPORTF_CONVERTER
Definition: msacm.h:62
#define DRV_FREE
Definition: mmsystem.h:124
static void cvtMM2416K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:506
static DWORD PCM_drvClose(DWORD dwDevID)
Definition: pcmconverter.c:67
#define MMSYSERR_NOTSUPPORTED
Definition: mmsystem.h:104
GLbitfield flags
Definition: glext.h:7161
static void cvtMS2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:916
static void cvtSS2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:875
WORD wFormatTag
Definition: mmreg.h:78
#define ACMDM_FILTERTAG_DETAILS
Definition: msacmdrv.h:55
DWORD dwFormatIndex
Definition: msacm.h:504
static void cvtSS88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:547
Definition: mxnamespace.c:44
static const PCM_CONVERT_CHANGE_RATE PCM_ConvertChangeRate[]
Definition: pcmconverter.c:957
#define MM_MICROSOFT
Definition: mmreg.h:144
GLuint GLuint dstMask
Definition: glext.h:9513
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLdouble s
Definition: gl.h:2039
#define ACM_FORMATTAGDETAILSF_LARGESTSIZE
Definition: msacm.h:184
GLenum src
Definition: glext.h:6340
DWORD dwFormatTagIndex
Definition: msacm.h:530
uint32_t DWORD_PTR
Definition: typedefs.h:63
#define ACMERR_NOTPOSSIBLE
Definition: msacm.h:36
static void cvtSM168K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:384
#define ACMDM_STREAM_UNPREPARE
Definition: msacmdrv.h:64
#define DRV_ENABLE
Definition: mmsystem.h:120
static void cvtMM168K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:423
static short M16(short l, short r)
Definition: pcmconverter.c:247
static unsigned char C248(int s)
Definition: pcmconverter.c:162
static LRESULT PCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
static void cvtSS168K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:432
const GLdouble * v
Definition: gl.h:2040
#define ACM_STREAMCONVERTF_START
Definition: msacm.h:206
static void cvtMS2416K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:483
#define ARRAY_SIZE(a)
Definition: main.h:24
DWORD fdwSupport
Definition: msacm.h:506
PWAVEFORMATEX pwfxSrc
Definition: msacmdrv.h:151
WORD cbSize
Definition: mmreg.h:84
static void cvtSS1616K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:310
static void cvtMS168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:752
GLenum GLenum dst
Definition: glext.h:6340
DWORD_PTR dwDriver
Definition: msacmdrv.h:107
static void cvtSM816K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:372
unsigned int UINT
Definition: ndis.h:50
#define MB_OK
Definition: winuser.h:784
WCHAR szFormatTag[ACMFORMATTAGDETAILS_FORMATTAG_CHARS]
Definition: msacm.h:535
#define MultiByteToWideChar
Definition: compat.h:100
#define PCM_RESAMPLE
Definition: pcmconverter.c:77
DWORD nSamplesPerSec
Definition: mmreg.h:80
WORD nBlockAlign
Definition: mmreg.h:82
WINE_DEFAULT_DEBUG_CHANNEL(msacm)
#define ACM_FORMATDETAILSF_INDEX
Definition: msacm.h:160
static void cvtSM816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:650
static void cvtMM1616K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:304
static void W24(unsigned char *dst, int s)
Definition: pcmconverter.c:215
FOURCC fccComp
Definition: msacmdrv.h:88
WORD wBitsPerSample
Definition: mmreg.h:83
static void cvtMS88K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:316
#define HIWORD(l)
Definition: typedefs.h:246
PWAVEFORMATEX pwfxSrc
Definition: msacmdrv.h:100
#define DRV_INSTALL
Definition: mmsystem.h:127
LRESULT WINAPI DefDriverProc(DWORD_PTR dwDriverIdentifier, HDRVR hDrv, UINT Msg, LPARAM lParam1, LPARAM lParam2)
Definition: driver.c:554
static void cvtMM1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:855
#define MM_MSFT_ACM_PCM
Definition: mmreg.h:150
static LRESULT PCM_DriverDetails(PACMDRIVERDETAILSW add)
Definition: pcmconverter.c:973
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
LONG_PTR LRESULT
Definition: windef.h:209
static void W16(unsigned char *dst, short s)
Definition: pcmconverter.c:204
DWORD dwFormatTag
Definition: msacm.h:505
static void cvtSM88K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:362
#define LOWORD(l)
Definition: pedump.c:82
static void cvtMM2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:937
#define HeapFree(x, y, z)
Definition: compat.h:394
#define ACM_FORMATSUGGESTF_WBITSPERSAMPLE
Definition: msacm.h:177
static void cvtSM2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:896
static DWORD PCM_drvOpen(LPCSTR str, PACMDRVOPENDESCW adod)
Definition: pcmconverter.c:55
#define ACMDM_FORMAT_DETAILS
Definition: msacmdrv.h:52
static int M24(int l, int r)
Definition: pcmconverter.c:228
static DWORD PCM_round(DWORD a, DWORD b, DWORD c)
static void cvtMS1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:834
#define ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC
Definition: msacm.h:58
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
static void cvtSS1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:793
#define ACMDM_STREAM_SIZE
Definition: msacmdrv.h:60
#define ACMDM_FILTER_DETAILS
Definition: msacmdrv.h:56