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 const 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 const 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(const WAVEFORMATEX *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 static void init_wfx_ima_adpcm(IMAADPCMWAVEFORMAT* awfx/*, DWORD nba*/)
128 register WAVEFORMATEX* pwfx = &awfx->wfx;
130 /* we assume wFormatTag, nChannels, nSamplesPerSec and wBitsPerSample
131 * have been initialized... */
133 if (pwfx->wFormatTag != WAVE_FORMAT_IMA_ADPCM) {FIXME("wrong FT\n"); return;}
134 if (ADPCM_GetFormatIndex(pwfx) == 0xFFFFFFFF) {FIXME("wrong fmt\n"); return;}
136 switch (pwfx->nSamplesPerSec)
138 case 8000: pwfx->nBlockAlign = 256 * pwfx->nChannels; break;
139 case 11025: pwfx->nBlockAlign = 256 * pwfx->nChannels; break;
140 case 22050: pwfx->nBlockAlign = 512 * pwfx->nChannels; break;
141 case 44100: pwfx->nBlockAlign = 1024 * pwfx->nChannels; break;
142 default: /*pwfx->nBlockAlign = nba;*/ break;
144 pwfx->cbSize = sizeof(WORD);
146 awfx->wSamplesPerBlock = (pwfx->nBlockAlign - (4 * pwfx->nChannels) * 2) / pwfx->nChannels + 1;
147 pwfx->nAvgBytesPerSec = (pwfx->nSamplesPerSec * pwfx->nBlockAlign) / awfx->wSamplesPerBlock;
150 /***********************************************************************
153 * Read a 16 bit sample (correctly handles endianess)
155 static inline short R16(const unsigned char* src)
157 return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));
160 /***********************************************************************
163 * Write a 16 bit sample (correctly handles endianess)
165 static inline void W16(unsigned char* dst, short s)
171 /* IMA (or DVI) APDCM codec routines */
173 static const unsigned IMA_StepTable[89] =
175 7, 8, 9, 10, 11, 12, 13, 14,
176 16, 17, 19, 21, 23, 25, 28, 31,
177 34, 37, 41, 45, 50, 55, 60, 66,
178 73, 80, 88, 97, 107, 118, 130, 143,
179 157, 173, 190, 209, 230, 253, 279, 307,
180 337, 371, 408, 449, 494, 544, 598, 658,
181 724, 796, 876, 963, 1060, 1166, 1282, 1411,
182 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
183 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
184 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
185 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
189 static const int IMA_IndexTable[16] =
191 -1, -1, -1, -1, 2, 4, 6, 8,
192 -1, -1, -1, -1, 2, 4, 6, 8
195 static inline void clamp_step_index(int* stepIndex)
197 if (*stepIndex < 0 ) *stepIndex = 0;
198 if (*stepIndex > 88) *stepIndex = 88;
201 static inline void clamp_sample(int* sample)
203 if (*sample < -32768) *sample = -32768;
204 if (*sample > 32767) *sample = 32767;
207 static inline void process_nibble(unsigned char code, int* stepIndex, int* sample)
214 step = IMA_StepTable[*stepIndex];
216 if (code & 1) diff += step >> 2;
217 if (code & 2) diff += step >> 1;
218 if (code & 4) diff += step;
219 if (code & 8) *sample -= diff;
220 else *sample += diff;
221 clamp_sample(sample);
222 *stepIndex += IMA_IndexTable[code];
223 clamp_step_index(stepIndex);
226 static inline unsigned char generate_nibble(int in, int* stepIndex, int* sample)
228 int effdiff, diff = in - *sample;
242 step = IMA_StepTable[*stepIndex];
243 effdiff = (step >> 3);
263 if (code & 8) *sample -= effdiff;
264 else *sample += effdiff;
265 clamp_sample(sample);
266 *stepIndex += IMA_IndexTable[code];
267 clamp_step_index(stepIndex);
271 static void cvtSSima16K(PACMDRVSTREAMINSTANCE adsi,
272 const unsigned char* src, LPDWORD nsrc,
273 unsigned char* dst, LPDWORD ndst)
276 int sampleL, sampleR;
277 int stepIndexL, stepIndexR;
278 int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
280 /* compute the number of entire blocks we can decode...
281 * it's the min of the number of entire blocks in source buffer and the number
282 * of entire blocks in destination buffer
284 DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign,
285 *ndst / (nsamp_blk * 2 * 2));
287 *nsrc = nblock * adsi->pwfxSrc->nBlockAlign;
288 *ndst = nblock * (nsamp_blk * 2 * 2);
290 nsamp_blk--; /* remove the sample in block header */
291 for (; nblock > 0; nblock--)
293 const unsigned char* in_src = src;
295 /* handle headers first */
297 stepIndexL = (unsigned)*(src + 2);
298 clamp_step_index(&stepIndexL);
300 W16(dst, sampleL); dst += 2;
303 stepIndexR = (unsigned)*(src + 2);
304 clamp_step_index(&stepIndexR);
306 W16(dst, sampleR); dst += 2;
308 for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 8)
310 for (i = 0; i < 4; i++)
312 process_nibble(*src, &stepIndexL, &sampleL);
313 W16(dst + (2 * i + 0) * 4 + 0, sampleL);
314 process_nibble(*src++ >> 4, &stepIndexL, &sampleL);
315 W16(dst + (2 * i + 1) * 4 + 0, sampleL);
317 for (i = 0; i < 4; i++)
319 process_nibble(*src , &stepIndexR, &sampleR);
320 W16(dst + (2 * i + 0) * 4 + 2, sampleR);
321 process_nibble(*src++ >>4, &stepIndexR, &sampleR);
322 W16(dst + (2 * i + 1) * 4 + 2, sampleR);
326 /* we have now to realign the source pointer on block */
327 src = in_src + adsi->pwfxSrc->nBlockAlign;
331 static void cvtMMima16K(PACMDRVSTREAMINSTANCE adsi,
332 const unsigned char* src, LPDWORD nsrc,
333 unsigned char* dst, LPDWORD ndst)
337 int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
339 /* compute the number of entire blocks we can decode...
340 * it's the min of the number of entire blocks in source buffer and the number
341 * of entire blocks in destination buffer
343 DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign,
344 *ndst / (nsamp_blk * 2));
346 *nsrc = nblock * adsi->pwfxSrc->nBlockAlign;
347 *ndst = nblock * nsamp_blk * 2;
349 nsamp_blk--; /* remove the sample in block header */
350 for (; nblock > 0; nblock--)
352 const unsigned char* in_src = src;
354 /* handle header first */
356 stepIndex = (unsigned)*(src + 2);
357 clamp_step_index(&stepIndex);
359 W16(dst, sample); dst += 2;
361 for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
363 process_nibble(*src, &stepIndex, &sample);
364 W16(dst, sample); dst += 2;
365 process_nibble(*src++ >> 4, &stepIndex, &sample);
366 W16(dst, sample); dst += 2;
368 /* we have now to realign the source pointer on block */
369 src = in_src + adsi->pwfxSrc->nBlockAlign;
373 static void cvtSS16imaK(PACMDRVSTREAMINSTANCE adsi,
374 const unsigned char* src, LPDWORD nsrc,
375 unsigned char* dst, LPDWORD ndst)
377 int stepIndexL, stepIndexR;
378 int sampleL, sampleR;
380 int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock;
382 /* compute the number of entire blocks we can decode...
383 * it's the min of the number of entire blocks in source buffer and the number
384 * of entire blocks in destination buffer
386 DWORD nblock = min(*nsrc / (nsamp_blk * 2 * 2),
387 *ndst / adsi->pwfxDst->nBlockAlign);
389 *nsrc = nblock * (nsamp_blk * 2 * 2);
390 *ndst = nblock * adsi->pwfxDst->nBlockAlign;
392 stepIndexL = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL;
393 stepIndexR = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexR;
395 nsamp_blk--; /* so that we won't count the sample in header while filling the block */
397 for (; nblock > 0; nblock--)
399 unsigned char* in_dst = dst;
401 /* generate header */
402 sampleL = R16(src); src += 2;
403 W16(dst, sampleL); dst += 2;
404 *dst = (unsigned char)(unsigned)stepIndexL;
407 sampleR = R16(src); src += 2;
408 W16(dst, sampleR); dst += 2;
409 *dst = (unsigned char)(unsigned)stepIndexR;
412 for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 8)
414 for (i = 0; i < 4; i++)
416 code1 = generate_nibble(R16(src + (2 * i + 0) * 2 + 0),
417 &stepIndexL, &sampleL);
418 code2 = generate_nibble(R16(src + (2 * i + 1) * 2 + 0),
419 &stepIndexL, &sampleL);
420 *dst++ = (code1 << 4) | code2;
422 for (i = 0; i < 4; i++)
424 code1 = generate_nibble(R16(src + (2 * i + 0) * 2 + 1),
425 &stepIndexR, &sampleR);
426 code2 = generate_nibble(R16(src + (2 * i + 1) * 2 + 1),
427 &stepIndexR, &sampleR);
428 *dst++ = (code1 << 4) | code2;
432 dst = in_dst + adsi->pwfxDst->nBlockAlign;
434 ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL = stepIndexL;
435 ((AcmAdpcmData*)adsi->dwDriver)->stepIndexR = stepIndexR;
438 static void cvtMM16imaK(PACMDRVSTREAMINSTANCE adsi,
439 const unsigned char* src, LPDWORD nsrc,
440 unsigned char* dst, LPDWORD ndst)
445 int nsamp_blk = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock;
447 /* compute the number of entire blocks we can decode...
448 * it's the min of the number of entire blocks in source buffer and the number
449 * of entire blocks in destination buffer
451 DWORD nblock = min(*nsrc / (nsamp_blk * 2),
452 *ndst / adsi->pwfxDst->nBlockAlign);
454 *nsrc = nblock * (nsamp_blk * 2);
455 *ndst = nblock * adsi->pwfxDst->nBlockAlign;
457 stepIndex = ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL;
458 nsamp_blk--; /* so that we won't count the sample in header while filling the block */
460 for (; nblock > 0; nblock--)
462 unsigned char* in_dst = dst;
464 /* generate header */
465 /* FIXME: what about the last effective sample from previous block ??? */
466 /* perhaps something like:
467 * sample += R16(src);
468 * clamp_sample(sample);
470 * + saving the sample in adsi->dwDriver when all blocks are done
471 + + reset should set the field in adsi->dwDriver to 0 too
473 sample = R16(src); src += 2;
474 W16(dst, sample); dst += 2;
475 *dst = (unsigned char)(unsigned)stepIndex;
478 for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
480 code1 = generate_nibble(R16(src), &stepIndex, &sample);
482 code2 = generate_nibble(R16(src), &stepIndex, &sample);
484 *dst++ = (code1 << 4) | code2;
486 dst = in_dst + adsi->pwfxDst->nBlockAlign;
488 ((AcmAdpcmData*)adsi->dwDriver)->stepIndexL = stepIndex;
491 /***********************************************************************
492 * ADPCM_DriverDetails
495 static LRESULT ADPCM_DriverDetails(PACMDRIVERDETAILSW add)
497 add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
498 add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
501 add->vdwACM = 0x3320000;
502 add->vdwDriver = 0x04000000;
503 add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
504 add->cFormatTags = 2; /* PCM, IMA ADPCM */
505 add->cFilterTags = 0;
507 MultiByteToWideChar( CP_ACP, 0, "Microsoft IMA ADPCM", -1,
508 add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) );
509 MultiByteToWideChar( CP_ACP, 0, "Microsoft IMA ADPCM CODEC", -1,
510 add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) );
511 MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
512 add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) );
513 MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
514 add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) );
515 add->szFeatures[0] = 0;
517 return MMSYSERR_NOERROR;
520 /***********************************************************************
521 * ADPCM_FormatTagDetails
524 static LRESULT ADPCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
526 static const WCHAR szPcm[]={'P','C','M',0};
527 static const WCHAR szImaAdPcm[]={'I','M','A',' ','A','D','P','C','M',0};
531 case ACM_FORMATTAGDETAILSF_INDEX:
532 if (aftd->dwFormatTagIndex >= 2) return ACMERR_NOTPOSSIBLE;
534 case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
535 if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
537 aftd->dwFormatTagIndex = 1; /* WAVE_FORMAT_IMA_ADPCM is bigger than PCM */
541 case ACM_FORMATTAGDETAILSF_FORMATTAG:
542 switch (aftd->dwFormatTag)
544 case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break;
545 case WAVE_FORMAT_IMA_ADPCM: aftd->dwFormatTagIndex = 1; break;
546 default: return ACMERR_NOTPOSSIBLE;
550 WARN("Unsupported query %08x\n", dwQuery);
551 return MMSYSERR_NOTSUPPORTED;
554 aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
555 switch (aftd->dwFormatTagIndex)
558 aftd->dwFormatTag = WAVE_FORMAT_PCM;
559 aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
560 aftd->cStandardFormats = NUM_PCM_FORMATS;
561 lstrcpyW(aftd->szFormatTag, szPcm);
564 aftd->dwFormatTag = WAVE_FORMAT_IMA_ADPCM;
565 aftd->cbFormatSize = sizeof(IMAADPCMWAVEFORMAT);
566 aftd->cStandardFormats = NUM_ADPCM_FORMATS;
567 lstrcpyW(aftd->szFormatTag, szImaAdPcm);
570 return MMSYSERR_NOERROR;
573 /***********************************************************************
574 * ADPCM_FormatDetails
577 static LRESULT ADPCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
581 case ACM_FORMATDETAILSF_FORMAT:
582 if (ADPCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
584 case ACM_FORMATDETAILSF_INDEX:
585 afd->pwfx->wFormatTag = afd->dwFormatTag;
586 switch (afd->dwFormatTag)
588 case WAVE_FORMAT_PCM:
589 if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE;
590 afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
591 afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
592 afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
593 /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible
594 * afd->pwfx->cbSize = 0;
596 afd->pwfx->nBlockAlign =
597 (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8;
598 afd->pwfx->nAvgBytesPerSec =
599 afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
601 case WAVE_FORMAT_IMA_ADPCM:
602 if (afd->dwFormatIndex >= NUM_ADPCM_FORMATS) return ACMERR_NOTPOSSIBLE;
603 afd->pwfx->nChannels = ADPCM_Formats[afd->dwFormatIndex].nChannels;
604 afd->pwfx->nSamplesPerSec = ADPCM_Formats[afd->dwFormatIndex].rate;
605 afd->pwfx->wBitsPerSample = ADPCM_Formats[afd->dwFormatIndex].nBits;
606 afd->pwfx->nBlockAlign = 1024;
607 /* we got 4 bits per sample */
608 afd->pwfx->nAvgBytesPerSec =
609 (afd->pwfx->nSamplesPerSec * 4) / 8;
610 if (afd->cbwfx >= sizeof(WAVEFORMATEX))
611 afd->pwfx->cbSize = sizeof(WORD);
612 if (afd->cbwfx >= sizeof(IMAADPCMWAVEFORMAT))
613 ((IMAADPCMWAVEFORMAT*)afd->pwfx)->wSamplesPerBlock = (1024 - 4 * afd->pwfx->nChannels) * (2 / afd->pwfx->nChannels) + 1;
616 WARN("Unsupported tag %08x\n", afd->dwFormatTag);
617 return MMSYSERR_INVALPARAM;
621 WARN("Unsupported query %08x\n", dwQuery);
622 return MMSYSERR_NOTSUPPORTED;
624 afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
625 afd->szFormat[0] = 0; /* let MSACM format this for us... */
627 return MMSYSERR_NOERROR;
630 /***********************************************************************
631 * ADPCM_FormatSuggest
634 static LRESULT ADPCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
637 if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
638 adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
639 adfs->pwfxSrc->wFormatTag == adfs->pwfxDst->wFormatTag ||
640 ADPCM_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
641 /* FIXME: should do those tests against the real size (according to format tag */
643 /* If no suggestion for destination, then copy source value */
644 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS))
645 adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
646 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC))
647 adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
649 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE))
651 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
652 adfs->pwfxDst->wBitsPerSample = 4;
654 adfs->pwfxDst->wBitsPerSample = 16;
656 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
658 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
659 adfs->pwfxDst->wFormatTag = WAVE_FORMAT_IMA_ADPCM;
661 adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM;
664 /* recompute other values */
665 switch (adfs->pwfxDst->wFormatTag)
667 case WAVE_FORMAT_PCM:
668 adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8;
669 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
670 /* check if result is ok */
671 if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
673 case WAVE_FORMAT_IMA_ADPCM:
674 init_wfx_ima_adpcm((IMAADPCMWAVEFORMAT*)adfs->pwfxDst);
675 /* FIXME: not handling header overhead */
676 TRACE("setting spb=%u\n", ((IMAADPCMWAVEFORMAT*)adfs->pwfxDst)->wSamplesPerBlock);
677 /* check if result is ok */
678 if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
685 return MMSYSERR_NOERROR;
688 /***********************************************************************
692 static void ADPCM_Reset(PACMDRVSTREAMINSTANCE adsi, AcmAdpcmData* aad)
694 aad->stepIndexL = aad->stepIndexR = 0;
697 /***********************************************************************
701 static LRESULT ADPCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
706 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
708 if (ADPCM_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
709 ADPCM_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
710 return ACMERR_NOTPOSSIBLE;
712 aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmAdpcmData));
713 if (aad == 0) return MMSYSERR_NOMEM;
715 adsi->dwDriver = (DWORD_PTR)aad;
717 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
718 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
722 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
723 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
725 /* resampling or mono <=> stereo not available
726 * ADPCM algo only define 16 bit per sample output
728 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
729 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
730 adsi->pwfxDst->wBitsPerSample != 16)
733 nspb = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxSrc)->wSamplesPerBlock;
734 TRACE("spb=%u\n", nspb);
736 /* we check that in a block, after the header, samples are present on
737 * 4-sample packet pattern
738 * we also check that the block alignment is bigger than the expected size
740 if (((nspb - 1) & 3) != 0) goto theEnd;
741 if ((((nspb - 1) / 2) + 4) * adsi->pwfxSrc->nChannels < adsi->pwfxSrc->nBlockAlign)
744 /* adpcm decoding... */
745 if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 2)
746 aad->convert = cvtSSima16K;
747 if (adsi->pwfxDst->wBitsPerSample == 16 && adsi->pwfxDst->nChannels == 1)
748 aad->convert = cvtMMima16K;
750 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
751 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM)
753 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
754 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
755 adsi->pwfxSrc->wBitsPerSample != 16)
758 nspb = ((LPIMAADPCMWAVEFORMAT)adsi->pwfxDst)->wSamplesPerBlock;
759 TRACE("spb=%u\n", nspb);
761 /* we check that in a block, after the header, samples are present on
762 * 4-sample packet pattern
763 * we also check that the block alignment is bigger than the expected size
765 if (((nspb - 1) & 3) != 0) goto theEnd;
766 if ((((nspb - 1) / 2) + 4) * adsi->pwfxDst->nChannels < adsi->pwfxDst->nBlockAlign)
769 /* adpcm coding... */
770 if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 2)
771 aad->convert = cvtSS16imaK;
772 if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 1)
773 aad->convert = cvtMM16imaK;
776 ADPCM_Reset(adsi, aad);
778 return MMSYSERR_NOERROR;
781 HeapFree(GetProcessHeap(), 0, aad);
783 return MMSYSERR_NOTSUPPORTED;
786 /***********************************************************************
790 static LRESULT ADPCM_StreamClose(PACMDRVSTREAMINSTANCE adsi)
792 HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
793 return MMSYSERR_NOERROR;
796 /***********************************************************************
800 static LRESULT ADPCM_StreamSize(const ACMDRVSTREAMINSTANCE *adsi, PACMDRVSTREAMSIZE adss)
804 switch (adss->fdwSize)
806 case ACM_STREAMSIZEF_DESTINATION:
807 /* cbDstLength => cbSrcLength */
808 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
809 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM)
811 nblocks = adss->cbDstLength / adsi->pwfxDst->nBlockAlign;
813 return ACMERR_NOTPOSSIBLE;
814 adss->cbSrcLength = nblocks * adsi->pwfxSrc->nBlockAlign * ((IMAADPCMWAVEFORMAT*)adsi->pwfxDst)->wSamplesPerBlock;
816 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
817 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
819 nblocks = adss->cbDstLength / (adsi->pwfxDst->nBlockAlign * ((IMAADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock);
821 return ACMERR_NOTPOSSIBLE;
822 adss->cbSrcLength = nblocks * adsi->pwfxSrc->nBlockAlign;
826 return MMSYSERR_NOTSUPPORTED;
829 case ACM_STREAMSIZEF_SOURCE:
830 /* cbSrcLength => cbDstLength */
831 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
832 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_IMA_ADPCM)
834 nblocks = adss->cbSrcLength / (adsi->pwfxSrc->nBlockAlign * ((IMAADPCMWAVEFORMAT*)adsi->pwfxDst)->wSamplesPerBlock);
836 return ACMERR_NOTPOSSIBLE;
837 if (adss->cbSrcLength % (adsi->pwfxSrc->nBlockAlign * ((IMAADPCMWAVEFORMAT*)adsi->pwfxDst)->wSamplesPerBlock))
838 /* Round block count up. */
840 adss->cbDstLength = nblocks * adsi->pwfxDst->nBlockAlign;
842 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_IMA_ADPCM &&
843 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
845 nblocks = adss->cbSrcLength / adsi->pwfxSrc->nBlockAlign;
847 return ACMERR_NOTPOSSIBLE;
848 if (adss->cbSrcLength % adsi->pwfxSrc->nBlockAlign)
849 /* Round block count up. */
851 adss->cbDstLength = nblocks * adsi->pwfxDst->nBlockAlign * ((IMAADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock;
855 return MMSYSERR_NOTSUPPORTED;
859 WARN("Unsupported query %08x\n", adss->fdwSize);
860 return MMSYSERR_NOTSUPPORTED;
862 return MMSYSERR_NOERROR;
865 /***********************************************************************
866 * ADPCM_StreamConvert
869 static LRESULT ADPCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
871 AcmAdpcmData* aad = (AcmAdpcmData*)adsi->dwDriver;
872 DWORD nsrc = adsh->cbSrcLength;
873 DWORD ndst = adsh->cbDstLength;
875 if (adsh->fdwConvert &
876 ~(ACM_STREAMCONVERTF_BLOCKALIGN|
877 ACM_STREAMCONVERTF_END|
878 ACM_STREAMCONVERTF_START))
880 FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert);
882 /* ACM_STREAMCONVERTF_BLOCKALIGN
883 * currently all conversions are block aligned, so do nothing for this flag
884 * ACM_STREAMCONVERTF_END
885 * no pending data, so do nothing for this flag
887 if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START))
889 ADPCM_Reset(adsi, aad);
892 aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
893 adsh->cbSrcLengthUsed = nsrc;
894 adsh->cbDstLengthUsed = ndst;
896 return MMSYSERR_NOERROR;
899 /**************************************************************************
900 * ADPCM_DriverProc [exported]
902 LRESULT CALLBACK ADPCM_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
903 LPARAM dwParam1, LPARAM dwParam2)
905 TRACE("(%08lx %p %04x %08lx %08lx);\n",
906 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
910 case DRV_LOAD: return 1;
911 case DRV_FREE: return 1;
912 case DRV_OPEN: return ADPCM_drvOpen((LPSTR)dwParam1);
913 case DRV_CLOSE: return ADPCM_drvClose(dwDevID);
914 case DRV_ENABLE: return 1;
915 case DRV_DISABLE: return 1;
916 case DRV_QUERYCONFIGURE: return 1;
917 case DRV_CONFIGURE: MessageBoxA(0, "MSACM IMA ADPCM filter !", "Wine Driver", MB_OK); return 1;
918 case DRV_INSTALL: return DRVCNF_RESTART;
919 case DRV_REMOVE: return DRVCNF_RESTART;
921 case ACMDM_DRIVER_NOTIFY:
922 /* no caching from other ACM drivers is done so far */
923 return MMSYSERR_NOERROR;
925 case ACMDM_DRIVER_DETAILS:
926 return ADPCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
928 case ACMDM_FORMATTAG_DETAILS:
929 return ADPCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
931 case ACMDM_FORMAT_DETAILS:
932 return ADPCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
934 case ACMDM_FORMAT_SUGGEST:
935 return ADPCM_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
937 case ACMDM_STREAM_OPEN:
938 return ADPCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
940 case ACMDM_STREAM_CLOSE:
941 return ADPCM_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
943 case ACMDM_STREAM_SIZE:
944 return ADPCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
946 case ACMDM_STREAM_CONVERT:
947 return ADPCM_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
949 case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
950 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
951 /* this converter is not a hardware driver */
952 case ACMDM_FILTERTAG_DETAILS:
953 case ACMDM_FILTER_DETAILS:
954 /* this converter is not a filter */
955 case ACMDM_STREAM_RESET:
956 /* only needed for asynchronous driver... we aren't, so just say it */
957 return MMSYSERR_NOTSUPPORTED;
958 case ACMDM_STREAM_PREPARE:
959 case ACMDM_STREAM_UNPREPARE:
960 /* nothing special to do here... so don't do anything */
961 return MMSYSERR_NOERROR;
964 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);