Changeset 6712 for trunk/src/msacm32/pcmconverter.c
- Timestamp:
- Sep 15, 2001, 11:47:44 AM (24 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/msacm32/pcmconverter.c
r6648 r6712 1 1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */ 2 /* $Id: pcmconverter.c,v 1.2 2001-09-05 13:11:26 bird Exp $ */ 2 3 3 /* 4 4 * MSACM32 library 5 5 * 6 * Copyright 2000 7 * 8 * 9 * + most of the computation should be done in fixed point arithmetic10 * 11 * 12 * 13 * 14 * 15 * 6 * Copyright 2000 Eric Pouech 7 * 8 * FIXME / TODO list 9 * + most of the computation should be done in fixed point arithmetic 10 * instead of floating point (16 bits for integral part, and 16 bits 11 * for fractional part for example) 12 * + implement PCM_FormatSuggest function 13 * + get rid of hack for PCM_DriverProc (msacm32.dll shouldn't export 14 * a DriverProc, but this would require implementing a generic 15 * embedded driver handling scheme in msacm32.dll which isn't done yet 16 16 */ 17 17 … … 35 35 * PCM_drvOpen 36 36 */ 37 static DWORDPCM_drvOpen(LPCSTR str)37 static DWORD PCM_drvOpen(LPCSTR str) 38 38 { 39 39 return 1; … … 43 43 * PCM_drvClose 44 44 */ 45 static DWORDPCM_drvClose(DWORD dwDevID)45 static DWORD PCM_drvClose(DWORD dwDevID) 46 46 { 47 47 return 1; 48 48 } 49 49 50 #define NUM_PCM_FORMATS(sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))51 #define NUM_OF(a,b)(((a)+(b)-1)/(b))50 #define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0])) 51 #define NUM_OF(a,b) (((a)+(b)-1)/(b)) 52 52 53 53 /* flags for fdwDriver */ 54 #define PCM_RESAMPLE 54 #define PCM_RESAMPLE 1 55 55 56 56 /* data used while converting */ … … 58 58 /* conversion routine, depending if rate conversion is required */ 59 59 union { 60 61 void (*cvtChangeRate)(struct tagAcmPcmData*, const unsigned char*, 62 60 void (*cvtKeepRate)(const unsigned char*, int, unsigned char*); 61 void (*cvtChangeRate)(struct tagAcmPcmData*, const unsigned char*, 62 LPDWORD, unsigned char*, LPDWORD); 63 63 } cvt; 64 64 /* the following fields are used only with rate conversion) */ 65 DWORD srcPos;/* position in source stream */66 double dstPos;/* position in destination stream */67 double dstIncr; /* value to increment dst stream when src stream68 65 DWORD srcPos; /* position in source stream */ 66 double dstPos; /* position in destination stream */ 67 double dstIncr; /* value to increment dst stream when src stream 68 is incremented by 1 */ 69 69 /* last source stream value read */ 70 70 union { 71 unsigned char b;/* 8 bit value */72 short s;/* 16 bit value */71 unsigned char b; /* 8 bit value */ 72 short s; /* 16 bit value */ 73 73 } last[2]; /* two channels max (stereo) */ 74 74 } AcmPcmData; … … 77 77 * also helps given a unique index to each of the supported formats 78 78 */ 79 static 80 int 81 int 82 int 79 static struct { 80 int nChannels; 81 int nBits; 82 int rate; 83 83 } PCM_Formats[] = { 84 84 {1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000}, … … 91 91 * PCM_GetFormatIndex 92 92 */ 93 static DWORDPCM_GetFormatIndex(LPWAVEFORMATEX wfx)93 static DWORD PCM_GetFormatIndex(LPWAVEFORMATEX wfx) 94 94 { 95 95 int i; 96 96 97 97 for (i = 0; i < NUM_PCM_FORMATS; i++) { 98 99 100 101 98 if (wfx->nChannels == PCM_Formats[i].nChannels && 99 wfx->nSamplesPerSec == PCM_Formats[i].rate && 100 wfx->wBitsPerSample == PCM_Formats[i].nBits) 101 return i; 102 102 } 103 103 return 0xFFFFFFFF; … … 107 107 * 108 108 * parameters: 109 * 110 * 111 * 112 * 109 * + 8 bit unsigned vs 16 bit signed 110 * + mono vs stereo (1 or 2 channels) 111 * + sampling rate (8.0, 11.025, 22.05, 44.1 kHz are defined, but algo shall work 112 * in all cases) 113 113 * 114 114 * mono => stereo: copy the same sample on Left & Right channels 115 115 * stereo =) mono: use the average value of samples from Left & Right channels 116 116 * resampling; we lookup for each destination sample the two source adjacent samples 117 * were src <= dst < src+1 (dst is increased by a fractional value which is118 * 119 * 117 * were src <= dst < src+1 (dst is increased by a fractional value which is 118 * equivalent to the increment by one on src); then we use a linear 119 * interpolation between src and src+1 120 120 */ 121 121 … … 125 125 * Converts a 8 bit sample to a 16 bit one 126 126 */ 127 static inline short C816(unsigned char b) 127 static inline short C816(unsigned char b) 128 128 { 129 129 return (short)(b ^ 0x80) * 256; … … 135 135 * Converts a 16 bit sample to a 8 bit one (data loss !!) 136 136 */ 137 static inline unsigned char C168(short s) 137 static inline unsigned char C168(short s) 138 138 { 139 139 return HIBYTE(s) ^ (unsigned char)0x80; … … 164 164 * M16 165 165 * 166 * Convert the (l,r) 16 bit stereo sample into a 16 bit mono 166 * Convert the (l,r) 16 bit stereo sample into a 16 bit mono 167 167 * (takes the mid-point of the two values) 168 168 */ … … 175 175 * M8 176 176 * 177 * Convert the (l,r) 8 bit stereo sample into a 8 bit mono 177 * Convert the (l,r) 8 bit stereo sample into a 8 bit mono 178 178 * (takes the mid-point of the two values) 179 179 */ … … 194 194 */ 195 195 196 static 196 static void cvtMM88K(const unsigned char* src, int ns, unsigned char* dst) 197 197 { 198 198 memcpy(dst, src, ns); 199 199 } 200 200 201 static 201 static void cvtSS88K(const unsigned char* src, int ns, unsigned char* dst) 202 202 { 203 203 memcpy(dst, src, ns * 2); 204 204 } 205 205 206 static 206 static void cvtMM1616K(const unsigned char* src, int ns, unsigned char* dst) 207 207 { 208 208 memcpy(dst, src, ns * 2); 209 209 } 210 210 211 static 211 static void cvtSS1616K(const unsigned char* src, int ns, unsigned char* dst) 212 212 { 213 213 memcpy(dst, src, ns * 4); 214 214 } 215 215 216 static 217 { 218 while (ns--) { 219 220 221 } 222 } 223 224 static 225 { 226 short 227 228 while (ns--) { 229 230 W16(dst, v);dst += 2;231 W16(dst, v);dst += 2;232 } 233 } 234 235 static 216 static void cvtMS88K(const unsigned char* src, int ns, unsigned char* dst) 217 { 218 while (ns--) { 219 *dst++ = *src; 220 *dst++ = *src++; 221 } 222 } 223 224 static void cvtMS816K(const unsigned char* src, int ns, unsigned char* dst) 225 { 226 short v; 227 228 while (ns--) { 229 v = C816(*src++); 230 W16(dst, v); dst += 2; 231 W16(dst, v); dst += 2; 232 } 233 } 234 235 static void cvtMS168K(const unsigned char* src, int ns, unsigned char* dst) 236 236 { 237 237 unsigned char v; 238 239 while (ns--) { 240 v = C168(R16(src));src += 2;241 242 243 } 244 } 245 246 static 247 { 248 short 249 250 while (ns--) { 251 v = R16(src);src += 2;252 W16(dst, v);dst += 2;253 W16(dst, v);dst += 2;254 } 255 } 256 257 static 258 { 259 while (ns--) { 260 261 262 } 263 } 264 265 static 266 { 267 short 268 269 while (ns--) { 270 271 272 W16(dst, v);dst += 2;273 } 274 } 275 276 static 277 { 278 while (ns--) { 279 280 281 } 282 } 283 284 static 285 { 286 while (ns--) { 287 W16(dst, M16(R16(src),R16(src+2)));dst += 2;288 289 } 290 } 291 292 static 293 { 294 while (ns--) { 295 W16(dst, C816(*src++));dst += 2;296 } 297 } 298 299 static 300 { 301 while (ns--) { 302 W16(dst, C816(*src++));dst += 2;303 W16(dst, C816(*src++));dst += 2;304 } 305 } 306 307 static 308 { 309 while (ns--) { 310 *dst++ = C168(R16(src));src += 2;311 } 312 } 313 314 static 315 { 316 while (ns--) { 317 *dst++ = C168(R16(src));src += 2;318 *dst++ = C168(R16(src));src += 2;319 } 320 } 321 322 static 323 cvtSS88K, 324 cvtSS816K, 325 cvtSS168K, 238 239 while (ns--) { 240 v = C168(R16(src)); src += 2; 241 *dst++ = v; 242 *dst++ = v; 243 } 244 } 245 246 static void cvtMS1616K(const unsigned char* src, int ns, unsigned char* dst) 247 { 248 short v; 249 250 while (ns--) { 251 v = R16(src); src += 2; 252 W16(dst, v); dst += 2; 253 W16(dst, v); dst += 2; 254 } 255 } 256 257 static void cvtSM88K(const unsigned char* src, int ns, unsigned char* dst) 258 { 259 while (ns--) { 260 *dst++ = M8(src[0], src[1]); 261 src += 2; 262 } 263 } 264 265 static void cvtSM816K(const unsigned char* src, int ns, unsigned char* dst) 266 { 267 short v; 268 269 while (ns--) { 270 v = M16(C816(src[0]), C816(src[1])); 271 src += 2; 272 W16(dst, v); dst += 2; 273 } 274 } 275 276 static void cvtSM168K(const unsigned char* src, int ns, unsigned char* dst) 277 { 278 while (ns--) { 279 *dst++ = C168(M16(R16(src), R16(src + 2))); 280 src += 4; 281 } 282 } 283 284 static void cvtSM1616K(const unsigned char* src, int ns, unsigned char* dst) 285 { 286 while (ns--) { 287 W16(dst, M16(R16(src),R16(src+2))); dst += 2; 288 src += 4; 289 } 290 } 291 292 static void cvtMM816K(const unsigned char* src, int ns, unsigned char* dst) 293 { 294 while (ns--) { 295 W16(dst, C816(*src++)); dst += 2; 296 } 297 } 298 299 static void cvtSS816K(const unsigned char* src, int ns, unsigned char* dst) 300 { 301 while (ns--) { 302 W16(dst, C816(*src++)); dst += 2; 303 W16(dst, C816(*src++)); dst += 2; 304 } 305 } 306 307 static void cvtMM168K(const unsigned char* src, int ns, unsigned char* dst) 308 { 309 while (ns--) { 310 *dst++ = C168(R16(src)); src += 2; 311 } 312 } 313 314 static void cvtSS168K(const unsigned char* src, int ns, unsigned char* dst) 315 { 316 while (ns--) { 317 *dst++ = C168(R16(src)); src += 2; 318 *dst++ = C168(R16(src)); src += 2; 319 } 320 } 321 322 static void (*PCM_ConvertKeepRate[16])(const unsigned char*, int, unsigned char*) = { 323 cvtSS88K, cvtSM88K, cvtMS88K, cvtMM88K, 324 cvtSS816K, cvtSM816K, cvtMS816K, cvtMM816K, 325 cvtSS168K, cvtSM168K, cvtMS168K, cvtMM168K, 326 326 cvtSS1616K, cvtSM1616K, cvtMS1616K, cvtMM1616K, 327 327 }; … … 333 333 * Linear interpolation is used 334 334 */ 335 static inline doubleI(double v1, double v2, double r)335 static inline double I(double v1, double v2, double r) 336 336 { 337 337 if (0.0 >= r || r > 1.0) FIXME("r!! %f\n", r); … … 339 339 } 340 340 341 static void cvtSS88C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,342 343 { 344 double 345 346 while (*nsrc != 0 && *ndst != 0) { 347 348 349 350 351 352 353 354 355 356 357 358 341 static void cvtSS88C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc, 342 unsigned char* dst, LPDWORD ndst) 343 { 344 double r; 345 346 while (*nsrc != 0 && *ndst != 0) { 347 while ((r = (double)apd->srcPos - apd->dstPos) <= 0) { 348 if (*nsrc == 0) return; 349 apd->last[0].b = *src++; 350 apd->last[1].b = *src++; 351 apd->srcPos++; 352 (*nsrc)--; 353 } 354 /* now do the interpolation */ 355 *dst++ = I(apd->last[0].b, src[0], r); 356 *dst++ = I(apd->last[1].b, src[1], r); 357 apd->dstPos += apd->dstIncr; 358 (*ndst)--; 359 359 } 360 360 } … … 368 368 * 369 369 */ 370 static void cvtSM88C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,371 372 { 373 double 374 375 while (*nsrc != 0 && *ndst != 0) { 376 377 378 379 380 381 382 383 384 385 386 387 } 388 } 389 390 static void cvtMS88C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,391 392 { 393 double 394 395 while (*nsrc != 0 && *ndst != 0) { 396 397 398 399 400 401 402 403 404 405 406 407 } 408 } 409 410 static void cvtMM88C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,411 412 { 413 double 414 415 while (*nsrc != 0 && *ndst != 0) { 416 417 418 419 420 421 422 423 424 425 426 } 427 } 428 429 static void cvtSS816C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,430 431 { 432 double 433 434 while (*nsrc != 0 && *ndst != 0) { 435 436 437 438 439 440 441 442 443 W16(dst, I(C816(apd->last[0].b), C816(src[0]), r));dst += 2;444 W16(dst, I(C816(apd->last[1].b), C816(src[1]), r));dst += 2;445 446 447 } 448 } 449 450 static void cvtSM816C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,451 452 { 453 double 454 455 while (*nsrc != 0 && *ndst != 0) { 456 457 458 459 460 461 462 463 464 465 466 467 468 469 } 470 } 471 472 static void cvtMS816C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,473 474 { 475 double 476 short 477 478 while (*nsrc != 0 && *ndst != 0) { 479 480 481 482 483 484 485 486 487 W16(dst, v);dst += 2;488 W16(dst, v);dst += 2;489 490 491 } 492 } 493 494 static void cvtMM816C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,495 496 { 497 double 498 499 while (*nsrc != 0 && *ndst != 0) { 500 501 502 503 504 505 506 507 508 509 510 511 } 512 } 513 514 static void cvtSS168C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,515 516 { 517 double 518 519 while (*nsrc != 0 && *ndst != 0) { 520 521 522 apd->last[0].s = R16(src);src += 2;523 apd->last[1].s = R16(src);src += 2;524 525 526 527 528 529 530 531 532 } 533 } 534 535 static void cvtSM168C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,536 537 { 538 double 539 540 while (*nsrc != 0 && *ndst != 0) { 541 542 543 apd->last[0].s = R16(src);src += 2;544 apd->last[1].s = R16(src);src += 2;545 546 547 548 549 *dst++ = C168(I(M16(apd->last[0].s, apd->last[1].s), 550 551 552 553 } 554 } 555 556 557 static void cvtMS168C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,558 559 { 560 double 561 562 while (*nsrc != 0 && *ndst != 0) { 563 564 565 apd->last[0].s = R16(src);src += 2;566 567 568 569 570 dst[0] = dst[1] = C168(I(apd->last[0].s, R16(src), r));dst += 2;571 572 573 } 574 } 575 576 577 static void cvtMM168C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,578 579 { 580 double 581 582 while (*nsrc != 0 && *ndst != 0) { 583 584 585 apd->last[0].s = R16(src);src += 2;586 587 588 589 590 591 592 593 } 594 } 595 596 static void cvtSS1616C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,597 598 { 599 double 600 601 while (*nsrc != 0 && *ndst != 0) { 602 603 604 apd->last[0].s = R16(src);src += 2;605 apd->last[1].s = R16(src);src += 2;606 607 608 609 610 W16(dst, I(apd->last[0].s, R16(src) , r));dst += 2;611 W16(dst, I(apd->last[1].s, R16(src+2), r));dst += 2;612 613 614 } 615 } 616 617 static void cvtSM1616C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,618 619 { 620 double 621 622 while (*nsrc != 0 && *ndst != 0) { 623 624 625 apd->last[0].s = R16(src);src += 2;626 apd->last[1].s = R16(src);src += 2;627 628 629 630 631 632 633 634 635 636 } 637 } 638 639 static void cvtMS1616C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,640 641 { 642 double 643 short 644 645 while (*nsrc != 0 && *ndst != 0) { 646 647 648 apd->last[0].s = R16(src);src += 2;649 650 651 652 653 654 W16(dst, v);dst += 2;655 W16(dst, v);dst += 2;656 657 658 } 659 } 660 661 static void cvtMM1616C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc,662 663 { 664 double 665 666 while (*nsrc != 0 && *ndst != 0) { 667 668 669 apd->last[0].s = R16(src);src += 2;670 671 672 673 674 W16(dst, I(apd->last[0].s, R16(src), r));dst += 2;675 676 677 } 678 } 679 680 static void (*PCM_ConvertChangeRate[16])(AcmPcmData* apd,681 const unsigned char* src, LPDWORD nsrc, 682 370 static void cvtSM88C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc, 371 unsigned char* dst, LPDWORD ndst) 372 { 373 double r; 374 375 while (*nsrc != 0 && *ndst != 0) { 376 while ((r = (double)apd->srcPos - apd->dstPos) <= 0) { 377 if (*nsrc == 0) return; 378 apd->last[0].b = *src++; 379 apd->last[1].b = *src++; 380 apd->srcPos++; 381 (*nsrc)--; 382 } 383 /* now do the interpolation */ 384 *dst++ = I(M8(apd->last[0].b, apd->last[1].b), M8(src[0], src[1]), r); 385 apd->dstPos += apd->dstIncr; 386 (*ndst)--; 387 } 388 } 389 390 static void cvtMS88C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc, 391 unsigned char* dst, LPDWORD ndst) 392 { 393 double r; 394 395 while (*nsrc != 0 && *ndst != 0) { 396 while ((r = (double)apd->srcPos - apd->dstPos) <= 0) { 397 if (*nsrc == 0) return; 398 apd->last[0].b = *src++; 399 apd->srcPos++; 400 (*nsrc)--; 401 } 402 /* now do the interpolation */ 403 dst[0] = dst[1] = I(apd->last[0].b, src[0], r); 404 dst += 2; 405 apd->dstPos += apd->dstIncr; 406 (*ndst)--; 407 } 408 } 409 410 static void cvtMM88C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc, 411 unsigned char* dst, LPDWORD ndst) 412 { 413 double r; 414 415 while (*nsrc != 0 && *ndst != 0) { 416 while ((r = (double)apd->srcPos - apd->dstPos) <= 0) { 417 if (*nsrc == 0) return; 418 apd->last[0].b = *src++; 419 apd->srcPos++; 420 (*nsrc)--; 421 } 422 /* now do the interpolation */ 423 *dst++ = I(apd->last[0].b, src[0], r); 424 apd->dstPos += apd->dstIncr; 425 (*ndst)--; 426 } 427 } 428 429 static void cvtSS816C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc, 430 unsigned char* dst, LPDWORD ndst) 431 { 432 double r; 433 434 while (*nsrc != 0 && *ndst != 0) { 435 while ((r = (double)apd->srcPos - apd->dstPos) <= 0) { 436 if (*nsrc == 0) return; 437 apd->last[0].b = *src++; 438 apd->last[1].b = *src++; 439 apd->srcPos++; 440 (*nsrc)--; 441 } 442 /* now do the interpolation */ 443 W16(dst, I(C816(apd->last[0].b), C816(src[0]), r)); dst += 2; 444 W16(dst, I(C816(apd->last[1].b), C816(src[1]), r)); dst += 2; 445 apd->dstPos += apd->dstIncr; 446 (*ndst)--; 447 } 448 } 449 450 static void cvtSM816C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc, 451 unsigned char* dst, LPDWORD ndst) 452 { 453 double r; 454 455 while (*nsrc != 0 && *ndst != 0) { 456 while ((r = (double)apd->srcPos - apd->dstPos) <= 0) { 457 if (*nsrc == 0) return; 458 apd->last[0].b = *src++; 459 apd->last[1].b = *src++; 460 apd->srcPos++; 461 (*nsrc)--; 462 } 463 /* now do the interpolation */ 464 W16(dst, I(M16(C816(apd->last[0].b), C816(apd->last[1].b)), 465 M16(C816(src[0]), C816(src[1])), r)); 466 dst += 2; 467 apd->dstPos += apd->dstIncr; 468 (*ndst)--; 469 } 470 } 471 472 static void cvtMS816C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc, 473 unsigned char* dst, LPDWORD ndst) 474 { 475 double r; 476 short v; 477 478 while (*nsrc != 0 && *ndst != 0) { 479 while ((r = (double)apd->srcPos - apd->dstPos) <= 0) { 480 if (*nsrc == 0) return; 481 apd->last[0].b = *src++; 482 apd->srcPos++; 483 (*nsrc)--; 484 } 485 /* now do the interpolation */ 486 v = I(C816(apd->last[0].b), C816(src[0]), r); 487 W16(dst, v); dst += 2; 488 W16(dst, v); dst += 2; 489 apd->dstPos += apd->dstIncr; 490 (*ndst)--; 491 } 492 } 493 494 static void cvtMM816C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc, 495 unsigned char* dst, LPDWORD ndst) 496 { 497 double r; 498 499 while (*nsrc != 0 && *ndst != 0) { 500 while ((r = (double)apd->srcPos - apd->dstPos) <= 0) { 501 if (*nsrc == 0) return; 502 apd->last[0].b = *src++; 503 apd->srcPos++; 504 (*nsrc)--; 505 } 506 /* now do the interpolation */ 507 W16(dst, I(C816(apd->last[0].b), C816(src[0]), r)); 508 dst += 2; 509 apd->dstPos += apd->dstIncr; 510 (*ndst)--; 511 } 512 } 513 514 static void cvtSS168C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc, 515 unsigned char* dst, LPDWORD ndst) 516 { 517 double r; 518 519 while (*nsrc != 0 && *ndst != 0) { 520 while ((r = (double)apd->srcPos - apd->dstPos) <= 0) { 521 if (*nsrc == 0) return; 522 apd->last[0].s = R16(src); src += 2; 523 apd->last[1].s = R16(src); src += 2; 524 apd->srcPos++; 525 (*nsrc)--; 526 } 527 /* now do the interpolation */ 528 *dst++ = C168(I(apd->last[0].s, R16(src) , r)); 529 *dst++ = C168(I(apd->last[1].s, R16(src+2), r)); 530 apd->dstPos += apd->dstIncr; 531 (*ndst)--; 532 } 533 } 534 535 static void cvtSM168C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc, 536 unsigned char* dst, LPDWORD ndst) 537 { 538 double r; 539 540 while (*nsrc != 0 && *ndst != 0) { 541 while ((r = (double)apd->srcPos - apd->dstPos) <= 0) { 542 if (*nsrc == 0) return; 543 apd->last[0].s = R16(src); src += 2; 544 apd->last[1].s = R16(src); src += 2; 545 apd->srcPos++; 546 (*nsrc)--; 547 } 548 /* now do the interpolation */ 549 *dst++ = C168(I(M16(apd->last[0].s, apd->last[1].s), 550 M16(R16(src), R16(src + 2)), r)); 551 apd->dstPos += apd->dstIncr; 552 (*ndst)--; 553 } 554 } 555 556 557 static void cvtMS168C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc, 558 unsigned char* dst, LPDWORD ndst) 559 { 560 double r; 561 562 while (*nsrc != 0 && *ndst != 0) { 563 while ((r = (double)apd->srcPos - apd->dstPos) <= 0) { 564 if (*nsrc == 0) return; 565 apd->last[0].s = R16(src); src += 2; 566 apd->srcPos++; 567 (*nsrc)--; 568 } 569 /* now do the interpolation */ 570 dst[0] = dst[1] = C168(I(apd->last[0].s, R16(src), r)); dst += 2; 571 apd->dstPos += apd->dstIncr; 572 (*ndst)--; 573 } 574 } 575 576 577 static void cvtMM168C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc, 578 unsigned char* dst, LPDWORD ndst) 579 { 580 double r; 581 582 while (*nsrc != 0 && *ndst != 0) { 583 while ((r = (double)apd->srcPos - apd->dstPos) <= 0) { 584 if (*nsrc == 0) return; 585 apd->last[0].s = R16(src); src += 2; 586 apd->srcPos++; 587 (*nsrc)--; 588 } 589 /* now do the interpolation */ 590 *dst++ = C168(I(apd->last[0].s, R16(src), r)); 591 apd->dstPos += apd->dstIncr; 592 (*ndst)--; 593 } 594 } 595 596 static void cvtSS1616C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc, 597 unsigned char* dst, LPDWORD ndst) 598 { 599 double r; 600 601 while (*nsrc != 0 && *ndst != 0) { 602 while ((r = (double)apd->srcPos - apd->dstPos) <= 0) { 603 if (*nsrc == 0) return; 604 apd->last[0].s = R16(src); src += 2; 605 apd->last[1].s = R16(src); src += 2; 606 apd->srcPos++; 607 (*nsrc)--; 608 } 609 /* now do the interpolation */ 610 W16(dst, I(apd->last[0].s, R16(src) , r)); dst += 2; 611 W16(dst, I(apd->last[1].s, R16(src+2), r)); dst += 2; 612 apd->dstPos += apd->dstIncr; 613 (*ndst)--; 614 } 615 } 616 617 static void cvtSM1616C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc, 618 unsigned char* dst, LPDWORD ndst) 619 { 620 double r; 621 622 while (*nsrc != 0 && *ndst != 0) { 623 while ((r = (double)apd->srcPos - apd->dstPos) <= 0) { 624 if (*nsrc == 0) return; 625 apd->last[0].s = R16(src); src += 2; 626 apd->last[1].s = R16(src); src += 2; 627 apd->srcPos++; 628 (*nsrc)--; 629 } 630 /* now do the interpolation */ 631 W16(dst, I(M16(apd->last[0].s, apd->last[1].s), 632 M16(R16(src), R16(src+2)), r)); 633 dst += 2; 634 apd->dstPos += apd->dstIncr; 635 (*ndst)--; 636 } 637 } 638 639 static void cvtMS1616C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc, 640 unsigned char* dst, LPDWORD ndst) 641 { 642 double r; 643 short v; 644 645 while (*nsrc != 0 && *ndst != 0) { 646 while ((r = (double)apd->srcPos - apd->dstPos) <= 0) { 647 if (*nsrc == 0) return; 648 apd->last[0].s = R16(src); src += 2; 649 apd->srcPos++; 650 (*nsrc)--; 651 } 652 /* now do the interpolation */ 653 v = I(apd->last[0].s, R16(src), r); 654 W16(dst, v); dst += 2; 655 W16(dst, v); dst += 2; 656 apd->dstPos += apd->dstIncr; 657 (*ndst)--; 658 } 659 } 660 661 static void cvtMM1616C(AcmPcmData* apd, const unsigned char* src, LPDWORD nsrc, 662 unsigned char* dst, LPDWORD ndst) 663 { 664 double r; 665 666 while (*nsrc != 0 && *ndst != 0) { 667 while ((r = (double)apd->srcPos - apd->dstPos) <= 0) { 668 if (*nsrc == 0) return; 669 apd->last[0].s = R16(src); src += 2; 670 apd->srcPos++; 671 (*nsrc)--; 672 } 673 /* now do the interpolation */ 674 W16(dst, I(apd->last[0].s, R16(src), r)); dst += 2; 675 apd->dstPos += apd->dstIncr; 676 (*ndst)--; 677 } 678 } 679 680 static void (*PCM_ConvertChangeRate[16])(AcmPcmData* apd, 681 const unsigned char* src, LPDWORD nsrc, 682 unsigned char* dst, LPDWORD ndst) = { 683 683 cvtSS88C, cvtSM88C, cvtMS88C, cvtMM88C, 684 cvtSS816C, 685 cvtSS168C, 684 cvtSS816C, cvtSM816C, cvtMS816C, cvtMM816C, 685 cvtSS168C, cvtSM168C, cvtMS168C, cvtMM168C, 686 686 cvtSS1616C, cvtSM1616C, cvtMS1616C, cvtMM1616C, 687 687 }; … … 691 691 * 692 692 */ 693 static 693 static LRESULT PCM_DriverDetails(PACMDRIVERDETAILSW add) 694 694 { 695 695 add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC; … … 712 712 add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) ); 713 713 add->szFeatures[0] = 0; 714 714 715 715 return MMSYSERR_NOERROR; 716 716 } … … 720 720 * 721 721 */ 722 static LRESULTPCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)722 static LRESULT PCM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery) 723 723 { 724 724 switch (dwQuery) { 725 725 case ACM_FORMATTAGDETAILSF_INDEX: 726 727 728 case ACM_FORMATTAGDETAILSF_FORMATTAG: 729 730 726 if (aftd->dwFormatTagIndex != 0) return ACMERR_NOTPOSSIBLE; 727 break; 728 case ACM_FORMATTAGDETAILSF_FORMATTAG: 729 if (aftd->dwFormatTag != WAVE_FORMAT_PCM) return ACMERR_NOTPOSSIBLE; 730 break; 731 731 case ACM_FORMATTAGDETAILSF_LARGESTSIZE: 732 if (aftd->dwFormatTag != WAVE_FORMAT_UNKNOWN && 733 734 735 732 if (aftd->dwFormatTag != WAVE_FORMAT_UNKNOWN && 733 aftd->dwFormatTag != WAVE_FORMAT_UNKNOWN) 734 return ACMERR_NOTPOSSIBLE; 735 break; 736 736 default: 737 738 739 } 740 737 WARN("Unsupported query %08lx\n", dwQuery); 738 return MMSYSERR_NOTSUPPORTED; 739 } 740 741 741 aftd->dwFormatTagIndex = 0; 742 742 aftd->dwFormatTag = WAVE_FORMAT_PCM; … … 745 745 aftd->cStandardFormats = NUM_PCM_FORMATS; 746 746 aftd->szFormatTag[0] = 0; 747 747 748 748 return MMSYSERR_NOERROR; 749 749 } … … 753 753 * 754 754 */ 755 static LRESULTPCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)755 static LRESULT PCM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery) 756 756 { 757 757 switch (dwQuery) { 758 758 case ACM_FORMATDETAILSF_FORMAT: 759 760 761 759 afd->dwFormatIndex = PCM_GetFormatIndex(afd->pwfx); 760 if (afd->dwFormatIndex == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; 761 break; 762 762 case ACM_FORMATDETAILSF_INDEX: 763 764 765 766 767 768 769 * afd->pwfx->cbSize = 0; 770 771 afd->pwfx->nBlockAlign = 772 773 afd->pwfx->nAvgBytesPerSec = 774 775 763 assert(afd->dwFormatIndex < NUM_PCM_FORMATS); 764 afd->pwfx->wFormatTag = WAVE_FORMAT_PCM; 765 afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels; 766 afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate; 767 afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits; 768 /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible 769 * afd->pwfx->cbSize = 0; 770 */ 771 afd->pwfx->nBlockAlign = 772 (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8; 773 afd->pwfx->nAvgBytesPerSec = 774 afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign; 775 break; 776 776 default: 777 778 return MMSYSERR_NOTSUPPORTED; 779 } 780 777 WARN("Unsupported query %08lx\n", dwQuery); 778 return MMSYSERR_NOTSUPPORTED; 779 } 780 781 781 afd->dwFormatTag = WAVE_FORMAT_PCM; 782 782 afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CONVERTER; 783 783 afd->szFormat[0] = 0; /* let MSACM format this for us... */ 784 784 785 785 return MMSYSERR_NOERROR; 786 786 } … … 790 790 * 791 791 */ 792 static LRESULTPCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs)792 static LRESULT PCM_FormatSuggest(PACMDRVFORMATSUGGEST adfs) 793 793 { 794 794 FIXME("(%p);\n", adfs); … … 800 800 * 801 801 */ 802 static voidPCM_Reset(AcmPcmData* apd, int srcNumBits)802 static void PCM_Reset(AcmPcmData* apd, int srcNumBits) 803 803 { 804 804 apd->srcPos = 0; … … 806 806 /* initialize with neutral value */ 807 807 if (srcNumBits == 16) { 808 809 808 apd->last[0].s = 0; 809 apd->last[1].s = 0; 810 810 } else { 811 812 811 apd->last[0].b = (BYTE)0x80; 812 apd->last[1].b = (BYTE)0x80; 813 813 } 814 814 } … … 818 818 * 819 819 */ 820 static LRESULTPCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi)821 { 822 AcmPcmData* 823 int 820 static LRESULT PCM_StreamOpen(PACMDRVSTREAMINSTANCE adsi) 821 { 822 AcmPcmData* apd; 823 int idx = 0; 824 824 825 825 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC)); 826 826 827 827 if (PCM_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF || 828 829 828 PCM_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF) 829 return ACMERR_NOTPOSSIBLE; 830 830 831 831 apd = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmPcmData)); … … 834 834 adsi->dwDriver = (DWORD)apd; 835 835 adsi->fdwDriver = 0; 836 836 837 837 if (adsi->pwfxSrc->wBitsPerSample == 16) idx += 8; 838 838 if (adsi->pwfxDst->wBitsPerSample == 16) idx += 4; … … 841 841 842 842 if (adsi->pwfxSrc->nSamplesPerSec == adsi->pwfxDst->nSamplesPerSec) { 843 843 apd->cvt.cvtKeepRate = PCM_ConvertKeepRate[idx]; 844 844 } else { 845 846 847 848 849 845 adsi->fdwDriver |= PCM_RESAMPLE; 846 apd->dstIncr = (double)(adsi->pwfxSrc->nSamplesPerSec) / 847 (double)(adsi->pwfxDst->nSamplesPerSec); 848 PCM_Reset(apd, adsi->pwfxSrc->wBitsPerSample); 849 apd->cvt.cvtChangeRate = PCM_ConvertChangeRate[idx]; 850 850 } 851 851 … … 857 857 * 858 858 */ 859 static LRESULTPCM_StreamClose(PACMDRVSTREAMINSTANCE adsi)859 static LRESULT PCM_StreamClose(PACMDRVSTREAMINSTANCE adsi) 860 860 { 861 861 HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver); … … 867 867 * 868 868 */ 869 static inline DWORDPCM_round(DWORD a, DWORD b, DWORD c)869 static inline DWORD PCM_round(DWORD a, DWORD b, DWORD c) 870 870 { 871 871 assert(a && b && c); … … 878 878 * 879 879 */ 880 static 880 static LRESULT PCM_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss) 881 881 { 882 882 switch (adss->fdwSize) { 883 883 case ACM_STREAMSIZEF_DESTINATION: 884 885 adss->cbSrcLength = PCM_round(adss->cbDstLength, 886 adsi->pwfxSrc->nAvgBytesPerSec, 887 888 884 /* cbDstLength => cbSrcLength */ 885 adss->cbSrcLength = PCM_round(adss->cbDstLength, 886 adsi->pwfxSrc->nAvgBytesPerSec, 887 adsi->pwfxDst->nAvgBytesPerSec); 888 break; 889 889 case ACM_STREAMSIZEF_SOURCE: 890 891 adss->cbDstLength = PCM_round(adss->cbSrcLength, 892 adsi->pwfxDst->nAvgBytesPerSec, 893 894 890 /* cbSrcLength => cbDstLength */ 891 adss->cbDstLength = PCM_round(adss->cbSrcLength, 892 adsi->pwfxDst->nAvgBytesPerSec, 893 adsi->pwfxSrc->nAvgBytesPerSec); 894 break; 895 895 default: 896 897 return MMSYSERR_NOTSUPPORTED; 896 WARN("Unsupported query %08lx\n", adss->fdwSize); 897 return MMSYSERR_NOTSUPPORTED; 898 898 } 899 899 return MMSYSERR_NOERROR; … … 906 906 static LRESULT PCM_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh) 907 907 { 908 AcmPcmData* 909 DWORD 910 DWORD 911 912 if (adsh->fdwConvert & 913 914 915 916 908 AcmPcmData* apd = (AcmPcmData*)adsi->dwDriver; 909 DWORD nsrc = NUM_OF(adsh->cbSrcLength, adsi->pwfxSrc->nBlockAlign); 910 DWORD ndst = NUM_OF(adsh->cbDstLength, adsi->pwfxDst->nBlockAlign); 911 912 if (adsh->fdwConvert & 913 ~(ACM_STREAMCONVERTF_BLOCKALIGN| 914 ACM_STREAMCONVERTF_END| 915 ACM_STREAMCONVERTF_START)) { 916 FIXME("Unsupported fdwConvert (%08lx), ignoring it\n", adsh->fdwConvert); 917 917 } 918 918 /* ACM_STREAMCONVERTF_BLOCKALIGN 919 * 919 * currently all conversions are block aligned, so do nothing for this flag 920 920 * ACM_STREAMCONVERTF_END 921 * 921 * no pending data, so do nothing for this flag 922 922 */ 923 if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START) && 924 925 923 if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START) && 924 (adsi->fdwDriver & PCM_RESAMPLE)) { 925 PCM_Reset(apd, adsi->pwfxSrc->wBitsPerSample); 926 926 } 927 927 928 928 /* do the job */ 929 929 if (adsi->fdwDriver & PCM_RESAMPLE) { 930 DWORDnsrc2 = nsrc;931 DWORDndst2 = ndst;932 933 934 935 930 DWORD nsrc2 = nsrc; 931 DWORD ndst2 = ndst; 932 933 apd->cvt.cvtChangeRate(apd, adsh->pbSrc, &nsrc2, adsh->pbDst, &ndst2); 934 nsrc -= nsrc2; 935 ndst -= ndst2; 936 936 } else { 937 938 939 940 937 if (nsrc < ndst) ndst = nsrc; else nsrc = ndst; 938 939 /* nsrc is now equal to ndst */ 940 apd->cvt.cvtKeepRate(adsh->pbSrc, nsrc, adsh->pbDst); 941 941 } 942 942 … … 948 948 949 949 /************************************************************************** 950 * PCM_DriverProc[exported]951 */ 952 LRESULT CALLBACK PCM_DriverProc(DWORD dwDevID, HDRVR hDriv, UINT wMsg,953 954 { 955 TRACE("(%08lx %08lx %u %08lx %08lx);\n", 956 957 950 * PCM_DriverProc [exported] 951 */ 952 LRESULT CALLBACK PCM_DriverProc(DWORD dwDevID, HDRVR hDriv, UINT wMsg, 953 LPARAM dwParam1, LPARAM dwParam2) 954 { 955 TRACE("(%08lx %08lx %u %08lx %08lx);\n", 956 dwDevID, (DWORD)hDriv, wMsg, dwParam1, dwParam2); 957 958 958 switch (wMsg) { 959 case DRV_LOAD: 960 case DRV_FREE: 961 case DRV_OPEN: 962 case DRV_CLOSE: 963 case DRV_ENABLE: return 1;964 case DRV_DISABLE: 965 case DRV_QUERYCONFIGURE: 966 case DRV_CONFIGURE: 967 case DRV_INSTALL: 968 case DRV_REMOVE: 969 959 case DRV_LOAD: return 1; 960 case DRV_FREE: return 1; 961 case DRV_OPEN: return PCM_drvOpen((LPSTR)dwParam1); 962 case DRV_CLOSE: return PCM_drvClose(dwDevID); 963 case DRV_ENABLE: return 1; 964 case DRV_DISABLE: return 1; 965 case DRV_QUERYCONFIGURE: return 1; 966 case DRV_CONFIGURE: MessageBoxA(0, "MSACM PCM filter !", "Wine Driver", MB_OK); return 1; 967 case DRV_INSTALL: return DRVCNF_RESTART; 968 case DRV_REMOVE: return DRVCNF_RESTART; 969 970 970 case ACMDM_DRIVER_NOTIFY: 971 972 973 971 /* no caching from other ACM drivers is done so far */ 972 return MMSYSERR_NOERROR; 973 974 974 case ACMDM_DRIVER_DETAILS: 975 976 975 return PCM_DriverDetails((PACMDRIVERDETAILSW)dwParam1); 976 977 977 case ACMDM_FORMATTAG_DETAILS: 978 979 978 return PCM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2); 979 980 980 case ACMDM_FORMAT_DETAILS: 981 982 981 return PCM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2); 982 983 983 case ACMDM_FORMAT_SUGGEST: 984 985 984 return PCM_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1); 985 986 986 case ACMDM_STREAM_OPEN: 987 988 987 return PCM_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1); 988 989 989 case ACMDM_STREAM_CLOSE: 990 991 990 return PCM_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1); 991 992 992 case ACMDM_STREAM_SIZE: 993 994 993 return PCM_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2); 994 995 995 case ACMDM_STREAM_CONVERT: 996 997 996 return PCM_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2); 997 998 998 case ACMDM_HARDWARE_WAVE_CAPS_INPUT: 999 999 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT: 1000 1000 /* this converter is not a hardware driver */ 1001 1001 case ACMDM_FILTERTAG_DETAILS: 1002 1002 case ACMDM_FILTER_DETAILS: 1003 1003 /* this converter is not a filter */ 1004 1004 case ACMDM_STREAM_RESET: 1005 1005 /* only needed for asynchronous driver... we aren't, so just say it */ 1006 1006 case ACMDM_STREAM_PREPARE: 1007 1007 case ACMDM_STREAM_UNPREPARE: 1008 1009 1010 1008 /* nothing special to do here... so don't do anything */ 1009 return MMSYSERR_NOTSUPPORTED; 1010 1011 1011 default: 1012 1012 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2); 1013 1013 } 1014 1014 return 0;
Note:
See TracChangeset
for help on using the changeset viewer.