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