4 * Copyright (C) 2001,2002 Eric Pouech
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.
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.
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
34 #include "wine/debug.h"
36 /* see http://www.pcisys.net/~melanson/codecs/adpcm.txt for the details */
38 WINE_DEFAULT_DEBUG_CHANNEL(adpcm);
40 /***********************************************************************
43 static LRESULT ADPCM_drvOpen(LPCSTR str)
48 /***********************************************************************
51 static LRESULT ADPCM_drvClose(DWORD_PTR dwDevID)
56 typedef struct tagAcmAdpcmData
58 void (*convert)(PACMDRVSTREAMINSTANCE adsi,
59 const unsigned char*, LPDWORD, unsigned char*, LPDWORD);
60 /* IMA encoding only */
66 /* table to list all supported formats... those are the basic ones. this
67 * also helps given a unique index to each of the supported formats
76 static Format PCM_Formats[] =
78 {1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000},
79 {1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025},
80 {1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050},
81 {1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100},
84 static Format ADPCM_Formats[] =
86 {1, 4, 8000}, {2, 4, 8000}, {1, 4, 11025}, {2, 4, 11025},
87 {1, 4, 22050}, {2, 4, 22050}, {1, 4, 44100}, {2, 4, 44100},
90 #define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
91 #define NUM_ADPCM_FORMATS (sizeof(ADPCM_Formats) / sizeof(ADPCM_Formats[0]))
93 /***********************************************************************
94 * ADPCM_GetFormatIndex
96 static DWORD ADPCM_GetFormatIndex(LPWAVEFORMATEX wfx)
101 switch (wfx->wFormatTag)
103 case WAVE_FORMAT_PCM:
104 hi = NUM_PCM_FORMATS;
107 case WAVE_FORMAT_IMA_ADPCM:
108 hi = NUM_ADPCM_FORMATS;
109 fmts = ADPCM_Formats;
115 for (i = 0; i < hi; i++)
117 if (wfx->nChannels == fmts[i].nChannels &&
118 wfx->nSamplesPerSec == fmts[i].rate &&
119 wfx->wBitsPerSample == fmts[i].nBits)
126 /***********************************************************************
129 * Read a 16 bit sample (correctly handles endianess)
131 static inline short R16(const unsigned char* src)
133 return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));
136 /***********************************************************************
139 * Write a 16 bit sample (correctly handles endianess)
141 static inline void W16(unsigned char* dst, short s)
147 /* IMA (or DVI) APDCM codec routines */
149 static const unsigned IMA_StepTable[89] =
151 7, 8, 9, 10, 11, 12, 13, 14,
152 16, 17, 19, 21, 23, 25, 28, 31,
153 34, 37, 41, 45, 50, 55, 60, 66,
154 73, 80, 88, 97, 107, 118, 130, 143,
155 157, 173, 190, 209, 230, 253, 279, 307,
156 337, 371, 408, 449, 494, 544, 598, 658,
157 724, 796, 876, 963, 1060, 1166, 1282, 1411,
158 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
159 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
160 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
161 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
165 static const int IMA_IndexTable[16] =
167 -1, -1, -1, -1, 2, 4, 6, 8,
168 -1, -1, -1, -1, 2, 4, 6, 8
171 static inline void clamp_step_index(int* stepIndex)
173 if (*stepIndex < 0 ) *stepIndex = 0;
174 if (*stepIndex > 88) *stepIndex = 88;
177 static inline void clamp_sample(int* sample)
179 if (*sample < -32768) *sample = -32768;
180 if (*sample > 32767) *sample = 32767;
183 static inline void process_nibble(unsigned char code, int* stepIndex, int* sample)
190 step = IMA_StepTable[*stepIndex];
192 if (code & 1) diff += step >> 2;
193 if (code & 2) diff += step >> 1;
194 if (code & 4) diff += step;
195 if (code & 8) *sample -= diff;
196 else *sample += diff;
197 clamp_sample(sample);
198 *stepIndex += IMA_IndexTable[code];
199 clamp_step_index(stepIndex);
202 static inline unsigned char generate_nibble(int in, int* stepIndex, int* sample)
204 int effdiff, diff = in - *sample;
218 step = IMA_StepTable[*stepIndex];
219 effdiff = (step >> 3);
239 if (code & 8) *sample -= effdiff;
240 else *sample += effdiff;
241 clamp_sample(sample);
242 *stepIndex += IMA_IndexTable[code];
243 clamp_step_index(stepIndex);
247 static void cvtSSima16K(PACMDRVSTREAMINSTANCE adsi,
248 const unsigned char* src, LPDWORD nsrc,
249 unsigned char* dst, LPDWORD ndst)
252 int sampleL, sampleR;
253 int stepIndexL, stepIndexR;
254 int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
256 /* compute the number of entire blocks we can decode...
257 * it's the min of the number of entire blocks in source buffer and the number
258 * of entire blocks in destination buffer
260 DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign,
261 *ndst / (nsamp_blk * 2 * 2));
263 *nsrc = nblock * adsi->pwfxSrc->nBlockAlign;
264 *ndst = nblock * (nsamp_blk * 2 * 2);
266 nsamp_blk--; /* remove the sample in block header */
267 for (; nblock > 0; nblock--)
269 const unsigned char* in_src = src;
271 /* handle headers first */
273 stepIndexL = (unsigned)*(src + 2);
274 clamp_step_index(&stepIndexL);
276 W16(dst, sampleL); dst += 2;
279 stepIndexR = (unsigned)*(src + 2);
280 clamp_step_index(&stepIndexR);
282 W16(dst, sampleR); dst += 2;
284 for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 8)
286 for (i = 0; i < 4; i++)
288 process_nibble(*src, &stepIndexL, &sampleL);
289 W16(dst + (2 * i + 0) * 4 + 0, sampleL);
290 process_nibble(*src++ >> 4, &stepIndexL, &sampleL);
291 W16(dst + (2 * i + 1) * 4 + 0, sampleL);
293 for (i = 0; i < 4; i++)
295 process_nibble(*src , &stepIndexR, &sampleR);
296 W16(dst + (2 * i + 0) * 4 + 2, sampleR);
297 process_nibble(*src++ >>4, &stepIndexR, &sampleR);
298 W16(dst + (2 * i + 1) * 4 + 2, sampleR);
302 /* we have now to realign the source pointer on block */
303 src = in_src + adsi->pwfxSrc->nBlockAlign;
307 static void cvtMMima16K(PACMDRVSTREAMINSTANCE adsi,
308 const unsigned char* src, LPDWORD nsrc,
309 unsigned char* dst, LPDWORD ndst)
313 int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
315 /* compute the number of entire blocks we can decode...
316 * it's the min of the number of entire blocks in source buffer and the number
317 * of entire blocks in destination buffer
319 DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign,
320 *ndst / (nsamp_blk * 2));
322 *nsrc = nblock * adsi->pwfxSrc->nBlockAlign;
323 *ndst = nblock * nsamp_blk * 2;
325 nsamp_blk--; /* remove the sample in block header */
326 for (; nblock > 0; nblock--)
328 const unsigned char* in_src = src;
330 /* handle header first */
332 stepIndex = (unsigned)*(src + 2);
333 clamp_step_index(&stepIndex);
335 W16(dst, sample); dst += 2;
337 for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
339 process_nibble(*src, &stepIndex, &sample);
340 W16(dst, sample); dst += 2;
341 process_nibble(*src++ >> 4, &stepIndex, &sample);
342 W16(dst, sample); dst += 2;
344 /* we have now to realign the source pointer on block */
345 src = in_src + adsi->pwfxSrc->nBlockAlign;
349 static void cvtSS16imaK(PACMDRVSTREAMINSTANCE adsi,
350 const unsigned char* src, LPDWORD nsrc,
351 unsigned char* dst, LPDWORD ndst)
353 int stepIndexL, stepIndexR;
354 int sampleL, sampleR;
356 int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock;
358 /* compute the number of entire blocks we can decode...
359 * it's the min of the number of entire blocks in source buffer and the number
360 * of entire blocks in destination buffer
362 DWORD nblock = min(*nsrc / (nsamp_blk * 2 * 2),
363 *ndst / adsi->pwfxDst->nBlockAlign);
365 *nsrc = nblock * (nsamp_blk * 2 * 2);
366 *ndst = nblock * adsi->pwfxDst->nBlockAlign;
368 stepIndexL = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL;
369 stepIndexR = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexR;
371 nsamp_blk--; /* so that we won't count the sample in header while filling the block */
373 for (; nblock > 0; nblock--)
375 unsigned char* in_dst = dst;
377 /* generate header */
378 sampleL = R16(src); src += 2;
379 W16(dst, sampleL); dst += 2;
380 *dst = (unsigned char)(unsigned)stepIndexL;
383 sampleR = R16(src); src += 2;
384 W16(dst, sampleR); dst += 2;
385 *dst = (unsigned char)(unsigned)stepIndexR;
388 for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 8)
390 for (i = 0; i < 4; i++)
392 code1 = generate_nibble(R16(src + (2 * i + 0) * 2 + 0),
393 &stepIndexL, &sampleL);
394 code2 = generate_nibble(R16(src + (2 * i + 1) * 2 + 0),
395 &stepIndexL, &sampleL);
396 *dst++ = (code1 << 4) | code2;
398 for (i = 0; i < 4; i++)
400 code1 = generate_nibble(R16(src + (2 * i + 0) * 2 + 1),
401 &stepIndexR, &sampleR);
402 code2 = generate_nibble(R16(src + (2 * i + 1) * 2 + 1),
403 &stepIndexR, &sampleR);
404 *dst++ = (code1 << 4) | code2;
408 dst = in_dst + adsi->pwfxDst->nBlockAlign;
410 ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL = stepIndexL;
411 ((AcmAdpcmData*)adsi->dwDriver)->stepIndexR = stepIndexR;
414 static void cvtMM16imaK(PACMDRVSTREAMINSTANCE adsi,
415 const unsigned char* src, LPDWORD nsrc,
416 unsigned char* dst, LPDWORD ndst)
421 int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock;
423 /* compute the number of entire blocks we can decode...
424 * it's the min of the number of entire blocks in source buffer and the number
425 * of entire blocks in destination buffer
427 DWORD nblock = min(*nsrc / (nsamp_blk * 2),
428 *ndst / adsi->pwfxDst->nBlockAlign);
430 *nsrc = nblock * (nsamp_blk * 2);
431 *ndst = nblock * adsi->pwfxDst->nBlockAlign;
433 stepIndex = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL;
434 nsamp_blk--; /* so that we won't count the sample in header while filling the block */
436 for (; nblock > 0; nblock--)
438 unsigned char* in_dst = dst;
440 /* generate header */
441 /* FIXME: what about the last effective sample from previous block ??? */
442 /* perhaps something like:
443 * sample += R16(src);
444 * clamp_sample(sample);
446 * + saving the sample in adsi->dwDriver when all blocks are done
447 + + reset should set the field in adsi->dwDriver to 0 too
449 sample = R16(src); src += 2;
450 W16(dst, sample); dst += 2;
451 *dst = (unsigned char)(unsigned)stepIndex;
454 for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
456 code1 = generate_nibble(R16(src), &stepIndex, &sample);
458 code2 = generate_nibble(R16(src), &stepIndex, &sample);
460 *dst++ = (code1 << 4) | code2;
462 dst = in_dst + adsi->pwfxDst->nBlockAlign;
464 ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL = stepIndex;
467 /***********************************************************************
468 * ADPCM_DriverDetails
471 static LRESULT ADPCM_DriverDetails(PACMDRIVERDETAILSW add)
473 add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
474 add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
477 add->vdwACM = 0x01000000;
478 add->vdwDriver = 0x01000000;
479 add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
480 add->cFormatTags = 2; /* PCM, IMA ADPCM */
481 add->cFilterTags = 0;
483 MultiByteToWideChar( CP_ACP, 0, "WINE-ADPCM", -1,
484 add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) );
485 MultiByteToWideChar( CP_ACP, 0, "Wine IMA ADPCM converter", -1,
486 add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) );
487 MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
488 add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) );
489 MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
490 add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) );
491 add->szFeatures[0] = 0;
493 return MMSYSERR_NOERROR;
496 /***********************************************************************
497 * ADPCM_FormatTagDetails
500 static LRESULT ADPCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
502 static const WCHAR szPcm[]={'P','C','M',0};
503 static const WCHAR szImaAdPcm[]={'I','M','A',' ','A','d','P','C','M',0};
507 case ACM_FORMATTAGDETAILSF_INDEX:
508 if (aftd->dwFormatTagIndex >= 2) return ACMERR_NOTPOSSIBLE;
510 case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
511 if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
513 aftd->dwFormatTagIndex = 1; /* WAVE_FORMAT_IMA_ADPCM is bigger than PCM */
517 case ACM_FORMATTAGDETAILSF_FORMATTAG:
518 switch (aftd->dwFormatTag)
520 case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break;
521 case WAVE_FORMAT_IMA_ADPCM: aftd->dwFormatTagIndex = 1; break;
522 default: return ACMERR_NOTPOSSIBLE;
526 WARN("Unsupported query %08x\n", dwQuery);
527 return MMSYSERR_NOTSUPPORTED;
530 aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
531 switch (aftd->dwFormatTagIndex)
534 aftd->dwFormatTag = WAVE_FORMAT_PCM;
535 aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
536 aftd->cStandardFormats = NUM_PCM_FORMATS;
537 lstrcpyW(aftd->szFormatTag, szPcm);
540 aftd->dwFormatTag = WAVE_FORMAT_IMA_ADPCM;
541 aftd->cbFormatSize = sizeof(IMAADPCMWAVEFORMAT);
542 aftd->cStandardFormats = NUM_ADPCM_FORMATS;
543 lstrcpyW(aftd->szFormatTag, szImaAdPcm);
546 return MMSYSERR_NOERROR;
549 /***********************************************************************
550 * ADPCM_FormatDetails
553 static LRESULT ADPCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
557 case ACM_FORMATDETAILSF_FORMAT:
558 if (ADPCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
560 case ACM_FORMATDETAILSF_INDEX:
561 afd->pwfx->wFormatTag = afd->dwFormatTag;
562 switch (afd->dwFormatTag)
564 case WAVE_FORMAT_PCM:
565 if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE;
566 afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
567 afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
568 afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
569 /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible
570 * afd->pwfx->cbSize = 0;
572 afd->pwfx->nBlockAlign =
573 (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8;
574 afd->pwfx->nAvgBytesPerSec =
575 afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
577 case WAVE_FORMAT_IMA_ADPCM:
578 if (afd->dwFormatIndex >= NUM_ADPCM_FORMATS) return ACMERR_NOTPOSSIBLE;
579 afd->pwfx->nChannels = ADPCM_Formats[afd->dwFormatIndex].nChannels;
580 afd->pwfx->nSamplesPerSec = ADPCM_Formats[afd->dwFormatIndex].rate;
581 afd->pwfx->wBitsPerSample = ADPCM_Formats[afd->dwFormatIndex].nBits;
582 afd->pwfx->nBlockAlign = 1024;
583 /* we got 4 bits per sample */
584 afd->pwfx->nAvgBytesPerSec =
585 (afd->pwfx->nSamplesPerSec * 4) / 8;
586 if (afd->cbwfx >= sizeof(WAVEFORMATEX))
587 afd->pwfx->cbSize = sizeof(WORD);
588 if (afd->cbwfx >= sizeof(IMAADPCMWAVEFORMAT))
589 ((IMAADPCMWAVEFORMAT*)afd->pwfx)->wSamplesPerBlock = (1024 - 4 * afd->pwfx->nChannels) * (2 / afd->pwfx->nChannels) + 1;
592 WARN("Unsupported tag %08x\n", afd->dwFormatTag);
593 return MMSYSERR_INVALPARAM;
597 WARN("Unsupported query %08x\n", dwQuery);
598 return MMSYSERR_NOTSUPPORTED;
600 afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
601 afd->szFormat[0] = 0; /* let MSACM format this for us... */
603 return MMSYSERR_NOERROR;
606 /***********************************************************************
607 * ADPCM_FormatSuggest
610 static LRESULT ADPCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
613 if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
614 adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
615 ADPCM_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
616 /* FIXME: should do those tests against the real size (according to format tag */
618 /* If no suggestion for destination, then copy source value */
619 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS))
620 adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
621 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC))
622 adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
624 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE))
626 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
627 adfs->pwfxDst->wBitsPerSample = 4;
629 adfs->pwfxDst->wBitsPerSample = 16;
631 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
633 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
634 adfs->pwfxDst->wFormatTag = WAVE_FORMAT_IMA_ADPCM;
636 adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM;
639 /* check if result is ok */
640 if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
642 /* recompute other values */
643 switch (adfs->pwfxDst->wFormatTag)
645 case WAVE_FORMAT_PCM:
646 adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8;
647 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
649 case WAVE_FORMAT_IMA_ADPCM:
650 adfs->pwfxDst->nBlockAlign = 1024;
651 /* FIXME: not handling header overhead */
652 adfs->pwfxDst->nAvgBytesPerSec = ((adfs->pwfxDst->nSamplesPerSec * 4) / 8) * adfs->pwfxSrc->nChannels;
653 ((IMAADPCMWAVEFORMAT*)adfs->pwfxDst)->wSamplesPerBlock = (1024 - 4 * adfs->pwfxSrc->nChannels) * (2 / adfs->pwfxSrc->nChannels) + 1;
654 TRACE("setting spb=%u\n", ((IMAADPCMWAVEFORMAT*)adfs->pwfxDst)->wSamplesPerBlock);
661 return MMSYSERR_NOERROR;
664 /***********************************************************************
668 static void ADPCM_Reset(PACMDRVSTREAMINSTANCE adsi, AcmAdpcmData* aad)
670 aad->stepIndexL = aad->stepIndexR = 0;
673 /***********************************************************************
677 static LRESULT ADPCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
682 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
684 if (ADPCM_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
685 ADPCM_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
686 return ACMERR_NOTPOSSIBLE;
688 aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmAdpcmData));
689 if (aad == 0) return MMSYSERR_NOMEM;
691 adsi->dwDriver = (DWORD)aad;
693 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
694 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
698 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
699 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
701 /* resampling or mono <=> stereo not available
702 * ADPCM algo only define 16 bit per sample output
704 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
705 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
706 adsi->pwfxDst->wBitsPerSample != 16)
709 nspb = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
710 TRACE("spb=%u\n", nspb);
712 /* we check that in a block, after the header, samples are present on
713 * 4-sample packet pattern
714 * we also check that the block alignement is bigger than the expected size
716 if (((nspb - 1) & 3) != 0) goto theEnd;
717 if ((((nspb - 1) / 2) + 4) * adsi->pwfxSrc->nChannels < adsi->pwfxSrc->nBlockAlign)
720 /* adpcm decoding... */
721 if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 2)
722 aad->convert = cvtSSima16K;
723 if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 1)
724 aad->convert = cvtMMima16K;
726 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
727 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM)
729 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
730 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
731 adsi->pwfxSrc->wBitsPerSample != 16)
734 nspb = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock;
735 TRACE("spb=%u\n", nspb);
737 /* we check that in a block, after the header, samples are present on
738 * 4-sample packet pattern
739 * we also check that the block alignement is bigger than the expected size
741 if (((nspb - 1) & 3) != 0) goto theEnd;
742 if ((((nspb - 1) / 2) + 4) * adsi->pwfxDst->nChannels < adsi->pwfxDst->nBlockAlign)
745 /* adpcm coding... */
746 if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 2)
747 aad->convert = cvtSS16imaK;
748 if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 1)
749 aad->convert = cvtMM16imaK;
752 ADPCM_Reset(adsi, aad);
754 return MMSYSERR_NOERROR;
757 HeapFree(GetProcessHeap(), 0, aad);
759 return MMSYSERR_NOTSUPPORTED;
762 /***********************************************************************
766 static LRESULT ADPCM_StreamClose(PACMDRVSTREAMINSTANCE adsi)
768 HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
769 return MMSYSERR_NOERROR;
772 /***********************************************************************
776 static inline DWORD ADPCM_round(DWORD a, DWORD b, DWORD c)
779 /* to be sure, always return an entire number of c... */
780 return ((double)a * (double)b + (double)c - 1) / (double)c;
783 /***********************************************************************
787 static LRESULT ADPCM_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss)
789 switch (adss->fdwSize)
791 case ACM_STREAMSIZEF_DESTINATION:
792 /* cbDstLength => cbSrcLength */
793 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
794 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM)
796 /* don't take block overhead into account, doesn't matter too much */
797 adss->cbSrcLength = adss->cbDstLength * 4;
799 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
800 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
802 FIXME("misses the block header overhead\n");
803 adss->cbSrcLength = 256 + adss->cbDstLength / 4;
807 return MMSYSERR_NOTSUPPORTED;
810 case ACM_STREAMSIZEF_SOURCE:
811 /* cbSrcLength => cbDstLength */
812 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
813 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM)
815 FIXME("misses the block header overhead\n");
816 adss->cbDstLength = 256 + adss->cbSrcLength / 4;
818 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
819 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
821 /* don't take block overhead into account, doesn't matter too much */
822 adss->cbDstLength = adss->cbSrcLength * 4;
826 return MMSYSERR_NOTSUPPORTED;
830 WARN("Unsupported query %08x\n", adss->fdwSize);
831 return MMSYSERR_NOTSUPPORTED;
833 return MMSYSERR_NOERROR;
836 /***********************************************************************
837 * ADPCM_StreamConvert
840 static LRESULT ADPCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
842 AcmAdpcmData* aad = (AcmAdpcmData*)adsi->dwDriver;
843 DWORD nsrc = adsh->cbSrcLength;
844 DWORD ndst = adsh->cbDstLength;
846 if (adsh->fdwConvert &
847 ~(ACM_STREAMCONVERTF_BLOCKALIGN|
848 ACM_STREAMCONVERTF_END|
849 ACM_STREAMCONVERTF_START))
851 FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert);
853 /* ACM_STREAMCONVERTF_BLOCKALIGN
854 * currently all conversions are block aligned, so do nothing for this flag
855 * ACM_STREAMCONVERTF_END
856 * no pending data, so do nothing for this flag
858 if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START))
860 ADPCM_Reset(adsi, aad);
863 aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
864 adsh->cbSrcLengthUsed = nsrc;
865 adsh->cbDstLengthUsed = ndst;
867 return MMSYSERR_NOERROR;
870 /**************************************************************************
871 * ADPCM_DriverProc [exported]
873 LRESULT CALLBACK ADPCM_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
874 LPARAM dwParam1, LPARAM dwParam2)
876 TRACE("(%08lx %p %04x %08lx %08lx);\n",
877 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
881 case DRV_LOAD: return 1;
882 case DRV_FREE: return 1;
883 case DRV_OPEN: return ADPCM_drvOpen((LPSTR)dwParam1);
884 case DRV_CLOSE: return ADPCM_drvClose(dwDevID);
885 case DRV_ENABLE: return 1;
886 case DRV_DISABLE: return 1;
887 case DRV_QUERYCONFIGURE: return 1;
888 case DRV_CONFIGURE: MessageBoxA(0, "MSACM IMA ADPCM filter !", "Wine Driver", MB_OK); return 1;
889 case DRV_INSTALL: return DRVCNF_RESTART;
890 case DRV_REMOVE: return DRVCNF_RESTART;
892 case ACMDM_DRIVER_NOTIFY:
893 /* no caching from other ACM drivers is done so far */
894 return MMSYSERR_NOERROR;
896 case ACMDM_DRIVER_DETAILS:
897 return ADPCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
899 case ACMDM_FORMATTAG_DETAILS:
900 return ADPCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
902 case ACMDM_FORMAT_DETAILS:
903 return ADPCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
905 case ACMDM_FORMAT_SUGGEST:
906 return ADPCM_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
908 case ACMDM_STREAM_OPEN:
909 return ADPCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
911 case ACMDM_STREAM_CLOSE:
912 return ADPCM_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
914 case ACMDM_STREAM_SIZE:
915 return ADPCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
917 case ACMDM_STREAM_CONVERT:
918 return ADPCM_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
920 case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
921 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
922 /* this converter is not a hardware driver */
923 case ACMDM_FILTERTAG_DETAILS:
924 case ACMDM_FILTER_DETAILS:
925 /* this converter is not a filter */
926 case ACMDM_STREAM_RESET:
927 /* only needed for asynchronous driver... we aren't, so just say it */
928 return MMSYSERR_NOTSUPPORTED;
929 case ACMDM_STREAM_PREPARE:
930 case ACMDM_STREAM_UNPREPARE:
931 /* nothing special to do here... so don't do anything */
932 return MMSYSERR_NOERROR;
935 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);