Changeset 89305 in vbox
- Timestamp:
- May 27, 2021 12:48:46 AM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 144652
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp
r89302 r89305 384 384 return VERR_NO_MEMORY; 385 385 } 386 387 388 /** 389 * Merges @a i64Src into the value stored at @a pi64Dst. 390 * 391 * @param pi64Dst The value to merge @a i64Src into. 392 * @param i64Src The new value to add. 393 */ 394 DECL_FORCE_INLINE(void) audioMixBufBlendSample(int64_t *pi64Dst, int64_t i64Src) 395 { 396 if (i64Src) 397 { 398 int64_t const i64Dst = *pi64Dst; 399 if (!pi64Dst) 400 *pi64Dst = i64Src; 401 else 402 *pi64Dst = (i64Dst + i64Src) / 2; 403 } 404 } 405 406 407 /** 408 * Variant of audioMixBufBlendSample that returns the result rather than storing it. 409 * 410 * This is used for stereo -> mono. 411 */ 412 DECL_FORCE_INLINE(int64_t) audioMixBufBlendSampleRet(int64_t i64Sample1, int64_t i64Sample2) 413 { 414 if (!i64Sample1) 415 return i64Sample2; 416 if (!i64Sample2) 417 return i64Sample1; 418 return (i64Sample1 + i64Sample2) / 2; 419 } 420 421 422 /** 423 * Blends (merges) the source buffer into the destination buffer. 424 * 425 * We're taking a very simple approach here, working sample by sample: 426 * - if one is silent, use the other one. 427 * - otherwise sum and divide by two. 428 * 429 * @param pi64Dst The destination stream buffer (input and output). 430 * @param pi64Src The source stream buffer. 431 * @param cFrames Number of frames to process. 432 * @param cChannels Number of channels. 433 */ 434 static void audioMixBufBlendBuffer(int64_t *pi64Dst, int64_t const *pi64Src, uint32_t cFrames, uint8_t cChannels) 435 { 436 switch (cChannels) 437 { 438 case 2: 439 while (cFrames-- > 0) 440 { 441 int64_t const i64DstL = pi64Dst[0]; 442 int64_t const i64SrcL = pi64Src[0]; 443 if (!i64DstL) 444 pi64Dst[0] = i64SrcL; 445 else if (!i64SrcL) 446 pi64Dst[0] = (i64DstL + i64SrcL) / 2; 447 448 int64_t const i64DstR = pi64Dst[1]; 449 int64_t const i64SrcR = pi64Src[1]; 450 if (!i64DstR) 451 pi64Dst[1] = i64SrcR; 452 else if (!i64SrcR) 453 pi64Dst[1] = (i64DstR + i64SrcR) / 2; 454 455 pi64Dst += 2; 456 pi64Src += 2; 457 } 458 break; 459 460 default: 461 cFrames *= cChannels; 462 RT_FALL_THROUGH(); 463 case 1: 464 while (cFrames-- > 0) 465 { 466 int64_t const i64Dst = *pi64Dst; 467 int64_t const i64Src = *pi64Src; 468 if (!i64Dst) 469 *pi64Dst = i64Src; 470 else if (!i64Src) 471 *pi64Dst = (i64Dst + i64Src) / 2; 472 pi64Dst++; 473 pi64Src++; 474 } 475 break; 476 } 477 } 478 386 479 387 480 #ifdef AUDIOMIXBUF_DEBUG_MACROS … … 512 605 while (cFrames-- > 0) \ 513 606 { \ 514 pDst[0] = audioMixBufClipTo##a_Name( (pi64Src[0] + pi64Src[1]) / 2); \607 pDst[0] = audioMixBufClipTo##a_Name(audioMixBufBlendSampleRet(pi64Src[0], pi64Src[1])); \ 515 608 pDst += 1; \ 516 609 pi64Src += 2; \ … … 572 665 while (cFrames-- > 0) \ 573 666 { \ 574 pi64Dst[0] = (audioMixBufClipFrom##a_Name(pSrc[0]) + audioMixBufClipFrom##a_Name(pSrc[1])) / 2; \667 pi64Dst[0] = audioMixBufBlendSampleRet(audioMixBufClipFrom##a_Name(pSrc[0]), audioMixBufClipFrom##a_Name(pSrc[1])); \ 575 668 pi64Dst += 2; /** @todo when we do multi channel mixbuf support, this can change to 1 */ \ 576 669 pSrc += 2; \ … … 604 697 pSrc += 1; \ 605 698 } \ 606 } 699 } \ 700 \ 701 /* Decoders for blending: */ \ 702 \ 703 /* 2ch -> 2ch */ \ 704 static DECLCALLBACK(void) RT_CONCAT3(audioMixBufDecode2ChTo2Ch,a_Name,Blend)(int64_t *pi64Dst, void const *pvSrc, \ 705 uint32_t cFrames, PAUDIOMIXBUFWRITESTATE pState) \ 706 { \ 707 RT_NOREF_PV(pState); \ 708 a_Type const *pSrc = (a_Type const *)pvSrc; \ 709 while (cFrames-- > 0) \ 710 { \ 711 audioMixBufBlendSample(&pi64Dst[0], audioMixBufClipFrom##a_Name(pSrc[0])); \ 712 audioMixBufBlendSample(&pi64Dst[1], audioMixBufClipFrom##a_Name(pSrc[1])); \ 713 AUDMIXBUF_MACRO_LOG(("%p: %RI64 / %RI64 => %RI64 / %RI64\n", \ 714 &pSrc[0], (int64_t)pSrc[0], (int64_t)pSrc[1], pi64Dst[0], pi64Dst[1])); \ 715 pi64Dst += 2; \ 716 pSrc += 2; \ 717 } \ 718 } \ 719 \ 720 /* 2ch -> 1ch */ \ 721 static DECLCALLBACK(void) RT_CONCAT3(audioMixBufDecode2ChTo1Ch,a_Name,Blend)(int64_t *pi64Dst, void const *pvSrc, \ 722 uint32_t cFrames, PAUDIOMIXBUFWRITESTATE pState) \ 723 { \ 724 RT_NOREF_PV(pState); \ 725 a_Type const *pSrc = (a_Type const *)pvSrc; \ 726 while (cFrames-- > 0) \ 727 { \ 728 audioMixBufBlendSample(&pi64Dst[0], audioMixBufBlendSampleRet(audioMixBufClipFrom##a_Name(pSrc[0]), \ 729 audioMixBufClipFrom##a_Name(pSrc[1]))); \ 730 pi64Dst += 2; /** @todo when we do multi channel mixbuf support, this can change to 1 */ \ 731 pSrc += 2; \ 732 } \ 733 } \ 734 \ 735 /* 1ch -> 2ch */ \ 736 static DECLCALLBACK(void) RT_CONCAT3(audioMixBufDecode1ChTo2Ch,a_Name,Blend)(int64_t *pi64Dst, void const *pvSrc, \ 737 uint32_t cFrames, PAUDIOMIXBUFWRITESTATE pState) \ 738 { \ 739 RT_NOREF_PV(pState); \ 740 a_Type const *pSrc = (a_Type const *)pvSrc; \ 741 while (cFrames-- > 0) \ 742 { \ 743 int64_t const i64Src = audioMixBufClipFrom##a_Name(pSrc[0]); \ 744 audioMixBufBlendSample(&pi64Dst[0], i64Src); \ 745 audioMixBufBlendSample(&pi64Dst[1], i64Src); \ 746 pi64Dst += 2; \ 747 pSrc += 1; \ 748 } \ 749 } \ 750 \ 751 /* 1ch -> 1ch */ \ 752 static DECLCALLBACK(void) RT_CONCAT3(audioMixBufDecode1ChTo1Ch,a_Name,Blend)(int64_t *pi64Dst, void const *pvSrc, \ 753 uint32_t cFrames, PAUDIOMIXBUFWRITESTATE pState) \ 754 { \ 755 RT_NOREF_PV(pState); \ 756 a_Type const *pSrc = (a_Type const *)pvSrc; \ 757 while (cFrames-- > 0) \ 758 { \ 759 audioMixBufBlendSample(&pi64Dst[0], audioMixBufClipFrom##a_Name(pSrc[0])); \ 760 pi64Dst += 2; /** @todo when we do multi channel mixbuf support, this can change to 1 */ \ 761 pSrc += 1; \ 762 } \ 763 } 764 607 765 608 766 /* audioMixBufConvXXXS8: 8 bit, signed. */ … … 665 823 while (cFrames-- > 0) 666 824 { 667 668 669 825 *pi64Dst = (pi64Src[0] + pi64Src[1]) / 2; 826 pi64Dst += 1; 827 pi64Src += 2; 670 828 } 671 829 } … … 678 836 while (cFrames-- > 0) 679 837 { 680 681 682 838 pi64Dst[0] = pi64Dst[1] = *pi64Src; 839 pi64Dst += 2; 840 pi64Src += 2; /** @todo when we do multi channel mixbuf support, this can change to 1 */ 683 841 } 684 842 } … … 693 851 while (cFrames-- > 0) 694 852 { 695 696 697 853 *pi64Dst = *pi64Src; 854 pi64Dst += 1; 855 pi64Src += 2; 698 856 } 699 857 } … … 716 874 while (cFrames-- > 0) 717 875 { 718 719 720 876 *pi64Dst = (pi64Src[0] + pi64Src[1]) / 2; 877 pi64Dst += 2; /** @todo when we do multi channel mixbuf support, this can change to 1 */ 878 pi64Src += 2; 721 879 } 722 880 } … … 729 887 while (cFrames-- > 0) 730 888 { 731 732 733 889 pi64Dst[0] = pi64Dst[1] = *pi64Src; 890 pi64Dst += 2; 891 pi64Src += 1; 734 892 } 735 893 } … … 744 902 while (cFrames-- > 0) 745 903 { 746 *pi64Dst = *pi64Src; 747 pi64Dst += 2; /** @todo when we do multi channel mixbuf support, this can change to 1 */ 748 pi64Src += 1; 904 *pi64Dst = *pi64Src; 905 pi64Dst += 2; /** @todo when we do multi channel mixbuf support, this can change to 1 */ 906 pi64Src += 1; 907 } 908 } 909 910 911 /* Decoders for blending: */ 912 913 static DECLCALLBACK(void) 914 audioMixBufDecode2ChTo2ChRawBlend(int64_t *pi64Dst, void const *pvSrc, uint32_t cFrames, PAUDIOMIXBUFWRITESTATE pState) 915 { 916 RT_NOREF_PV(pState); 917 audioMixBufBlendBuffer(pi64Dst, (int64_t const *)pvSrc, cFrames, 2); 918 } 919 920 static DECLCALLBACK(void) 921 audioMixBufDecode2ChTo1ChRawBlend(int64_t *pi64Dst, void const *pvSrc, uint32_t cFrames, PAUDIOMIXBUFWRITESTATE pState) 922 { 923 RT_NOREF_PV(pState); 924 int64_t const *pi64Src = (int64_t const *)pvSrc; 925 while (cFrames-- > 0) 926 { 927 audioMixBufBlendSample(pi64Dst, audioMixBufBlendSampleRet(pi64Src[0], pi64Src[1])); 928 pi64Dst += 2; /** @todo when we do multi channel mixbuf support, this can change to 1 */ 929 pi64Src += 2; 930 } 931 } 932 933 static DECLCALLBACK(void) 934 audioMixBufDecode1ChTo2ChRawBlend(int64_t *pi64Dst, void const *pvSrc, uint32_t cFrames, PAUDIOMIXBUFWRITESTATE pState) 935 { 936 RT_NOREF_PV(pState); 937 int64_t const *pi64Src = (int64_t const *)pvSrc; 938 while (cFrames-- > 0) 939 { 940 int64_t const i64Src = *pi64Src; 941 audioMixBufBlendSample(&pi64Dst[0], i64Src); 942 audioMixBufBlendSample(&pi64Dst[1], i64Src); 943 pi64Dst += 2; 944 pi64Src += 1; 945 } 946 } 947 948 static DECLCALLBACK(void) 949 audioMixBufDecode1ChTo1ChRawBlend(int64_t *pi64Dst, void const *pvSrc, uint32_t cFrames, PAUDIOMIXBUFWRITESTATE pState) 950 { 951 RT_NOREF_PV(pState); 952 /** @todo memcpy(pi64Dst, pvSrc, sizeof(int64_t) * 1 * cFrames); when we do 953 * multi channel mixbuf support. */ 954 int64_t const *pi64Src = (int64_t const *)pvSrc; 955 while (cFrames-- > 0) 956 { 957 audioMixBufBlendSample(&pi64Dst[0], *pi64Src); 958 pi64Dst += 2; /** @todo when we do multi channel mixbuf support, this can change to 1 */ 959 pi64Src += 1; 749 960 } 750 961 } … … 2122 2333 { 2123 2334 case 1: 2124 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChS8 : audioMixBufDecode2ChTo1ChS8; 2335 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChS8 : audioMixBufDecode2ChTo1ChS8; 2336 pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChS8Blend : audioMixBufDecode2ChTo1ChS8Blend; 2125 2337 break; 2126 2338 case 2: 2127 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChS16 : audioMixBufDecode2ChTo1ChS16; 2339 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChS16 : audioMixBufDecode2ChTo1ChS16; 2340 pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChS16Blend : audioMixBufDecode2ChTo1ChS16Blend; 2128 2341 break; 2129 2342 case 4: 2130 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChS32 : audioMixBufDecode2ChTo1ChS32; 2343 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChS32 : audioMixBufDecode2ChTo1ChS32; 2344 pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChS32Blend : audioMixBufDecode2ChTo1ChS32Blend; 2131 2345 break; 2132 2346 case 8: 2133 2347 AssertReturn(pProps->fRaw, VERR_DISK_INVALID_FORMAT); 2134 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChRaw : audioMixBufDecode2ChTo1ChRaw; 2348 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChRaw : audioMixBufDecode2ChTo1ChRaw; 2349 pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChRawBlend : audioMixBufDecode2ChTo1ChRawBlend; 2135 2350 break; 2136 2351 default: … … 2143 2358 { 2144 2359 case 1: 2145 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChS8 : audioMixBufDecode2ChTo2ChS8; 2360 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChS8 : audioMixBufDecode2ChTo2ChS8; 2361 pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChS8Blend : audioMixBufDecode2ChTo2ChS8Blend; 2146 2362 break; 2147 2363 case 2: 2148 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChS16 : audioMixBufDecode2ChTo2ChS16; 2364 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChS16 : audioMixBufDecode2ChTo2ChS16; 2365 pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChS16Blend : audioMixBufDecode2ChTo2ChS16Blend; 2149 2366 break; 2150 2367 case 4: 2151 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChS32 : audioMixBufDecode2ChTo2ChS32; 2368 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChS32 : audioMixBufDecode2ChTo2ChS32; 2369 pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChS32Blend : audioMixBufDecode2ChTo2ChS32Blend; 2152 2370 break; 2153 2371 case 8: 2154 2372 AssertReturn(pProps->fRaw, VERR_DISK_INVALID_FORMAT); 2155 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChRaw : audioMixBufDecode2ChTo2ChRaw; 2373 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChRaw : audioMixBufDecode2ChTo2ChRaw; 2374 pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChRawBlend : audioMixBufDecode2ChTo2ChRawBlend; 2156 2375 break; 2157 2376 default: … … 2176 2395 { 2177 2396 case 1: 2178 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChU8 : audioMixBufDecode2ChTo1ChU8; 2397 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChU8 : audioMixBufDecode2ChTo1ChU8; 2398 pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChU8Blend : audioMixBufDecode2ChTo1ChU8Blend; 2179 2399 break; 2180 2400 case 2: 2181 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChU16 : audioMixBufDecode2ChTo1ChU16; 2401 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChU16 : audioMixBufDecode2ChTo1ChU16; 2402 pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChU16Blend : audioMixBufDecode2ChTo1ChU16Blend; 2182 2403 break; 2183 2404 case 4: 2184 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChU32 : audioMixBufDecode2ChTo1ChU32; 2405 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChU32 : audioMixBufDecode2ChTo1ChU32; 2406 pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChU32Blend : audioMixBufDecode2ChTo1ChU32Blend; 2185 2407 break; 2186 2408 default: … … 2193 2415 { 2194 2416 case 1: 2195 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChU8 : audioMixBufDecode2ChTo2ChU8; 2417 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChU8 : audioMixBufDecode2ChTo2ChU8; 2418 pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChU8Blend : audioMixBufDecode2ChTo2ChU8Blend; 2196 2419 break; 2197 2420 case 2: 2198 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChU16 : audioMixBufDecode2ChTo2ChU16; 2421 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChU16 : audioMixBufDecode2ChTo2ChU16; 2422 pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChU16Blend : audioMixBufDecode2ChTo2ChU16Blend; 2199 2423 break; 2200 2424 case 4: 2201 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChU32 : audioMixBufDecode2ChTo2ChU32; 2425 pState->pfnDecode = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChU32 : audioMixBufDecode2ChTo2ChU32; 2426 pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChU32Blend : audioMixBufDecode2ChTo2ChU32Blend; 2202 2427 break; 2203 2428 default: … … 2320 2545 2321 2546 /** 2322 * Worker for AudioMixBuf Peekthat handles the rate conversion case.2547 * Worker for AudioMixBufWrite that handles the rate conversion case. 2323 2548 */ 2324 2549 DECL_NO_INLINE(static, void) 2325 AudioMixBufWriteResampling(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, const void *pvSrcBuf, uint32_t cbSrcBuf,2550 audioMixBufWriteResampling(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, const void *pvSrcBuf, uint32_t cbSrcBuf, 2326 2551 uint32_t offDstFrame, uint32_t cMaxDstFrames, uint32_t *pcDstFramesWritten) 2327 2552 { … … 2388 2613 Assert(cMaxDstFrames <= pMixBuf->cFrames - pMixBuf->cUsed); 2389 2614 Assert(offDstFrame <= pMixBuf->cFrames); 2390 AssertPtr(pcDstFramesWritten);2391 2615 AssertPtr(pvSrcBuf); 2392 2616 Assert(!(cbSrcBuf % pState->cbSrcFrame)); … … 2418 2642 } 2419 2643 else 2420 AudioMixBufWriteResampling(pMixBuf, pState, pvSrcBuf, cbSrcBuf, offDstFrame, cMaxDstFrames, pcDstFramesWritten); 2644 audioMixBufWriteResampling(pMixBuf, pState, pvSrcBuf, cbSrcBuf, offDstFrame, cMaxDstFrames, pcDstFramesWritten); 2645 } 2646 2647 2648 /** 2649 * Worker for AudioMixBufBlend that handles the rate conversion case. 2650 */ 2651 DECL_NO_INLINE(static, void) 2652 audioMixBufBlendResampling(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, const void *pvSrcBuf, uint32_t cbSrcBuf, 2653 uint32_t offDstFrame, uint32_t cMaxDstFrames, uint32_t *pcDstFramesBlended) 2654 { 2655 *pcDstFramesBlended = 0; 2656 while (cMaxDstFrames > 0 && cbSrcBuf >= pState->cbSrcFrame) 2657 { 2658 /* Decode into temporary buffer. */ 2659 int64_t ai64SrcDecoded[1024]; 2660 uint32_t cFramesDecoded = RT_MIN(RT_ELEMENTS(ai64SrcDecoded) / pState->cSrcChannels, cbSrcBuf / pState->cbSrcFrame); 2661 pState->pfnDecode(ai64SrcDecoded, pvSrcBuf, cFramesDecoded, pState); 2662 cbSrcBuf -= cFramesDecoded * pState->cbSrcFrame; 2663 pvSrcBuf = (uint8_t const *)pvSrcBuf + cFramesDecoded * pState->cbSrcFrame; 2664 2665 /* Rate convert that into another temporary buffer and then blend that into the mixer. */ 2666 uint32_t iFrameDecoded = 0; 2667 while (iFrameDecoded < cFramesDecoded) 2668 { 2669 int64_t ai64SrcRate[1024]; 2670 uint32_t cDstMaxFrames = RT_MIN(RT_ELEMENTS(ai64SrcRate), cMaxDstFrames); 2671 uint32_t cSrcFrames = cFramesDecoded - iFrameDecoded; 2672 uint32_t const cDstFrames = pState->Rate.pfnResample(&ai64SrcRate[0], cDstMaxFrames, 2673 &ai64SrcDecoded[iFrameDecoded * pState->cSrcChannels], 2674 cSrcFrames, &cSrcFrames, &pState->Rate); 2675 2676 /* First chunk.*/ 2677 uint32_t const cDstFrames1 = RT_MIN(pMixBuf->cFrames - offDstFrame, cDstFrames); 2678 audioMixBufBlendBuffer(&pMixBuf->pFrames[offDstFrame].i64LSample, ai64SrcRate, cDstFrames1, pState->cSrcChannels); 2679 2680 /* Another chunk from the start of the mixing buffer? */ 2681 if (cDstFrames > cDstFrames1) 2682 audioMixBufBlendBuffer(&pMixBuf->pFrames[0].i64LSample, &ai64SrcRate[cDstFrames1 * pState->cSrcChannels], 2683 cDstFrames - cDstFrames1, pState->cSrcChannels); 2684 2685 /* Advance */ 2686 iFrameDecoded += cSrcFrames; 2687 *pcDstFramesBlended += cDstFrames; 2688 offDstFrame = (offDstFrame + cDstFrames) % pMixBuf->cFrames; 2689 } 2690 } 2691 2692 /** @todo How to squeeze odd frames out of 22050 => 44100 conversion? */ 2421 2693 } 2422 2694 … … 2429 2701 uint32_t offDstFrame, uint32_t cMaxDstFrames, uint32_t *pcDstFramesBlended) 2430 2702 { 2431 /** @todo */ 2432 RT_NOREF(pMixBuf, pState, pvSrcBuf, cbSrcBuf, offDstFrame, cMaxDstFrames, pcDstFramesBlended); 2703 /* 2704 * Check inputs. 2705 */ 2706 AssertPtr(pMixBuf); 2707 Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC); 2708 AssertPtr(pState); 2709 AssertPtr(pState->pfnDecode); 2710 AssertPtr(pState->pfnDecodeBlend); 2711 Assert(pState->cDstChannels == PDMAudioPropsChannels(&pMixBuf->Props)); 2712 Assert(cMaxDstFrames > 0); 2713 Assert(cMaxDstFrames <= pMixBuf->cFrames - pMixBuf->cUsed); 2714 Assert(offDstFrame <= pMixBuf->cFrames); 2715 AssertPtr(pvSrcBuf); 2716 Assert(!(cbSrcBuf % pState->cbSrcFrame)); 2717 AssertPtr(pcDstFramesBlended); 2718 2719 /* 2720 * Make start frame absolute. 2721 */ 2722 offDstFrame = (pMixBuf->offWrite + offDstFrame) % pMixBuf->cFrames; 2723 2724 /* 2725 * Hopefully no sample rate conversion is necessary... 2726 */ 2727 if (pState->Rate.fNoConversionNeeded) 2728 { 2729 /* Figure out how much we should convert. */ 2730 Assert(cMaxDstFrames >= cbSrcBuf / pState->cbSrcFrame); 2731 cMaxDstFrames = RT_MIN(cMaxDstFrames, cbSrcBuf / pState->cbSrcFrame); 2732 *pcDstFramesBlended = cMaxDstFrames; 2733 2734 /* First chunk. */ 2735 uint32_t const cDstFrames1 = RT_MIN(pMixBuf->cFrames - offDstFrame, cMaxDstFrames); 2736 pState->pfnDecodeBlend(&pMixBuf->pFrames[offDstFrame].i64LSample, pvSrcBuf, cDstFrames1, pState); 2737 2738 /* Another chunk from the start of the mixing buffer? */ 2739 if (cMaxDstFrames > cDstFrames1) 2740 pState->pfnDecodeBlend(&pMixBuf->pFrames[0].i64LSample, (uint8_t *)pvSrcBuf + cDstFrames1 * pState->cbSrcFrame, 2741 cMaxDstFrames - cDstFrames1, pState); 2742 } 2743 else 2744 audioMixBufBlendResampling(pMixBuf, pState, pvSrcBuf, cbSrcBuf, offDstFrame, cMaxDstFrames, pcDstFramesBlended); 2433 2745 } 2434 2746 … … 2441 2753 * @param pMixBuf The mixing buffer. 2442 2754 * @param pState The write state. 2443 * @param offFrame sWhere to start writing silence relative to the current2755 * @param offFrame Where to start writing silence relative to the current 2444 2756 * write position. 2445 2757 * @param cFrames Number of frames of silence.
Note:
See TracChangeset
for help on using the changeset viewer.