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