ReactOS  0.4.14-dev-554-g2f8d847
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 
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 
50 
51 /***********************************************************************
52  * PCM_drvOpen
53  */
55 {
56  TRACE("(%p, %p)\n", str, adod);
57 
58  return (adod == NULL) ||
61 }
62 
63 /***********************************************************************
64  * PCM_drvClose
65  */
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 {
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
528  NULL, NULL, NULL, NULL, /* TODO: 8->24 */
531  NULL, NULL, NULL, NULL, /* TODO: 16->24 */
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
959  NULL, NULL, NULL, NULL, /* TODO: 8->24 */
962  NULL, NULL, NULL, NULL, /* TODO: 16->24 */
963  NULL, NULL, NULL, NULL, /* TODO: 24->8 */
964  NULL, NULL, NULL, NULL, /* TODO: 24->16 */
966 };
967 
968 /***********************************************************************
969  * PCM_DriverDetails
970  *
971  */
973 {
974  TRACE("(%p)\n", add);
975 
978  add->wMid = MM_MICROSOFT;
979  add->wPid = MM_MSFT_ACM_PCM;
980  add->vdwACM = 0x01000000;
981  add->vdwDriver = 0x01000000;
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  */
1003 {
1004  TRACE("(%p, %08x)\n", aftd, dwQuery);
1005 
1006  switch (dwQuery) {
1008  if (aftd->dwFormatTagIndex != 0) {
1009  WARN("not possible\n");
1010  return ACMERR_NOTPOSSIBLE;
1011  }
1012  break;
1014  if (aftd->dwFormatTag != WAVE_FORMAT_PCM) {
1015  WARN("not possible\n");
1016  return ACMERR_NOTPOSSIBLE;
1017  }
1018  break;
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);
1036  aftd->szFormatTag[0] = 0;
1037 
1038  return MMSYSERR_NOERROR;
1039 }
1040 
1041 /***********************************************************************
1042  * PCM_FormatDetails
1043  *
1044  */
1046 {
1047  TRACE("(%p, %08x)\n", afd, dwQuery);
1048 
1049  switch (dwQuery) {
1051  if (PCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) {
1052  WARN("not possible\n");
1053  return ACMERR_NOTPOSSIBLE;
1054  }
1055  break;
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 
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  */
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  }
1104  adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
1105  }
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;
1130 
1131  return MMSYSERR_NOERROR;
1132 }
1133 
1134 /***********************************************************************
1135  * PCM_StreamOpen
1136  *
1137  */
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;
1196  } else {
1197  flags = PCM_RESAMPLE;
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  */
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  */
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  */
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) {
1251  /* cbDstLength => cbSrcLength */
1252  adss->cbSrcLength = PCM_round(adss->cbDstLength & dstMask,
1253  adsi->pwfxSrc->nAvgBytesPerSec,
1254  adsi->pwfxDst->nAvgBytesPerSec) & srcMask;
1255  break;
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  */
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",
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",
1288  adsi->pwfxDst->nBlockAlign, adsi->pwfxDst->wBitsPerSample, adsi->pwfxDst->cbSize);
1289 
1290  if (adsh->fdwConvert &
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  */
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 
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 
1373  /* this converter is not a hardware driver */
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:
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 }
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:86
static void cvtMS816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:669
static void cvtSS248K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:472
static void cvtMM816K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:403
static short C816(unsigned char b)
Definition: pcmconverter.c:141
#define ACM_STREAMSIZEF_DESTINATION
Definition: msacm.h:218
static void cvtSS88K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:297
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:463
static unsigned char M8(unsigned char a, unsigned char b)
Definition: pcmconverter.c:265
#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:628
static void cvtMS816K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:325
static void cvtMS88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:587
void(* PCM_CONVERT_CHANGE_RATE)(const DWORD, const unsigned char *, DWORD *, const DWORD, unsigned char *, DWORD *)
Definition: pcmconverter.c:80
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:441
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:710
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:349
#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:608
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:731
#define assert(x)
Definition: debug.h:53
#define DRV_CLOSE
Definition: mmsystem.h:122
static unsigned char C168(short s)
Definition: pcmconverter.c:151
int rate
Definition: pcmconverter.c:97
#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:514
int nChannels
Definition: pcmconverter.c:95
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:78
static void cvtMS168K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:337
static void cvtMM816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:690
#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:393
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:181
LRESULT CALLBACK PCM_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg, LPARAM dwParam1, LPARAM dwParam2)
static short C2416(int s)
Definition: pcmconverter.c:171
#define ACM_FORMATDETAILSF_FORMAT
Definition: msacm.h:161
static LRESULT PCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
static int R24(const unsigned char *src)
Definition: pcmconverter.c:193
#define ACMDM_DRIVER_DETAILS
Definition: msacmdrv.h:46
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:772
#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:291
static void cvtSM88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:567
unsigned int idx
Definition: utils.c:41
static void cvtSM2416K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:494
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:110
DWORD cStandardFormats
Definition: msacm.h:534
static void cvtSM248K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:453
#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:73
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:813
LONG_PTR LPARAM
Definition: windef.h:208
#define ACM_FORMATSUGGESTF_NCHANNELS
Definition: msacm.h:175
#define DRV_LOAD(x)
int nBits
Definition: pcmconverter.c:96
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:403
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
static const PCM_CONVERT_KEEP_RATE PCM_ConvertKeepRate[]
Definition: pcmconverter.c:525
#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:87
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:412
#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:505
static DWORD PCM_drvClose(DWORD dwDevID)
Definition: pcmconverter.c:66
#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:915
static void cvtSS2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:874
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:546
Definition: mxnamespace.c:44
static const struct @460 PCM_Formats[]
static const PCM_CONVERT_CHANGE_RATE PCM_ConvertChangeRate[]
Definition: pcmconverter.c:956
#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:383
#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:422
static short M16(short l, short r)
Definition: pcmconverter.c:246
static unsigned char C248(int s)
Definition: pcmconverter.c:161
static LRESULT PCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
static void cvtSS168K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:431
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:482
#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:309
static void cvtMS168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:751
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:371
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:76
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:649
static void cvtMM1616K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:303
static void W24(unsigned char *dst, int s)
Definition: pcmconverter.c:214
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:315
#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
union tagAcmPcmData::@461 cvt
static void cvtMM1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, const DWORD dstRate, unsigned char *dst, DWORD *ndst)
Definition: pcmconverter.c:854
#define MM_MSFT_ACM_PCM
Definition: mmreg.h:150
static LRESULT PCM_DriverDetails(PACMDRIVERDETAILSW add)
Definition: pcmconverter.c:972
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:203
DWORD dwFormatTag
Definition: msacm.h:505
static void cvtSM88K(const unsigned char *src, int ns, unsigned char *dst)
Definition: pcmconverter.c:361
#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:936
#define HeapFree(x, y, z)
Definition: compat.h:402
#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:895
static DWORD PCM_drvOpen(LPCSTR str, PACMDRVOPENDESCW adod)
Definition: pcmconverter.c:54
#define ACMDM_FORMAT_DETAILS
Definition: msacmdrv.h:52
static int M24(int l, int r)
Definition: pcmconverter.c:227
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:833
#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:792
#define ACMDM_STREAM_SIZE
Definition: msacmdrv.h:60
#define ACMDM_FILTER_DETAILS
Definition: msacmdrv.h:56