ReactOS 0.4.15-dev-7924-g5949c20
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;
215 clamp_sample(&sample);
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 assert(*src <= 6);
323 coeff = MSADPCM_CoeffSet[*src++];
324
325 idelta = R16(src); src += 2;
326 sample1 = R16(src); src += 2;
327 sample2 = R16(src); src += 2;
328
329 /* store samples from block head */
330 if(adsi->pwfxDst->wBitsPerSample == 8){
331 *dst = C168(sample2); ++dst;
332 *dst = C168(sample1); ++dst;
333
334 for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
335 {
336 process_nibble(*src >> 4, &idelta, &sample1, &sample2, &coeff);
337 *dst = C168(sample1); ++dst;
338 process_nibble(*src++ & 0x0F, &idelta, &sample1, &sample2, &coeff);
339 *dst = C168(sample1); ++dst;
340 }
341 }else if(adsi->pwfxDst->wBitsPerSample == 16){
342 W16(dst, sample2); dst += 2;
343 W16(dst, sample1); dst += 2;
344
345 for (nsamp = nsamp_blk; nsamp > 0; nsamp -= 2)
346 {
347 process_nibble(*src >> 4, &idelta, &sample1, &sample2, &coeff);
348 W16(dst, sample1); dst += 2;
349 process_nibble(*src++ & 0x0F, &idelta, &sample1, &sample2, &coeff);
350 W16(dst, sample1); dst += 2;
351 }
352 }
353
354 src = in_src + adsi->pwfxSrc->nBlockAlign;
355 }
356}
357
358#if 0
359static void cvtSS16msK(PACMDRVSTREAMINSTANCE adsi,
360 const unsigned char* src, LPDWORD nsrc,
361 unsigned char* dst, LPDWORD ndst)
362{
363}
364
365static void cvtMM16msK(PACMDRVSTREAMINSTANCE adsi,
366 const unsigned char* src, LPDWORD nsrc,
367 unsigned char* dst, LPDWORD ndst)
368{
369}
370#endif
371
372/***********************************************************************
373 * ADPCM_DriverDetails
374 *
375 */
377{
380 add->wMid = MM_MICROSOFT;
382 add->vdwACM = 0x01000000;
383 add->vdwDriver = 0x01000000;
385 add->cFormatTags = 2; /* PCM, MS ADPCM */
386 add->cFilterTags = 0;
387 add->hicon = NULL;
388 MultiByteToWideChar( CP_ACP, 0, "MS-ADPCM", -1,
389 add->szShortName, ARRAY_SIZE( add->szShortName ));
390 MultiByteToWideChar( CP_ACP, 0, "Wine MS ADPCM converter", -1,
391 add->szLongName, ARRAY_SIZE( add->szLongName ));
392 MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
393 add->szCopyright, ARRAY_SIZE( add->szCopyright ));
394 MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
395 add->szLicensing, ARRAY_SIZE( add->szLicensing ));
396 add->szFeatures[0] = 0;
397
398 return MMSYSERR_NOERROR;
399}
400
401/***********************************************************************
402 * ADPCM_FormatTagDetails
403 *
404 */
406{
407 static const WCHAR szPcm[]={'P','C','M',0};
408 static const WCHAR szMsAdPcm[]={'M','i','c','r','o','s','o','f','t',' ','A','D','P','C','M',0};
409
410 switch (dwQuery)
411 {
413 if (aftd->dwFormatTagIndex >= 2) return ACMERR_NOTPOSSIBLE;
414 break;
416 if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
417 {
418 aftd->dwFormatTagIndex = 1; /* WAVE_FORMAT_ADPCM is bigger than PCM */
419 break;
420 }
421 /* fall through */
423 switch (aftd->dwFormatTag)
424 {
425 case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break;
426 case WAVE_FORMAT_ADPCM: aftd->dwFormatTagIndex = 1; break;
427 default: return ACMERR_NOTPOSSIBLE;
428 }
429 break;
430 default:
431 WARN("Unsupported query %08x\n", dwQuery);
433 }
434
436 switch (aftd->dwFormatTagIndex)
437 {
438 case 0:
440 aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
442 lstrcpyW(aftd->szFormatTag, szPcm);
443 break;
444 case 1:
446 aftd->cbFormatSize = sizeof(ADPCMWAVEFORMAT) + (7 - 1) * sizeof(ADPCMCOEFSET);
448 lstrcpyW(aftd->szFormatTag, szMsAdPcm);
449 break;
450 }
451 return MMSYSERR_NOERROR;
452}
453
454/***********************************************************************
455 * ADPCM_FormatDetails
456 *
457 */
459{
460 switch (dwQuery)
461 {
463 if (ADPCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
464 break;
466 afd->pwfx->wFormatTag = afd->dwFormatTag;
467 switch (afd->dwFormatTag)
468 {
469 case WAVE_FORMAT_PCM:
474 /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible
475 * afd->pwfx->cbSize = 0;
476 */
477 afd->pwfx->nBlockAlign =
478 (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8;
479 afd->pwfx->nAvgBytesPerSec =
480 afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
481 break;
484 if (afd->cbwfx < sizeof(ADPCMWAVEFORMAT) + (7 - 1) * sizeof(ADPCMCOEFSET))
485 return ACMERR_NOTPOSSIBLE;
490 break;
491 default:
492 WARN("Unsupported tag %08x\n", afd->dwFormatTag);
493 return MMSYSERR_INVALPARAM;
494 }
495 break;
496 default:
497 WARN("Unsupported query %08x\n", dwQuery);
499 }
501 afd->szFormat[0] = 0; /* let MSACM format this for us... */
502
503 return MMSYSERR_NOERROR;
504}
505
506/***********************************************************************
507 * ADPCM_FormatSuggest
508 *
509 */
511{
512 /* some tests ... */
513 if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
514 adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
515 adfs->pwfxSrc->wFormatTag == adfs->pwfxDst->wFormatTag ||
516 ADPCM_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
517 /* FIXME: should do those tests against the real size (according to format tag */
518
519 /* If no suggestion for destination, then copy source value */
521 adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
524
526 {
527 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
528 adfs->pwfxDst->wBitsPerSample = 4;
529 else
530 adfs->pwfxDst->wBitsPerSample = 16;
531 }
533 {
534 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
536 else
538 }
539
540 /* recompute other values */
541 switch (adfs->pwfxDst->wFormatTag)
542 {
543 case WAVE_FORMAT_PCM:
544 adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8;
546 /* check if result is ok */
547 if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
548 break;
550 if (adfs->cbwfxDst < sizeof(ADPCMWAVEFORMAT) + (7 - 1) * sizeof(ADPCMCOEFSET))
551 return ACMERR_NOTPOSSIBLE;
553 /* check if result is ok */
554 if (ADPCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
555 break;
556 default:
557 return ACMERR_NOTPOSSIBLE;
558 }
559
560 return MMSYSERR_NOERROR;
561}
562
563/***********************************************************************
564 * ADPCM_Reset
565 *
566 */
568{
569}
570
571/***********************************************************************
572 * ADPCM_StreamOpen
573 *
574 */
576{
577 AcmAdpcmData* aad;
578
580
581 if (ADPCM_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
582 ADPCM_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
583 return ACMERR_NOTPOSSIBLE;
584
585 aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmAdpcmData));
586 if (aad == 0) return MMSYSERR_NOMEM;
587
588 adsi->dwDriver = (DWORD_PTR)aad;
589
590 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
592 {
593 goto theEnd;
594 }
595 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM &&
597 {
598 /* resampling or mono <=> stereo not available */
599 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
600 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels)
601 goto theEnd;
602
603#if 0
604 {
605 unsigned int nspb = ((IMAADPCMWAVEFORMAT*)adsi->pwfxSrc)->wSamplesPerBlock;
606 FIXME("spb=%u\n", nspb);
607
608 /* we check that in a block, after the header, samples are present on
609 * 4-sample packet pattern
610 * we also check that the block alignment is bigger than the expected size
611 */
612 if (((nspb - 1) & 3) != 0) goto theEnd;
613 if ((((nspb - 1) / 2) + 4) * adsi->pwfxSrc->nChannels < adsi->pwfxSrc->nBlockAlign)
614 goto theEnd;
615 }
616#endif
617
618 /* adpcm decoding... */
619 if (adsi->pwfxDst->nChannels == 2)
620 aad->convert = cvtSSms16K;
621 else if (adsi->pwfxDst->nChannels == 1)
622 aad->convert = cvtMMms16K;
623 }
624 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
626 {
627 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
628 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
629 adsi->pwfxSrc->wBitsPerSample != 16)
630 goto theEnd;
631#if 0
632 nspb = ((IMAADPCMWAVEFORMAT*)adsi->pwfxDst)->wSamplesPerBlock;
633 FIXME("spb=%u\n", nspb);
634
635 /* we check that in a block, after the header, samples are present on
636 * 4-sample packet pattern
637 * we also check that the block alignment is bigger than the expected size
638 */
639 if (((nspb - 1) & 3) != 0) goto theEnd;
640 if ((((nspb - 1) / 2) + 4) * adsi->pwfxDst->nChannels < adsi->pwfxDst->nBlockAlign)
641 goto theEnd;
642#endif
643#if 0
644 /* adpcm coding... */
645 if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 2)
646 aad->convert = cvtSS16msK;
647 if (adsi->pwfxSrc->wBitsPerSample == 16 && adsi->pwfxSrc->nChannels == 1)
648 aad->convert = cvtMM16msK;
649#endif
650 FIXME("We don't support encoding yet\n");
651 goto theEnd;
652 }
653 else goto theEnd;
654 ADPCM_Reset(adsi, aad);
655
656 return MMSYSERR_NOERROR;
657
658 theEnd:
659 HeapFree(GetProcessHeap(), 0, aad);
660 adsi->dwDriver = 0L;
662}
663
664/***********************************************************************
665 * ADPCM_StreamClose
666 *
667 */
669{
670 HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
671 return MMSYSERR_NOERROR;
672}
673
674/***********************************************************************
675 * ADPCM_StreamSize
676 *
677 */
679{
680 DWORD nblocks;
681 WORD wSamplesPerBlock;
682 /* wSamplesPerBlock formula comes from MSDN ADPCMWAVEFORMAT page.*/
683 switch (adss->fdwSize)
684 {
686 /* cbDstLength => cbSrcLength */
687 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
689 {
690 wSamplesPerBlock = adsi->pwfxDst->nBlockAlign * 2 / adsi->pwfxDst->nChannels - 12;
691 nblocks = adss->cbDstLength / adsi->pwfxDst->nBlockAlign;
692 if (nblocks == 0)
693 return ACMERR_NOTPOSSIBLE;
694 adss->cbSrcLength = nblocks * adsi->pwfxSrc->nBlockAlign * wSamplesPerBlock;
695 }
696 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM &&
698 {
699 wSamplesPerBlock = adsi->pwfxSrc->nBlockAlign * 2 / adsi->pwfxSrc->nChannels - 12;
700 nblocks = adss->cbDstLength / (adsi->pwfxDst->nBlockAlign * wSamplesPerBlock);
701 if (nblocks == 0)
702 return ACMERR_NOTPOSSIBLE;
703 adss->cbSrcLength = nblocks * adsi->pwfxSrc->nBlockAlign;
704 }
705 else
706 {
708 }
709 break;
711 /* cbSrcLength => cbDstLength */
712 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
714 {
715 wSamplesPerBlock = adsi->pwfxDst->nBlockAlign * 2 / adsi->pwfxDst->nChannels - 12;
716 nblocks = adss->cbSrcLength / (adsi->pwfxSrc->nBlockAlign * wSamplesPerBlock);
717 if (nblocks == 0)
718 return ACMERR_NOTPOSSIBLE;
719 if (adss->cbSrcLength % (adsi->pwfxSrc->nBlockAlign * wSamplesPerBlock))
720 /* Round block count up. */
721 nblocks++;
722 adss->cbDstLength = nblocks * adsi->pwfxDst->nBlockAlign;
723 }
724 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM &&
726 {
727 wSamplesPerBlock = adsi->pwfxSrc->nBlockAlign * 2 / adsi->pwfxSrc->nChannels - 12;
728 nblocks = adss->cbSrcLength / adsi->pwfxSrc->nBlockAlign;
729 if (nblocks == 0)
730 return ACMERR_NOTPOSSIBLE;
731 if (adss->cbSrcLength % adsi->pwfxSrc->nBlockAlign)
732 /* Round block count up. */
733 nblocks++;
734 adss->cbDstLength = nblocks * adsi->pwfxDst->nBlockAlign * wSamplesPerBlock;
735 }
736 else
737 {
739 }
740 break;
741 default:
742 WARN("Unsupported query %08x\n", adss->fdwSize);
744 }
745 return MMSYSERR_NOERROR;
746}
747
748/***********************************************************************
749 * ADPCM_StreamConvert
750 *
751 */
753{
754 AcmAdpcmData* aad = (AcmAdpcmData*)adsi->dwDriver;
755 DWORD nsrc = adsh->cbSrcLength;
756 DWORD ndst = adsh->cbDstLength;
757
758 if (adsh->fdwConvert &
762 {
763 FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert);
764 }
765 /* ACM_STREAMCONVERTF_BLOCKALIGN
766 * currently all conversions are block aligned, so do nothing for this flag
767 * ACM_STREAMCONVERTF_END
768 * no pending data, so do nothing for this flag
769 */
771 {
772 ADPCM_Reset(adsi, aad);
773 }
774
775 aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
776 adsh->cbSrcLengthUsed = nsrc;
777 adsh->cbDstLengthUsed = ndst;
778
779 return MMSYSERR_NOERROR;
780}
781
782/**************************************************************************
783 * ADPCM_DriverProc [exported]
784 */
785LRESULT CALLBACK ADPCM_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
786 LPARAM dwParam1, LPARAM dwParam2)
787{
788 TRACE("(%08lx %p %04x %08lx %08lx);\n",
789 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
790
791 switch (wMsg)
792 {
793 case DRV_LOAD: return 1;
794 case DRV_FREE: return 1;
795 case DRV_OPEN: return ADPCM_drvOpen((LPSTR)dwParam1);
796 case DRV_CLOSE: return ADPCM_drvClose(dwDevID);
797 case DRV_ENABLE: return 1;
798 case DRV_DISABLE: return 1;
799 case DRV_QUERYCONFIGURE: return 1;
800 case DRV_CONFIGURE: MessageBoxA(0, "MSACM MS ADPCM filter !", "Wine Driver", MB_OK); return 1;
801 case DRV_INSTALL: return DRVCNF_RESTART;
802 case DRV_REMOVE: return DRVCNF_RESTART;
803
805 /* no caching from other ACM drivers is done so far */
806 return MMSYSERR_NOERROR;
807
809 return ADPCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
810
812 return ADPCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
813
815 return ADPCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
816
819
821 return ADPCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
822
825
827 return ADPCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
828
831
834 /* this converter is not a hardware driver */
837 /* this converter is not a filter */
839 /* only needed for asynchronous driver... we aren't, so just say it */
843 /* nothing special to do here... so don't do anything */
844 return MMSYSERR_NOERROR;
845
846 default:
847 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
848 }
849}
#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:33
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#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
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 assert(x)
Definition: debug.h:53
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
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
#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
#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:785
struct tagAcmAdpcmData AcmAdpcmData
static LRESULT ADPCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
Definition: msadp32.c:510
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:668
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:575
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:567
static LRESULT ADPCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
Definition: msadp32.c:405
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:376
static LRESULT ADPCM_StreamSize(const ACMDRVSTREAMINSTANCE *adsi, PACMDRVSTREAMSIZE adss)
Definition: msadp32.c:678
static LRESULT ADPCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
Definition: msadp32.c:752
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:458
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
unsigned int UINT
Definition: ndis.h:50
#define LPDWORD
Definition: nt_native.h:46
#define L(x)
Definition: ntvdm.h:50
int nBits
Definition: pcmconverter.c:96
int rate
Definition: pcmconverter.c:97
int nChannels
Definition: pcmconverter.c:95
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
DWORD cFilterTags
Definition: msacm.h:311
WCHAR szCopyright[ACMDRIVERDETAILS_COPYRIGHT_CHARS]
Definition: msacm.h:317
WCHAR szLongName[ACMDRIVERDETAILS_LONGNAME_CHARS]
Definition: msacm.h:316
WCHAR szShortName[ACMDRIVERDETAILS_SHORTNAME_CHARS]
Definition: msacm.h:315
FOURCC fccComp
Definition: msacm.h:301
WCHAR szLicensing[ACMDRIVERDETAILS_LICENSING_CHARS]
Definition: msacm.h:318
FOURCC fccType
Definition: msacm.h:300
WCHAR szFeatures[ACMDRIVERDETAILS_FEATURES_CHARS]
Definition: msacm.h:319
DWORD cFormatTags
Definition: msacm.h:310
DWORD fdwSupport
Definition: msacm.h:309
DWORD vdwDriver
Definition: msacm.h:307
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
void(* convert)(PACMDRVSTREAMINSTANCE adsi, const unsigned char *, LPDWORD, unsigned char *, LPDWORD)
Definition: imaadp32.c:50
#define DWORD_PTR
Definition: treelist.c:76
uint32_t DWORD_PTR
Definition: typedefs.h:65
uint32_t * LPDWORD
Definition: typedefs.h:59
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
int WINAPI MessageBoxA(_In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType)
#define MB_OK
Definition: winuser.h:790
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180