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