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