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