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
22 #define WIN32_NO_STATUS
32 //#include "mmsystem.h"
36 #include <wine/debug.h>
38 /* see http://www.pcisys.net/~melanson/codecs/adpcm.txt for the details */
40 WINE_DEFAULT_DEBUG_CHANNEL(adpcm
);
42 /***********************************************************************
45 static LRESULT
ADPCM_drvClose(DWORD_PTR dwDevID
)
50 typedef struct tagAcmAdpcmData
52 void (*convert
)(PACMDRVSTREAMINSTANCE adsi
,
53 const unsigned char*, LPDWORD
, unsigned char*, LPDWORD
);
54 /* IMA encoding only */
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
70 static const Format PCM_Formats
[] =
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},
78 static const Format ADPCM_Formats
[] =
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},
84 #define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
85 #define NUM_ADPCM_FORMATS (sizeof(ADPCM_Formats) / sizeof(ADPCM_Formats[0]))
87 /***********************************************************************
88 * ADPCM_GetFormatIndex
90 static DWORD
ADPCM_GetFormatIndex(const WAVEFORMATEX
*wfx
)
95 switch (wfx
->wFormatTag
)
101 case WAVE_FORMAT_IMA_ADPCM
:
102 hi
= NUM_ADPCM_FORMATS
;
103 fmts
= ADPCM_Formats
;
109 for (i
= 0; i
< hi
; i
++)
111 if (wfx
->nChannels
== fmts
[i
].nChannels
&&
112 wfx
->nSamplesPerSec
== fmts
[i
].rate
&&
113 wfx
->wBitsPerSample
== fmts
[i
].nBits
)
117 switch (wfx
->wFormatTag
)
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)
127 case WAVE_FORMAT_IMA_ADPCM
:
128 if(3 > wfx
->nChannels
&&
129 wfx
->nChannels
> 0 &&
130 wfx
->wBitsPerSample
== 4 &&
139 static void init_wfx_ima_adpcm(IMAADPCMWAVEFORMAT
* awfx
/*, DWORD nba*/)
141 WAVEFORMATEX
* pwfx
= &awfx
->wfx
;
143 /* we assume wFormatTag, nChannels, nSamplesPerSec and wBitsPerSample
144 * have been initialized... */
146 if (pwfx
->wFormatTag
!= WAVE_FORMAT_IMA_ADPCM
) {FIXME("wrong FT\n"); return;}
147 if (ADPCM_GetFormatIndex(pwfx
) == 0xFFFFFFFF) {FIXME("wrong fmt\n"); return;}
149 switch (pwfx
->nSamplesPerSec
)
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;
157 pwfx
->cbSize
= sizeof(WORD
);
159 awfx
->wSamplesPerBlock
= (pwfx
->nBlockAlign
- (4 * pwfx
->nChannels
) * 2) / pwfx
->nChannels
+ 1;
160 pwfx
->nAvgBytesPerSec
= (pwfx
->nSamplesPerSec
* pwfx
->nBlockAlign
) / awfx
->wSamplesPerBlock
;
163 /***********************************************************************
166 * Read a 16 bit sample (correctly handles endianness)
168 static inline short R16(const unsigned char* src
)
170 return (short)((unsigned short)src
[0] | ((unsigned short)src
[1] << 8));
173 /***********************************************************************
176 * Write a 16 bit sample (correctly handles endianness)
178 static inline void W16(unsigned char* dst
, short s
)
184 /* IMA (or DVI) APDCM codec routines */
186 static const unsigned IMA_StepTable
[89] =
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,
202 static const int IMA_IndexTable
[16] =
204 -1, -1, -1, -1, 2, 4, 6, 8,
205 -1, -1, -1, -1, 2, 4, 6, 8
208 static inline void clamp_step_index(int* stepIndex
)
210 if (*stepIndex
< 0 ) *stepIndex
= 0;
211 if (*stepIndex
> 88) *stepIndex
= 88;
214 static inline void clamp_sample(int* sample
)
216 if (*sample
< -32768) *sample
= -32768;
217 if (*sample
> 32767) *sample
= 32767;
220 static inline void process_nibble(unsigned char code
, int* stepIndex
, int* sample
)
227 step
= IMA_StepTable
[*stepIndex
];
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
);
239 static inline unsigned char generate_nibble(int in
, int* stepIndex
, int* sample
)
241 int effdiff
, diff
= in
- *sample
;
255 step
= IMA_StepTable
[*stepIndex
];
256 effdiff
= (step
>> 3);
276 if (code
& 8) *sample
-= effdiff
;
277 else *sample
+= effdiff
;
278 clamp_sample(sample
);
279 *stepIndex
+= IMA_IndexTable
[code
];
280 clamp_step_index(stepIndex
);
284 static void cvtSSima16K(PACMDRVSTREAMINSTANCE adsi
,
285 const unsigned char* src
, LPDWORD nsrc
,
286 unsigned char* dst
, LPDWORD ndst
)
289 int sampleL
, sampleR
;
290 int stepIndexL
, stepIndexR
;
291 int nsamp_blk
= ((LPIMAADPCMWAVEFORMAT
)adsi
->pwfxSrc
)->wSamplesPerBlock
;
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
297 DWORD nblock
= min(*nsrc
/ adsi
->pwfxSrc
->nBlockAlign
,
298 *ndst
/ (nsamp_blk
* 2 * 2));
300 *nsrc
= nblock
* adsi
->pwfxSrc
->nBlockAlign
;
301 *ndst
= nblock
* (nsamp_blk
* 2 * 2);
303 nsamp_blk
--; /* remove the sample in block header */
304 for (; nblock
> 0; nblock
--)
306 const unsigned char* in_src
= src
;
308 /* handle headers first */
310 stepIndexL
= (unsigned)*(src
+ 2);
311 clamp_step_index(&stepIndexL
);
313 W16(dst
, sampleL
); dst
+= 2;
316 stepIndexR
= (unsigned)*(src
+ 2);
317 clamp_step_index(&stepIndexR
);
319 W16(dst
, sampleR
); dst
+= 2;
321 for (nsamp
= nsamp_blk
; nsamp
> 0; nsamp
-= 8)
323 for (i
= 0; i
< 4; i
++)
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
);
330 for (i
= 0; i
< 4; i
++)
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
);
339 /* we have now to realign the source pointer on block */
340 src
= in_src
+ adsi
->pwfxSrc
->nBlockAlign
;
344 static void cvtMMima16K(PACMDRVSTREAMINSTANCE adsi
,
345 const unsigned char* src
, LPDWORD nsrc
,
346 unsigned char* dst
, LPDWORD ndst
)
350 int nsamp_blk
= ((LPIMAADPCMWAVEFORMAT
)adsi
->pwfxSrc
)->wSamplesPerBlock
;
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
356 DWORD nblock
= min(*nsrc
/ adsi
->pwfxSrc
->nBlockAlign
,
357 *ndst
/ (nsamp_blk
* 2));
359 *nsrc
= nblock
* adsi
->pwfxSrc
->nBlockAlign
;
360 *ndst
= nblock
* nsamp_blk
* 2;
362 nsamp_blk
--; /* remove the sample in block header */
363 for (; nblock
> 0; nblock
--)
365 const unsigned char* in_src
= src
;
367 /* handle header first */
369 stepIndex
= (unsigned)*(src
+ 2);
370 clamp_step_index(&stepIndex
);
372 W16(dst
, sample
); dst
+= 2;
374 for (nsamp
= nsamp_blk
; nsamp
> 0; nsamp
-= 2)
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;
381 /* we have now to realign the source pointer on block */
382 src
= in_src
+ adsi
->pwfxSrc
->nBlockAlign
;
386 static void cvtSS16imaK(PACMDRVSTREAMINSTANCE adsi
,
387 const unsigned char* src
, LPDWORD nsrc
,
388 unsigned char* dst
, LPDWORD ndst
)
390 int stepIndexL
, stepIndexR
;
391 int sampleL
, sampleR
;
393 int nsamp_blk
= ((LPIMAADPCMWAVEFORMAT
)adsi
->pwfxDst
)->wSamplesPerBlock
;
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
399 DWORD nblock
= min(*nsrc
/ (nsamp_blk
* 2 * 2),
400 *ndst
/ adsi
->pwfxDst
->nBlockAlign
);
402 *nsrc
= nblock
* (nsamp_blk
* 2 * 2);
403 *ndst
= nblock
* adsi
->pwfxDst
->nBlockAlign
;
405 stepIndexL
= ((AcmAdpcmData
*)adsi
->dwDriver
)->stepIndexL
;
406 stepIndexR
= ((AcmAdpcmData
*)adsi
->dwDriver
)->stepIndexR
;
408 nsamp_blk
--; /* so that we won't count the sample in header while filling the block */
410 for (; nblock
> 0; nblock
--)
412 unsigned char* in_dst
= dst
;
414 /* generate header */
415 sampleL
= R16(src
); src
+= 2;
416 W16(dst
, sampleL
); dst
+= 2;
417 *dst
= (unsigned char)(unsigned)stepIndexL
;
420 sampleR
= R16(src
); src
+= 2;
421 W16(dst
, sampleR
); dst
+= 2;
422 *dst
= (unsigned char)(unsigned)stepIndexR
;
425 for (nsamp
= nsamp_blk
; nsamp
> 0; nsamp
-= 8)
427 for (i
= 0; i
< 4; i
++)
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
;
435 for (i
= 0; i
< 4; i
++)
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
;
445 dst
= in_dst
+ adsi
->pwfxDst
->nBlockAlign
;
447 ((AcmAdpcmData
*)adsi
->dwDriver
)->stepIndexL
= stepIndexL
;
448 ((AcmAdpcmData
*)adsi
->dwDriver
)->stepIndexR
= stepIndexR
;
451 static void cvtMM16imaK(PACMDRVSTREAMINSTANCE adsi
,
452 const unsigned char* src
, LPDWORD nsrc
,
453 unsigned char* dst
, LPDWORD ndst
)
458 int nsamp_blk
= ((LPIMAADPCMWAVEFORMAT
)adsi
->pwfxDst
)->wSamplesPerBlock
;
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
464 DWORD nblock
= min(*nsrc
/ (nsamp_blk
* 2),
465 *ndst
/ adsi
->pwfxDst
->nBlockAlign
);
467 *nsrc
= nblock
* (nsamp_blk
* 2);
468 *ndst
= nblock
* adsi
->pwfxDst
->nBlockAlign
;
470 stepIndex
= ((AcmAdpcmData
*)adsi
->dwDriver
)->stepIndexL
;
471 nsamp_blk
--; /* so that we won't count the sample in header while filling the block */
473 for (; nblock
> 0; nblock
--)
475 unsigned char* in_dst
= dst
;
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);
483 * + saving the sample in adsi->dwDriver when all blocks are done
484 + + reset should set the field in adsi->dwDriver to 0 too
486 sample
= R16(src
); src
+= 2;
487 W16(dst
, sample
); dst
+= 2;
488 *dst
= (unsigned char)(unsigned)stepIndex
;
491 for (nsamp
= nsamp_blk
; nsamp
> 0; nsamp
-= 2)
493 code1
= generate_nibble(R16(src
), &stepIndex
, &sample
);
495 code2
= generate_nibble(R16(src
), &stepIndex
, &sample
);
497 *dst
++ = (code1
<< 4) | code2
;
499 dst
= in_dst
+ adsi
->pwfxDst
->nBlockAlign
;
501 ((AcmAdpcmData
*)adsi
->dwDriver
)->stepIndexL
= stepIndex
;
504 /***********************************************************************
505 * ADPCM_DriverDetails
508 static LRESULT
ADPCM_DriverDetails(PACMDRIVERDETAILSW add
)
510 add
->fccType
= ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC
;
511 add
->fccComp
= ACMDRIVERDETAILS_FCCCOMP_UNDEFINED
;
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;
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;
530 return MMSYSERR_NOERROR
;
533 /***********************************************************************
534 * ADPCM_FormatTagDetails
537 static LRESULT
ADPCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd
, DWORD dwQuery
)
539 static const WCHAR szPcm
[]={'P','C','M',0};
540 static const WCHAR szImaAdPcm
[]={'I','M','A',' ','A','D','P','C','M',0};
544 case ACM_FORMATTAGDETAILSF_INDEX
:
545 if (aftd
->dwFormatTagIndex
>= 2) return ACMERR_NOTPOSSIBLE
;
547 case ACM_FORMATTAGDETAILSF_LARGESTSIZE
:
548 if (aftd
->dwFormatTag
== WAVE_FORMAT_UNKNOWN
)
550 aftd
->dwFormatTagIndex
= 1; /* WAVE_FORMAT_IMA_ADPCM is bigger than PCM */
554 case ACM_FORMATTAGDETAILSF_FORMATTAG
:
555 switch (aftd
->dwFormatTag
)
557 case WAVE_FORMAT_PCM
: aftd
->dwFormatTagIndex
= 0; break;
558 case WAVE_FORMAT_IMA_ADPCM
: aftd
->dwFormatTagIndex
= 1; break;
559 default: return ACMERR_NOTPOSSIBLE
;
563 WARN("Unsupported query %08x\n", dwQuery
);
564 return MMSYSERR_NOTSUPPORTED
;
567 aftd
->fdwSupport
= ACMDRIVERDETAILS_SUPPORTF_CODEC
;
568 switch (aftd
->dwFormatTagIndex
)
571 aftd
->dwFormatTag
= WAVE_FORMAT_PCM
;
572 aftd
->cbFormatSize
= sizeof(PCMWAVEFORMAT
);
573 aftd
->cStandardFormats
= NUM_PCM_FORMATS
;
574 lstrcpyW(aftd
->szFormatTag
, szPcm
);
577 aftd
->dwFormatTag
= WAVE_FORMAT_IMA_ADPCM
;
578 aftd
->cbFormatSize
= sizeof(IMAADPCMWAVEFORMAT
);
579 aftd
->cStandardFormats
= NUM_ADPCM_FORMATS
;
580 lstrcpyW(aftd
->szFormatTag
, szImaAdPcm
);
583 return MMSYSERR_NOERROR
;
586 /***********************************************************************
587 * ADPCM_FormatDetails
590 static LRESULT
ADPCM_FormatDetails(PACMFORMATDETAILSW afd
, DWORD dwQuery
)
594 case ACM_FORMATDETAILSF_FORMAT
:
595 if (ADPCM_GetFormatIndex(afd
->pwfx
) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE
;
597 case ACM_FORMATDETAILSF_INDEX
:
598 afd
->pwfx
->wFormatTag
= afd
->dwFormatTag
;
599 switch (afd
->dwFormatTag
)
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;
609 afd
->pwfx
->nBlockAlign
=
610 (afd
->pwfx
->nChannels
* afd
->pwfx
->wBitsPerSample
) / 8;
611 afd
->pwfx
->nAvgBytesPerSec
=
612 afd
->pwfx
->nSamplesPerSec
* afd
->pwfx
->nBlockAlign
;
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;
629 WARN("Unsupported tag %08x\n", afd
->dwFormatTag
);
630 return MMSYSERR_INVALPARAM
;
634 WARN("Unsupported query %08x\n", dwQuery
);
635 return MMSYSERR_NOTSUPPORTED
;
637 afd
->fdwSupport
= ACMDRIVERDETAILS_SUPPORTF_CODEC
;
638 afd
->szFormat
[0] = 0; /* let MSACM format this for us... */
640 return MMSYSERR_NOERROR
;
643 /***********************************************************************
644 * ADPCM_FormatSuggest
647 static LRESULT
ADPCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs
)
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
;
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
;
661 if (!(adfs
->fdwSuggest
& ACM_FORMATSUGGESTF_WBITSPERSAMPLE
))
663 if (adfs
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
)
664 adfs
->pwfxDst
->wBitsPerSample
= 4;
666 adfs
->pwfxDst
->wBitsPerSample
= 16;
668 if (!(adfs
->fdwSuggest
& ACM_FORMATSUGGESTF_WFORMATTAG
))
670 if (adfs
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
)
671 adfs
->pwfxDst
->wFormatTag
= WAVE_FORMAT_IMA_ADPCM
;
673 adfs
->pwfxDst
->wFormatTag
= WAVE_FORMAT_PCM
;
676 /* recompute other values */
677 switch (adfs
->pwfxDst
->wFormatTag
)
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
;
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
;
695 return ACMERR_NOTPOSSIBLE
;
698 return MMSYSERR_NOERROR
;
701 /***********************************************************************
705 static void ADPCM_Reset(PACMDRVSTREAMINSTANCE adsi
, AcmAdpcmData
* aad
)
707 aad
->stepIndexL
= aad
->stepIndexR
= 0;
710 /***********************************************************************
714 static LRESULT
ADPCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi
)
719 assert(!(adsi
->fdwOpen
& ACM_STREAMOPENF_ASYNC
));
721 if (ADPCM_GetFormatIndex(adsi
->pwfxSrc
) == 0xFFFFFFFF ||
722 ADPCM_GetFormatIndex(adsi
->pwfxDst
) == 0xFFFFFFFF)
723 return ACMERR_NOTPOSSIBLE
;
725 aad
= HeapAlloc(GetProcessHeap(), 0, sizeof(AcmAdpcmData
));
726 if (aad
== 0) return MMSYSERR_NOMEM
;
728 adsi
->dwDriver
= (DWORD_PTR
)aad
;
730 if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
&&
731 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
735 else if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_IMA_ADPCM
&&
736 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
738 /* resampling or mono <=> stereo not available
739 * ADPCM algo only define 16 bit per sample output
741 if (adsi
->pwfxSrc
->nSamplesPerSec
!= adsi
->pwfxDst
->nSamplesPerSec
||
742 adsi
->pwfxSrc
->nChannels
!= adsi
->pwfxDst
->nChannels
||
743 adsi
->pwfxDst
->wBitsPerSample
!= 16)
746 nspb
= ((LPIMAADPCMWAVEFORMAT
)adsi
->pwfxSrc
)->wSamplesPerBlock
;
747 TRACE("spb=%u\n", nspb
);
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
753 if (((nspb
- 1) & 3) != 0) goto theEnd
;
754 if ((((nspb
- 1) / 2) + 4) * adsi
->pwfxSrc
->nChannels
< adsi
->pwfxSrc
->nBlockAlign
)
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
;
763 else if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
&&
764 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_IMA_ADPCM
)
766 if (adsi
->pwfxSrc
->nSamplesPerSec
!= adsi
->pwfxDst
->nSamplesPerSec
||
767 adsi
->pwfxSrc
->nChannels
!= adsi
->pwfxDst
->nChannels
||
768 adsi
->pwfxSrc
->wBitsPerSample
!= 16)
771 nspb
= ((LPIMAADPCMWAVEFORMAT
)adsi
->pwfxDst
)->wSamplesPerBlock
;
772 TRACE("spb=%u\n", nspb
);
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
778 if (((nspb
- 1) & 3) != 0) goto theEnd
;
779 if ((((nspb
- 1) / 2) + 4) * adsi
->pwfxDst
->nChannels
< adsi
->pwfxDst
->nBlockAlign
)
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
;
789 ADPCM_Reset(adsi
, aad
);
791 return MMSYSERR_NOERROR
;
794 HeapFree(GetProcessHeap(), 0, aad
);
796 return MMSYSERR_NOTSUPPORTED
;
799 /***********************************************************************
803 static LRESULT
ADPCM_StreamClose(PACMDRVSTREAMINSTANCE adsi
)
805 HeapFree(GetProcessHeap(), 0, (void*)adsi
->dwDriver
);
806 return MMSYSERR_NOERROR
;
809 /***********************************************************************
813 static LRESULT
ADPCM_StreamSize(const ACMDRVSTREAMINSTANCE
*adsi
, PACMDRVSTREAMSIZE adss
)
817 switch (adss
->fdwSize
)
819 case ACM_STREAMSIZEF_DESTINATION
:
820 /* cbDstLength => cbSrcLength */
821 if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
&&
822 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_IMA_ADPCM
)
824 nblocks
= adss
->cbDstLength
/ adsi
->pwfxDst
->nBlockAlign
;
826 return ACMERR_NOTPOSSIBLE
;
827 adss
->cbSrcLength
= nblocks
* adsi
->pwfxSrc
->nBlockAlign
* ((IMAADPCMWAVEFORMAT
*)adsi
->pwfxDst
)->wSamplesPerBlock
;
829 else if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_IMA_ADPCM
&&
830 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
832 nblocks
= adss
->cbDstLength
/ (adsi
->pwfxDst
->nBlockAlign
* ((IMAADPCMWAVEFORMAT
*)adsi
->pwfxSrc
)->wSamplesPerBlock
);
834 return ACMERR_NOTPOSSIBLE
;
835 adss
->cbSrcLength
= nblocks
* adsi
->pwfxSrc
->nBlockAlign
;
839 return MMSYSERR_NOTSUPPORTED
;
842 case ACM_STREAMSIZEF_SOURCE
:
843 /* cbSrcLength => cbDstLength */
844 if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
&&
845 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_IMA_ADPCM
)
847 nblocks
= adss
->cbSrcLength
/ (adsi
->pwfxSrc
->nBlockAlign
* ((IMAADPCMWAVEFORMAT
*)adsi
->pwfxDst
)->wSamplesPerBlock
);
849 return ACMERR_NOTPOSSIBLE
;
850 if (adss
->cbSrcLength
% (adsi
->pwfxSrc
->nBlockAlign
* ((IMAADPCMWAVEFORMAT
*)adsi
->pwfxDst
)->wSamplesPerBlock
))
851 /* Round block count up. */
853 adss
->cbDstLength
= nblocks
* adsi
->pwfxDst
->nBlockAlign
;
855 else if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_IMA_ADPCM
&&
856 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
858 nblocks
= adss
->cbSrcLength
/ adsi
->pwfxSrc
->nBlockAlign
;
860 return ACMERR_NOTPOSSIBLE
;
861 if (adss
->cbSrcLength
% adsi
->pwfxSrc
->nBlockAlign
)
862 /* Round block count up. */
864 adss
->cbDstLength
= nblocks
* adsi
->pwfxDst
->nBlockAlign
* ((IMAADPCMWAVEFORMAT
*)adsi
->pwfxSrc
)->wSamplesPerBlock
;
868 return MMSYSERR_NOTSUPPORTED
;
872 WARN("Unsupported query %08x\n", adss
->fdwSize
);
873 return MMSYSERR_NOTSUPPORTED
;
875 return MMSYSERR_NOERROR
;
878 /***********************************************************************
879 * ADPCM_StreamConvert
882 static LRESULT
ADPCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi
, PACMDRVSTREAMHEADER adsh
)
884 AcmAdpcmData
* aad
= (AcmAdpcmData
*)adsi
->dwDriver
;
885 DWORD nsrc
= adsh
->cbSrcLength
;
886 DWORD ndst
= adsh
->cbDstLength
;
888 if (adsh
->fdwConvert
&
889 ~(ACM_STREAMCONVERTF_BLOCKALIGN
|
890 ACM_STREAMCONVERTF_END
|
891 ACM_STREAMCONVERTF_START
))
893 FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh
->fdwConvert
);
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
900 if ((adsh
->fdwConvert
& ACM_STREAMCONVERTF_START
))
902 ADPCM_Reset(adsi
, aad
);
905 aad
->convert(adsi
, adsh
->pbSrc
, &nsrc
, adsh
->pbDst
, &ndst
);
906 adsh
->cbSrcLengthUsed
= nsrc
;
907 adsh
->cbDstLengthUsed
= ndst
;
909 return MMSYSERR_NOERROR
;
912 /**************************************************************************
913 * ADPCM_DriverProc [exported]
915 LRESULT CALLBACK
ADPCM_DriverProc(DWORD_PTR dwDevID
, HDRVR hDriv
, UINT wMsg
,
916 LPARAM dwParam1
, LPARAM dwParam2
)
918 TRACE("(%08lx %p %04x %08lx %08lx);\n",
919 dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
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
;
934 case ACMDM_DRIVER_NOTIFY
:
935 /* no caching from other ACM drivers is done so far */
936 return MMSYSERR_NOERROR
;
938 case ACMDM_DRIVER_DETAILS
:
939 return ADPCM_DriverDetails((PACMDRIVERDETAILSW
)dwParam1
);
941 case ACMDM_FORMATTAG_DETAILS
:
942 return ADPCM_FormatTagDetails((PACMFORMATTAGDETAILSW
)dwParam1
, dwParam2
);
944 case ACMDM_FORMAT_DETAILS
:
945 return ADPCM_FormatDetails((PACMFORMATDETAILSW
)dwParam1
, dwParam2
);
947 case ACMDM_FORMAT_SUGGEST
:
948 return ADPCM_FormatSuggest((PACMDRVFORMATSUGGEST
)dwParam1
);
950 case ACMDM_STREAM_OPEN
:
951 return ADPCM_StreamOpen((PACMDRVSTREAMINSTANCE
)dwParam1
);
953 case ACMDM_STREAM_CLOSE
:
954 return ADPCM_StreamClose((PACMDRVSTREAMINSTANCE
)dwParam1
);
956 case ACMDM_STREAM_SIZE
:
957 return ADPCM_StreamSize((PACMDRVSTREAMINSTANCE
)dwParam1
, (PACMDRVSTREAMSIZE
)dwParam2
);
959 case ACMDM_STREAM_CONVERT
:
960 return ADPCM_StreamConvert((PACMDRVSTREAMINSTANCE
)dwParam1
, (PACMDRVSTREAMHEADER
)dwParam2
);
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
;
977 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);