1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */ 2 3 /* 4 * MSACM32 library 5 * 6 * Copyright 2000 Eric Pouech 7 * Copyright 2004 Robert Reif 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public 11 * License as published by the Free Software Foundation; either 12 * version 2.1 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with this library; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 22 * 23 * FIXME / TODO list 24 * + get rid of hack for PCM_DriverProc (msacm32.dll shouldn't export 25 * a DriverProc, but this would require implementing a generic 26 * embedded driver handling scheme in msacm32.dll which isn't done yet 27 */ 28 29 30 #include <assert.h> 31 #include <stdarg.h> 32 #include <string.h> 33 34 #include "windef.h" 35 #include "winbase.h" 36 #include "mmsystem.h" 37 #define NOBITMAP 38 #include "mmreg.h" 39 #include "msacm.h" 40 #include "wingdi.h" 41 #include "winnls.h" 42 #include "winuser.h" 43 44 #include "msacmdrv.h" 45 #include "wineacm.h" 46 47 #include "wine/debug.h" 48 49 WINE_DEFAULT_DEBUG_CHANNEL(msacm); 50 51 /*********************************************************************** 52 * PCM_drvOpen 53 */ 54 static DWORD PCM_drvOpen(LPCSTR str, PACMDRVOPENDESCW adod) 55 { 56 TRACE("(%p, %p)\n", str, adod); 57 58 return (adod == NULL) || 59 (adod->fccType == ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC && 60 adod->fccComp == ACMDRIVERDETAILS_FCCCOMP_UNDEFINED); 61 } 62 63 /*********************************************************************** 64 * PCM_drvClose 65 */ 66 static DWORD PCM_drvClose(DWORD dwDevID) 67 { 68 TRACE("(%d)\n", dwDevID); 69 70 return 1; 71 } 72 73 #define NUM_OF(a,b) ((a)/(b)) 74 75 /* flags for fdwDriver */ 76 #define PCM_RESAMPLE 1 77 78 typedef void (*PCM_CONVERT_KEEP_RATE)(const unsigned char*, int, unsigned char*); 79 80 typedef void (*PCM_CONVERT_CHANGE_RATE)(const DWORD, const unsigned char*, DWORD*, const DWORD, unsigned char*, DWORD*); 81 82 /* data used while converting */ 83 typedef struct tagAcmPcmData { 84 /* conversion routine, depending if rate conversion is required */ 85 union { 86 PCM_CONVERT_KEEP_RATE cvtKeepRate; 87 PCM_CONVERT_CHANGE_RATE cvtChangeRate; 88 } cvt; 89 } AcmPcmData; 90 91 /* table to list all supported formats... those are the basic ones. this 92 * also helps given a unique index to each of the supported formats 93 */ 94 static const struct { 95 int nChannels; 96 int nBits; 97 int rate; 98 } PCM_Formats[] = { 99 {1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000}, {1, 24, 8000}, {2, 24, 8000}, 100 {1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025}, {1, 24, 11025}, {2, 24, 11025}, 101 {1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050}, {1, 24, 22050}, {2, 24, 22050}, 102 {1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100}, {1, 24, 44100}, {2, 24, 44100}, 103 {1, 8, 48000}, {2, 8, 48000}, {1, 16, 48000}, {2, 16, 48000}, {1, 24, 48000}, {2, 24, 48000}, 104 {1, 8, 96000}, {2, 8, 96000}, {1, 16, 96000}, {2, 16, 96000}, {1, 24, 96000}, {2, 24, 96000}, 105 }; 106 107 /*********************************************************************** 108 * PCM_GetFormatIndex 109 */ 110 static DWORD PCM_GetFormatIndex(LPWAVEFORMATEX wfx) 111 { 112 unsigned int i; 113 TRACE("(%p)\n", wfx); 114 115 for (i = 0; i < ARRAY_SIZE(PCM_Formats); i++) { 116 if (wfx->nChannels == PCM_Formats[i].nChannels && 117 wfx->nSamplesPerSec == PCM_Formats[i].rate && 118 wfx->wBitsPerSample == PCM_Formats[i].nBits) 119 return i; 120 } 121 return 0xFFFFFFFF; 122 } 123 124 /* PCM Conversions: 125 * 126 * parameters: 127 * + 8 bit unsigned vs 16 bit signed 128 * + mono vs stereo (1 or 2 channels) 129 * + sampling rate (8.0, 11.025, 22.05, 44.1 kHz are defined, but algo 130 * shall work in all cases) 131 * 132 * mono => stereo: copy the same sample on Left & Right channels 133 * stereo => mono: use the sum of Left & Right channels 134 */ 135 136 /*********************************************************************** 137 * C816 138 * 139 * Converts a 8 bit sample to a 16 bit one 140 */ 141 static inline short C816(unsigned char b) 142 { 143 return (b - 128) << 8; 144 } 145 146 /*********************************************************************** 147 * C168 148 * 149 * Converts a 16 bit sample to a 8 bit one (data loss !!) 150 */ 151 static inline unsigned char C168(short s) 152 { 153 return HIBYTE(s) ^ (unsigned char)0x80; 154 } 155 156 /*********************************************************************** 157 * C248 158 * 159 * Converts a 24 bit sample to a 8 bit one (data loss !!) 160 */ 161 static inline unsigned char C248(int s) 162 { 163 return HIBYTE(HIWORD(s)) ^ (unsigned char)0x80; 164 } 165 166 /*********************************************************************** 167 * C2416 168 * 169 * Converts a 24 bit sample to a 16 bit one (data loss !!) 170 */ 171 static inline short C2416(int s) 172 { 173 return HIWORD(s); 174 } 175 176 /*********************************************************************** 177 * R16 178 * 179 * Read a 16 bit sample (correctly handles endianness) 180 */ 181 static inline short R16(const unsigned char* src) 182 { 183 return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8)); 184 } 185 186 /*********************************************************************** 187 * R24 188 * 189 * Read a 24 bit sample (correctly handles endianness) 190 * Note, to support signed arithmetic, the values are shifted high in the int 191 * and low 8 bytes are unused. 192 */ 193 static inline int R24(const unsigned char* src) 194 { 195 return ((int)src[0] | (int)src[1] << 8 | (int)src[2] << 16) << 8; 196 } 197 198 /*********************************************************************** 199 * W16 200 * 201 * Write a 16 bit sample (correctly handles endianness) 202 */ 203 static inline void W16(unsigned char* dst, short s) 204 { 205 dst[0] = LOBYTE(s); 206 dst[1] = HIBYTE(s); 207 } 208 209 /*********************************************************************** 210 * W24 211 * 212 * Write a 24 bit sample (correctly handles endianness) 213 */ 214 static inline void W24(unsigned char* dst, int s) 215 { 216 dst[0] = HIBYTE(LOWORD(s)); 217 dst[1] = LOBYTE(HIWORD(s)); 218 dst[2] = HIBYTE(HIWORD(s)); 219 } 220 221 /*********************************************************************** 222 * M24 223 * 224 * Convert the (l,r) 24 bit stereo sample into a 24 bit mono 225 * (takes the sum of the two values) 226 */ 227 static inline int M24(int l, int r) 228 { 229 LONGLONG sum = l + r; 230 231 /* clip sum to saturation */ 232 if (sum > 0x7fffff00) 233 sum = 0x7fffff00; 234 else if (sum < -0x7fffff00) 235 sum = -0x7fffff00; 236 237 return sum; 238 } 239 240 /*********************************************************************** 241 * M16 242 * 243 * Convert the (l,r) 16 bit stereo sample into a 16 bit mono 244 * (takes the sum of the two values) 245 */ 246 static inline short M16(short l, short r) 247 { 248 int sum = l + r; 249 250 /* clip sum to saturation */ 251 if (sum > 32767) 252 sum = 32767; 253 else if (sum < -32768) 254 sum = -32768; 255 256 return sum; 257 } 258 259 /*********************************************************************** 260 * M8 261 * 262 * Convert the (l,r) 8 bit stereo sample into a 8 bit mono 263 * (takes the sum of the two values) 264 */ 265 static inline unsigned char M8(unsigned char a, unsigned char b) 266 { 267 int l = a - 128; 268 int r = b - 128; 269 int sum = (l + r) + 128; 270 271 /* clip sum to saturation */ 272 if (sum > 0xff) 273 sum = 0xff; 274 else if (sum < 0) 275 sum = 0; 276 277 return sum; 278 } 279 280 /* the conversion routines without rate conversion are labelled cvt<X><Y><N><M>K 281 * where : 282 * <X> is the (M)ono/(S)tereo configuration of input channel 283 * <Y> is the (M)ono/(S)tereo configuration of output channel 284 * <N> is the number of bits of input channel (8 or 16) 285 * <M> is the number of bits of output channel (8 or 16) 286 * 287 * in the parameters, ns is always the number of samples, so the size of input 288 * buffer (resp output buffer) is ns * (<X> == 'Mono' ? 1:2) * (<N> == 8 ? 1:2) 289 */ 290 291 static void cvtMM88K(const unsigned char* src, int ns, unsigned char* dst) 292 { 293 TRACE("(%p, %d, %p)\n", src, ns, dst); 294 memcpy(dst, src, ns); 295 } 296 297 static void cvtSS88K(const unsigned char* src, int ns, unsigned char* dst) 298 { 299 TRACE("(%p, %d, %p)\n", src, ns, dst); 300 memcpy(dst, src, ns * 2); 301 } 302 303 static void cvtMM1616K(const unsigned char* src, int ns, unsigned char* dst) 304 { 305 TRACE("(%p, %d, %p)\n", src, ns, dst); 306 memcpy(dst, src, ns * 2); 307 } 308 309 static void cvtSS1616K(const unsigned char* src, int ns, unsigned char* dst) 310 { 311 TRACE("(%p, %d, %p)\n", src, ns, dst); 312 memcpy(dst, src, ns * 4); 313 } 314 315 static void cvtMS88K(const unsigned char* src, int ns, unsigned char* dst) 316 { 317 TRACE("(%p, %d, %p)\n", src, ns, dst); 318 319 while (ns--) { 320 *dst++ = *src; 321 *dst++ = *src++; 322 } 323 } 324 325 static void cvtMS816K(const unsigned char* src, int ns, unsigned char* dst) 326 { 327 short v; 328 TRACE("(%p, %d, %p)\n", src, ns, dst); 329 330 while (ns--) { 331 v = C816(*src++); 332 W16(dst, v); dst += 2; 333 W16(dst, v); dst += 2; 334 } 335 } 336 337 static void cvtMS168K(const unsigned char* src, int ns, unsigned char* dst) 338 { 339 unsigned char v; 340 TRACE("(%p, %d, %p)\n", src, ns, dst); 341 342 while (ns--) { 343 v = C168(R16(src)); src += 2; 344 *dst++ = v; 345 *dst++ = v; 346 } 347 } 348 349 static void cvtMS1616K(const unsigned char* src, int ns, unsigned char* dst) 350 { 351 short v; 352 TRACE("(%p, %d, %p)\n", src, ns, dst); 353 354 while (ns--) { 355 v = R16(src); src += 2; 356 W16(dst, v); dst += 2; 357 W16(dst, v); dst += 2; 358 } 359 } 360 361 static void cvtSM88K(const unsigned char* src, int ns, unsigned char* dst) 362 { 363 TRACE("(%p, %d, %p)\n", src, ns, dst); 364 365 while (ns--) { 366 *dst++ = M8(src[0], src[1]); 367 src += 2; 368 } 369 } 370 371 static void cvtSM816K(const unsigned char* src, int ns, unsigned char* dst) 372 { 373 short v; 374 TRACE("(%p, %d, %p)\n", src, ns, dst); 375 376 while (ns--) { 377 v = M16(C816(src[0]), C816(src[1])); 378 src += 2; 379 W16(dst, v); dst += 2; 380 } 381 } 382 383 static void cvtSM168K(const unsigned char* src, int ns, unsigned char* dst) 384 { 385 TRACE("(%p, %d, %p)\n", src, ns, dst); 386 387 while (ns--) { 388 *dst++ = C168(M16(R16(src), R16(src + 2))); 389 src += 4; 390 } 391 } 392 393 static void cvtSM1616K(const unsigned char* src, int ns, unsigned char* dst) 394 { 395 TRACE("(%p, %d, %p)\n", src, ns, dst); 396 397 while (ns--) { 398 W16(dst, M16(R16(src),R16(src+2))); dst += 2; 399 src += 4; 400 } 401 } 402 403 static void cvtMM816K(const unsigned char* src, int ns, unsigned char* dst) 404 { 405 TRACE("(%p, %d, %p)\n", src, ns, dst); 406 407 while (ns--) { 408 W16(dst, C816(*src++)); dst += 2; 409 } 410 } 411 412 static void cvtSS816K(const unsigned char* src, int ns, unsigned char* dst) 413 { 414 TRACE("(%p, %d, %p)\n", src, ns, dst); 415 416 while (ns--) { 417 W16(dst, C816(*src++)); dst += 2; 418 W16(dst, C816(*src++)); dst += 2; 419 } 420 } 421 422 static void cvtMM168K(const unsigned char* src, int ns, unsigned char* dst) 423 { 424 TRACE("(%p, %d, %p)\n", src, ns, dst); 425 426 while (ns--) { 427 *dst++ = C168(R16(src)); src += 2; 428 } 429 } 430 431 static void cvtSS168K(const unsigned char* src, int ns, unsigned char* dst) 432 { 433 TRACE("(%p, %d, %p)\n", src, ns, dst); 434 435 while (ns--) { 436 *dst++ = C168(R16(src)); src += 2; 437 *dst++ = C168(R16(src)); src += 2; 438 } 439 } 440 441 static void cvtMS248K(const unsigned char* src, int ns, unsigned char* dst) 442 { 443 unsigned char v; 444 TRACE("(%p, %d, %p)\n", src, ns, dst); 445 446 while (ns--) { 447 v = C248(R24(src)); src += 3; 448 *dst++ = v; 449 *dst++ = v; 450 } 451 } 452 453 static void cvtSM248K(const unsigned char* src, int ns, unsigned char* dst) 454 { 455 TRACE("(%p, %d, %p)\n", src, ns, dst); 456 457 while (ns--) { 458 *dst++ = C248(M24(R24(src), R24(src + 3))); 459 src += 6; 460 } 461 } 462 463 static void cvtMM248K(const unsigned char* src, int ns, unsigned char* dst) 464 { 465 TRACE("(%p, %d, %p)\n", src, ns, dst); 466 467 while (ns--) { 468 *dst++ = C248(R24(src)); src += 3; 469 } 470 } 471 472 static void cvtSS248K(const unsigned char* src, int ns, unsigned char* dst) 473 { 474 TRACE("(%p, %d, %p)\n", src, ns, dst); 475 476 while (ns--) { 477 *dst++ = C248(R24(src)); src += 3; 478 *dst++ = C248(R24(src)); src += 3; 479 } 480 } 481 482 static void cvtMS2416K(const unsigned char* src, int ns, unsigned char* dst) 483 { 484 short v; 485 TRACE("(%p, %d, %p)\n", src, ns, dst); 486 487 while (ns--) { 488 v = C2416(R24(src)); src += 3; 489 W16(dst, v); dst += 2; 490 W16(dst, v); dst += 2; 491 } 492 } 493 494 static void cvtSM2416K(const unsigned char* src, int ns, unsigned char* dst) 495 { 496 TRACE("(%p, %d, %p)\n", src, ns, dst); 497 498 while (ns--) { 499 W16(dst, C2416(M24(R24(src), R24(src + 3)))); 500 dst += 2; 501 src += 6; 502 } 503 } 504 505 static void cvtMM2416K(const unsigned char* src, int ns, unsigned char* dst) 506 { 507 TRACE("(%p, %d, %p)\n", src, ns, dst); 508 509 while (ns--) { 510 W16(dst, C2416(R24(src))); dst += 2; src += 3; 511 } 512 } 513 514 static void cvtSS2416K(const unsigned char* src, int ns, unsigned char* dst) 515 { 516 TRACE("(%p, %d, %p)\n", src, ns, dst); 517 518 while (ns--) { 519 W16(dst, C2416(R24(src))); dst += 2; src += 3; 520 W16(dst, C2416(R24(src))); dst += 2; src += 3; 521 } 522 } 523 524 525 static const PCM_CONVERT_KEEP_RATE PCM_ConvertKeepRate[] = { 526 cvtSS88K, cvtSM88K, cvtMS88K, cvtMM88K, 527 cvtSS816K, cvtSM816K, cvtMS816K, cvtMM816K, 528 NULL, NULL, NULL, NULL, /* TODO: 8->24 */ 529 cvtSS168K, cvtSM168K, cvtMS168K, cvtMM168K, 530 cvtSS1616K, cvtSM1616K, cvtMS1616K, cvtMM1616K, 531 NULL, NULL, NULL, NULL, /* TODO: 16->24 */ 532 cvtSS248K, cvtSM248K, cvtMS248K, cvtMM248K, 533 cvtSS2416K, cvtSM2416K, cvtMS2416K, cvtMM2416K, 534 NULL, NULL, NULL, NULL, /* TODO: 24->24 */ 535 }; 536 537 /* the conversion routines with rate conversion are labelled cvt<X><Y><N><M>C 538 * where : 539 * <X> is the (M)ono/(S)tereo configuration of input channel 540 * <Y> is the (M)ono/(S)tereo configuration of output channel 541 * <N> is the number of bits of input channel (8 or 16) 542 * <M> is the number of bits of output channel (8 or 16) 543 * 544 */ 545 546 static void cvtSS88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 547 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 548 { 549 DWORD error = srcRate / 2; 550 DWORD maxSrc = *nsrc, maxDst = *ndst; 551 *ndst = 0; 552 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 553 error += dstRate; 554 while (error > srcRate) { 555 if (*ndst == maxDst) 556 return; 557 (*ndst)++; 558 error -= srcRate; 559 560 *dst++ = src[0]; 561 *dst++ = src[1]; 562 } 563 src += 2; 564 } 565 } 566 567 static void cvtSM88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 568 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 569 { 570 DWORD error = srcRate / 2; 571 DWORD maxSrc = *nsrc, maxDst = *ndst; 572 *ndst = 0; 573 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 574 error += dstRate; 575 while (error > srcRate) { 576 if (*ndst == maxDst) 577 return; 578 (*ndst)++; 579 error -= srcRate; 580 581 *dst++ = M8(src[0], src[1]); 582 } 583 src += 2; 584 } 585 } 586 587 static void cvtMS88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 588 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 589 { 590 DWORD error = srcRate / 2; 591 DWORD maxSrc = *nsrc, maxDst = *ndst; 592 *ndst = 0; 593 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 594 error += dstRate; 595 while (error > srcRate) { 596 if (*ndst == maxDst) 597 return; 598 (*ndst)++; 599 error -= srcRate; 600 601 *dst++ = src[0]; 602 *dst++ = src[0]; 603 } 604 src += 1; 605 } 606 } 607 608 static void cvtMM88C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 609 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 610 { 611 DWORD error = srcRate / 2; 612 DWORD maxSrc = *nsrc, maxDst = *ndst; 613 *ndst = 0; 614 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 615 error += dstRate; 616 while (error > srcRate) { 617 if (*ndst == maxDst) 618 return; 619 (*ndst)++; 620 error -= srcRate; 621 622 *dst++ = src[0]; 623 } 624 src += 1; 625 } 626 } 627 628 static void cvtSS816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 629 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 630 { 631 DWORD error = srcRate / 2; 632 DWORD maxSrc = *nsrc, maxDst = *ndst; 633 *ndst = 0; 634 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 635 error += dstRate; 636 while (error > srcRate) { 637 if (*ndst == maxDst) 638 return; 639 (*ndst)++; 640 error -= srcRate; 641 642 W16(dst, C816(src[0])); dst += 2; 643 W16(dst, C816(src[1])); dst += 2; 644 } 645 src += 2; 646 } 647 } 648 649 static void cvtSM816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 650 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 651 { 652 DWORD error = srcRate / 2; 653 DWORD maxSrc = *nsrc, maxDst = *ndst; 654 *ndst = 0; 655 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 656 error += dstRate; 657 while (error > srcRate) { 658 if (*ndst == maxDst) 659 return; 660 (*ndst)++; 661 error -= srcRate; 662 663 W16(dst, M16(C816(src[0]), C816(src[1]))); dst += 2; 664 } 665 src += 2; 666 } 667 } 668 669 static void cvtMS816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 670 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 671 { 672 DWORD error = srcRate / 2; 673 DWORD maxSrc = *nsrc, maxDst = *ndst; 674 *ndst = 0; 675 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 676 error += dstRate; 677 while (error > srcRate) { 678 if (*ndst == maxDst) 679 return; 680 (*ndst)++; 681 error -= srcRate; 682 683 W16(dst, C816(src[0])); dst += 2; 684 W16(dst, C816(src[0])); dst += 2; 685 } 686 src += 1; 687 } 688 } 689 690 static void cvtMM816C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 691 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 692 { 693 DWORD error = srcRate / 2; 694 DWORD maxSrc = *nsrc, maxDst = *ndst; 695 *ndst = 0; 696 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 697 error += dstRate; 698 while (error > srcRate) { 699 if (*ndst == maxDst) 700 return; 701 (*ndst)++; 702 error -= srcRate; 703 704 W16(dst, C816(src[0])); dst += 2; 705 } 706 src += 1; 707 } 708 } 709 710 static void cvtSS168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 711 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 712 { 713 DWORD error = srcRate / 2; 714 DWORD maxSrc = *nsrc, maxDst = *ndst; 715 *ndst = 0; 716 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 717 error += dstRate; 718 while (error > srcRate) { 719 if (*ndst == maxDst) 720 return; 721 (*ndst)++; 722 error -= srcRate; 723 724 *dst++ = C168(R16(src)); 725 *dst++ = C168(R16(src + 2)); 726 } 727 src += 4; 728 } 729 } 730 731 static void cvtSM168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 732 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 733 { 734 DWORD error = srcRate / 2; 735 DWORD maxSrc = *nsrc, maxDst = *ndst; 736 *ndst = 0; 737 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 738 error += dstRate; 739 while (error > srcRate) { 740 if (*ndst == maxDst) 741 return; 742 (*ndst)++; 743 error -= srcRate; 744 745 *dst++ = C168(M16(R16(src), R16(src + 2))); 746 } 747 src += 4; 748 } 749 } 750 751 static void cvtMS168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 752 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 753 { 754 DWORD error = srcRate / 2; 755 DWORD maxSrc = *nsrc, maxDst = *ndst; 756 *ndst = 0; 757 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 758 error += dstRate; 759 while (error > srcRate) { 760 if (*ndst == maxDst) 761 return; 762 (*ndst)++; 763 error -= srcRate; 764 765 *dst++ = C168(R16(src)); 766 *dst++ = C168(R16(src)); 767 } 768 src += 2; 769 } 770 } 771 772 static void cvtMM168C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 773 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 774 { 775 DWORD error = srcRate / 2; 776 DWORD maxSrc = *nsrc, maxDst = *ndst; 777 *ndst = 0; 778 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 779 error += dstRate; 780 while (error > srcRate) { 781 if (*ndst == maxDst) 782 return; 783 (*ndst)++; 784 error -= srcRate; 785 786 *dst++ = C168(R16(src)); 787 } 788 src += 2; 789 } 790 } 791 792 static void cvtSS1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 793 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 794 { 795 DWORD error = srcRate / 2; 796 DWORD maxSrc = *nsrc, maxDst = *ndst; 797 *ndst = 0; 798 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 799 error += dstRate; 800 while (error > srcRate) { 801 if (*ndst == maxDst) 802 return; 803 (*ndst)++; 804 error -= srcRate; 805 806 W16(dst, R16(src)); dst += 2; 807 W16(dst, R16(src + 2)); dst += 2; 808 } 809 src += 4; 810 } 811 } 812 813 static void cvtSM1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 814 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 815 { 816 DWORD error = srcRate / 2; 817 DWORD maxSrc = *nsrc, maxDst = *ndst; 818 *ndst = 0; 819 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 820 error += dstRate; 821 while (error > srcRate) { 822 if (*ndst == maxDst) 823 return; 824 (*ndst)++; 825 error -= srcRate; 826 827 W16(dst, M16(R16(src), R16(src + 2))); dst += 2; 828 } 829 src += 4; 830 } 831 } 832 833 static void cvtMS1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 834 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 835 { 836 DWORD error = srcRate / 2; 837 DWORD maxSrc = *nsrc, maxDst = *ndst; 838 *ndst = 0; 839 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 840 error += dstRate; 841 while (error > srcRate) { 842 if (*ndst == maxDst) 843 return; 844 (*ndst)++; 845 error -= srcRate; 846 847 W16(dst, R16(src)); dst += 2; 848 W16(dst, R16(src)); dst += 2; 849 } 850 src += 2; 851 } 852 } 853 854 static void cvtMM1616C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 855 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 856 { 857 DWORD error = srcRate / 2; 858 DWORD maxSrc = *nsrc, maxDst = *ndst; 859 *ndst = 0; 860 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 861 error += dstRate; 862 while (error > srcRate) { 863 if (*ndst == maxDst) 864 return; 865 (*ndst)++; 866 error -= srcRate; 867 868 W16(dst, R16(src)); dst += 2; 869 } 870 src += 2; 871 } 872 } 873 874 static void cvtSS2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 875 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 876 { 877 DWORD error = srcRate / 2; 878 DWORD maxSrc = *nsrc, maxDst = *ndst; 879 *ndst = 0; 880 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 881 error += dstRate; 882 while (error > srcRate) { 883 if (*ndst == maxDst) 884 return; 885 (*ndst)++; 886 error -= srcRate; 887 888 W24(dst, R24(src)); dst += 3; 889 W24(dst, R24(src + 3)); dst += 3; 890 } 891 src += 6; 892 } 893 } 894 895 static void cvtSM2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 896 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 897 { 898 DWORD error = srcRate / 2; 899 DWORD maxSrc = *nsrc, maxDst = *ndst; 900 *ndst = 0; 901 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 902 error += dstRate; 903 while (error > srcRate) { 904 if (*ndst == maxDst) 905 return; 906 (*ndst)++; 907 error -= srcRate; 908 909 W24(dst, M24(R24(src), R24(src + 3))); dst += 3; 910 } 911 src += 6; 912 } 913 } 914 915 static void cvtMS2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 916 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 917 { 918 DWORD error = srcRate / 2; 919 DWORD maxSrc = *nsrc, maxDst = *ndst; 920 *ndst = 0; 921 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 922 error += dstRate; 923 while (error > srcRate) { 924 if (*ndst == maxDst) 925 return; 926 (*ndst)++; 927 error -= srcRate; 928 929 W24(dst, R24(src)); dst += 3; 930 W24(dst, R24(src)); dst += 3; 931 } 932 src += 3; 933 } 934 } 935 936 static void cvtMM2424C(const DWORD srcRate, const unsigned char *src, DWORD *nsrc, 937 const DWORD dstRate, unsigned char *dst, DWORD *ndst) 938 { 939 DWORD error = srcRate / 2; 940 DWORD maxSrc = *nsrc, maxDst = *ndst; 941 *ndst = 0; 942 for (*nsrc = 0; *nsrc < maxSrc; (*nsrc)++) { 943 error += dstRate; 944 while (error > srcRate) { 945 if (*ndst == maxDst) 946 return; 947 (*ndst)++; 948 error -= srcRate; 949 950 W24(dst, R24(src)); dst += 3; 951 } 952 src += 3; 953 } 954 } 955 956 static const PCM_CONVERT_CHANGE_RATE PCM_ConvertChangeRate[] = { 957 cvtSS88C, cvtSM88C, cvtMS88C, cvtMM88C, 958 cvtSS816C, cvtSM816C, cvtMS816C, cvtMM816C, 959 NULL, NULL, NULL, NULL, /* TODO: 8->24 */ 960 cvtSS168C, cvtSM168C, cvtMS168C, cvtMM168C, 961 cvtSS1616C, cvtSM1616C, cvtMS1616C, cvtMM1616C, 962 NULL, NULL, NULL, NULL, /* TODO: 16->24 */ 963 NULL, NULL, NULL, NULL, /* TODO: 24->8 */ 964 NULL, NULL, NULL, NULL, /* TODO: 24->16 */ 965 cvtSS2424C, cvtSM2424C, cvtMS2424C, cvtMM2424C, 966 }; 967 968 /*********************************************************************** 969 * PCM_DriverDetails 970 * 971 */ 972 static LRESULT PCM_DriverDetails(PACMDRIVERDETAILSW add) 973 { 974 TRACE("(%p)\n", add); 975 976 add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC; 977 add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED; 978 add->wMid = MM_MICROSOFT; 979 add->wPid = MM_MSFT_ACM_PCM; 980 add->vdwACM = 0x01000000; 981 add->vdwDriver = 0x01000000; 982 add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CONVERTER; 983 add->cFormatTags = 1; 984 add->cFilterTags = 0; 985 add->hicon = NULL; 986 MultiByteToWideChar(CP_ACP, 0, "MS-PCM", -1, add->szShortName, ARRAY_SIZE(add->szShortName)); 987 MultiByteToWideChar(CP_ACP, 0, "Wine PCM converter", -1, 988 add->szLongName, ARRAY_SIZE(add->szLongName)); 989 MultiByteToWideChar(CP_ACP, 0, "Brought to you by the Wine team...", -1, 990 add->szCopyright, ARRAY_SIZE(add->szCopyright)); 991 MultiByteToWideChar(CP_ACP, 0, "Refer to LICENSE file", -1, 992 add->szLicensing, ARRAY_SIZE(add->szLicensing) ); 993 add->szFeatures[0] = 0; 994 995 return MMSYSERR_NOERROR; 996 } 997 998 /*********************************************************************** 999 * PCM_FormatTagDetails 1000 * 1001 */ 1002 static LRESULT PCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery) 1003 { 1004 TRACE("(%p, %08x)\n", aftd, dwQuery); 1005 1006 switch (dwQuery) { 1007 case ACM_FORMATTAGDETAILSF_INDEX: 1008 if (aftd->dwFormatTagIndex != 0) { 1009 WARN("not possible\n"); 1010 return ACMERR_NOTPOSSIBLE; 1011 } 1012 break; 1013 case ACM_FORMATTAGDETAILSF_FORMATTAG: 1014 if (aftd->dwFormatTag != WAVE_FORMAT_PCM) { 1015 WARN("not possible\n"); 1016 return ACMERR_NOTPOSSIBLE; 1017 } 1018 break; 1019 case ACM_FORMATTAGDETAILSF_LARGESTSIZE: 1020 if (aftd->dwFormatTag != WAVE_FORMAT_UNKNOWN && 1021 aftd->dwFormatTag != WAVE_FORMAT_PCM) { 1022 WARN("not possible\n"); 1023 return ACMERR_NOTPOSSIBLE; 1024 } 1025 break; 1026 default: 1027 WARN("Unsupported query %08x\n", dwQuery); 1028 return MMSYSERR_NOTSUPPORTED; 1029 } 1030 1031 aftd->dwFormatTagIndex = 0; 1032 aftd->dwFormatTag = WAVE_FORMAT_PCM; 1033 aftd->cbFormatSize = sizeof(PCMWAVEFORMAT); 1034 aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CONVERTER; 1035 aftd->cStandardFormats = ARRAY_SIZE(PCM_Formats); 1036 aftd->szFormatTag[0] = 0; 1037 1038 return MMSYSERR_NOERROR; 1039 } 1040 1041 /*********************************************************************** 1042 * PCM_FormatDetails 1043 * 1044 */ 1045 static LRESULT PCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery) 1046 { 1047 TRACE("(%p, %08x)\n", afd, dwQuery); 1048 1049 switch (dwQuery) { 1050 case ACM_FORMATDETAILSF_FORMAT: 1051 if (PCM_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) { 1052 WARN("not possible\n"); 1053 return ACMERR_NOTPOSSIBLE; 1054 } 1055 break; 1056 case ACM_FORMATDETAILSF_INDEX: 1057 assert(afd->dwFormatIndex < ARRAY_SIZE(PCM_Formats)); 1058 afd->pwfx->wFormatTag = WAVE_FORMAT_PCM; 1059 afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels; 1060 afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate; 1061 afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits; 1062 /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not 1063 * accessible afd->pwfx->cbSize = 0; 1064 */ 1065 afd->pwfx->nBlockAlign = 1066 (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8; 1067 afd->pwfx->nAvgBytesPerSec = 1068 afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign; 1069 break; 1070 default: 1071 WARN("Unsupported query %08x\n", dwQuery); 1072 return MMSYSERR_NOTSUPPORTED; 1073 } 1074 1075 afd->dwFormatTag = WAVE_FORMAT_PCM; 1076 afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CONVERTER; 1077 afd->szFormat[0] = 0; /* let MSACM format this for us... */ 1078 afd->cbwfx = sizeof(PCMWAVEFORMAT); 1079 1080 return MMSYSERR_NOERROR; 1081 } 1082 1083 /*********************************************************************** 1084 * PCM_FormatSuggest 1085 * 1086 */ 1087 static LRESULT PCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs) 1088 { 1089 TRACE("(%p)\n", adfs); 1090 1091 /* some tests ... */ 1092 if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) || 1093 adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) || 1094 PCM_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) { 1095 WARN("not possible\n"); 1096 return ACMERR_NOTPOSSIBLE; 1097 } 1098 1099 /* is no suggestion for destination, then copy source value */ 1100 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS)) { 1101 adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels; 1102 } 1103 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC)) { 1104 adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec; 1105 } 1106 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE)) { 1107 adfs->pwfxDst->wBitsPerSample = adfs->pwfxSrc->wBitsPerSample; 1108 } 1109 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG)) { 1110 if (adfs->pwfxSrc->wFormatTag != WAVE_FORMAT_PCM) { 1111 WARN("source format 0x%x not supported\n", adfs->pwfxSrc->wFormatTag); 1112 return ACMERR_NOTPOSSIBLE; 1113 } 1114 adfs->pwfxDst->wFormatTag = adfs->pwfxSrc->wFormatTag; 1115 } else { 1116 if (adfs->pwfxDst->wFormatTag != WAVE_FORMAT_PCM) { 1117 WARN("destination format 0x%x not supported\n", adfs->pwfxDst->wFormatTag); 1118 return ACMERR_NOTPOSSIBLE; 1119 } 1120 } 1121 /* check if result is ok */ 1122 if (PCM_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) { 1123 WARN("not possible\n"); 1124 return ACMERR_NOTPOSSIBLE; 1125 } 1126 1127 /* recompute other values */ 1128 adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8; 1129 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign; 1130 1131 return MMSYSERR_NOERROR; 1132 } 1133 1134 /*********************************************************************** 1135 * PCM_StreamOpen 1136 * 1137 */ 1138 static LRESULT PCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi) 1139 { 1140 AcmPcmData* apd; 1141 int idx; 1142 DWORD flags; 1143 1144 TRACE("(%p)\n", adsi); 1145 1146 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC)); 1147 1148 switch(adsi->pwfxSrc->wBitsPerSample){ 1149 case 8: 1150 idx = 0; 1151 break; 1152 case 16: 1153 idx = 12; 1154 break; 1155 case 24: 1156 if (adsi->pwfxSrc->nBlockAlign != 3 * adsi->pwfxSrc->nChannels) { 1157 FIXME("Source: 24-bit samples must be packed\n"); 1158 return MMSYSERR_NOTSUPPORTED; 1159 } 1160 idx = 24; 1161 break; 1162 default: 1163 FIXME("Unsupported source bit depth: %u\n", adsi->pwfxSrc->wBitsPerSample); 1164 return MMSYSERR_NOTSUPPORTED; 1165 } 1166 1167 switch(adsi->pwfxDst->wBitsPerSample){ 1168 case 8: 1169 break; 1170 case 16: 1171 idx += 4; 1172 break; 1173 case 24: 1174 if (adsi->pwfxDst->nBlockAlign != 3 * adsi->pwfxDst->nChannels) { 1175 FIXME("Destination: 24-bit samples must be packed\n"); 1176 return MMSYSERR_NOTSUPPORTED; 1177 } 1178 idx += 8; 1179 break; 1180 default: 1181 FIXME("Unsupported destination bit depth: %u\n", adsi->pwfxDst->wBitsPerSample); 1182 return MMSYSERR_NOTSUPPORTED; 1183 } 1184 1185 if (adsi->pwfxSrc->nChannels == 1) idx += 2; 1186 1187 if (adsi->pwfxDst->nChannels == 1) idx += 1; 1188 1189 apd = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmPcmData)); 1190 if (!apd) 1191 return MMSYSERR_NOMEM; 1192 1193 if (adsi->pwfxSrc->nSamplesPerSec == adsi->pwfxDst->nSamplesPerSec) { 1194 flags = 0; 1195 apd->cvt.cvtKeepRate = PCM_ConvertKeepRate[idx]; 1196 } else { 1197 flags = PCM_RESAMPLE; 1198 apd->cvt.cvtChangeRate = PCM_ConvertChangeRate[idx]; 1199 } 1200 1201 if(!apd->cvt.cvtChangeRate && !apd->cvt.cvtKeepRate){ 1202 FIXME("Unimplemented conversion from %u -> %u bps\n", 1203 adsi->pwfxSrc->wBitsPerSample, 1204 adsi->pwfxDst->wBitsPerSample); 1205 HeapFree(GetProcessHeap(), 0, apd); 1206 return MMSYSERR_NOTSUPPORTED; 1207 } 1208 1209 adsi->dwDriver = (DWORD_PTR)apd; 1210 adsi->fdwDriver = flags; 1211 1212 return MMSYSERR_NOERROR; 1213 } 1214 1215 /*********************************************************************** 1216 * PCM_StreamClose 1217 * 1218 */ 1219 static LRESULT PCM_StreamClose(PACMDRVSTREAMINSTANCE adsi) 1220 { 1221 TRACE("(%p)\n", adsi); 1222 1223 HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver); 1224 return MMSYSERR_NOERROR; 1225 } 1226 1227 /*********************************************************************** 1228 * PCM_round 1229 * 1230 */ 1231 static inline DWORD PCM_round(DWORD a, DWORD b, DWORD c) 1232 { 1233 assert(c); 1234 /* to be sure, always return an entire number of c... */ 1235 return ((double)a * (double)b + (double)c - 1) / (double)c; 1236 } 1237 1238 /*********************************************************************** 1239 * PCM_StreamSize 1240 * 1241 */ 1242 static LRESULT PCM_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss) 1243 { 1244 DWORD srcMask = ~(adsi->pwfxSrc->nBlockAlign - 1); 1245 DWORD dstMask = ~(adsi->pwfxDst->nBlockAlign - 1); 1246 1247 TRACE("(%p, %p)\n", adsi, adss); 1248 1249 switch (adss->fdwSize) { 1250 case ACM_STREAMSIZEF_DESTINATION: 1251 /* cbDstLength => cbSrcLength */ 1252 adss->cbSrcLength = PCM_round(adss->cbDstLength & dstMask, 1253 adsi->pwfxSrc->nAvgBytesPerSec, 1254 adsi->pwfxDst->nAvgBytesPerSec) & srcMask; 1255 break; 1256 case ACM_STREAMSIZEF_SOURCE: 1257 /* cbSrcLength => cbDstLength */ 1258 adss->cbDstLength = PCM_round(adss->cbSrcLength & srcMask, 1259 adsi->pwfxDst->nAvgBytesPerSec, 1260 adsi->pwfxSrc->nAvgBytesPerSec) & dstMask; 1261 break; 1262 default: 1263 WARN("Unsupported query %08x\n", adss->fdwSize); 1264 return MMSYSERR_NOTSUPPORTED; 1265 } 1266 return MMSYSERR_NOERROR; 1267 } 1268 1269 /*********************************************************************** 1270 * PCM_StreamConvert 1271 * 1272 */ 1273 static LRESULT PCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh) 1274 { 1275 AcmPcmData* apd = (AcmPcmData*)adsi->dwDriver; 1276 DWORD nsrc = NUM_OF(adsh->cbSrcLength, adsi->pwfxSrc->nBlockAlign); 1277 DWORD ndst = NUM_OF(adsh->cbDstLength, adsi->pwfxDst->nBlockAlign); 1278 1279 TRACE("(%p, %p)\n", adsi, adsh); 1280 1281 TRACE("nsrc=%d,adsh->cbSrcLength=%d\n", nsrc, adsh->cbSrcLength); 1282 TRACE("ndst=%d,adsh->cbDstLength=%d\n", ndst, adsh->cbDstLength); 1283 TRACE("src [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%u, nAvgBytesPerSec=%u, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n", 1284 adsi->pwfxSrc->wFormatTag, adsi->pwfxSrc->nChannels, adsi->pwfxSrc->nSamplesPerSec, adsi->pwfxSrc->nAvgBytesPerSec, 1285 adsi->pwfxSrc->nBlockAlign, adsi->pwfxSrc->wBitsPerSample, adsi->pwfxSrc->cbSize); 1286 TRACE("dst [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%u, nAvgBytesPerSec=%u, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n", 1287 adsi->pwfxDst->wFormatTag, adsi->pwfxDst->nChannels, adsi->pwfxDst->nSamplesPerSec, adsi->pwfxDst->nAvgBytesPerSec, 1288 adsi->pwfxDst->nBlockAlign, adsi->pwfxDst->wBitsPerSample, adsi->pwfxDst->cbSize); 1289 1290 if (adsh->fdwConvert & 1291 ~(ACM_STREAMCONVERTF_BLOCKALIGN| 1292 ACM_STREAMCONVERTF_END| 1293 ACM_STREAMCONVERTF_START)) { 1294 FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert); 1295 } 1296 /* ACM_STREAMCONVERTF_BLOCKALIGN 1297 * currently all conversions are block aligned, so do nothing for this flag 1298 * ACM_STREAMCONVERTF_END 1299 * no pending data, so do nothing for this flag 1300 */ 1301 if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START) && 1302 (adsi->fdwDriver & PCM_RESAMPLE)) { 1303 } 1304 1305 /* do the job */ 1306 if (adsi->fdwDriver & PCM_RESAMPLE) { 1307 apd->cvt.cvtChangeRate(adsi->pwfxSrc->nSamplesPerSec, adsh->pbSrc, &nsrc, 1308 adsi->pwfxDst->nSamplesPerSec, adsh->pbDst, &ndst); 1309 } else { 1310 if (nsrc < ndst) ndst = nsrc; else nsrc = ndst; 1311 1312 /* nsrc is now equal to ndst */ 1313 apd->cvt.cvtKeepRate(adsh->pbSrc, nsrc, adsh->pbDst); 1314 } 1315 1316 adsh->cbSrcLengthUsed = nsrc * adsi->pwfxSrc->nBlockAlign; 1317 adsh->cbDstLengthUsed = ndst * adsi->pwfxDst->nBlockAlign; 1318 1319 return MMSYSERR_NOERROR; 1320 } 1321 1322 /************************************************************************** 1323 * DriverProc (MSACM32.@) 1324 */ 1325 LRESULT CALLBACK PCM_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg, 1326 LPARAM dwParam1, LPARAM dwParam2) 1327 { 1328 TRACE("(%08lx %p %u %08lx %08lx);\n", 1329 dwDevID, hDriv, wMsg, dwParam1, dwParam2); 1330 1331 switch (wMsg) { 1332 case DRV_LOAD: return 1; 1333 case DRV_FREE: return 1; 1334 case DRV_OPEN: return PCM_drvOpen((LPSTR)dwParam1, (PACMDRVOPENDESCW)dwParam2); 1335 case DRV_CLOSE: return PCM_drvClose(dwDevID); 1336 case DRV_ENABLE: return 1; 1337 case DRV_DISABLE: return 1; 1338 case DRV_QUERYCONFIGURE: return 1; 1339 case DRV_CONFIGURE: MessageBoxA(0, "MSACM PCM filter !", "Wine Driver", MB_OK); return 1; 1340 case DRV_INSTALL: return DRVCNF_RESTART; 1341 case DRV_REMOVE: return DRVCNF_RESTART; 1342 1343 case ACMDM_DRIVER_NOTIFY: 1344 /* no caching from other ACM drivers is done so far */ 1345 return MMSYSERR_NOERROR; 1346 1347 case ACMDM_DRIVER_DETAILS: 1348 return PCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1); 1349 1350 case ACMDM_FORMATTAG_DETAILS: 1351 return PCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2); 1352 1353 case ACMDM_FORMAT_DETAILS: 1354 return PCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2); 1355 1356 case ACMDM_FORMAT_SUGGEST: 1357 return PCM_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1); 1358 1359 case ACMDM_STREAM_OPEN: 1360 return PCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1); 1361 1362 case ACMDM_STREAM_CLOSE: 1363 return PCM_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1); 1364 1365 case ACMDM_STREAM_SIZE: 1366 return PCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2); 1367 1368 case ACMDM_STREAM_CONVERT: 1369 return PCM_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2); 1370 1371 case ACMDM_HARDWARE_WAVE_CAPS_INPUT: 1372 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT: 1373 /* this converter is not a hardware driver */ 1374 case ACMDM_FILTERTAG_DETAILS: 1375 case ACMDM_FILTER_DETAILS: 1376 /* this converter is not a filter */ 1377 case ACMDM_STREAM_RESET: 1378 /* only needed for asynchronous driver... we aren't, so just say it */ 1379 case ACMDM_STREAM_PREPARE: 1380 case ACMDM_STREAM_UNPREPARE: 1381 /* nothing special to do here... so don't do anything */ 1382 return MMSYSERR_NOTSUPPORTED; 1383 1384 default: 1385 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2); 1386 } 1387 } 1388