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 /***********************************************************************
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 alignment 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 alignment 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 LRESULT
ADPCM_StreamSize(const ACMDRVSTREAMINSTANCE
*adsi
, PACMDRVSTREAMSIZE adss
)
778 switch (adss
->fdwSize
)
780 case ACM_STREAMSIZEF_DESTINATION
:
781 /* cbDstLength => cbSrcLength */
782 if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
&&
783 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_IMA_ADPCM
)
785 /* don't take block overhead into account, doesn't matter too much */
786 adss
->cbSrcLength
= adss
->cbDstLength
* 4;
788 else if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_IMA_ADPCM
&&
789 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
791 FIXME("misses the block header overhead\n");
792 adss
->cbSrcLength
= 256 + adss
->cbDstLength
/ 4;
796 return MMSYSERR_NOTSUPPORTED
;
799 case ACM_STREAMSIZEF_SOURCE
:
800 /* cbSrcLength => cbDstLength */
801 if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
&&
802 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_IMA_ADPCM
)
804 FIXME("misses the block header overhead\n");
805 adss
->cbDstLength
= 256 + adss
->cbSrcLength
/ 4;
807 else if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_IMA_ADPCM
&&
808 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
810 /* don't take block overhead into account, doesn't matter too much */
811 adss
->cbDstLength
= adss
->cbSrcLength
* 4;
815 return MMSYSERR_NOTSUPPORTED
;
819 WARN("Unsupported query %08x\n", adss
->fdwSize
);
820 return MMSYSERR_NOTSUPPORTED
;
822 return MMSYSERR_NOERROR
;
825 /***********************************************************************
826 * ADPCM_StreamConvert
829 static LRESULT
ADPCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi
, PACMDRVSTREAMHEADER adsh
)
831 AcmAdpcmData
* aad
= (AcmAdpcmData
*)adsi
->dwDriver
;
832 DWORD nsrc
= adsh
->cbSrcLength
;
833 DWORD ndst
= adsh
->cbDstLength
;
835 if (adsh
->fdwConvert
&
836 ~(ACM_STREAMCONVERTF_BLOCKALIGN
|
837 ACM_STREAMCONVERTF_END
|
838 ACM_STREAMCONVERTF_START
))
840 FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh
->fdwConvert
);
842 /* ACM_STREAMCONVERTF_BLOCKALIGN
843 * currently all conversions are block aligned, so do nothing for this flag
844 * ACM_STREAMCONVERTF_END
845 * no pending data, so do nothing for this flag
847 if ((adsh
->fdwConvert
& ACM_STREAMCONVERTF_START
))
849 ADPCM_Reset(adsi
, aad
);
852 aad
->convert(adsi
, adsh
->pbSrc
, &nsrc
, adsh
->pbDst
, &ndst
);
853 adsh
->cbSrcLengthUsed
= nsrc
;
854 adsh
->cbDstLengthUsed
= ndst
;
856 return MMSYSERR_NOERROR
;
859 /**************************************************************************
860 * ADPCM_DriverProc [exported]
862 LRESULT CALLBACK
ADPCM_DriverProc(DWORD_PTR dwDevID
, HDRVR hDriv
, UINT wMsg
,
863 LPARAM dwParam1
, LPARAM dwParam2
)
865 TRACE("(%08lx %p %04x %08lx %08lx);\n",
866 dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
870 case DRV_LOAD
: return 1;
871 case DRV_FREE
: return 1;
872 case DRV_OPEN
: return ADPCM_drvOpen((LPSTR
)dwParam1
);
873 case DRV_CLOSE
: return ADPCM_drvClose(dwDevID
);
874 case DRV_ENABLE
: return 1;
875 case DRV_DISABLE
: return 1;
876 case DRV_QUERYCONFIGURE
: return 1;
877 case DRV_CONFIGURE
: MessageBoxA(0, "MSACM IMA ADPCM filter !", "Wine Driver", MB_OK
); return 1;
878 case DRV_INSTALL
: return DRVCNF_RESTART
;
879 case DRV_REMOVE
: return DRVCNF_RESTART
;
881 case ACMDM_DRIVER_NOTIFY
:
882 /* no caching from other ACM drivers is done so far */
883 return MMSYSERR_NOERROR
;
885 case ACMDM_DRIVER_DETAILS
:
886 return ADPCM_DriverDetails((PACMDRIVERDETAILSW
)dwParam1
);
888 case ACMDM_FORMATTAG_DETAILS
:
889 return ADPCM_FormatTagDetails((PACMFORMATTAGDETAILSW
)dwParam1
, dwParam2
);
891 case ACMDM_FORMAT_DETAILS
:
892 return ADPCM_FormatDetails((PACMFORMATDETAILSW
)dwParam1
, dwParam2
);
894 case ACMDM_FORMAT_SUGGEST
:
895 return ADPCM_FormatSuggest((PACMDRVFORMATSUGGEST
)dwParam1
);
897 case ACMDM_STREAM_OPEN
:
898 return ADPCM_StreamOpen((PACMDRVSTREAMINSTANCE
)dwParam1
);
900 case ACMDM_STREAM_CLOSE
:
901 return ADPCM_StreamClose((PACMDRVSTREAMINSTANCE
)dwParam1
);
903 case ACMDM_STREAM_SIZE
:
904 return ADPCM_StreamSize((PACMDRVSTREAMINSTANCE
)dwParam1
, (PACMDRVSTREAMSIZE
)dwParam2
);
906 case ACMDM_STREAM_CONVERT
:
907 return ADPCM_StreamConvert((PACMDRVSTREAMINSTANCE
)dwParam1
, (PACMDRVSTREAMHEADER
)dwParam2
);
909 case ACMDM_HARDWARE_WAVE_CAPS_INPUT
:
910 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT
:
911 /* this converter is not a hardware driver */
912 case ACMDM_FILTERTAG_DETAILS
:
913 case ACMDM_FILTER_DETAILS
:
914 /* this converter is not a filter */
915 case ACMDM_STREAM_RESET
:
916 /* only needed for asynchronous driver... we aren't, so just say it */
917 return MMSYSERR_NOTSUPPORTED
;
918 case ACMDM_STREAM_PREPARE
:
919 case ACMDM_STREAM_UNPREPARE
:
920 /* nothing special to do here... so don't do anything */
921 return MMSYSERR_NOERROR
;
924 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);