ReactOS 0.4.17-dev-966-gf06eace
msadp32.c
Go to the documentation of this file.
1/*
2 * MS ADPCM handling
3 *
4 * Copyright (C) 2002 Eric Pouech
5 *
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22#include <assert.h>
23#include <stdarg.h>
24#include <string.h>
25#include "windef.h"
26#include "winbase.h"
27#include "wingdi.h"
28#include "winuser.h"
29#include "winnls.h"
30#include "mmsystem.h"
31#include "mmreg.h"
32#include "msacm.h"
33#include "msacmdrv.h"
34#include "wine/debug.h"
35
36/* see http://www.pcisys.net/~melanson/codecs/adpcm.txt for the details */
37
39
40/***********************************************************************
41 * ADPCM_drvOpen
42 */
44{
45 return 1;
46}
47
48/***********************************************************************
49 * ADPCM_drvClose
50 */
52{
53 return 1;
54}
55
56typedef struct tagAcmAdpcmData
57{
58 void (*convert)(const ACMDRVSTREAMINSTANCE *adsi,
59 const unsigned char*, LPDWORD, unsigned char*, LPDWORD);
61
62/* table to list all supported formats... those are the basic ones. this
63 * also helps given a unique index to each of the supported formats
64 */
65typedef struct
66{
67 int nChannels;
68 int nBits;
69 int rate;
70} Format;
71
72static const Format PCM_Formats[] =
73{
74 {1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000},
75 {1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025},
76 {1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050},
77 {1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100},
78};
79
80static const Format ADPCM_Formats[] =
81{
82 {1, 4, 8000}, {2, 4, 8000}, {1, 4, 11025}, {2, 4, 11025},
83 {1, 4, 22050}, {2, 4, 22050}, {1, 4, 44100}, {2, 4, 44100},
84};
85
86static int MS_Delta[] =
87{
88 230, 230, 230, 230, 307, 409, 512, 614,
89 768, 614, 512, 409, 307, 230, 230, 230
90};
91
92
94{
95 {256, 0}, {512, -256}, {0, 0}, {192, 64}, {240, 0}, {460, -208}, {392, -232}
96};
97
98/***********************************************************************
99 * ADPCM_GetFormatIndex
100 */
102{
103 int i, hi;
104 const Format* fmts;
105
106 switch (wfx->wFormatTag)
107 {
108 case WAVE_FORMAT_PCM:
111 break;
115 break;
116 default:
117 return 0xFFFFFFFF;
118 }
119
120 for (i = 0; i < hi; i++)
121 {
122 if (wfx->nChannels == fmts[i].nChannels &&
123 wfx->nSamplesPerSec == fmts[i].rate &&
124 wfx->wBitsPerSample == fmts[i].nBits)
125 return i;
126 }
127
128 switch (wfx->wFormatTag)
129 {
130 case WAVE_FORMAT_PCM:
131 if(3 > wfx->nChannels &&
132 wfx->nChannels > 0 &&
133 wfx->nAvgBytesPerSec == 2 * wfx->nSamplesPerSec * wfx->nChannels &&
134 wfx->nBlockAlign == 2 * wfx->nChannels &&
135 wfx->wBitsPerSample == 16)
136 return hi;
137 break;
139 if(3 > wfx->nChannels &&
140 wfx->nChannels > 0 &&
141 wfx->wBitsPerSample == 4 &&
142 wfx->cbSize == 32)
143 return hi;
144 break;
145 }
146
147 return 0xFFFFFFFF;
148}
149
151{
152 register WAVEFORMATEX* pwfx = &awfx->wfx;
153
154 /* we assume wFormatTag, nChannels, nSamplesPerSec and wBitsPerSample
155 * have been initialized... */
156
157 if (pwfx->wFormatTag != WAVE_FORMAT_ADPCM) {FIXME("wrong FT\n"); return;}
158 if (ADPCM_GetFormatIndex(pwfx) == 0xFFFFFFFF) {FIXME("wrong fmt\n"); return;}
159
160 switch (pwfx->nSamplesPerSec)
161 {
162 case 8000: pwfx->nBlockAlign = 256 * pwfx->nChannels; break;
163 case 11025: pwfx->nBlockAlign = 256 * pwfx->nChannels; break;
164 case 22050: pwfx->nBlockAlign = 512 * pwfx->nChannels; break;
165 case 44100: pwfx->nBlockAlign = 1024 * pwfx->nChannels; break;
166 default: break;
167 }
168 pwfx->cbSize = 2 * sizeof(WORD) + 7 * sizeof(ADPCMCOEFSET);
169 /* 7 is the size of the block head (which contains two samples) */
170
171 awfx->wSamplesPerBlock = pwfx->nBlockAlign * 2 / pwfx->nChannels - 12;
172 pwfx->nAvgBytesPerSec = (pwfx->nSamplesPerSec * pwfx->nBlockAlign) / awfx->wSamplesPerBlock;
173 awfx->wNumCoef = 7;
174 memcpy(awfx->aCoef, MSADPCM_CoeffSet, 7 * sizeof(ADPCMCOEFSET));
175}
176
177/***********************************************************************
178 * R16
179 *
180 * Read a 16 bit sample (correctly handles endianness)
181 */
182static inline short R16(const unsigned char* src)
183{
184 return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));
185}
186
187/***********************************************************************
188 * W16
189 *
190 * Write a 16 bit sample (correctly handles endianness)
191 */
192static inline void W16(unsigned char* dst, short s)
193{
194 dst[0] = LOBYTE(s);
195 dst[1] = HIBYTE(s);
196}
197
198static inline void clamp_sample(int* sample)
199{
200 if (*sample < -32768) *sample = -32768;
201 if (*sample > 32767) *sample = 32767;
202}
203
204static inline void process_nibble(unsigned nibble, int* idelta,
205 int* sample1, int* sample2,
206 const ADPCMCOEFSET* coeff)
207{
208 int sample;
209 int snibble;
210
211 /* nibble is in fact a signed 4 bit integer => propagate sign if needed */
212 snibble = (nibble & 0x08) ? (nibble - 16) : nibble;
213 sample = ((*sample1 * coeff->iCoef1) + (*sample2 * coeff->iCoef2)) / 256 +
214 snibble * *idelta;
216
217 *sample2 = *sample1;
218 *sample1 = sample;
219 *idelta = ((MS_Delta[nibble] * *idelta) / 256);
220 if (*idelta < 16) *idelta = 16;
221}
222
223static inline unsigned char C168(short s)
224{
225 return HIBYTE(s) ^ (unsigned char)0x80;
226}
227
228static void cvtSSms16K(const ACMDRVSTREAMINSTANCE *adsi,
229 const unsigned char* src, LPDWORD nsrc,
230 unsigned char* dst, LPDWORD ndst)
231{
232 int ideltaL, ideltaR;
233 int sample1L, sample2L;
234 int sample1R, sample2R;
235 ADPCMCOEFSET coeffL, coeffR;
236 int nsamp;
237 int nsamp_blk = ((ADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock;
238 DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign,
239 *ndst / (nsamp_blk * adsi->pwfxDst->nBlockAlign));
240
241 *nsrc = nblock * adsi->pwfxSrc->nBlockAlign;
242 *ndst = nblock * nsamp_blk * adsi->pwfxDst->nBlockAlign;
243
244 nsamp_blk -= 2; /* see below for samples from block head */
245 for (; nblock > 0; nblock--)
246 {
247 const unsigned char* in_src = src;
248
249 /* Catch a problem from Tomb Raider III (bug 21000) where it passes
250 * invalid data after a valid sequence of blocks */
251 if (*src > 6 || *(src + 1) > 6)
252 {
253 /* Recalculate the amount of used output buffer. We are not changing
254 * nsrc, let's assume the bad data was parsed */
255 *ndst -= nblock * nsamp_blk * adsi->pwfxDst->nBlockAlign;
256 WARN("Invalid ADPCM data, stopping conversion\n");
257 break;
258 }
259 coeffL = MSADPCM_CoeffSet[*src++];
260 coeffR = MSADPCM_CoeffSet[*src++];
261
262 ideltaL = R16(src); src += 2;
263 ideltaR = R16(src); src += 2;
264 sample1L = R16(src); src += 2;
265 sample1R = R16(src); src += 2;
266 sample2L = R16(src); src += 2;
267 sample2R = R16(src); src += 2;
268
269 if(adsi->pwfxDst->wBitsPerSample == 8){
270 /* store samples from block head */
271 *dst = C168(sample2L); ++dst;
272 *dst = C168(sample2R); ++dst;
273 *dst = C168(sample1L); ++dst;
274 *dst = C168(sample1R); ++dst;
275
276 for (nsamp = nsamp_blk; nsamp > 0; nsamp--)
277 {
278 process_nibble(*src >> 4, &ideltaL, &sample1L, &sample2L, &coeffL);
279 *dst = C168(sample1L); ++dst;
280 process_nibble(*src++ & 0x0F, &ideltaR, &sample1R, &sample2R, &coeffR);
281 *dst = C168(sample1R); ++dst;
282 }
283 }else if(adsi->pwfxDst->wBitsPerSample == 16){
284 /* store samples from block head */
285 W16(dst, sample2L); dst += 2;
286 W16(dst, sample2R); dst += 2;
287 W16(dst, sample1L); dst += 2;
288 W16(dst, sample1R); dst += 2;
289
290 for (nsamp = nsamp_blk; nsamp > 0; nsamp--)
291 {
292 process_nibble(*src >> 4, &ideltaL, &sample1L, &sample2L, &coeffL);
293 W16(dst, sample1L); dst += 2;
294 process_nibble(*src++ & 0x0F, &ideltaR, &sample1R, &sample2R, &coeffR);
295 W16(dst, sample1R); dst += 2;
296 }
297 }
298 src = in_src + adsi->pwfxSrc->nBlockAlign;
299 }
300}
301
302static void cvtMMms16K(const ACMDRVSTREAMINSTANCE *adsi,
303 const unsigned char* src, LPDWORD nsrc,
304 unsigned char* dst, LPDWORD ndst)
305{
306 int idelta;
307 int sample1, sample2;
308 ADPCMCOEFSET coeff;
309 int nsamp;
310 int nsamp_blk = ((ADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock;
311 DWORD nblock = min(*nsrc / adsi->pwfxSrc->nBlockAlign,
312 *ndst / (nsamp_blk * adsi->pwfxDst->nBlockAlign));
313
314 *nsrc = nblock * adsi->pwfxSrc->nBlockAlign;
315 *ndst = nblock * nsamp_blk * adsi->pwfxDst->nBlockAlign;
316
317 nsamp_blk -= 2; /* see below for samples from block head */
318 for (; nblock > 0; nblock--)
319 {
320 const unsigned char* in_src = src;
321
322 /* Catch a problem from Lord of the Rings War of the Ring where it
323 * passes invalid data. */
324 if (*src > 6)
325 {
326 *ndst -= nblock * nsamp_blk * adsi->pwfxDst->nBlockAlign;
327 WARN("Invalid ADPCM data, stopping conversion\n");
328 break;
329 }
330 coeff = MSADPCM_CoeffSet[*src++];
331
332 idelta = R16(src); src += 2;
333 sample1 = R16(src); src += 2;
334 sample2 = R16(src); src += 2;
335
336 /* store samples from block head */
337 if(adsi->pwfxDst->wBitsPerSample == 8){
338 *dst = C168(sample2); ++dst;
339 *dst = C168(sample1); ++dst;
340
341 for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
342 {
343 process_nibble(*src >> 4, &idelta, &sample1, &sample2, &coeff);
344 *dst = C168(sample1); ++dst;
345 process_nibble(*src++ & 0x0F, &idelta, &sample1, &sample2, &coeff);
346 *dst = C168(sample1); ++dst;
347 }
348 }else if(adsi->pwfxDst->wBitsPerSample == 16){
349 W16(dst, sample2); dst += 2;
350 W16(dst, sample1); dst += 2;
351
352 for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
353 {
354 process_nibble(*src >> 4, &idelta, &sample1, &sample2, &coeff);
355 W16(dst, sample1); dst += 2;
356 process_nibble(*src++ & 0x0F, &idelta, &sample1, &sample2, &coeff);
357 W16(dst, sample1); dst += 2;
358 }
359 }
360
361 src = in_src + adsi->pwfxSrc->nBlockAlign;
362 }
363}
364
365#if 0
366static void cvtSS16msK(PACMDRVSTREAMINSTANCE adsi,
367 const unsigned char* src, LPDWORD nsrc,
368 unsigned char* dst, LPDWORD ndst)
369{
370}
371
372static void cvtMM16msK(PACMDRVSTREAMINSTANCE adsi,
373 const unsigned char* src, LPDWORD nsrc,
374 unsigned char* dst, LPDWORD ndst)
375{
376}
377#endif
378
379/***********************************************************************
380 * ADPCM_DriverDetails
381 *
382 */
384{
387 add->wMid = MM_MICROSOFT;
388 add->wPid = MM_MSFT_ACM_MSADPCM;
389 add->vdwACM = 0x01000000;
390 add->vdwDriver = 0x01000000;
391 add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
392 add->cFormatTags = 2; /* PCM, MS ADPCM */
393 add->cFilterTags = 0;
394 add->hicon = NULL;
395 MultiByteToWideChar( CP_ACP, 0, "MS-ADPCM", -1,
396 add->szShortName, ARRAY_SIZE( add->szShortName ));
397 MultiByteToWideChar( CP_ACP, 0, "Wine MS ADPCM converter", -1,
398 add->szLongName, ARRAY_SIZE( add->szLongName ));
399 MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
400 add->szCopyright, ARRAY_SIZE( add->szCopyright ));
401 MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
402 add->szLicensing, ARRAY_SIZE( add->szLicensing ));
403 add->szFeatures[0] = 0;
404
405 return MMSYSERR_NOERROR;
406}
407
408/***********************************************************************
409 * ADPCM_FormatTagDetails
410 *
411 */
413{
414 switch (dwQuery)
415 {
417 if (aftd->dwFormatTagIndex >= 2) return ACMERR_NOTPOSSIBLE;
418 break;
420 if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
421 {
422 aftd->dwFormatTagIndex = 1; /* WAVE_FORMAT_ADPCM is bigger than PCM */
423 break;
424 }
425 /* fall through */
427 switch (aftd->dwFormatTag)
428 {
429 case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break;
430 case WAVE_FORMAT_ADPCM: aftd->dwFormatTagIndex = 1; break;
431 default: return ACMERR_NOTPOSSIBLE;
432 }
433 break;
434 default:
435 WARN("Unsupported query %08lx\n", dwQuery);
437 }
438
440 switch (aftd->dwFormatTagIndex)
441 {
442 case 0:
444 aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
446 lstrcpyW(aftd->szFormatTag, L"PCM");
447 break;
448 case 1:
450 aftd->cbFormatSize = sizeof(ADPCMWAVEFORMAT) + (7 - 1) * sizeof(ADPCMCOEFSET);
452 lstrcpyW(aftd->szFormatTag, L"Microsoft ADPCM");
453 break;
454 }
455 return MMSYSERR_NOERROR;
456}
457
458/***********************************************************************
459 * ADPCM_FormatDetails
460 *
461 */
463{
464 switch (dwQuery)
465 {
467 if (ADPCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
468 break;
470 afd->pwfx->wFormatTag = afd->dwFormatTag;
471 switch (afd->dwFormatTag)
472 {
473 case WAVE_FORMAT_PCM:
478 /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible
479 * afd->pwfx->cbSize = 0;
480 */
481 afd->pwfx->nBlockAlign =
482 (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8;
483 afd->pwfx->nAvgBytesPerSec =
484 afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
485 break;
488 if (afd->cbwfx < sizeof(ADPCMWAVEFORMAT) + (7 - 1) * sizeof(ADPCMCOEFSET))
489 return ACMERR_NOTPOSSIBLE;
494 break;
495 default:
496 WARN("Unsupported tag %08lx\n", afd->dwFormatTag);
497 return MMSYSERR_INVALPARAM;
498 }
499 break;
500 default:
501 WARN("Unsupported query %08lx\n", dwQuery);
503 }
505 afd->szFormat[0] = 0; /* let MSACM format this for us... */
506
507 return MMSYSERR_NOERROR;
508}
509
510/***********************************************************************
511 * ADPCM_FormatSuggest
512 *
513 */
515{
516 /* some tests ... */
517 if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
518 adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
519 adfs->pwfxSrc->wFormatTag == adfs->pwfxDst->wFormatTag ||
520 ADPCM_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
521 /* FIXME: should do those tests against the real size (according to format tag */
522
523 /* If no suggestion for destination, then copy source value */
525 adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
528
530 {
531 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
532 adfs->pwfxDst->wBitsPerSample = 4;
533 else
534 adfs->pwfxDst->wBitsPerSample = 16;
535 }
537 {
538 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
540 else
542 }
543
544 /* recompute other values */
545 switch (adfs->pwfxDst->wFormatTag)
546 {
547 case WAVE_FORMAT_PCM:
548 adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8;
550 /* check if result is ok */
551 if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
552 break;
554 if (adfs->cbwfxDst < sizeof(ADPCMWAVEFORMAT) + (7 - 1) * sizeof(ADPCMCOEFSET))
555 return ACMERR_NOTPOSSIBLE;
557 /* check if result is ok */
558 if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
559 break;
560 default:
561 return ACMERR_NOTPOSSIBLE;
562 }
563
564 return MMSYSERR_NOERROR;
565}
566
567/***********************************************************************
568 * ADPCM_Reset
569 *
570 */
572{
573}
574
575/***********************************************************************
576 * ADPCM_StreamOpen
577 *
578 */
580{
581 AcmAdpcmData* aad;
582
584
585 if (ADPCM_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
586 ADPCM_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
587 return ACMERR_NOTPOSSIBLE;
588
589 aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmAdpcmData));
590 if (aad == 0) return MMSYSERR_NOMEM;
591
592 adsi->dwDriver = (DWORD_PTR)aad;
593
594 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
596 {
597 goto theEnd;
598 }
599 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM &&
601 {
602 /* resampling or mono <=> stereo not available */
603 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
604 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels)
605 goto theEnd;
606
607#if 0
608 {
609 unsigned int nspb = ((IMAADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock;
610 FIXME("spb=%u\n", nspb);
611
612 /* we check that in a block, after the header, samples are present on
613 * 4-sample packet pattern
614 * we also check that the block alignment is bigger than the expected size
615 */
616 if (((nspb - 1) & 3) != 0) goto theEnd;
617 if ((((nspb - 1) / 2) + 4) * adsi->pwfxSrc->nChannels < adsi->pwfxSrc->nBlockAlign)
618 goto theEnd;
619 }
620#endif
621
622 /* adpcm decoding... */
623 if (adsi->pwfxDst->nChannels == 2)
624 aad->convert = cvtSSms16K;
625 else if (adsi->pwfxDst->nChannels == 1)
626 aad->convert = cvtMMms16K;
627 }
628 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
630 {
631 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
632 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
633 adsi->pwfxSrc->wBitsPerSample != 16)
634 goto theEnd;
635#if 0
636 nspb = ((IMAADPCMWAVEFORMAT*)adsi->pwfxDst)->wSamplesPerBlock;
637 FIXME("spb=%u\n", nspb);
638
639 /* we check that in a block, after the header, samples are present on
640 * 4-sample packet pattern
641 * we also check that the block alignment is bigger than the expected size
642 */
643 if (((nspb - 1) & 3) != 0) goto theEnd;
644 if ((((nspb - 1) / 2) + 4) * adsi->pwfxDst->nChannels < adsi->pwfxDst->nBlockAlign)
645 goto theEnd;
646#endif
647#if 0
648 /* adpcm coding... */
649 if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 2)
650 aad->convert = cvtSS16msK;
651 if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 1)
652 aad->convert = cvtMM16msK;
653#endif
654 FIXME("We don't support encoding yet\n");
655 goto theEnd;
656 }
657 else goto theEnd;
658 ADPCM_Reset(adsi, aad);
659
660 return MMSYSERR_NOERROR;
661
662 theEnd:
663 HeapFree(GetProcessHeap(), 0, aad);
664 adsi->dwDriver = 0L;
666}
667
668/***********************************************************************
669 * ADPCM_StreamClose
670 *
671 */
673{
674 HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
675 return MMSYSERR_NOERROR;
676}
677
678/***********************************************************************
679 * ADPCM_StreamSize
680 *
681 */
683{
684 DWORD nblocks;
685 WORD wSamplesPerBlock;
686 /* wSamplesPerBlock formula comes from MSDN ADPCMWAVEFORMAT page.*/
687 switch (adss->fdwSize)
688 {
690 /* cbDstLength => cbSrcLength */
691 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
693 {
694 wSamplesPerBlock = adsi->pwfxDst->nBlockAlign * 2 / adsi->pwfxDst->nChannels - 12;
695 nblocks = adss->cbDstLength / adsi->pwfxDst->nBlockAlign;
696 if (nblocks == 0)
697 return ACMERR_NOTPOSSIBLE;
698 adss->cbSrcLength = nblocks * adsi->pwfxSrc->nBlockAlign * wSamplesPerBlock;
699 }
700 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM &&
702 {
703 wSamplesPerBlock = adsi->pwfxSrc->nBlockAlign * 2 / adsi->pwfxSrc->nChannels - 12;
704 nblocks = adss->cbDstLength / (adsi->pwfxDst->nBlockAlign * wSamplesPerBlock);
705 if (nblocks == 0)
706 return ACMERR_NOTPOSSIBLE;
707 adss->cbSrcLength = nblocks * adsi->pwfxSrc->nBlockAlign;
708 }
709 else
710 {
712 }
713 break;
715 /* cbSrcLength => cbDstLength */
716 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
718 {
719 wSamplesPerBlock = adsi->pwfxDst->nBlockAlign * 2 / adsi->pwfxDst->nChannels - 12;
720 nblocks = adss->cbSrcLength / (adsi->pwfxSrc->nBlockAlign * wSamplesPerBlock);
721 if (nblocks == 0)
722 return ACMERR_NOTPOSSIBLE;
723 if (adss->cbSrcLength % (adsi->pwfxSrc->nBlockAlign * wSamplesPerBlock))
724 /* Round block count up. */
725 nblocks++;
726 adss->cbDstLength = nblocks * adsi->pwfxDst->nBlockAlign;
727 }
728 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM &&
730 {
731 wSamplesPerBlock = adsi->pwfxSrc->nBlockAlign * 2 / adsi->pwfxSrc->nChannels - 12;
732 nblocks = adss->cbSrcLength / adsi->pwfxSrc->nBlockAlign;
733 if (nblocks == 0)
734 return ACMERR_NOTPOSSIBLE;
735 if (adss->cbSrcLength % adsi->pwfxSrc->nBlockAlign)
736 /* Round block count up. */
737 nblocks++;
738 adss->cbDstLength = nblocks * adsi->pwfxDst->nBlockAlign * wSamplesPerBlock;
739 }
740 else
741 {
743 }
744 break;
745 default:
746 WARN("Unsupported query %08lx\n", adss->fdwSize);
748 }
749 return MMSYSERR_NOERROR;
750}
751
752/***********************************************************************
753 * ADPCM_StreamConvert
754 *
755 */
757{
758 AcmAdpcmData* aad = (AcmAdpcmData*)adsi->dwDriver;
759 DWORD nsrc = adsh->cbSrcLength;
760 DWORD ndst = adsh->cbDstLength;
761
762 if (adsh->fdwConvert &
766 {
767 FIXME("Unsupported fdwConvert (%08lx), ignoring it\n", adsh->fdwConvert);
768 }
769 /* ACM_STREAMCONVERTF_BLOCKALIGN
770 * currently all conversions are block aligned, so do nothing for this flag
771 * ACM_STREAMCONVERTF_END
772 * no pending data, so do nothing for this flag
773 */
775 {
776 ADPCM_Reset(adsi, aad);
777 }
778
779 aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
780 adsh->cbSrcLengthUsed = nsrc;
781 adsh->cbDstLengthUsed = ndst;
782
783 return MMSYSERR_NOERROR;
784}
785
786/**************************************************************************
787 * ADPCM_DriverProc [exported]
788 */
789LRESULT CALLBACK ADPCM_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
790 LPARAM dwParam1, LPARAM dwParam2)
791{
792 TRACE("(%08Ix %p %04x %08Ix %08Ix);\n",
793 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
794
795 switch (wMsg)
796 {
797 case DRV_LOAD: return 1;
798 case DRV_FREE: return 1;
799 case DRV_OPEN: return ADPCM_drvOpen((LPSTR)dwParam1);
800 case DRV_CLOSE: return ADPCM_drvClose(dwDevID);
801 case DRV_ENABLE: return 1;
802 case DRV_DISABLE: return 1;
803 case DRV_QUERYCONFIGURE: return 1;
804 case DRV_CONFIGURE: MessageBoxA(0, "MSACM MS ADPCM filter !", "Wine Driver", MB_OK); return 1;
805 case DRV_INSTALL: return DRVCNF_RESTART;
806 case DRV_REMOVE: return DRVCNF_RESTART;
807
809 /* no caching from other ACM drivers is done so far */
810 return MMSYSERR_NOERROR;
811
813 return ADPCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
814
816 return ADPCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
817
819 return ADPCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
820
823
825 return ADPCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
826
829
831 return ADPCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
832
835
838 /* this converter is not a hardware driver */
841 /* this converter is not a filter */
843 /* only needed for asynchronous driver... we aren't, so just say it */
847 /* nothing special to do here... so don't do anything */
848 return MMSYSERR_NOERROR;
849
850 default:
851 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
852 }
853}
unsigned int rate
Definition: audiorecord.c:87
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define WAVE_FORMAT_ADPCM
Definition: constants.h:426
#define WAVE_FORMAT_PCM
Definition: constants.h:425
#define ARRAY_SIZE(A)
Definition: main.h:20
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define NULL
Definition: types.h:112
#define GetProcessHeap()
Definition: compat.h:736
#define CP_ACP
Definition: compat.h:109
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define CALLBACK
Definition: compat.h:35
#define lstrcpyW
Definition: compat.h:749
#define MultiByteToWideChar
Definition: compat.h:110
#define assert(_expr)
Definition: assert.h:32
unsigned char
Definition: typeof.h:29
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:94
LRESULT WINAPI DefDriverProc(DWORD_PTR dwDriverIdentifier, HDRVR hDrv, UINT Msg, LPARAM lParam1, LPARAM lParam2)
Definition: driver.c:554
#define L(x)
Definition: resources.c:13
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
GLdouble s
Definition: gl.h:2039
GLenum src
Definition: glext.h:6340
GLenum GLenum dst
Definition: glext.h:6340
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
unsigned int UINT
Definition: sysinfo.c:13
#define DRV_LOAD(x)
#define LOBYTE(W)
Definition: jmemdos.c:487
#define HIBYTE(W)
Definition: jmemdos.c:486
if(dx< 0)
Definition: linetemp.h:194
LONG_PTR LPARAM
Definition: minwindef.h:175
LONG_PTR LRESULT
Definition: minwindef.h:176
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define WAVE_FORMAT_UNKNOWN
Definition: mmreg.h:95
struct adpcmcoef_tag ADPCMCOEFSET
#define MM_MSFT_ACM_MSADPCM
Definition: mmreg.h:146
struct adpcmwaveformat_tag ADPCMWAVEFORMAT
#define MM_MICROSOFT
Definition: mmreg.h:144
#define DRV_CLOSE
Definition: mmsystem.h:122
#define MMSYSERR_NOMEM
Definition: mmsystem.h:103
#define DRV_QUERYCONFIGURE
Definition: mmsystem.h:126
#define MMSYSERR_NOTSUPPORTED
Definition: mmsystem.h:104
#define DRVCNF_RESTART
Definition: mmsystem.h:135
#define DRV_REMOVE
Definition: mmsystem.h:128
#define DRV_ENABLE
Definition: mmsystem.h:120
#define DRV_CONFIGURE
Definition: mmsystem.h:125
#define DRV_OPEN
Definition: mmsystem.h:121
struct pcmwaveformat_tag PCMWAVEFORMAT
#define DRV_INSTALL
Definition: mmsystem.h:127
#define MMSYSERR_INVALPARAM
Definition: mmsystem.h:107
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define DRV_FREE
Definition: mmsystem.h:124
#define DRV_DISABLE
Definition: mmsystem.h:123
static struct fmt fmts[]
#define min(a, b)
Definition: monoChain.cc:55
#define ACM_STREAMCONVERTF_START
Definition: msacm.h:206
#define ACM_FORMATTAGDETAILSF_FORMATTAG
Definition: msacm.h:183
#define ACM_STREAMCONVERTF_BLOCKALIGN
Definition: msacm.h:205
#define ACM_STREAMOPENF_ASYNC
Definition: msacm.h:214
#define ACMDRIVERDETAILS_FCCCOMP_UNDEFINED
Definition: msacm.h:59
#define ACM_FORMATSUGGESTF_WFORMATTAG
Definition: msacm.h:174
#define ACM_FORMATSUGGESTF_NCHANNELS
Definition: msacm.h:175
#define ACMERR_NOTPOSSIBLE
Definition: msacm.h:36
#define ACM_FORMATDETAILSF_FORMAT
Definition: msacm.h:161
#define ACM_STREAMSIZEF_SOURCE
Definition: msacm.h:217
#define ACM_FORMATTAGDETAILSF_LARGESTSIZE
Definition: msacm.h:184
#define ACM_STREAMSIZEF_DESTINATION
Definition: msacm.h:218
#define ACM_FORMATDETAILSF_INDEX
Definition: msacm.h:160
#define ACM_FORMATTAGDETAILSF_INDEX
Definition: msacm.h:182
#define ACM_FORMATSUGGESTF_WBITSPERSAMPLE
Definition: msacm.h:177
#define ACM_STREAMCONVERTF_END
Definition: msacm.h:207
#define ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC
Definition: msacm.h:58
#define ACMDRIVERDETAILS_SUPPORTF_CODEC
Definition: msacm.h:61
#define ACM_FORMATSUGGESTF_NSAMPLESPERSEC
Definition: msacm.h:176
#define ACMDM_STREAM_PREPARE
Definition: msacmdrv.h:63
#define ACMDM_STREAM_CLOSE
Definition: msacmdrv.h:59
#define ACMDM_STREAM_CONVERT
Definition: msacmdrv.h:61
#define ACMDM_FORMAT_SUGGEST
Definition: msacmdrv.h:53
#define ACMDM_FILTER_DETAILS
Definition: msacmdrv.h:56
#define ACMDM_HARDWARE_WAVE_CAPS_INPUT
Definition: msacmdrv.h:48
#define ACMDM_DRIVER_NOTIFY
Definition: msacmdrv.h:45
#define ACMDM_FORMAT_DETAILS
Definition: msacmdrv.h:52
#define ACMDM_STREAM_SIZE
Definition: msacmdrv.h:60
#define ACMDM_FILTERTAG_DETAILS
Definition: msacmdrv.h:55
#define ACMDM_HARDWARE_WAVE_CAPS_OUTPUT
Definition: msacmdrv.h:49
#define ACMDM_FORMATTAG_DETAILS
Definition: msacmdrv.h:51
#define ACMDM_STREAM_UNPREPARE
Definition: msacmdrv.h:64
#define ACMDM_STREAM_OPEN
Definition: msacmdrv.h:58
#define ACMDM_DRIVER_DETAILS
Definition: msacmdrv.h:46
#define ACMDM_STREAM_RESET
Definition: msacmdrv.h:62
static void init_wfx_adpcm(ADPCMWAVEFORMAT *awfx)
Definition: msadp32.c:150
LRESULT CALLBACK ADPCM_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg, LPARAM dwParam1, LPARAM dwParam2)
Definition: msadp32.c:789
struct tagAcmAdpcmData AcmAdpcmData
static LRESULT ADPCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
Definition: msadp32.c:514
static void cvtSSms16K(const ACMDRVSTREAMINSTANCE *adsi, const unsigned char *src, LPDWORD nsrc, unsigned char *dst, LPDWORD ndst)
Definition: msadp32.c:228
static LRESULT ADPCM_StreamClose(PACMDRVSTREAMINSTANCE adsi)
Definition: msadp32.c:672
static const Format ADPCM_Formats[]
Definition: msadp32.c:80
static ADPCMCOEFSET MSADPCM_CoeffSet[]
Definition: msadp32.c:93
static LRESULT ADPCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
Definition: msadp32.c:579
static unsigned char C168(short s)
Definition: msadp32.c:223
static LRESULT ADPCM_drvOpen(LPCSTR str)
Definition: msadp32.c:43
static void ADPCM_Reset(PACMDRVSTREAMINSTANCE adsi, AcmAdpcmData *aad)
Definition: msadp32.c:571
static LRESULT ADPCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
Definition: msadp32.c:412
static void clamp_sample(int *sample)
Definition: msadp32.c:198
static void W16(unsigned char *dst, short s)
Definition: msadp32.c:192
static void process_nibble(unsigned nibble, int *idelta, int *sample1, int *sample2, const ADPCMCOEFSET *coeff)
Definition: msadp32.c:204
static LRESULT ADPCM_DriverDetails(PACMDRIVERDETAILSW add)
Definition: msadp32.c:383
static LRESULT ADPCM_StreamSize(const ACMDRVSTREAMINSTANCE *adsi, PACMDRVSTREAMSIZE adss)
Definition: msadp32.c:682
static LRESULT ADPCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
Definition: msadp32.c:756
static DWORD ADPCM_GetFormatIndex(const WAVEFORMATEX *wfx)
Definition: msadp32.c:101
static LRESULT ADPCM_drvClose(DWORD_PTR dwDevID)
Definition: msadp32.c:51
static const Format PCM_Formats[]
Definition: msadp32.c:72
static LRESULT ADPCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
Definition: msadp32.c:462
static int MS_Delta[]
Definition: msadp32.c:86
static short R16(const unsigned char *src)
Definition: msadp32.c:182
static void cvtMMms16K(const ACMDRVSTREAMINSTANCE *adsi, const unsigned char *src, LPDWORD nsrc, unsigned char *dst, LPDWORD ndst)
Definition: msadp32.c:302
#define LPDWORD
Definition: nt_native.h:46
int nBits
Definition: pcmconverter.c:96
int nChannels
Definition: pcmconverter.c:95
int WINAPI MessageBoxA(_In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType)
#define MB_OK
Definition: winuser.h:801
const WCHAR * str
#define TRACE(s)
Definition: solgame.cpp:4
int nChannels
Definition: imaadp32.c:63
int nBits
Definition: imaadp32.c:64
int rate
Definition: imaadp32.c:65
DWORD nAvgBytesPerSec
Definition: audioclient.idl:43
WORD wBitsPerSample
Definition: audioclient.idl:45
DWORD nSamplesPerSec
Definition: audioclient.idl:42
PWAVEFORMATEX pwfxSrc
Definition: msacmdrv.h:151
PWAVEFORMATEX pwfxDst
Definition: msacmdrv.h:153
PWAVEFORMATEX pwfxSrc
Definition: msacmdrv.h:100
PWAVEFORMATEX pwfxDst
Definition: msacmdrv.h:101
DWORD_PTR dwDriver
Definition: msacmdrv.h:107
WCHAR szFormat[ACMFORMATDETAILS_FORMAT_CHARS]
Definition: msacm.h:509
DWORD dwFormatTag
Definition: msacm.h:505
DWORD dwFormatIndex
Definition: msacm.h:504
DWORD fdwSupport
Definition: msacm.h:506
PWAVEFORMATEX pwfx
Definition: msacm.h:507
WCHAR szFormatTag[ACMFORMATTAGDETAILS_FORMATTAG_CHARS]
Definition: msacm.h:535
DWORD dwFormatTagIndex
Definition: msacm.h:530
DWORD cStandardFormats
Definition: msacm.h:534
WORD nBlockAlign
Definition: mmreg.h:82
DWORD nAvgBytesPerSec
Definition: mmreg.h:81
DWORD nSamplesPerSec
Definition: mmreg.h:80
WORD nChannels
Definition: mmreg.h:79
WORD wFormatTag
Definition: mmreg.h:78
WORD wBitsPerSample
Definition: mmreg.h:83
short iCoef1
Definition: mmreg.h:163
short iCoef2
Definition: mmreg.h:164
ADPCMCOEFSET aCoef[1]
Definition: mmreg.h:174
WAVEFORMATEX wfx
Definition: mmreg.h:170
WORD wSamplesPerBlock
Definition: mmreg.h:171
Definition: wave.c:25
void(* convert)(PACMDRVSTREAMINSTANCE adsi, const unsigned char *, LPDWORD, unsigned char *, LPDWORD)
Definition: imaadp32.c:50
#define DWORD_PTR
Definition: treelist.c:76
const char * LPCSTR
Definition: typedefs.h:52
uint32_t DWORD_PTR
Definition: typedefs.h:65
uint32_t * LPDWORD
Definition: typedefs.h:59
char * LPSTR
Definition: typedefs.h:51