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