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