msxml3: Fix parameter validation for endElement().
[wine] / dlls / imaadp32.acm / imaadp32.c
1 /*
2  * IMA ADPCM handling
3  *
4  *      Copyright (C) 2001,2002         Eric Pouech
5  *
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <assert.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winnls.h"
30 #include "mmsystem.h"
31 #include "mmreg.h"
32 #include "msacm.h"
33 #include "msacmdrv.h"
34 #include "wine/debug.h"
35
36 /* see http://www.pcisys.net/~melanson/codecs/adpcm.txt for the details */
37
38 WINE_DEFAULT_DEBUG_CHANNEL(adpcm);
39
40 /***********************************************************************
41  *           ADPCM_drvClose
42  */
43 static LRESULT ADPCM_drvClose(DWORD_PTR dwDevID)
44 {
45     return 1;
46 }
47
48 typedef struct tagAcmAdpcmData
49 {
50     void (*convert)(PACMDRVSTREAMINSTANCE adsi,
51                     const unsigned char*, LPDWORD, unsigned char*, LPDWORD);
52     /* IMA encoding only */
53     BYTE        stepIndexL;
54     BYTE        stepIndexR;
55     /* short    sample; */
56 } AcmAdpcmData;
57
58 /* table to list all supported formats... those are the basic ones. this
59  * also helps given a unique index to each of the supported formats
60  */
61 typedef struct
62 {
63     int         nChannels;
64     int         nBits;
65     int         rate;
66 } Format;
67
68 static const Format PCM_Formats[] =
69 {
70     {1,  8,  8000}, {2,  8,  8000}, {1, 16,  8000}, {2, 16,  8000},
71     {1,  8, 11025}, {2,  8, 11025}, {1, 16, 11025}, {2, 16, 11025},
72     {1,  8, 22050}, {2,  8, 22050}, {1, 16, 22050}, {2, 16, 22050},
73     {1,  8, 44100}, {2,  8, 44100}, {1, 16, 44100}, {2, 16, 44100},
74 };
75
76 static const Format ADPCM_Formats[] =
77 {
78     {1,  4,  8000}, {2, 4,  8000},  {1,  4, 11025}, {2,  4, 11025},
79     {1,  4, 22050}, {2, 4, 22050},  {1,  4, 44100}, {2,  4, 44100},
80 };
81
82 #define NUM_PCM_FORMATS         (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
83 #define NUM_ADPCM_FORMATS       (sizeof(ADPCM_Formats) / sizeof(ADPCM_Formats[0]))
84
85 /***********************************************************************
86  *           ADPCM_GetFormatIndex
87  */
88 static  DWORD   ADPCM_GetFormatIndex(const WAVEFORMATEX *wfx)
89 {
90     int             i, hi;
91     const Format*   fmts;
92
93     switch (wfx->wFormatTag)
94     {
95     case WAVE_FORMAT_PCM:
96         hi = NUM_PCM_FORMATS;
97         fmts = PCM_Formats;
98         break;
99     case WAVE_FORMAT_IMA_ADPCM:
100         hi = NUM_ADPCM_FORMATS;
101         fmts = ADPCM_Formats;
102         break;
103     default:
104         return 0xFFFFFFFF;
105     }
106
107     for (i = 0; i < hi; i++)
108     {
109         if (wfx->nChannels == fmts[i].nChannels &&
110             wfx->nSamplesPerSec == fmts[i].rate &&
111             wfx->wBitsPerSample == fmts[i].nBits)
112             return i;
113     }
114
115     switch (wfx->wFormatTag)
116     {
117     case WAVE_FORMAT_PCM:
118         if(3 > wfx->nChannels &&
119            wfx->nChannels > 0 &&
120            wfx->nAvgBytesPerSec == 2 * wfx->nSamplesPerSec * wfx->nChannels &&
121            wfx->nBlockAlign == 2 * wfx->nChannels &&
122            wfx->wBitsPerSample == 16)
123            return hi;
124         break;
125     case WAVE_FORMAT_IMA_ADPCM:
126         if(3 > wfx->nChannels &&
127            wfx->nChannels > 0 &&
128            wfx->wBitsPerSample == 4 &&
129            wfx->cbSize == 2)
130            return hi;
131         break;
132     }
133
134     return 0xFFFFFFFF;
135 }
136
137 static void     init_wfx_ima_adpcm(IMAADPCMWAVEFORMAT* awfx/*, DWORD nba*/)
138 {
139     register WAVEFORMATEX*      pwfx = &awfx->wfx;
140
141     /* we assume wFormatTag, nChannels, nSamplesPerSec and wBitsPerSample
142      * have been initialized... */
143
144     if (pwfx->wFormatTag != WAVE_FORMAT_IMA_ADPCM) {FIXME("wrong FT\n"); return;}
145     if (ADPCM_GetFormatIndex(pwfx) == 0xFFFFFFFF) {FIXME("wrong fmt\n"); return;}
146
147     switch (pwfx->nSamplesPerSec)
148     {
149     case  8000: pwfx->nBlockAlign = 256 * pwfx->nChannels;   break;
150     case 11025: pwfx->nBlockAlign = 256 * pwfx->nChannels;   break;
151     case 22050: pwfx->nBlockAlign = 512 * pwfx->nChannels;   break;
152     case 44100: pwfx->nBlockAlign = 1024 * pwfx->nChannels;  break;
153     default: /*pwfx->nBlockAlign = nba;*/  break;
154     }
155     pwfx->cbSize = sizeof(WORD);
156
157     awfx->wSamplesPerBlock = (pwfx->nBlockAlign - (4 * pwfx->nChannels) * 2) / pwfx->nChannels + 1;
158     pwfx->nAvgBytesPerSec = (pwfx->nSamplesPerSec * pwfx->nBlockAlign) / awfx->wSamplesPerBlock;
159 }
160
161 /***********************************************************************
162  *           R16
163  *
164  * Read a 16 bit sample (correctly handles endianness)
165  */
166 static inline short  R16(const unsigned char* src)
167 {
168     return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));
169 }
170
171 /***********************************************************************
172  *           W16
173  *
174  * Write a 16 bit sample (correctly handles endianness)
175  */
176 static inline void  W16(unsigned char* dst, short s)
177 {
178     dst[0] = LOBYTE(s);
179     dst[1] = HIBYTE(s);
180 }
181
182 /* IMA (or DVI) APDCM codec routines */
183
184 static const unsigned IMA_StepTable[89] =
185 {
186     7, 8, 9, 10, 11, 12, 13, 14,
187     16, 17, 19, 21, 23, 25, 28, 31,
188     34, 37, 41, 45, 50, 55, 60, 66,
189     73, 80, 88, 97, 107, 118, 130, 143,
190     157, 173, 190, 209, 230, 253, 279, 307,
191     337, 371, 408, 449, 494, 544, 598, 658,
192     724, 796, 876, 963, 1060, 1166, 1282, 1411,
193     1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
194     3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
195     7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
196     15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
197     32767
198 };
199
200 static const int IMA_IndexTable[16] =
201 {
202     -1, -1, -1, -1, 2, 4, 6, 8,
203     -1, -1, -1, -1, 2, 4, 6, 8
204 };
205
206 static inline void clamp_step_index(int* stepIndex)
207 {
208     if (*stepIndex < 0 ) *stepIndex = 0;
209     if (*stepIndex > 88) *stepIndex = 88;
210 }
211
212 static inline void clamp_sample(int* sample)
213 {
214     if (*sample < -32768) *sample = -32768;
215     if (*sample >  32767) *sample =  32767;
216 }
217
218 static inline void process_nibble(unsigned char code, int* stepIndex, int* sample)
219 {
220     unsigned step;
221     int diff;
222
223     code &= 0x0F;
224
225     step = IMA_StepTable[*stepIndex];
226     diff = step >> 3;
227     if (code & 1) diff += step >> 2;
228     if (code & 2) diff += step >> 1;
229     if (code & 4) diff += step;
230     if (code & 8)       *sample -= diff;
231     else                *sample += diff;
232     clamp_sample(sample);
233     *stepIndex += IMA_IndexTable[code];
234     clamp_step_index(stepIndex);
235 }
236
237 static inline unsigned char generate_nibble(int in, int* stepIndex, int* sample)
238 {
239     int effdiff, diff = in - *sample;
240     unsigned step;
241     unsigned char code;
242
243     if (diff < 0)
244     {
245         diff = -diff;
246         code = 8;
247     }
248     else
249     {
250         code = 0;
251     }
252
253     step = IMA_StepTable[*stepIndex];
254     effdiff = (step >> 3);
255     if (diff >= step)
256     {
257         code |= 4;
258         diff -= step;
259         effdiff += step;
260     }
261     step >>= 1;
262     if (diff >= step)
263     {
264         code |= 2;
265         diff -= step;
266         effdiff += step;
267     }
268     step >>= 1;
269     if (diff >= step)
270     {
271         code |= 1;
272         effdiff += step;
273     }
274     if (code & 8)       *sample -= effdiff;
275     else                *sample += effdiff;
276     clamp_sample(sample);
277     *stepIndex += IMA_IndexTable[code];
278     clamp_step_index(stepIndex);
279     return code;
280 }
281
282 static  void cvtSSima16K(PACMDRVSTREAMINSTANCE adsi,
283                          const unsigned char* src, LPDWORD nsrc,
284                          unsigned char* dst, LPDWORD ndst)
285 {
286     int         i;
287     int         sampleL, sampleR;
288     int         stepIndexL, stepIndexR;
289     int         nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
290     int         nsamp;
291     /* compute the number of entire blocks we can decode...
292      * it's the min of the number of entire blocks in source buffer and the number
293      * of entire blocks in destination buffer
294      */
295     DWORD       nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign,
296                              *ndst / (nsamp_blk * 2 * 2));
297
298     *nsrc = nblock * adsi->pwfxSrc->nBlockAlign;
299     *ndst = nblock * (nsamp_blk * 2 * 2);
300
301     nsamp_blk--; /* remove the sample in block header */
302     for (; nblock > 0; nblock--)
303     {
304         const unsigned char* in_src = src;
305
306         /* handle headers first */
307         sampleL = R16(src);
308         stepIndexL = (unsigned)*(src + 2);
309         clamp_step_index(&stepIndexL);
310         src += 4;
311         W16(dst, sampleL);      dst += 2;
312
313         sampleR = R16(src);
314         stepIndexR = (unsigned)*(src + 2);
315         clamp_step_index(&stepIndexR);
316         src += 4;
317         W16(dst, sampleR);      dst += 2;
318
319         for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 8)
320         {
321             for (i = 0; i < 4; i++)
322             {
323                 process_nibble(*src, &stepIndexL, &sampleL);
324                 W16(dst + (2 * i + 0) * 4 + 0, sampleL);
325                 process_nibble(*src++ >> 4, &stepIndexL, &sampleL);
326                 W16(dst + (2 * i + 1) * 4 + 0, sampleL);
327             }
328             for (i = 0; i < 4; i++)
329             {
330                 process_nibble(*src , &stepIndexR, &sampleR);
331                 W16(dst + (2 * i + 0) * 4 + 2, sampleR);
332                 process_nibble(*src++ >>4, &stepIndexR, &sampleR);
333                 W16(dst + (2 * i + 1) * 4 + 2, sampleR);
334             }
335             dst += 32;
336         }
337         /* we have now to realign the source pointer on block */
338         src = in_src + adsi->pwfxSrc->nBlockAlign;
339     }
340 }
341
342 static  void cvtMMima16K(PACMDRVSTREAMINSTANCE adsi,
343                          const unsigned char* src, LPDWORD nsrc,
344                          unsigned char* dst, LPDWORD ndst)
345 {
346     int         sample;
347     int         stepIndex;
348     int         nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
349     int         nsamp;
350     /* compute the number of entire blocks we can decode...
351      * it's the min of the number of entire blocks in source buffer and the number
352      * of entire blocks in destination buffer
353      */
354     DWORD       nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign,
355                              *ndst / (nsamp_blk * 2));
356
357     *nsrc = nblock * adsi->pwfxSrc->nBlockAlign;
358     *ndst = nblock * nsamp_blk * 2;
359
360     nsamp_blk--; /* remove the sample in block header */
361     for (; nblock > 0; nblock--)
362     {
363         const unsigned char*    in_src = src;
364
365         /* handle header first */
366         sample = R16(src);
367         stepIndex = (unsigned)*(src + 2);
368         clamp_step_index(&stepIndex);
369         src += 4;
370         W16(dst, sample);       dst += 2;
371
372         for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
373         {
374             process_nibble(*src, &stepIndex, &sample);
375             W16(dst, sample); dst += 2;
376             process_nibble(*src++ >> 4, &stepIndex, &sample);
377             W16(dst, sample); dst += 2;
378         }
379         /* we have now to realign the source pointer on block */
380         src = in_src + adsi->pwfxSrc->nBlockAlign;
381     }
382 }
383
384 static  void cvtSS16imaK(PACMDRVSTREAMINSTANCE adsi,
385                          const unsigned char* src, LPDWORD nsrc,
386                          unsigned char* dst, LPDWORD ndst)
387 {
388     int         stepIndexL, stepIndexR;
389     int         sampleL, sampleR;
390     BYTE        code1, code2;
391     int         nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock;
392     int         i, nsamp;
393     /* compute the number of entire blocks we can decode...
394      * it's the min of the number of entire blocks in source buffer and the number
395      * of entire blocks in destination buffer
396      */
397     DWORD       nblock = min(*nsrc / (nsamp_blk * 2 * 2),
398                              *ndst / adsi->pwfxDst->nBlockAlign);
399
400     *nsrc = nblock * (nsamp_blk * 2 * 2);
401     *ndst = nblock * adsi->pwfxDst->nBlockAlign;
402
403     stepIndexL = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL;
404     stepIndexR = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexR;
405
406     nsamp_blk--; /* so that we won't count the sample in header while filling the block */
407
408     for (; nblock > 0; nblock--)
409     {
410         unsigned char*   in_dst = dst;
411
412         /* generate header */
413         sampleL = R16(src);  src += 2;
414         W16(dst, sampleL); dst += 2;
415         *dst = (unsigned char)(unsigned)stepIndexL;
416         dst += 2;
417
418         sampleR = R16(src); src += 2;
419         W16(dst, sampleR); dst += 2;
420         *dst = (unsigned char)(unsigned)stepIndexR;
421         dst += 2;
422
423         for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 8)
424         {
425             for (i = 0; i < 4; i++)
426             {
427                 code1 = generate_nibble(R16(src + (2 * i + 0) * 2 + 0),
428                                         &stepIndexL, &sampleL);
429                 code2 = generate_nibble(R16(src + (2 * i + 1) * 2 + 0),
430                                         &stepIndexL, &sampleL);
431                 *dst++ = (code1 << 4) | code2;
432             }
433             for (i = 0; i < 4; i++)
434             {
435                 code1 = generate_nibble(R16(src + (2 * i + 0) * 2 + 1),
436                                         &stepIndexR, &sampleR);
437                 code2 = generate_nibble(R16(src + (2 * i + 1) * 2 + 1),
438                                         &stepIndexR, &sampleR);
439                 *dst++ = (code1 << 4) | code2;
440             }
441             src += 32;
442         }
443         dst = in_dst + adsi->pwfxDst->nBlockAlign;
444     }
445     ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL = stepIndexL;
446     ((AcmAdpcmData*)adsi->dwDriver)->stepIndexR = stepIndexR;
447 }
448
449 static  void cvtMM16imaK(PACMDRVSTREAMINSTANCE adsi,
450                          const unsigned char* src, LPDWORD nsrc,
451                          unsigned char* dst, LPDWORD ndst)
452 {
453     int         stepIndex;
454     int         sample;
455     BYTE        code1, code2;
456     int         nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock;
457     int         nsamp;
458     /* compute the number of entire blocks we can decode...
459      * it's the min of the number of entire blocks in source buffer and the number
460      * of entire blocks in destination buffer
461      */
462     DWORD       nblock = min(*nsrc / (nsamp_blk * 2),
463                              *ndst / adsi->pwfxDst->nBlockAlign);
464
465     *nsrc = nblock * (nsamp_blk * 2);
466     *ndst = nblock * adsi->pwfxDst->nBlockAlign;
467
468     stepIndex = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL;
469     nsamp_blk--; /* so that we won't count the sample in header while filling the block */
470
471     for (; nblock > 0; nblock--)
472     {
473         unsigned char*   in_dst = dst;
474
475         /* generate header */
476         /* FIXME: what about the last effective sample from previous block ??? */
477         /* perhaps something like:
478          *      sample += R16(src);
479          *      clamp_sample(sample);
480          * and with :
481          *      + saving the sample in adsi->dwDriver when all blocks are done
482          +      + reset should set the field in adsi->dwDriver to 0 too
483          */
484         sample = R16(src); src += 2;
485         W16(dst, sample); dst += 2;
486         *dst = (unsigned char)(unsigned)stepIndex;
487         dst += 2;
488
489         for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
490         {
491             code1 = generate_nibble(R16(src), &stepIndex, &sample);
492             src += 2;
493             code2 = generate_nibble(R16(src), &stepIndex, &sample);
494             src += 2;
495             *dst++ = (code1 << 4) | code2;
496         }
497         dst = in_dst + adsi->pwfxDst->nBlockAlign;
498     }
499     ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL = stepIndex;
500 }
501
502 /***********************************************************************
503  *           ADPCM_DriverDetails
504  *
505  */
506 static  LRESULT ADPCM_DriverDetails(PACMDRIVERDETAILSW add)
507 {
508     add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
509     add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
510     add->wMid = 0x1;
511     add->wPid = 0x22;
512     add->vdwACM = 0x3320000;
513     add->vdwDriver = 0x04000000;
514     add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
515     add->cFormatTags = 2; /* PCM, IMA ADPCM */
516     add->cFilterTags = 0;
517     add->hicon = NULL;
518     MultiByteToWideChar( CP_ACP, 0, "Microsoft IMA ADPCM", -1,
519                          add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) );
520     MultiByteToWideChar( CP_ACP, 0, "Microsoft IMA ADPCM CODEC", -1,
521                          add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) );
522     MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
523                          add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) );
524     MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
525                          add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) );
526     add->szFeatures[0] = 0;
527
528     return MMSYSERR_NOERROR;
529 }
530
531 /***********************************************************************
532  *           ADPCM_FormatTagDetails
533  *
534  */
535 static  LRESULT ADPCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
536 {
537     static const WCHAR szPcm[]={'P','C','M',0};
538     static const WCHAR szImaAdPcm[]={'I','M','A',' ','A','D','P','C','M',0};
539
540     switch (dwQuery)
541     {
542     case ACM_FORMATTAGDETAILSF_INDEX:
543         if (aftd->dwFormatTagIndex >= 2) return ACMERR_NOTPOSSIBLE;
544         break;
545     case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
546         if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
547         {
548             aftd->dwFormatTagIndex = 1; /* WAVE_FORMAT_IMA_ADPCM is bigger than PCM */
549             break;
550         }
551         /* fall thru */
552     case ACM_FORMATTAGDETAILSF_FORMATTAG:
553         switch (aftd->dwFormatTag)
554         {
555         case WAVE_FORMAT_PCM:           aftd->dwFormatTagIndex = 0; break;
556         case WAVE_FORMAT_IMA_ADPCM:     aftd->dwFormatTagIndex = 1; break;
557         default:                        return ACMERR_NOTPOSSIBLE;
558         }
559         break;
560     default:
561         WARN("Unsupported query %08x\n", dwQuery);
562         return MMSYSERR_NOTSUPPORTED;
563     }
564
565     aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
566     switch (aftd->dwFormatTagIndex)
567     {
568     case 0:
569         aftd->dwFormatTag = WAVE_FORMAT_PCM;
570         aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
571         aftd->cStandardFormats = NUM_PCM_FORMATS;
572         lstrcpyW(aftd->szFormatTag, szPcm);
573         break;
574     case 1:
575         aftd->dwFormatTag = WAVE_FORMAT_IMA_ADPCM;
576         aftd->cbFormatSize = sizeof(IMAADPCMWAVEFORMAT);
577         aftd->cStandardFormats = NUM_ADPCM_FORMATS;
578         lstrcpyW(aftd->szFormatTag, szImaAdPcm);
579         break;
580     }
581     return MMSYSERR_NOERROR;
582 }
583
584 /***********************************************************************
585  *           ADPCM_FormatDetails
586  *
587  */
588 static  LRESULT ADPCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
589 {
590     switch (dwQuery)
591     {
592     case ACM_FORMATDETAILSF_FORMAT:
593         if (ADPCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
594         break;
595     case ACM_FORMATDETAILSF_INDEX:
596         afd->pwfx->wFormatTag = afd->dwFormatTag;
597         switch (afd->dwFormatTag)
598         {
599         case WAVE_FORMAT_PCM:
600             if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE;
601             afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
602             afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
603             afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
604             /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible
605              * afd->pwfx->cbSize = 0;
606              */
607             afd->pwfx->nBlockAlign =
608                 (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8;
609             afd->pwfx->nAvgBytesPerSec =
610                 afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
611             break;
612         case WAVE_FORMAT_IMA_ADPCM:
613             if (afd->dwFormatIndex >= NUM_ADPCM_FORMATS) return ACMERR_NOTPOSSIBLE;
614             afd->pwfx->nChannels = ADPCM_Formats[afd->dwFormatIndex].nChannels;
615             afd->pwfx->nSamplesPerSec = ADPCM_Formats[afd->dwFormatIndex].rate;
616             afd->pwfx->wBitsPerSample = ADPCM_Formats[afd->dwFormatIndex].nBits;
617             afd->pwfx->nBlockAlign = 1024;
618             /* we got 4 bits per sample */
619             afd->pwfx->nAvgBytesPerSec =
620                 (afd->pwfx->nSamplesPerSec * 4) / 8;
621             if (afd->cbwfx >= sizeof(WAVEFORMATEX))
622                 afd->pwfx->cbSize = sizeof(WORD);
623             if (afd->cbwfx >= sizeof(IMAADPCMWAVEFORMAT))
624                 ((IMAADPCMWAVEFORMAT*)afd->pwfx)->wSamplesPerBlock = (1024 - 4 * afd->pwfx->nChannels) * (2 / afd->pwfx->nChannels) + 1;
625             break;
626         default:
627             WARN("Unsupported tag %08x\n", afd->dwFormatTag);
628             return MMSYSERR_INVALPARAM;
629         }
630         break;
631     default:
632         WARN("Unsupported query %08x\n", dwQuery);
633         return MMSYSERR_NOTSUPPORTED;
634     }
635     afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
636     afd->szFormat[0] = 0; /* let MSACM format this for us... */
637
638     return MMSYSERR_NOERROR;
639 }
640
641 /***********************************************************************
642  *           ADPCM_FormatSuggest
643  *
644  */
645 static  LRESULT ADPCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
646 {
647     /* some tests ... */
648     if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
649         adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
650         adfs->pwfxSrc->wFormatTag == adfs->pwfxDst->wFormatTag ||
651         ADPCM_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
652
653     /* If no suggestion for destination, then copy source value */
654     if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS))
655         adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
656     if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC))
657         adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
658
659     if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE))
660     {
661         if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
662             adfs->pwfxDst->wBitsPerSample = 4;
663         else
664             adfs->pwfxDst->wBitsPerSample = 16;
665     }
666     if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
667     {
668         if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
669             adfs->pwfxDst->wFormatTag = WAVE_FORMAT_IMA_ADPCM;
670         else
671             adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM;
672     }
673
674     /* recompute other values */
675     switch (adfs->pwfxDst->wFormatTag)
676     {
677     case WAVE_FORMAT_PCM:
678         if (adfs->cbwfxSrc < sizeof(IMAADPCMWAVEFORMAT)) return ACMERR_NOTPOSSIBLE;
679         adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8;
680         adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
681         /* check if result is ok */
682         if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
683         break;
684     case WAVE_FORMAT_IMA_ADPCM:
685         if (adfs->cbwfxDst < sizeof(IMAADPCMWAVEFORMAT)) return ACMERR_NOTPOSSIBLE;
686         init_wfx_ima_adpcm((IMAADPCMWAVEFORMAT*)adfs->pwfxDst);
687         /* FIXME: not handling header overhead */
688         TRACE("setting spb=%u\n", ((IMAADPCMWAVEFORMAT*)adfs->pwfxDst)->wSamplesPerBlock);
689         /* check if result is ok */
690         if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
691         break;
692     default:
693         return ACMERR_NOTPOSSIBLE;
694     }
695
696     return MMSYSERR_NOERROR;
697 }
698
699 /***********************************************************************
700  *           ADPCM_Reset
701  *
702  */
703 static  void    ADPCM_Reset(PACMDRVSTREAMINSTANCE adsi, AcmAdpcmData* aad)
704 {
705     aad->stepIndexL = aad->stepIndexR = 0;
706 }
707
708 /***********************************************************************
709  *           ADPCM_StreamOpen
710  *
711  */
712 static  LRESULT ADPCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
713 {
714     AcmAdpcmData*       aad;
715     unsigned            nspb;
716
717     assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
718
719     if (ADPCM_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
720         ADPCM_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
721         return ACMERR_NOTPOSSIBLE;
722
723     aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmAdpcmData));
724     if (aad == 0) return MMSYSERR_NOMEM;
725
726     adsi->dwDriver = (DWORD_PTR)aad;
727
728     if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
729         adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
730     {
731         goto theEnd;
732     }
733     else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
734              adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
735     {
736         /* resampling or mono <=> stereo not available
737          * ADPCM algo only define 16 bit per sample output
738          */
739         if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
740             adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
741             adsi->pwfxDst->wBitsPerSample != 16)
742             goto theEnd;
743
744         nspb = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
745         TRACE("spb=%u\n", nspb);
746
747         /* we check that in a block, after the header, samples are present on
748          * 4-sample packet pattern
749          * we also check that the block alignment is bigger than the expected size
750          */
751         if (((nspb - 1) & 3) != 0) goto theEnd;
752         if ((((nspb - 1) / 2) + 4) * adsi->pwfxSrc->nChannels < adsi->pwfxSrc->nBlockAlign)
753             goto theEnd;
754
755         /* adpcm decoding... */
756         if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 2)
757             aad->convert = cvtSSima16K;
758         if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 1)
759             aad->convert = cvtMMima16K;
760     }
761     else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
762              adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM)
763     {
764         if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
765             adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
766             adsi->pwfxSrc->wBitsPerSample != 16)
767             goto theEnd;
768
769         nspb = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock;
770         TRACE("spb=%u\n", nspb);
771
772         /* we check that in a block, after the header, samples are present on
773          * 4-sample packet pattern
774          * we also check that the block alignment is bigger than the expected size
775          */
776         if (((nspb - 1) & 3) != 0) goto theEnd;
777         if ((((nspb - 1) / 2) + 4) * adsi->pwfxDst->nChannels < adsi->pwfxDst->nBlockAlign)
778             goto theEnd;
779
780         /* adpcm coding... */
781         if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 2)
782             aad->convert = cvtSS16imaK;
783         if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 1)
784             aad->convert = cvtMM16imaK;
785     }
786     else goto theEnd;
787     ADPCM_Reset(adsi, aad);
788
789     return MMSYSERR_NOERROR;
790
791  theEnd:
792     HeapFree(GetProcessHeap(), 0, aad);
793     adsi->dwDriver = 0L;
794     return MMSYSERR_NOTSUPPORTED;
795 }
796
797 /***********************************************************************
798  *           ADPCM_StreamClose
799  *
800  */
801 static  LRESULT ADPCM_StreamClose(PACMDRVSTREAMINSTANCE adsi)
802 {
803     HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
804     return MMSYSERR_NOERROR;
805 }
806
807 /***********************************************************************
808  *           ADPCM_StreamSize
809  *
810  */
811 static  LRESULT ADPCM_StreamSize(const ACMDRVSTREAMINSTANCE *adsi, PACMDRVSTREAMSIZE adss)
812 {
813     DWORD nblocks;
814
815     switch (adss->fdwSize)
816     {
817     case ACM_STREAMSIZEF_DESTINATION:
818         /* cbDstLength => cbSrcLength */
819         if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
820             adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM)
821         {
822             nblocks = adss->cbDstLength / adsi->pwfxDst->nBlockAlign;
823             if (nblocks == 0)
824                 return ACMERR_NOTPOSSIBLE;
825             adss->cbSrcLength = nblocks * adsi->pwfxSrc->nBlockAlign * ((IMAADPCMWAVEFORMAT*)adsi->pwfxDst)->wSamplesPerBlock;
826         }
827         else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
828                  adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
829         {
830             nblocks = adss->cbDstLength / (adsi->pwfxDst->nBlockAlign * ((IMAADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock);
831             if (nblocks == 0)
832                 return ACMERR_NOTPOSSIBLE;
833             adss->cbSrcLength = nblocks * adsi->pwfxSrc->nBlockAlign;
834         }
835         else
836         {
837             return MMSYSERR_NOTSUPPORTED;
838         }
839         break;
840     case ACM_STREAMSIZEF_SOURCE:
841         /* cbSrcLength => cbDstLength */
842         if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
843             adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM)
844         {
845             nblocks = adss->cbSrcLength / (adsi->pwfxSrc->nBlockAlign * ((IMAADPCMWAVEFORMAT*)adsi->pwfxDst)->wSamplesPerBlock);
846             if (nblocks == 0)
847                 return ACMERR_NOTPOSSIBLE;
848             if (adss->cbSrcLength % (adsi->pwfxSrc->nBlockAlign * ((IMAADPCMWAVEFORMAT*)adsi->pwfxDst)->wSamplesPerBlock))
849                 /* Round block count up. */
850                 nblocks++;
851             adss->cbDstLength = nblocks * adsi->pwfxDst->nBlockAlign;
852         }
853         else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
854                  adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
855         {
856             nblocks = adss->cbSrcLength / adsi->pwfxSrc->nBlockAlign;
857             if (nblocks == 0)
858                 return ACMERR_NOTPOSSIBLE;
859             if (adss->cbSrcLength % adsi->pwfxSrc->nBlockAlign)
860                 /* Round block count up. */
861                 nblocks++;
862             adss->cbDstLength = nblocks * adsi->pwfxDst->nBlockAlign * ((IMAADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock;
863         }
864         else
865         {
866             return MMSYSERR_NOTSUPPORTED;
867         }
868         break;
869     default:
870         WARN("Unsupported query %08x\n", adss->fdwSize);
871         return MMSYSERR_NOTSUPPORTED;
872     }
873     return MMSYSERR_NOERROR;
874 }
875
876 /***********************************************************************
877  *           ADPCM_StreamConvert
878  *
879  */
880 static LRESULT ADPCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
881 {
882     AcmAdpcmData*       aad = (AcmAdpcmData*)adsi->dwDriver;
883     DWORD               nsrc = adsh->cbSrcLength;
884     DWORD               ndst = adsh->cbDstLength;
885
886     if (adsh->fdwConvert &
887         ~(ACM_STREAMCONVERTF_BLOCKALIGN|
888           ACM_STREAMCONVERTF_END|
889           ACM_STREAMCONVERTF_START))
890     {
891         FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert);
892     }
893     /* ACM_STREAMCONVERTF_BLOCKALIGN
894      *  currently all conversions are block aligned, so do nothing for this flag
895      * ACM_STREAMCONVERTF_END
896      *  no pending data, so do nothing for this flag
897      */
898     if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START))
899     {
900         ADPCM_Reset(adsi, aad);
901     }
902
903     aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
904     adsh->cbSrcLengthUsed = nsrc;
905     adsh->cbDstLengthUsed = ndst;
906
907     return MMSYSERR_NOERROR;
908 }
909
910 /**************************************************************************
911  *                      ADPCM_DriverProc                        [exported]
912  */
913 LRESULT CALLBACK ADPCM_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
914                                          LPARAM dwParam1, LPARAM dwParam2)
915 {
916     TRACE("(%08lx %p %04x %08lx %08lx);\n",
917           dwDevID, hDriv, wMsg, dwParam1, dwParam2);
918
919     switch (wMsg)
920     {
921     case DRV_LOAD:              return 1;
922     case DRV_FREE:              return 1;
923     case DRV_OPEN:              return 1;
924     case DRV_CLOSE:             return ADPCM_drvClose(dwDevID);
925     case DRV_ENABLE:            return 1;
926     case DRV_DISABLE:           return 1;
927     case DRV_QUERYCONFIGURE:    return 1;
928     case DRV_CONFIGURE:         MessageBoxA(0, "MSACM IMA ADPCM filter !", "Wine Driver", MB_OK); return 1;
929     case DRV_INSTALL:           return DRVCNF_RESTART;
930     case DRV_REMOVE:            return DRVCNF_RESTART;
931
932     case ACMDM_DRIVER_NOTIFY:
933         /* no caching from other ACM drivers is done so far */
934         return MMSYSERR_NOERROR;
935
936     case ACMDM_DRIVER_DETAILS:
937         return ADPCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
938
939     case ACMDM_FORMATTAG_DETAILS:
940         return ADPCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
941
942     case ACMDM_FORMAT_DETAILS:
943         return ADPCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
944
945     case ACMDM_FORMAT_SUGGEST:
946         return ADPCM_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
947
948     case ACMDM_STREAM_OPEN:
949         return ADPCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
950
951     case ACMDM_STREAM_CLOSE:
952         return ADPCM_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
953
954     case ACMDM_STREAM_SIZE:
955         return ADPCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
956
957     case ACMDM_STREAM_CONVERT:
958         return ADPCM_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
959
960     case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
961     case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
962         /* this converter is not a hardware driver */
963     case ACMDM_FILTERTAG_DETAILS:
964     case ACMDM_FILTER_DETAILS:
965         /* this converter is not a filter */
966     case ACMDM_STREAM_RESET:
967         /* only needed for asynchronous driver... we aren't, so just say it */
968         return MMSYSERR_NOTSUPPORTED;
969     case ACMDM_STREAM_PREPARE:
970     case ACMDM_STREAM_UNPREPARE:
971         /* nothing special to do here... so don't do anything */
972         return MMSYSERR_NOERROR;
973
974     default:
975         return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
976     }
977 }