Implemented MakeSureDirectoryPathExists.
[wine] / dlls / msacm / pcmconverter.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2
3 /*
4  *      MSACM32 library
5  *
6  *      Copyright 2000          Eric Pouech
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  *      FIXME / TODO list
23  *      + most of the computation should be done in fixed point arithmetic
24  *        instead of floating point (16 bits for integral part, and 16 bits
25  *        for fractional part for example)
26  *      + implement PCM_FormatSuggest function
27  *      + get rid of hack for PCM_DriverProc (msacm32.dll shouldn't export
28  *        a DriverProc, but this would require implementing a generic
29  *        embedded driver handling scheme in msacm32.dll which isn't done yet
30  */
31
32 #include "config.h"
33
34 #include <assert.h>
35 #include <string.h>
36
37 #include "msacm.h"
38 #include "winbase.h"
39 #include "wingdi.h"
40 #include "winnls.h"
41 #include "winuser.h"
42
43 #include "msacmdrv.h"
44 #include "wineacm.h"
45
46 #include "wine/debug.h"
47
48 WINE_DEFAULT_DEBUG_CHANNEL(msacm);
49
50 /***********************************************************************
51  *           PCM_drvOpen
52  */
53 static  DWORD   PCM_drvOpen(LPCSTR str, PACMDRVOPENDESCW adod)
54 {
55     return (adod == NULL) ||
56         (adod->fccType == ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC &&
57          adod->fccComp == ACMDRIVERDETAILS_FCCCOMP_UNDEFINED);
58 }
59
60 /***********************************************************************
61  *           PCM_drvClose
62  */
63 static  DWORD   PCM_drvClose(DWORD dwDevID)
64 {
65     return 1;
66 }
67
68 #define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
69 #define NUM_OF(a,b)     (((a)+(b)-1)/(b))
70
71 /* flags for fdwDriver */
72 #define PCM_RESAMPLE    1
73
74 /* data used while converting */
75 typedef struct tagAcmPcmData {
76     /* conversion routine, depending if rate conversion is required */
77     union {
78         void (*cvtKeepRate)(const unsigned char*, int, unsigned char*);
79         void (*cvtChangeRate)(struct tagAcmPcmData*, const unsigned char*,
80                               LPDWORD, unsigned char*, LPDWORD);
81     } cvt;
82     /* the following fields are used only with rate conversion) */
83     DWORD       srcPos;         /* position in source stream */
84     double      dstPos;         /* position in destination stream */
85     double      dstIncr;        /* value to increment dst stream when src stream
86                                    is incremented by 1 */
87     /* last source stream value read */
88     union {
89         unsigned char   b;      /*  8 bit value */
90         short           s;      /* 16 bit value */
91     } last[2]; /* two channels max (stereo) */
92 } AcmPcmData;
93
94 /* table to list all supported formats... those are the basic ones. this
95  * also helps given a unique index to each of the supported formats
96  */
97 static  struct {
98     int         nChannels;
99     int         nBits;
100     int         rate;
101 } PCM_Formats[] = {
102     {1,  8,  8000}, {2,  8,  8000}, {1, 16,  8000}, {2, 16,  8000},
103     {1,  8, 11025}, {2,  8, 11025}, {1, 16, 11025}, {2, 16, 11025},
104     {1,  8, 22050}, {2,  8, 22050}, {1, 16, 22050}, {2, 16, 22050},
105     {1,  8, 44100}, {2,  8, 44100}, {1, 16, 44100}, {2, 16, 44100},
106     {1,  8, 48000}, {2,  8, 48000}, {1, 16, 48000}, {2, 16, 48000},
107     {1,  8, 96000}, {2,  8, 96000}, {1, 16, 96000}, {2, 16, 96000}
108 };
109
110 /***********************************************************************
111  *           PCM_GetFormatIndex
112  */
113 static DWORD PCM_GetFormatIndex(LPWAVEFORMATEX wfx)
114 {
115     int i;
116
117     for (i = 0; i < NUM_PCM_FORMATS; i++) {
118         if (wfx->nChannels == PCM_Formats[i].nChannels &&
119             wfx->nSamplesPerSec == PCM_Formats[i].rate &&
120             wfx->wBitsPerSample == PCM_Formats[i].nBits)
121             return i;
122     }
123     return 0xFFFFFFFF;
124 }
125
126 /* PCM Conversions:
127  *
128  * parameters:
129  *      + 8 bit unsigned vs 16 bit signed
130  *      + mono vs stereo (1 or 2 channels)
131  *      + sampling rate (8.0, 11.025, 22.05, 44.1 kHz are defined, but algo
132  *        shall work in all cases)
133  *
134  * mono => stereo: copy the same sample on Left & Right channels
135  * stereo =) mono: use the average value of samples from Left & Right channels
136  * resampling; we lookup for each destination sample the two source adjacent
137  *      samples were src <= dst < src+1 (dst is increased by a fractional
138  *      value which is equivalent to the increment by one on src); then we
139  *      use a linear interpolation between src and src+1
140  */
141
142 /***********************************************************************
143  *           C816
144  *
145  * Converts a 8 bit sample to a 16 bit one
146  */
147 static inline short C816(unsigned char b)
148 {
149     return (short)((b+(b << 8))-32768);
150 }
151
152 /***********************************************************************
153  *           C168
154  *
155  * Converts a 16 bit sample to a 8 bit one (data loss !!)
156  */
157 static inline unsigned char C168(short s)
158 {
159     return HIBYTE(s) ^ (unsigned char)0x80;
160 }
161
162 /***********************************************************************
163  *           R16
164  *
165  * Read a 16 bit sample (correctly handles endianess)
166  */
167 static inline short  R16(const unsigned char* src)
168 {
169     return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));
170 }
171
172 /***********************************************************************
173  *           W16
174  *
175  * Write a 16 bit sample (correctly handles endianess)
176  */
177 static inline void  W16(unsigned char* dst, short s)
178 {
179     dst[0] = LOBYTE(s);
180     dst[1] = HIBYTE(s);
181 }
182
183 /***********************************************************************
184  *           M16
185  *
186  * Convert the (l,r) 16 bit stereo sample into a 16 bit mono
187  * (takes the mid-point of the two values)
188  */
189 static inline short M16(short l, short r)
190 {
191     return (l + r) / 2;
192 }
193
194 /***********************************************************************
195  *           M8
196  *
197  * Convert the (l,r) 8 bit stereo sample into a 8 bit mono
198  * (takes the mid-point of the two values)
199  */
200 static inline unsigned char M8(unsigned char a, unsigned char b)
201 {
202     return (unsigned char)((a + b) / 2);
203 }
204
205 /* the conversion routines without rate conversion are labelled cvt<X><Y><N><M>K
206  * where :
207  * <X> is the (M)ono/(S)tereo configuration of  input channel
208  * <Y> is the (M)ono/(S)tereo configuration of output channel
209  * <N> is the number of bits of  input channel (8 or 16)
210  * <M> is the number of bits of output channel (8 or 16)
211  *
212  * in the parameters, ns is always the number of samples, so the size of input
213  * buffer (resp output buffer) is ns * (<X> == 'Mono' ? 1:2) * (<N> == 8 ? 1:2)
214  */
215
216 static  void cvtMM88K(const unsigned char* src, int ns, unsigned char* dst)
217 {
218     memcpy(dst, src, ns);
219 }
220
221 static  void cvtSS88K(const unsigned char* src, int ns, unsigned char* dst)
222 {
223     memcpy(dst, src, ns * 2);
224 }
225
226 static  void cvtMM1616K(const unsigned char* src, int ns, unsigned char* dst)
227 {
228     memcpy(dst, src, ns * 2);
229 }
230
231 static  void cvtSS1616K(const unsigned char* src, int ns, unsigned char* dst)
232 {
233     memcpy(dst, src, ns * 4);
234 }
235
236 static  void cvtMS88K(const unsigned char* src, int ns, unsigned char* dst)
237 {
238     while (ns--) {
239         *dst++ = *src;
240         *dst++ = *src++;
241     }
242 }
243
244 static  void cvtMS816K(const unsigned char* src, int ns, unsigned char* dst)
245 {
246     short       v;
247
248     while (ns--) {
249         v = C816(*src++);
250         W16(dst, v);            dst += 2;
251         W16(dst, v);            dst += 2;
252     }
253 }
254
255 static  void cvtMS168K(const unsigned char* src, int ns, unsigned char* dst)
256 {
257     unsigned char v;
258
259     while (ns--) {
260         v = C168(R16(src));             src += 2;
261         *dst++ = v;
262         *dst++ = v;
263     }
264 }
265
266 static  void cvtMS1616K(const unsigned char* src, int ns, unsigned char* dst)
267 {
268     short       v;
269
270     while (ns--) {
271         v = R16(src);           src += 2;
272         W16(dst, v);            dst += 2;
273         W16(dst, v);            dst += 2;
274     }
275 }
276
277 static  void cvtSM88K(const unsigned char* src, int ns, unsigned char* dst)
278 {
279     while (ns--) {
280         *dst++ = M8(src[0], src[1]);
281         src += 2;
282     }
283 }
284
285 static  void cvtSM816K(const unsigned char* src, int ns, unsigned char* dst)
286 {
287     short       v;
288
289     while (ns--) {
290         v = M16(C816(src[0]), C816(src[1]));
291         src += 2;
292         W16(dst, v);            dst += 2;
293     }
294 }
295
296 static  void cvtSM168K(const unsigned char* src, int ns, unsigned char* dst)
297 {
298     while (ns--) {
299         *dst++ = C168(M16(R16(src), R16(src + 2)));
300         src += 4;
301     }
302 }
303
304 static  void cvtSM1616K(const unsigned char* src, int ns, unsigned char* dst)
305 {
306     while (ns--) {
307         W16(dst, M16(R16(src),R16(src+2)));     dst += 2;
308         src += 4;
309     }
310 }
311
312 static  void cvtMM816K(const unsigned char* src, int ns, unsigned char* dst)
313 {
314     while (ns--) {
315         W16(dst, C816(*src++));         dst += 2;
316     }
317 }
318
319 static  void cvtSS816K(const unsigned char* src, int ns, unsigned char* dst)
320 {
321     while (ns--) {
322         W16(dst, C816(*src++)); dst += 2;
323         W16(dst, C816(*src++)); dst += 2;
324     }
325 }
326
327 static  void cvtMM168K(const unsigned char* src, int ns, unsigned char* dst)
328 {
329     while (ns--) {
330         *dst++ = C168(R16(src));        src += 2;
331     }
332 }
333
334 static  void cvtSS168K(const unsigned char* src, int ns, unsigned char* dst)
335 {
336     while (ns--) {
337         *dst++ = C168(R16(src));        src += 2;
338         *dst++ = C168(R16(src));        src += 2;
339     }
340 }
341
342 static  void (*PCM_ConvertKeepRate[16])(const unsigned char*, int, unsigned char*) = {
343     cvtSS88K,   cvtSM88K,   cvtMS88K,   cvtMM88K,
344     cvtSS816K,  cvtSM816K,  cvtMS816K,  cvtMM816K,
345     cvtSS168K,  cvtSM168K,  cvtMS168K,  cvtMM168K,
346     cvtSS1616K, cvtSM1616K, cvtMS1616K, cvtMM1616K,
347 };
348
349 /***********************************************************************
350  *           I
351  *
352  * Interpolate the value at r (r in ]0, 1]) between the two points v1 and v2
353  * Linear interpolation is used
354  */
355 static  inline double   I(double v1, double v2, double r)
356 {
357     if (0.0 >= r || r > 1.0) FIXME("r!! %f\n", r);
358     return (1.0 - r) * v1 + r * v2;
359 }
360
361 static  void cvtSS88C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,
362                       unsigned char* dst, LPDWORD ndst)
363 {
364     double              r;
365
366     while (*nsrc != 0 && *ndst != 0) {
367         while ((r = (double)apd->srcPos - apd->dstPos) <= 0) {
368             if (*nsrc == 0) return;
369             apd->last[0].b = *src++;
370             apd->last[1].b = *src++;
371             apd->srcPos++;
372             (*nsrc)--;
373         }
374         /* now do the interpolation */
375         *dst++ = I(apd->last[0].b, src[0], r);
376         *dst++ = I(apd->last[1].b, src[1], r);
377         apd->dstPos += apd->dstIncr;
378         (*ndst)--;
379     }
380 }
381
382 /* the conversion routines with rate conversion are labelled cvt<X><Y><N><M>C
383  * where :
384  * <X> is the (M)ono/(S)tereo configuration of  input channel
385  * <Y> is the (M)ono/(S)tereo configuration of output channel
386  * <N> is the number of bits of  input channel (8 or 16)
387  * <M> is the number of bits of output channel (8 or 16)
388  *
389  */
390 static  void cvtSM88C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,
391                       unsigned char* dst, LPDWORD ndst)
392 {
393     double      r;
394
395     while (*nsrc != 0 && *ndst != 0) {
396         while ((r = (double)apd->srcPos - apd->dstPos) <= 0) {
397             if (*nsrc == 0) return;
398             apd->last[0].b = *src++;
399             apd->last[1].b = *src++;
400             apd->srcPos++;
401             (*nsrc)--;
402         }
403         /* now do the interpolation */
404         *dst++ = I(M8(apd->last[0].b, apd->last[1].b), M8(src[0], src[1]), r);
405         apd->dstPos += apd->dstIncr;
406         (*ndst)--;
407     }
408 }
409
410 static  void cvtMS88C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,
411                       unsigned char* dst, LPDWORD ndst)
412 {
413     double      r;
414
415     while (*nsrc != 0 && *ndst != 0) {
416         while ((r = (double)apd->srcPos - apd->dstPos) <= 0) {
417             if (*nsrc == 0) return;
418             apd->last[0].b = *src++;
419             apd->srcPos++;
420             (*nsrc)--;
421         }
422         /* now do the interpolation */
423         dst[0] = dst[1] = I(apd->last[0].b, src[0], r);
424         dst += 2;
425         apd->dstPos += apd->dstIncr;
426         (*ndst)--;
427     }
428 }
429
430 static  void cvtMM88C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,
431                       unsigned char* dst, LPDWORD ndst)
432 {
433     double      r;
434
435     while (*nsrc != 0 && *ndst != 0) {
436         while ((r = (double)apd->srcPos - apd->dstPos) <= 0) {
437             if (*nsrc == 0) return;
438             apd->last[0].b = *src++;
439             apd->srcPos++;
440             (*nsrc)--;
441         }
442         /* now do the interpolation */
443         *dst++ = I(apd->last[0].b, src[0], r);
444         apd->dstPos += apd->dstIncr;
445         (*ndst)--;
446     }
447 }
448
449 static  void cvtSS816C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,
450                        unsigned char* dst, LPDWORD ndst)
451 {
452     double      r;
453
454     while (*nsrc != 0 && *ndst != 0) {
455         while ((r = (double)apd->srcPos - apd->dstPos) <= 0) {
456             if (*nsrc == 0) return;
457             apd->last[0].b = *src++;
458             apd->last[1].b = *src++;
459             apd->srcPos++;
460             (*nsrc)--;
461         }
462         /* now do the interpolation */
463         W16(dst, I(C816(apd->last[0].b), C816(src[0]), r));     dst += 2;
464         W16(dst, I(C816(apd->last[1].b), C816(src[1]), r));     dst += 2;
465         apd->dstPos += apd->dstIncr;
466         (*ndst)--;
467     }
468 }
469
470 static  void cvtSM816C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,
471                         unsigned char* dst, LPDWORD ndst)
472 {
473     double      r;
474
475     while (*nsrc != 0 && *ndst != 0) {
476         while ((r = (double)apd->srcPos - apd->dstPos) <= 0) {
477             if (*nsrc == 0) return;
478             apd->last[0].b = *src++;
479             apd->last[1].b = *src++;
480             apd->srcPos++;
481             (*nsrc)--;
482         }
483         /* now do the interpolation */
484         W16(dst, I(M16(C816(apd->last[0].b), C816(apd->last[1].b)),
485                     M16(C816(src[0]), C816(src[1])), r));
486         dst += 2;
487         apd->dstPos += apd->dstIncr;
488         (*ndst)--;
489     }
490 }
491
492 static  void cvtMS816C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,
493                         unsigned char* dst, LPDWORD ndst)
494 {
495     double      r;
496     short       v;
497
498     while (*nsrc != 0 && *ndst != 0) {
499         while ((r = (double)apd->srcPos - apd->dstPos) <= 0) {
500             if (*nsrc == 0) return;
501             apd->last[0].b = *src++;
502             apd->srcPos++;
503             (*nsrc)--;
504         }
505         /* now do the interpolation */
506         v = I(C816(apd->last[0].b), C816(src[0]), r);
507         W16(dst, v);            dst += 2;
508         W16(dst, v);            dst += 2;
509         apd->dstPos += apd->dstIncr;
510         (*ndst)--;
511     }
512 }
513
514 static  void cvtMM816C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,
515                         unsigned char* dst, LPDWORD ndst)
516 {
517     double      r;
518
519     while (*nsrc != 0 && *ndst != 0) {
520         while ((r = (double)apd->srcPos - apd->dstPos) <= 0) {
521             if (*nsrc == 0) return;
522             apd->last[0].b = *src++;
523             apd->srcPos++;
524             (*nsrc)--;
525         }
526         /* now do the interpolation */
527         W16(dst, I(C816(apd->last[0].b), C816(src[0]), r));
528         dst += 2;
529         apd->dstPos += apd->dstIncr;
530         (*ndst)--;
531     }
532 }
533
534 static  void cvtSS168C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,
535                         unsigned char* dst, LPDWORD ndst)
536 {
537     double      r;
538
539     while (*nsrc != 0 && *ndst != 0) {
540         while ((r = (double)apd->srcPos - apd->dstPos) <= 0) {
541             if (*nsrc == 0) return;
542             apd->last[0].s = R16(src);  src += 2;
543             apd->last[1].s = R16(src);  src += 2;
544             apd->srcPos++;
545             (*nsrc)--;
546         }
547         /* now do the interpolation */
548         *dst++ = C168(I(apd->last[0].s, R16(src)  , r));
549         *dst++ = C168(I(apd->last[1].s, R16(src+2), r));
550         apd->dstPos += apd->dstIncr;
551         (*ndst)--;
552     }
553 }
554
555 static  void cvtSM168C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,
556                         unsigned char* dst, LPDWORD ndst)
557 {
558     double      r;
559
560     while (*nsrc != 0 && *ndst != 0) {
561         while ((r = (double)apd->srcPos - apd->dstPos) <= 0) {
562             if (*nsrc == 0) return;
563             apd->last[0].s = R16(src);  src += 2;
564             apd->last[1].s = R16(src);  src += 2;
565             apd->srcPos++;
566             (*nsrc)--;
567         }
568         /* now do the interpolation */
569         *dst++ = C168(I(M16(apd->last[0].s, apd->last[1].s),
570                         M16(R16(src), R16(src + 2)), r));
571         apd->dstPos += apd->dstIncr;
572         (*ndst)--;
573     }
574 }
575
576
577 static  void cvtMS168C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,
578                         unsigned char* dst, LPDWORD ndst)
579 {
580     double      r;
581
582     while (*nsrc != 0 && *ndst != 0) {
583         while ((r = (double)apd->srcPos - apd->dstPos) <= 0) {
584             if (*nsrc == 0) return;
585             apd->last[0].s = R16(src);  src += 2;
586             apd->srcPos++;
587             (*nsrc)--;
588         }
589         /* now do the interpolation */
590         dst[0] = dst[1] = C168(I(apd->last[0].s, R16(src), r)); dst += 2;
591         apd->dstPos += apd->dstIncr;
592         (*ndst)--;
593     }
594 }
595
596
597 static  void cvtMM168C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,
598                         unsigned char* dst, LPDWORD ndst)
599 {
600     double      r;
601
602     while (*nsrc != 0 && *ndst != 0) {
603         while ((r = (double)apd->srcPos - apd->dstPos) <= 0) {
604             if (*nsrc == 0) return;
605             apd->last[0].s = R16(src);  src += 2;
606             apd->srcPos++;
607             (*nsrc)--;
608         }
609         /* now do the interpolation */
610         *dst++ = C168(I(apd->last[0].s, R16(src), r));
611         apd->dstPos += apd->dstIncr;
612         (*ndst)--;
613     }
614 }
615
616 static  void cvtSS1616C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,
617                         unsigned char* dst, LPDWORD ndst)
618 {
619     double      r;
620
621     while (*nsrc != 0 && *ndst != 0) {
622         while ((r = (double)apd->srcPos - apd->dstPos) <= 0) {
623             if (*nsrc == 0) return;
624             apd->last[0].s = R16(src);  src += 2;
625             apd->last[1].s = R16(src);  src += 2;
626             apd->srcPos++;
627             (*nsrc)--;
628         }
629         /* now do the interpolation */
630         W16(dst, I(apd->last[0].s, R16(src)  , r));     dst += 2;
631         W16(dst, I(apd->last[1].s, R16(src+2), r));     dst += 2;
632         apd->dstPos += apd->dstIncr;
633         (*ndst)--;
634     }
635 }
636
637 static  void cvtSM1616C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,
638                         unsigned char* dst, LPDWORD ndst)
639 {
640     double      r;
641
642     while (*nsrc != 0 && *ndst != 0) {
643         while ((r = (double)apd->srcPos - apd->dstPos) <= 0) {
644             if (*nsrc == 0) return;
645             apd->last[0].s = R16(src);  src += 2;
646             apd->last[1].s = R16(src);  src += 2;
647             apd->srcPos++;
648             (*nsrc)--;
649         }
650         /* now do the interpolation */
651         W16(dst, I(M16(apd->last[0].s, apd->last[1].s),
652                    M16(R16(src), R16(src+2)), r));
653         dst += 2;
654         apd->dstPos += apd->dstIncr;
655         (*ndst)--;
656     }
657 }
658
659 static  void cvtMS1616C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,
660                         unsigned char* dst, LPDWORD ndst)
661 {
662     double      r;
663     short       v;
664
665     while (*nsrc != 0 && *ndst != 0) {
666         while ((r = (double)apd->srcPos - apd->dstPos) <= 0) {
667             if (*nsrc == 0) return;
668             apd->last[0].s = R16(src);  src += 2;
669             apd->srcPos++;
670             (*nsrc)--;
671         }
672         /* now do the interpolation */
673         v = I(apd->last[0].s, R16(src), r);
674         W16(dst, v);            dst += 2;
675         W16(dst, v);            dst += 2;
676         apd->dstPos += apd->dstIncr;
677         (*ndst)--;
678     }
679 }
680
681 static  void cvtMM1616C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,
682                         unsigned char* dst, LPDWORD ndst)
683 {
684     double      r;
685
686     while (*nsrc != 0 && *ndst != 0) {
687         while ((r = (double)apd->srcPos - apd->dstPos) <= 0) {
688             if (*nsrc == 0) return;
689             apd->last[0].s = R16(src);  src += 2;
690             apd->srcPos++;
691             (*nsrc)--;
692         }
693         /* now do the interpolation */
694         W16(dst, I(apd->last[0].s, R16(src), r));       dst += 2;
695         apd->dstPos += apd->dstIncr;
696         (*ndst)--;
697     }
698 }
699
700 static  void (*PCM_ConvertChangeRate[16])(AcmPcmData* apd,
701                                           const unsigned char* src, LPDWORD nsrc,
702                                           unsigned char* dst, LPDWORD ndst) = {
703     cvtSS88C,   cvtSM88C,   cvtMS88C,   cvtMM88C,
704     cvtSS816C,  cvtSM816C,  cvtMS816C,  cvtMM816C,
705     cvtSS168C,  cvtSM168C,  cvtMS168C,  cvtMM168C,
706     cvtSS1616C, cvtSM1616C, cvtMS1616C, cvtMM1616C,
707 };
708
709 /***********************************************************************
710  *           PCM_DriverDetails
711  *
712  */
713 static  LRESULT PCM_DriverDetails(PACMDRIVERDETAILSW add)
714 {
715     add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
716     add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
717     add->wMid = 0xFF;
718     add->wPid = 0x00;
719     add->vdwACM = 0x01000000;
720     add->vdwDriver = 0x01000000;
721     add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CONVERTER;
722     add->cFormatTags = 1;
723     add->cFilterTags = 0;
724     add->hicon = NULL;
725     MultiByteToWideChar( CP_ACP, 0, "WINE-PCM", -1,
726                          add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) );
727     MultiByteToWideChar( CP_ACP, 0, "Wine PCM converter", -1,
728                          add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) );
729     MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
730                          add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) );
731     MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
732                          add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) );
733     add->szFeatures[0] = 0;
734
735     return MMSYSERR_NOERROR;
736 }
737
738 /***********************************************************************
739  *           PCM_FormatTagDetails
740  *
741  */
742 static  LRESULT PCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
743 {
744     switch (dwQuery) {
745     case ACM_FORMATTAGDETAILSF_INDEX:
746         if (aftd->dwFormatTagIndex != 0) return ACMERR_NOTPOSSIBLE;
747         break;
748     case ACM_FORMATTAGDETAILSF_FORMATTAG:
749         if (aftd->dwFormatTag != WAVE_FORMAT_PCM) return ACMERR_NOTPOSSIBLE;
750         break;
751     case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
752         if (aftd->dwFormatTag != WAVE_FORMAT_UNKNOWN &&
753             aftd->dwFormatTag != WAVE_FORMAT_PCM)
754             return ACMERR_NOTPOSSIBLE;
755         break;
756     default:
757         WARN("Unsupported query %08lx\n", dwQuery);
758         return MMSYSERR_NOTSUPPORTED;
759     }
760
761     aftd->dwFormatTagIndex = 0;
762     aftd->dwFormatTag = WAVE_FORMAT_PCM;
763     aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
764     aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CONVERTER;
765     aftd->cStandardFormats = NUM_PCM_FORMATS;
766     aftd->szFormatTag[0] = 0;
767
768     return MMSYSERR_NOERROR;
769 }
770
771 /***********************************************************************
772  *           PCM_FormatDetails
773  *
774  */
775 static  LRESULT PCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
776 {
777     switch (dwQuery) {
778     case ACM_FORMATDETAILSF_FORMAT:
779         if (PCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
780         break;
781     case ACM_FORMATDETAILSF_INDEX:
782         assert(afd->dwFormatIndex < NUM_PCM_FORMATS);
783         afd->pwfx->wFormatTag = WAVE_FORMAT_PCM;
784         afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
785         afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
786         afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
787         /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not
788          * accessible afd->pwfx->cbSize = 0;
789          */
790         afd->pwfx->nBlockAlign =
791             (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8;
792         afd->pwfx->nAvgBytesPerSec =
793             afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
794         break;
795     default:
796         WARN("Unsupported query %08lx\n", dwQuery);
797         return MMSYSERR_NOTSUPPORTED;
798     }
799
800     afd->dwFormatTag = WAVE_FORMAT_PCM;
801     afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CONVERTER;
802     afd->szFormat[0] = 0; /* let MSACM format this for us... */
803     afd->cbwfx = sizeof(PCMWAVEFORMAT);
804
805     return MMSYSERR_NOERROR;
806 }
807
808 /***********************************************************************
809  *           PCM_FormatSuggest
810  *
811  */
812 static  LRESULT PCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
813 {
814     /* some tests ... */
815     if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
816         adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
817         PCM_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
818
819     /* is no suggestion for destination, then copy source value */
820     if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS)) {
821         adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
822     }
823     if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC)) {
824         adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
825     }
826     if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE)) {
827         adfs->pwfxDst->wBitsPerSample = adfs->pwfxSrc->wBitsPerSample;
828     }
829     if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG)) {
830         if (adfs->pwfxSrc->wFormatTag != WAVE_FORMAT_PCM) return ACMERR_NOTPOSSIBLE;
831         adfs->pwfxDst->wFormatTag = adfs->pwfxSrc->wFormatTag;
832     }
833     /* check if result is ok */
834     if (PCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
835
836     /* recompute other values */
837     adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8;
838     adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
839
840     return MMSYSERR_NOERROR;
841 }
842
843 /***********************************************************************
844  *           PCM_Reset
845  *
846  */
847 static  void    PCM_Reset(AcmPcmData* apd, int srcNumBits)
848 {
849     apd->srcPos = 0;
850     apd->dstPos = 0;
851     /* initialize with neutral value */
852     if (srcNumBits == 16) {
853         apd->last[0].s = 0;
854         apd->last[1].s = 0;
855     } else {
856         apd->last[0].b = (BYTE)0x80;
857         apd->last[1].b = (BYTE)0x80;
858     }
859 }
860
861 /***********************************************************************
862  *           PCM_StreamOpen
863  *
864  */
865 static  LRESULT PCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
866 {
867     AcmPcmData* apd;
868     int         idx = 0;
869
870     assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
871
872     if (PCM_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
873         PCM_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
874         return ACMERR_NOTPOSSIBLE;
875
876     apd = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmPcmData));
877     if (apd == 0) return MMSYSERR_NOMEM;
878
879     adsi->dwDriver = (DWORD)apd;
880     adsi->fdwDriver = 0;
881
882     if (adsi->pwfxSrc->wBitsPerSample == 16) idx += 8;
883     if (adsi->pwfxDst->wBitsPerSample == 16) idx += 4;
884     if (adsi->pwfxSrc->nChannels      == 1)  idx += 2;
885     if (adsi->pwfxDst->nChannels      == 1)  idx += 1;
886
887     if (adsi->pwfxSrc->nSamplesPerSec == adsi->pwfxDst->nSamplesPerSec) {
888         apd->cvt.cvtKeepRate = PCM_ConvertKeepRate[idx];
889     } else {
890         adsi->fdwDriver |= PCM_RESAMPLE;
891         apd->dstIncr = (double)(adsi->pwfxSrc->nSamplesPerSec) /
892             (double)(adsi->pwfxDst->nSamplesPerSec);
893         PCM_Reset(apd, adsi->pwfxSrc->wBitsPerSample);
894         apd->cvt.cvtChangeRate = PCM_ConvertChangeRate[idx];
895     }
896
897     return MMSYSERR_NOERROR;
898 }
899
900 /***********************************************************************
901  *           PCM_StreamClose
902  *
903  */
904 static  LRESULT PCM_StreamClose(PACMDRVSTREAMINSTANCE adsi)
905 {
906     HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
907     return MMSYSERR_NOERROR;
908 }
909
910 /***********************************************************************
911  *           PCM_round
912  *
913  */
914 static  inline DWORD    PCM_round(DWORD a, DWORD b, DWORD c)
915 {
916     assert(a && b && c);
917     /* to be sure, always return an entire number of c... */
918     return ((double)a * (double)b + (double)c - 1) / (double)c;
919 }
920
921 /***********************************************************************
922  *           PCM_StreamSize
923  *
924  */
925 static  LRESULT PCM_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss)
926 {
927     DWORD       srcMask = ~(adsi->pwfxSrc->nBlockAlign - 1);
928     DWORD       dstMask = ~(adsi->pwfxDst->nBlockAlign - 1);
929
930     switch (adss->fdwSize) {
931     case ACM_STREAMSIZEF_DESTINATION:
932         /* cbDstLength => cbSrcLength */
933         adss->cbSrcLength = PCM_round(adss->cbDstLength & dstMask,
934                                       adsi->pwfxSrc->nAvgBytesPerSec,
935                                       adsi->pwfxDst->nAvgBytesPerSec) & srcMask;
936         break;
937     case ACM_STREAMSIZEF_SOURCE:
938         /* cbSrcLength => cbDstLength */
939         adss->cbDstLength =  PCM_round(adss->cbSrcLength & srcMask,
940                                        adsi->pwfxDst->nAvgBytesPerSec,
941                                        adsi->pwfxSrc->nAvgBytesPerSec) & dstMask;
942         break;
943     default:
944         WARN("Unsupported query %08lx\n", adss->fdwSize);
945         return MMSYSERR_NOTSUPPORTED;
946     }
947     return MMSYSERR_NOERROR;
948 }
949
950 /***********************************************************************
951  *           PCM_StreamConvert
952  *
953  */
954 static LRESULT PCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
955 {
956     AcmPcmData* apd = (AcmPcmData*)adsi->dwDriver;
957     DWORD       nsrc = NUM_OF(adsh->cbSrcLength, adsi->pwfxSrc->nBlockAlign);
958     DWORD       ndst = NUM_OF(adsh->cbDstLength, adsi->pwfxDst->nBlockAlign);
959
960     if (adsh->fdwConvert &
961         ~(ACM_STREAMCONVERTF_BLOCKALIGN|
962           ACM_STREAMCONVERTF_END|
963           ACM_STREAMCONVERTF_START)) {
964         FIXME("Unsupported fdwConvert (%08lx), ignoring it\n", adsh->fdwConvert);
965     }
966     /* ACM_STREAMCONVERTF_BLOCKALIGN
967      *  currently all conversions are block aligned, so do nothing for this flag
968      * ACM_STREAMCONVERTF_END
969      *  no pending data, so do nothing for this flag
970      */
971     if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START) &&
972         (adsi->fdwDriver & PCM_RESAMPLE)) {
973         PCM_Reset(apd, adsi->pwfxSrc->wBitsPerSample);
974     }
975
976     /* do the job */
977     if (adsi->fdwDriver & PCM_RESAMPLE) {
978         DWORD   nsrc2 = nsrc;
979         DWORD   ndst2 = ndst;
980
981         apd->cvt.cvtChangeRate(apd, adsh->pbSrc, &nsrc2, adsh->pbDst, &ndst2);
982         nsrc -= nsrc2;
983         ndst -= ndst2;
984     } else {
985         if (nsrc < ndst) ndst = nsrc; else nsrc = ndst;
986
987         /* nsrc is now equal to ndst */
988         apd->cvt.cvtKeepRate(adsh->pbSrc, nsrc, adsh->pbDst);
989     }
990
991     adsh->cbSrcLengthUsed = nsrc * adsi->pwfxSrc->nBlockAlign;
992     adsh->cbDstLengthUsed = ndst * adsi->pwfxDst->nBlockAlign;
993
994     return MMSYSERR_NOERROR;
995 }
996
997 /**************************************************************************
998  *                      DriverProc (MSACM32.@)
999  */
1000 LRESULT CALLBACK        PCM_DriverProc(DWORD dwDevID, HDRVR hDriv, UINT wMsg,
1001                                        LPARAM dwParam1, LPARAM dwParam2)
1002 {
1003     TRACE("(%08lx %08lx %u %08lx %08lx);\n",
1004           dwDevID, (DWORD)hDriv, wMsg, dwParam1, dwParam2);
1005
1006     switch (wMsg) {
1007     case DRV_LOAD:              return 1;
1008     case DRV_FREE:              return 1;
1009     case DRV_OPEN:              return PCM_drvOpen((LPSTR)dwParam1, (PACMDRVOPENDESCW)dwParam2);
1010     case DRV_CLOSE:             return PCM_drvClose(dwDevID);
1011     case DRV_ENABLE:            return 1;
1012     case DRV_DISABLE:           return 1;
1013     case DRV_QUERYCONFIGURE:    return 1;
1014     case DRV_CONFIGURE:         MessageBoxA(0, "MSACM PCM filter !", "Wine Driver", MB_OK); return 1;
1015     case DRV_INSTALL:           return DRVCNF_RESTART;
1016     case DRV_REMOVE:            return DRVCNF_RESTART;
1017
1018     case ACMDM_DRIVER_NOTIFY:
1019         /* no caching from other ACM drivers is done so far */
1020         return MMSYSERR_NOERROR;
1021
1022     case ACMDM_DRIVER_DETAILS:
1023         return PCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
1024
1025     case ACMDM_FORMATTAG_DETAILS:
1026         return PCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
1027
1028     case ACMDM_FORMAT_DETAILS:
1029         return PCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
1030
1031     case ACMDM_FORMAT_SUGGEST:
1032         return PCM_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
1033
1034     case ACMDM_STREAM_OPEN:
1035         return PCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
1036
1037     case ACMDM_STREAM_CLOSE:
1038         return PCM_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
1039
1040     case ACMDM_STREAM_SIZE:
1041         return PCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
1042
1043     case ACMDM_STREAM_CONVERT:
1044         return PCM_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
1045
1046     case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
1047     case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
1048         /* this converter is not a hardware driver */
1049     case ACMDM_FILTERTAG_DETAILS:
1050     case ACMDM_FILTER_DETAILS:
1051         /* this converter is not a filter */
1052     case ACMDM_STREAM_RESET:
1053         /* only needed for asynchronous driver... we aren't, so just say it */
1054     case ACMDM_STREAM_PREPARE:
1055     case ACMDM_STREAM_UNPREPARE:
1056         /* nothing special to do here... so don't do anything */
1057         return MMSYSERR_NOTSUPPORTED;
1058
1059     default:
1060         return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1061     }
1062     return 0;
1063 }