VirtualBox

Changeset 89382 in vbox for trunk


Ignore:
Timestamp:
May 31, 2021 12:03:03 AM (4 years ago)
Author:
vboxsync
Message:

AudioMixBuffer: Added generic decoders and encoders for arbitrary channel counts using generic source->destionation channel mapping (the mapping may need more work). Instantiated the resampler code for up to 12 channels. Untested. bugref:9890

Location:
trunk/src/VBox/Devices/Audio
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp

    r89378 r89382  
    329329    \
    330330    /* Encoders for peek: */ \
     331    \
     332    /* Generic */ \
     333    static DECLCALLBACK(void) RT_CONCAT(audioMixBufEncodeGeneric,a_Name)(void *pvDst, int32_t const *pi32Src, uint32_t cFrames, \
     334                                                                         PAUDIOMIXBUFPEEKSTATE pState) \
     335    { \
     336        RT_NOREF_PV(pState); \
     337        uintptr_t const cSrcChannels = pState->cSrcChannels; \
     338        uintptr_t const cDstChannels = pState->cDstChannels; \
     339        a_Type         *pDst = (a_Type *)pvDst; \
     340        while (cFrames-- > 0) \
     341        { \
     342            uintptr_t idxDst = cDstChannels; \
     343            while (idxDst-- > 0) \
     344            { \
     345                int8_t idxSrc = pState->aidxChannelMap[idxDst]; \
     346                if (idxSrc >= 0) \
     347                    pDst[idxDst] = audioMixBufSampleTo##a_Name(pi32Src[idxSrc]); \
     348                else if (idxSrc != -2) \
     349                    pDst[idxDst] = (_aSigned) ? 0 : (_aMax >> 1); \
     350                else \
     351                    pDst[idxDst] = 0; \
     352            } \
     353            pDst    += cDstChannels; \
     354            pi32Src += cSrcChannels; \
     355        } \
     356    } \
    331357    \
    332358    /* 2ch -> 2ch */ \
     
    389415    \
    390416    /* Decoders for write: */ \
     417    \
     418    /* Generic */ \
     419    static DECLCALLBACK(void) RT_CONCAT(audioMixBufDecodeGeneric,a_Name)(int32_t *pi32Dst, void const *pvSrc, uint32_t cFrames, \
     420                                                                         PAUDIOMIXBUFWRITESTATE pState) \
     421    { \
     422        RT_NOREF_PV(pState); \
     423        uintptr_t const cSrcChannels = pState->cSrcChannels; \
     424        uintptr_t const cDstChannels = pState->cDstChannels; \
     425        a_Type const   *pSrc         = (a_Type const *)pvSrc; \
     426        while (cFrames-- > 0) \
     427        { \
     428            uintptr_t idxDst = cDstChannels; \
     429            while (idxDst-- > 0) \
     430            { \
     431                int8_t idxSrc = pState->aidxChannelMap[idxDst]; \
     432                if (idxSrc >= 0) \
     433                    pi32Dst[idxDst] = audioMixBufSampleTo##a_Name(pSrc[idxSrc]); \
     434                else if (idxSrc != -2) \
     435                    pi32Dst[idxDst] = (_aSigned) ? 0 : (_aMax >> 1); \
     436                else \
     437                    pi32Dst[idxDst] = 0; \
     438            } \
     439            pi32Dst += cDstChannels; \
     440            pSrc    += cSrcChannels; \
     441        } \
     442    } \
    391443    \
    392444    /* 2ch -> 2ch */ \
     
    451503    /* Decoders for blending: */ \
    452504    \
     505    /* Generic */ \
     506    static DECLCALLBACK(void) RT_CONCAT3(audioMixBufDecodeGeneric,a_Name,Blend)(int32_t *pi32Dst, void const *pvSrc, \
     507                                                                                uint32_t cFrames, PAUDIOMIXBUFWRITESTATE pState) \
     508    { \
     509        RT_NOREF_PV(pState); \
     510        uintptr_t const cSrcChannels = pState->cSrcChannels; \
     511        uintptr_t const cDstChannels = pState->cDstChannels; \
     512        a_Type const   *pSrc         = (a_Type const *)pvSrc; \
     513        while (cFrames-- > 0) \
     514        { \
     515            uintptr_t idxDst = cDstChannels; \
     516            while (idxDst-- > 0) \
     517            { \
     518                int8_t idxSrc = pState->aidxChannelMap[idxDst]; \
     519                if (idxSrc >= 0) \
     520                    audioMixBufBlendSample(&pi32Dst[idxDst], audioMixBufSampleTo##a_Name(pSrc[idxSrc])); \
     521            } \
     522            pi32Dst += cDstChannels; \
     523            pSrc    += cSrcChannels; \
     524        } \
     525    } \
     526    \
    453527    /* 2ch -> 2ch */ \
    454528    static DECLCALLBACK(void) RT_CONCAT3(audioMixBufDecode2ChTo2Ch,a_Name,Blend)(int32_t *pi32Dst, void const *pvSrc, \
     
    544618        (a_pi32Dst)[1] = (a_pi32Src)[1]; \
    545619    } while (0)
     620#define COPY_LAST_FRAME_3CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
     621        (a_pi32Dst)[0] = (a_pi32Src)[0]; \
     622        (a_pi32Dst)[1] = (a_pi32Src)[1]; \
     623        (a_pi32Dst)[2] = (a_pi32Src)[2]; \
     624    } while (0)
     625#define COPY_LAST_FRAME_4CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
     626        (a_pi32Dst)[0] = (a_pi32Src)[0]; \
     627        (a_pi32Dst)[1] = (a_pi32Src)[1]; \
     628        (a_pi32Dst)[2] = (a_pi32Src)[2]; \
     629        (a_pi32Dst)[3] = (a_pi32Src)[3]; \
     630    } while (0)
     631#define COPY_LAST_FRAME_5CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
     632        (a_pi32Dst)[0] = (a_pi32Src)[0]; \
     633        (a_pi32Dst)[1] = (a_pi32Src)[1]; \
     634        (a_pi32Dst)[2] = (a_pi32Src)[2]; \
     635        (a_pi32Dst)[3] = (a_pi32Src)[3]; \
     636        (a_pi32Dst)[4] = (a_pi32Src)[4]; \
     637    } while (0)
     638#define COPY_LAST_FRAME_6CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
     639        (a_pi32Dst)[0] = (a_pi32Src)[0]; \
     640        (a_pi32Dst)[1] = (a_pi32Src)[1]; \
     641        (a_pi32Dst)[2] = (a_pi32Src)[2]; \
     642        (a_pi32Dst)[3] = (a_pi32Src)[3]; \
     643        (a_pi32Dst)[4] = (a_pi32Src)[4]; \
     644        (a_pi32Dst)[5] = (a_pi32Src)[5]; \
     645    } while (0)
     646#define COPY_LAST_FRAME_7CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
     647        (a_pi32Dst)[0] = (a_pi32Src)[0]; \
     648        (a_pi32Dst)[1] = (a_pi32Src)[1]; \
     649        (a_pi32Dst)[2] = (a_pi32Src)[2]; \
     650        (a_pi32Dst)[3] = (a_pi32Src)[3]; \
     651        (a_pi32Dst)[4] = (a_pi32Src)[4]; \
     652        (a_pi32Dst)[5] = (a_pi32Src)[5]; \
     653        (a_pi32Dst)[6] = (a_pi32Src)[6]; \
     654    } while (0)
     655#define COPY_LAST_FRAME_8CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
     656        (a_pi32Dst)[0] = (a_pi32Src)[0]; \
     657        (a_pi32Dst)[1] = (a_pi32Src)[1]; \
     658        (a_pi32Dst)[2] = (a_pi32Src)[2]; \
     659        (a_pi32Dst)[3] = (a_pi32Src)[3]; \
     660        (a_pi32Dst)[4] = (a_pi32Src)[4]; \
     661        (a_pi32Dst)[5] = (a_pi32Src)[5]; \
     662        (a_pi32Dst)[6] = (a_pi32Src)[6]; \
     663        (a_pi32Dst)[7] = (a_pi32Src)[7]; \
     664    } while (0)
     665#define COPY_LAST_FRAME_9CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
     666        (a_pi32Dst)[0] = (a_pi32Src)[0]; \
     667        (a_pi32Dst)[1] = (a_pi32Src)[1]; \
     668        (a_pi32Dst)[2] = (a_pi32Src)[2]; \
     669        (a_pi32Dst)[3] = (a_pi32Src)[3]; \
     670        (a_pi32Dst)[4] = (a_pi32Src)[4]; \
     671        (a_pi32Dst)[5] = (a_pi32Src)[5]; \
     672        (a_pi32Dst)[6] = (a_pi32Src)[6]; \
     673        (a_pi32Dst)[7] = (a_pi32Src)[7]; \
     674        (a_pi32Dst)[8] = (a_pi32Src)[8]; \
     675    } while (0)
     676#define COPY_LAST_FRAME_10CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
     677        (a_pi32Dst)[0] = (a_pi32Src)[0]; \
     678        (a_pi32Dst)[1] = (a_pi32Src)[1]; \
     679        (a_pi32Dst)[2] = (a_pi32Src)[2]; \
     680        (a_pi32Dst)[3] = (a_pi32Src)[3]; \
     681        (a_pi32Dst)[4] = (a_pi32Src)[4]; \
     682        (a_pi32Dst)[5] = (a_pi32Src)[5]; \
     683        (a_pi32Dst)[6] = (a_pi32Src)[6]; \
     684        (a_pi32Dst)[7] = (a_pi32Src)[7]; \
     685        (a_pi32Dst)[8] = (a_pi32Src)[8]; \
     686        (a_pi32Dst)[9] = (a_pi32Src)[9]; \
     687    } while (0)
     688#define COPY_LAST_FRAME_11CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
     689        (a_pi32Dst)[0] = (a_pi32Src)[0]; \
     690        (a_pi32Dst)[1] = (a_pi32Src)[1]; \
     691        (a_pi32Dst)[2] = (a_pi32Src)[2]; \
     692        (a_pi32Dst)[3] = (a_pi32Src)[3]; \
     693        (a_pi32Dst)[4] = (a_pi32Src)[4]; \
     694        (a_pi32Dst)[5] = (a_pi32Src)[5]; \
     695        (a_pi32Dst)[6] = (a_pi32Src)[6]; \
     696        (a_pi32Dst)[7] = (a_pi32Src)[7]; \
     697        (a_pi32Dst)[8] = (a_pi32Src)[8]; \
     698        (a_pi32Dst)[9] = (a_pi32Src)[9]; \
     699        (a_pi32Dst)[10] = (a_pi32Src)[10]; \
     700    } while (0)
     701#define COPY_LAST_FRAME_12CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
     702        (a_pi32Dst)[0] = (a_pi32Src)[0]; \
     703        (a_pi32Dst)[1] = (a_pi32Src)[1]; \
     704        (a_pi32Dst)[2] = (a_pi32Src)[2]; \
     705        (a_pi32Dst)[3] = (a_pi32Src)[3]; \
     706        (a_pi32Dst)[4] = (a_pi32Src)[4]; \
     707        (a_pi32Dst)[5] = (a_pi32Src)[5]; \
     708        (a_pi32Dst)[6] = (a_pi32Src)[6]; \
     709        (a_pi32Dst)[7] = (a_pi32Src)[7]; \
     710        (a_pi32Dst)[8] = (a_pi32Src)[8]; \
     711        (a_pi32Dst)[9] = (a_pi32Src)[9]; \
     712        (a_pi32Dst)[10] = (a_pi32Src)[10]; \
     713        (a_pi32Dst)[11] = (a_pi32Src)[11]; \
     714    } while (0)
    546715
    547716#define INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_iCh) \
     
    553722        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
    554723        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
     724    } while (0)
     725#define INTERPOLATE_3CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
     726        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
     727        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
     728        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
     729    } while (0)
     730#define INTERPOLATE_4CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
     731        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
     732        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
     733        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
     734        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 3); \
     735    } while (0)
     736#define INTERPOLATE_5CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
     737        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
     738        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
     739        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
     740        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 3); \
     741        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 4); \
     742    } while (0)
     743#define INTERPOLATE_6CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
     744        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
     745        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
     746        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
     747        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 3); \
     748        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 4); \
     749        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 5); \
     750    } while (0)
     751#define INTERPOLATE_7CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
     752        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
     753        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
     754        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
     755        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 3); \
     756        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 4); \
     757        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 5); \
     758        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 6); \
     759    } while (0)
     760#define INTERPOLATE_8CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
     761        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
     762        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
     763        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
     764        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 3); \
     765        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 4); \
     766        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 5); \
     767        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 6); \
     768        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 7); \
     769    } while (0)
     770#define INTERPOLATE_9CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
     771        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
     772        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
     773        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
     774        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 3); \
     775        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 4); \
     776        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 5); \
     777        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 6); \
     778        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 7); \
     779        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 8); \
     780    } while (0)
     781#define INTERPOLATE_10CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
     782        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
     783        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
     784        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
     785        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 3); \
     786        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 4); \
     787        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 5); \
     788        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 6); \
     789        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 7); \
     790        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 8); \
     791        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 9); \
     792    } while (0)
     793#define INTERPOLATE_11CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
     794        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
     795        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
     796        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
     797        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 3); \
     798        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 4); \
     799        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 5); \
     800        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 6); \
     801        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 7); \
     802        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 8); \
     803        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 9); \
     804        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 10); \
     805    } while (0)
     806#define INTERPOLATE_12CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
     807        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
     808        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
     809        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
     810        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 3); \
     811        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 4); \
     812        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 5); \
     813        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 6); \
     814        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 7); \
     815        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 8); \
     816        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 9); \
     817        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 10); \
     818        INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 11); \
    555819    } while (0)
    556820
     
    610874AUDIOMIXBUF_RESAMPLE(1,Generic)
    611875AUDIOMIXBUF_RESAMPLE(2,Generic)
     876AUDIOMIXBUF_RESAMPLE(3,Generic)
     877AUDIOMIXBUF_RESAMPLE(4,Generic)
     878AUDIOMIXBUF_RESAMPLE(5,Generic)
     879AUDIOMIXBUF_RESAMPLE(6,Generic)
     880AUDIOMIXBUF_RESAMPLE(7,Generic)
     881AUDIOMIXBUF_RESAMPLE(8,Generic)
     882AUDIOMIXBUF_RESAMPLE(9,Generic)
     883AUDIOMIXBUF_RESAMPLE(10,Generic)
     884AUDIOMIXBUF_RESAMPLE(11,Generic)
     885AUDIOMIXBUF_RESAMPLE(12,Generic)
    612886
    613887
     
    678952        switch (cChannels)
    679953        {
    680             case 1: pRate->pfnResample = audioMixBufResample1ChGeneric; break;
    681             case 2: pRate->pfnResample = audioMixBufResample2ChGeneric; break;
     954            case  1: pRate->pfnResample = audioMixBufResample1ChGeneric; break;
     955            case  2: pRate->pfnResample = audioMixBufResample2ChGeneric; break;
     956            case  3: pRate->pfnResample = audioMixBufResample3ChGeneric; break;
     957            case  4: pRate->pfnResample = audioMixBufResample4ChGeneric; break;
     958            case  5: pRate->pfnResample = audioMixBufResample5ChGeneric; break;
     959            case  6: pRate->pfnResample = audioMixBufResample6ChGeneric; break;
     960            case  7: pRate->pfnResample = audioMixBufResample7ChGeneric; break;
     961            case  8: pRate->pfnResample = audioMixBufResample8ChGeneric; break;
     962            case  9: pRate->pfnResample = audioMixBufResample9ChGeneric; break;
     963            case 10: pRate->pfnResample = audioMixBufResample10ChGeneric; break;
     964            case 11: pRate->pfnResample = audioMixBufResample11ChGeneric; break;
     965            case 12: pRate->pfnResample = audioMixBufResample12ChGeneric; break;
    682966            default:
    683967                AssertMsgFailedReturn(("resampling %u changes is not implemented yet\n", cChannels), VERR_OUT_OF_RANGE);
     
    9851269
    9861270/**
     1271 * Creates a mapping between desination channels and source source channels.
     1272 *
     1273 * @param   paidxChannelMap     Where to store the mapping.  Indexed by
     1274 *                              destination channel.  Entry is either source
     1275 *                              channel index or -1 for zero and -2 for silence.
     1276 * @param   pSrcProps           The source properties.
     1277 * @param   pDstProps           The desination properties.
     1278 */
     1279static void audioMixBufInitChannelMap(int8_t paidxChannelMap[PDMAUDIO_MAX_CHANNELS],
     1280                                      PCPDMAUDIOPCMPROPS pSrcProps, PCPDMAUDIOPCMPROPS pDstProps)
     1281{
     1282    uintptr_t const cDstChannels = PDMAudioPropsChannels(pDstProps);
     1283    uintptr_t const cSrcChannels = PDMAudioPropsChannels(pSrcProps);
     1284    uintptr_t       idxDst;
     1285    for (idxDst = 0; idxDst < cDstChannels; idxDst++)
     1286    {
     1287        uint8_t const idDstCh = pDstProps->aidChannels[idxDst];
     1288        if (idDstCh >= PDMAUDIOCHANNELID_FRONT_LEFT && idDstCh < PDMAUDIOCHANNELID_END)
     1289        {
     1290            uintptr_t idxSrc;
     1291            for (idxSrc = 0; idxSrc < cSrcChannels; idxSrc++)
     1292                if (idDstCh == pSrcProps->aidChannels[idxSrc])
     1293                {
     1294                    paidxChannelMap[idxDst] = idxSrc;
     1295                    break;
     1296                }
     1297            if (idxSrc >= cSrcChannels)
     1298            {
     1299                /** @todo deal with mono. */
     1300                paidxChannelMap[idxDst] = -2;
     1301            }
     1302        }
     1303        else if (idDstCh == PDMAUDIOCHANNELID_UNKNOWN)
     1304        {
     1305            /** @todo What to do here?  Pick unused source channels in order? */
     1306            paidxChannelMap[idxDst] = -2;
     1307        }
     1308        else
     1309        {
     1310            AssertMsg(idDstCh == PDMAUDIOCHANNELID_UNUSED_SILENCE || idDstCh == PDMAUDIOCHANNELID_UNUSED_ZERO,
     1311                      ("idxDst=%u idDstCh=%u\n", idxDst, idDstCh));
     1312            paidxChannelMap[idxDst] = idDstCh == PDMAUDIOCHANNELID_UNUSED_SILENCE ? -2 : -1;
     1313        }
     1314    }
     1315
     1316    /* Set the remainder to -1 just to be sure their are safe. */
     1317    for (; idxDst < PDMAUDIO_MAX_CHANNELS; idxDst++)
     1318        paidxChannelMap[idxDst] = -1;
     1319}
     1320
     1321
     1322/**
    9871323 * Initializes the peek state, setting up encoder and (if necessary) resampling.
    9881324 *
     
    9981334     * Pick the encoding function first.
    9991335     */
    1000     uint8_t const cSrcCh = PDMAudioPropsChannels(&pMixBuf->Props);
    1001     uint8_t const cDstCh = PDMAudioPropsChannels(pProps);
    1002     pState->cSrcChannels = cSrcCh;
    1003     pState->cDstChannels = cDstCh;
    1004     pState->cbDstFrame   = PDMAudioPropsFrameSize(pProps);
     1336    uint8_t const cbSample = PDMAudioPropsSampleSize(pProps);
     1337    uint8_t const cSrcCh   = PDMAudioPropsChannels(&pMixBuf->Props);
     1338    uint8_t const cDstCh   = PDMAudioPropsChannels(pProps);
     1339    pState->cSrcChannels   = cSrcCh;
     1340    pState->cDstChannels   = cDstCh;
     1341    pState->cbDstFrame     = PDMAudioPropsFrameSize(pProps);
     1342    audioMixBufInitChannelMap(pState->aidxChannelMap, &pMixBuf->Props, pProps);
     1343    AssertReturn(cDstCh > 0 && cDstCh < PDMAUDIO_MAX_CHANNELS, VERR_OUT_OF_RANGE);
     1344    AssertReturn(cSrcCh > 0 && cSrcCh < PDMAUDIO_MAX_CHANNELS, VERR_OUT_OF_RANGE);
     1345
    10051346    if (PDMAudioPropsIsSigned(pProps))
    10061347    {
     1348        /* Assign generic encoder first. */
     1349        switch (cbSample)
     1350        {
     1351            case 1: pState->pfnEncode = audioMixBufEncodeGenericS8; break;
     1352            case 2: pState->pfnEncode = audioMixBufEncodeGenericS16; break;
     1353            case 4: pState->pfnEncode = audioMixBufEncodeGenericS32; break;
     1354            case 8:
     1355                AssertReturn(pProps->fRaw, VERR_DISK_INVALID_FORMAT);
     1356                pState->pfnEncode = audioMixBufEncodeGenericRaw;
     1357                break;
     1358            default:
     1359                AssertMsgFailedReturn(("%u bytes\n", cbSample), VERR_OUT_OF_RANGE);
     1360        }
     1361
     1362        /* Any specializations available? */
    10071363        switch (cDstCh)
    10081364        {
    10091365            case 1:
    1010                 AssertReturn(cSrcCh == 1 || cSrcCh == 2, VERR_OUT_OF_RANGE);
    1011                 switch (PDMAudioPropsSampleSize(pProps))
    1012                 {
    1013                     case 1:
    1014                         pState->pfnEncode = cSrcCh == 1 ? audioMixBufEncode1ChTo1ChS8  : audioMixBufEncode2ChTo1ChS8;
    1015                         break;
    1016                     case 2:
    1017                         pState->pfnEncode = cSrcCh == 1 ? audioMixBufEncode1ChTo1ChS16 : audioMixBufEncode2ChTo1ChS16;
    1018                         break;
    1019                     case 4:
    1020                         pState->pfnEncode = cSrcCh == 1 ? audioMixBufEncode1ChTo1ChS32 : audioMixBufEncode2ChTo1ChS32;
    1021                         break;
    1022                     case 8:
    1023                         AssertReturn(pProps->fRaw, VERR_DISK_INVALID_FORMAT);
    1024                         pState->pfnEncode = cSrcCh == 1 ? audioMixBufEncode1ChTo1ChRaw : audioMixBufEncode2ChTo1ChRaw;
    1025                         break;
    1026                     default:
    1027                         AssertMsgFailedReturn(("%u bytes\n", PDMAudioPropsSampleSize(pProps)), VERR_OUT_OF_RANGE);
    1028                 }
     1366                if (cSrcCh == 1)
     1367                    switch (cbSample)
     1368                    {
     1369                        case 1: pState->pfnEncode = audioMixBufEncode1ChTo1ChS8; break;
     1370                        case 2: pState->pfnEncode = audioMixBufEncode1ChTo1ChS16; break;
     1371                        case 4: pState->pfnEncode = audioMixBufEncode1ChTo1ChS32; break;
     1372                        case 8: pState->pfnEncode = audioMixBufEncode1ChTo1ChRaw; break;
     1373                    }
     1374                else if (cSrcCh == 2)
     1375                    switch (cbSample)
     1376                    {
     1377                        case 1: pState->pfnEncode = audioMixBufEncode2ChTo1ChS8; break;
     1378                        case 2: pState->pfnEncode = audioMixBufEncode2ChTo1ChS16; break;
     1379                        case 4: pState->pfnEncode = audioMixBufEncode2ChTo1ChS32; break;
     1380                        case 8: pState->pfnEncode = audioMixBufEncode2ChTo1ChRaw; break;
     1381                    }
    10291382                break;
     1383
    10301384            case 2:
    1031                 AssertReturn(cSrcCh == 1 || cSrcCh == 2, VERR_OUT_OF_RANGE);
    1032                 switch (PDMAudioPropsSampleSize(pProps))
    1033                 {
    1034                     case 1:
    1035                         pState->pfnEncode = cSrcCh == 1 ? audioMixBufEncode1ChTo2ChS8  : audioMixBufEncode2ChTo2ChS8;
    1036                         break;
    1037                     case 2:
    1038                         pState->pfnEncode = cSrcCh == 1 ? audioMixBufEncode1ChTo2ChS16 : audioMixBufEncode2ChTo2ChS16;
    1039                         break;
    1040                     case 4:
    1041                         pState->pfnEncode = cSrcCh == 1 ? audioMixBufEncode1ChTo2ChS32 : audioMixBufEncode2ChTo2ChS32;
    1042                         break;
    1043                     case 8:
    1044                         AssertReturn(pProps->fRaw, VERR_DISK_INVALID_FORMAT);
    1045                         pState->pfnEncode = cSrcCh == 1 ? audioMixBufEncode1ChTo2ChRaw : audioMixBufEncode2ChTo2ChRaw;
    1046                         break;
    1047                     default:
    1048                         AssertMsgFailedReturn(("%u bytes\n", PDMAudioPropsSampleSize(pProps)), VERR_OUT_OF_RANGE);
    1049                 }
     1385                if (cSrcCh == 1)
     1386                    switch (cbSample)
     1387                    {
     1388                        case 1: pState->pfnEncode = audioMixBufEncode1ChTo2ChS8; break;
     1389                        case 2: pState->pfnEncode = audioMixBufEncode1ChTo2ChS16; break;
     1390                        case 4: pState->pfnEncode = audioMixBufEncode1ChTo2ChS32; break;
     1391                        case 8: pState->pfnEncode = audioMixBufEncode1ChTo2ChRaw; break;
     1392                    }
     1393                else if (cSrcCh == 2)
     1394                    switch (cbSample)
     1395                    {
     1396                        case 1: pState->pfnEncode = audioMixBufEncode2ChTo2ChS8; break;
     1397                        case 2: pState->pfnEncode = audioMixBufEncode2ChTo2ChS16; break;
     1398                        case 4: pState->pfnEncode = audioMixBufEncode2ChTo2ChS32; break;
     1399                        case 8: pState->pfnEncode = audioMixBufEncode2ChTo2ChRaw; break;
     1400                    }
    10501401                break;
     1402        }
     1403    }
     1404    else
     1405    {
     1406        /* Assign generic encoder first. */
     1407        switch (cbSample)
     1408        {
     1409            case 1: pState->pfnEncode = audioMixBufEncodeGenericU8; break;
     1410            case 2: pState->pfnEncode = audioMixBufEncodeGenericU16; break;
     1411            case 4: pState->pfnEncode = audioMixBufEncodeGenericU32; break;
    10511412            default:
    1052                 /* Note: We may have dedicated encoders for a few selected multichannel
    1053                          configurations, and generic ones that encodes channel by channel (i.e.
    1054                          add the mixer channel count, destination frame size, and an array of
    1055                          destination channel frame offsets to the state). */
    1056                 AssertMsgFailedReturn(("from %u to %u channels is not implemented yet\n", cSrcCh, cDstCh), VERR_OUT_OF_RANGE);
     1413                AssertMsgFailedReturn(("%u bytes\n", cbSample), VERR_OUT_OF_RANGE);
    10571414        }
    1058     }
    1059     else
    1060     {
     1415
     1416        /* Any specializations available? */
    10611417        switch (cDstCh)
    10621418        {
    10631419            case 1:
    1064                 AssertReturn(cSrcCh == 1 || cSrcCh == 2, VERR_OUT_OF_RANGE);
    1065                 switch (PDMAudioPropsSampleSize(pProps))
    1066                 {
    1067                     case 1:
    1068                         pState->pfnEncode = cSrcCh == 1 ? audioMixBufEncode1ChTo1ChU8  : audioMixBufEncode2ChTo1ChU8;
    1069                         break;
    1070                     case 2:
    1071                         pState->pfnEncode = cSrcCh == 1 ? audioMixBufEncode1ChTo1ChU16 : audioMixBufEncode2ChTo1ChU16;
    1072                         break;
    1073                     case 4:
    1074                         pState->pfnEncode = cSrcCh == 1 ? audioMixBufEncode1ChTo1ChU32 : audioMixBufEncode2ChTo1ChU32;
    1075                         break;
    1076                     default:
    1077                         AssertMsgFailedReturn(("%u bytes\n", PDMAudioPropsSampleSize(pProps)), VERR_OUT_OF_RANGE);
    1078                 }
     1420                if (cSrcCh == 1)
     1421                    switch (cbSample)
     1422                    {
     1423                        case 1: pState->pfnEncode = audioMixBufEncode1ChTo1ChU8; break;
     1424                        case 2: pState->pfnEncode = audioMixBufEncode1ChTo1ChU16; break;
     1425                        case 4: pState->pfnEncode = audioMixBufEncode1ChTo1ChU32; break;
     1426                    }
     1427                else if (cSrcCh == 2)
     1428                    switch (cbSample)
     1429                    {
     1430                        case 1: pState->pfnEncode = audioMixBufEncode2ChTo1ChU8; break;
     1431                        case 2: pState->pfnEncode = audioMixBufEncode2ChTo1ChU16; break;
     1432                        case 4: pState->pfnEncode = audioMixBufEncode2ChTo1ChU32; break;
     1433                    }
    10791434                break;
     1435
    10801436            case 2:
    1081                 AssertReturn(cSrcCh == 1 || cSrcCh == 2, VERR_OUT_OF_RANGE);
    1082                 switch (PDMAudioPropsSampleSize(pProps))
    1083                 {
    1084                     case 1:
    1085                         pState->pfnEncode = cSrcCh == 1 ? audioMixBufEncode1ChTo2ChU8  : audioMixBufEncode2ChTo2ChU8;
    1086                         break;
    1087                     case 2:
    1088                         pState->pfnEncode = cSrcCh == 1 ? audioMixBufEncode1ChTo2ChU16 : audioMixBufEncode2ChTo2ChU16;
    1089                         break;
    1090                     case 4:
    1091                         pState->pfnEncode = cSrcCh == 1 ? audioMixBufEncode1ChTo2ChU32 : audioMixBufEncode2ChTo2ChU32;
    1092                         break;
    1093                     default:
    1094                         AssertMsgFailedReturn(("%u bytes\n", PDMAudioPropsSampleSize(pProps)), VERR_OUT_OF_RANGE);
    1095                 }
     1437                if (cSrcCh == 1)
     1438                    switch (cbSample)
     1439                    {
     1440                        case 1: pState->pfnEncode = audioMixBufEncode1ChTo2ChU8; break;
     1441                        case 2: pState->pfnEncode = audioMixBufEncode1ChTo2ChU16; break;
     1442                        case 4: pState->pfnEncode = audioMixBufEncode1ChTo2ChU32; break;
     1443                    }
     1444                else if (cSrcCh == 2)
     1445                    switch (cbSample)
     1446                    {
     1447                        case 1: pState->pfnEncode = audioMixBufEncode2ChTo2ChU8; break;
     1448                        case 2: pState->pfnEncode = audioMixBufEncode2ChTo2ChU16; break;
     1449                        case 4: pState->pfnEncode = audioMixBufEncode2ChTo2ChU32; break;
     1450                    }
    10961451                break;
    1097             default:
    1098                 /* Note: We may have dedicated encoders for a few selected multichannel
    1099                          configurations, and generic ones that encodes channel by channel (i.e.
    1100                          add an array of destination channel frame offsets to the state). */
    1101                 AssertMsgFailedReturn(("from %u to %u channels is not implemented yet\n", cSrcCh, cDstCh), VERR_OUT_OF_RANGE);
    11021452        }
    11031453    }
     
    11251475     * Pick the encoding function first.
    11261476     */
    1127     uint8_t const cSrcCh = PDMAudioPropsChannels(pProps);
    1128     uint8_t const cDstCh = PDMAudioPropsChannels(&pMixBuf->Props);
    1129     pState->cSrcChannels = cSrcCh;
    1130     pState->cDstChannels = cDstCh;
    1131     pState->cbSrcFrame   = PDMAudioPropsFrameSize(pProps);
     1477    uint8_t const cbSample = PDMAudioPropsSampleSize(pProps);
     1478    uint8_t const cSrcCh   = PDMAudioPropsChannels(pProps);
     1479    uint8_t const cDstCh   = PDMAudioPropsChannels(&pMixBuf->Props);
     1480    pState->cSrcChannels   = cSrcCh;
     1481    pState->cDstChannels   = cDstCh;
     1482    pState->cbSrcFrame     = PDMAudioPropsFrameSize(pProps);
     1483    audioMixBufInitChannelMap(pState->aidxChannelMap, pProps, &pMixBuf->Props);
     1484
    11321485    if (PDMAudioPropsIsSigned(pProps))
    11331486    {
     1487        /* Assign generic decoders first. */
     1488        switch (cbSample)
     1489        {
     1490            case 1:
     1491                pState->pfnDecode      = audioMixBufDecodeGenericS8;
     1492                pState->pfnDecodeBlend = audioMixBufDecodeGenericS8Blend;
     1493                break;
     1494            case 2:
     1495                pState->pfnDecode      = audioMixBufDecodeGenericS16;
     1496                pState->pfnDecodeBlend = audioMixBufDecodeGenericS16Blend;
     1497                break;
     1498            case 4:
     1499                pState->pfnDecode      = audioMixBufDecodeGenericS32;
     1500                pState->pfnDecodeBlend = audioMixBufDecodeGenericS32Blend;
     1501                break;
     1502            case 8:
     1503                AssertReturn(pProps->fRaw, VERR_DISK_INVALID_FORMAT);
     1504                pState->pfnDecode      = audioMixBufDecodeGenericRaw;
     1505                pState->pfnDecodeBlend = audioMixBufDecodeGenericRawBlend;
     1506                break;
     1507            default:
     1508                AssertMsgFailedReturn(("%u bytes\n", cbSample), VERR_OUT_OF_RANGE);
     1509        }
     1510
     1511        /* Any specializations available? */
    11341512        switch (cDstCh)
    11351513        {
    11361514            case 1:
    1137                 AssertReturn(cSrcCh == 1 || cSrcCh == 2, VERR_OUT_OF_RANGE);
    1138                 switch (PDMAudioPropsSampleSize(pProps))
    1139                 {
    1140                     case 1:
    1141                         pState->pfnDecode      = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChS8       : audioMixBufDecode2ChTo1ChS8;
    1142                         pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChS8Blend  : audioMixBufDecode2ChTo1ChS8Blend;
    1143                         break;
    1144                     case 2:
    1145                         pState->pfnDecode      = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChS16      : audioMixBufDecode2ChTo1ChS16;
    1146                         pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChS16Blend : audioMixBufDecode2ChTo1ChS16Blend;
    1147                         break;
    1148                     case 4:
    1149                         pState->pfnDecode      = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChS32      : audioMixBufDecode2ChTo1ChS32;
    1150                         pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChS32Blend : audioMixBufDecode2ChTo1ChS32Blend;
    1151                         break;
    1152                     case 8:
    1153                         AssertReturn(pProps->fRaw, VERR_DISK_INVALID_FORMAT);
    1154                         pState->pfnDecode      = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChRaw      : audioMixBufDecode2ChTo1ChRaw;
    1155                         pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChRawBlend : audioMixBufDecode2ChTo1ChRawBlend;
    1156                         break;
    1157                     default:
    1158                         AssertMsgFailedReturn(("%u bytes\n", PDMAudioPropsSampleSize(pProps)), VERR_OUT_OF_RANGE);
    1159                 }
     1515                if (cSrcCh == 1)
     1516                    switch (cbSample)
     1517                    {
     1518                        case 1:
     1519                            pState->pfnDecode      = audioMixBufDecode1ChTo1ChS8;
     1520                            pState->pfnDecodeBlend = audioMixBufDecode1ChTo1ChS8Blend;
     1521                            break;
     1522                        case 2:
     1523                            pState->pfnDecode      = audioMixBufDecode1ChTo1ChS16;
     1524                            pState->pfnDecodeBlend = audioMixBufDecode1ChTo1ChS16Blend;
     1525                            break;
     1526                        case 4:
     1527                            pState->pfnDecode      = audioMixBufDecode1ChTo1ChS32;
     1528                            pState->pfnDecodeBlend = audioMixBufDecode1ChTo1ChS32Blend;
     1529                            break;
     1530                        case 8:
     1531                            pState->pfnDecode      = audioMixBufDecode1ChTo1ChRaw;
     1532                            pState->pfnDecodeBlend = audioMixBufDecode1ChTo1ChRawBlend;
     1533                            break;
     1534                    }
     1535                else if (cSrcCh == 2)
     1536                    switch (cbSample)
     1537                    {
     1538                        case 1:
     1539                            pState->pfnDecode      = audioMixBufDecode2ChTo1ChS8;
     1540                            pState->pfnDecodeBlend = audioMixBufDecode2ChTo1ChS8Blend;
     1541                            break;
     1542                        case 2:
     1543                            pState->pfnDecode      = audioMixBufDecode2ChTo1ChS16;
     1544                            pState->pfnDecodeBlend = audioMixBufDecode2ChTo1ChS16Blend;
     1545                            break;
     1546                        case 4:
     1547                            pState->pfnDecode      = audioMixBufDecode2ChTo1ChS32;
     1548                            pState->pfnDecodeBlend = audioMixBufDecode2ChTo1ChS32Blend;
     1549                            break;
     1550                        case 8:
     1551                            pState->pfnDecode      = audioMixBufDecode2ChTo1ChRaw;
     1552                            pState->pfnDecodeBlend = audioMixBufDecode2ChTo1ChRawBlend;
     1553                            break;
     1554                    }
     1555                break;
     1556
     1557            case 2:
     1558                if (cSrcCh == 1)
     1559                    switch (cbSample)
     1560                    {
     1561                        case 1:
     1562                            pState->pfnDecode      = audioMixBufDecode1ChTo2ChS8;
     1563                            pState->pfnDecodeBlend = audioMixBufDecode1ChTo2ChS8Blend;
     1564                            break;
     1565                        case 2:
     1566                            pState->pfnDecode      = audioMixBufDecode1ChTo2ChS16;
     1567                            pState->pfnDecodeBlend = audioMixBufDecode1ChTo2ChS16Blend;
     1568                            break;
     1569                        case 4:
     1570                            pState->pfnDecode      = audioMixBufDecode1ChTo2ChS32;
     1571                            pState->pfnDecodeBlend = audioMixBufDecode1ChTo2ChS32Blend;
     1572                            break;
     1573                        case 8:
     1574                            pState->pfnDecode      = audioMixBufDecode1ChTo2ChRaw;
     1575                            pState->pfnDecodeBlend = audioMixBufDecode1ChTo2ChRawBlend;
     1576                            break;
     1577                    }
     1578                else if (cSrcCh == 2)
     1579                    switch (cbSample)
     1580                    {
     1581                        case 1:
     1582                            pState->pfnDecode      = audioMixBufDecode2ChTo2ChS8;
     1583                            pState->pfnDecodeBlend = audioMixBufDecode2ChTo2ChS8Blend;
     1584                            break;
     1585                        case 2:
     1586                            pState->pfnDecode      = audioMixBufDecode2ChTo2ChS16;
     1587                            pState->pfnDecodeBlend = audioMixBufDecode2ChTo2ChS16Blend;
     1588                            break;
     1589                        case 4:
     1590                            pState->pfnDecode      = audioMixBufDecode2ChTo2ChS32;
     1591                            pState->pfnDecodeBlend = audioMixBufDecode2ChTo2ChS32Blend;
     1592                            break;
     1593                        case 8:
     1594                            pState->pfnDecode      = audioMixBufDecode2ChTo2ChRaw;
     1595                            pState->pfnDecodeBlend = audioMixBufDecode2ChTo2ChRawBlend;
     1596                            break;
     1597                    }
     1598                break;
     1599        }
     1600    }
     1601    else
     1602    {
     1603        /* Assign generic decoders first. */
     1604        switch (cbSample)
     1605        {
     1606            case 1:
     1607                pState->pfnDecode      = audioMixBufDecodeGenericU8;
     1608                pState->pfnDecodeBlend = audioMixBufDecodeGenericU8Blend;
    11601609                break;
    11611610            case 2:
    1162                 AssertReturn(cSrcCh == 1 || cSrcCh == 2, VERR_OUT_OF_RANGE);
    1163                 switch (PDMAudioPropsSampleSize(pProps))
    1164                 {
    1165                     case 1:
    1166                         pState->pfnDecode      = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChS8       : audioMixBufDecode2ChTo2ChS8;
    1167                         pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChS8Blend  : audioMixBufDecode2ChTo2ChS8Blend;
    1168                         break;
    1169                     case 2:
    1170                         pState->pfnDecode      = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChS16      : audioMixBufDecode2ChTo2ChS16;
    1171                         pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChS16Blend : audioMixBufDecode2ChTo2ChS16Blend;
    1172                         break;
    1173                     case 4:
    1174                         pState->pfnDecode      = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChS32      : audioMixBufDecode2ChTo2ChS32;
    1175                         pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChS32Blend : audioMixBufDecode2ChTo2ChS32Blend;
    1176                         break;
    1177                     case 8:
    1178                         AssertReturn(pProps->fRaw, VERR_DISK_INVALID_FORMAT);
    1179                         pState->pfnDecode      = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChRaw      : audioMixBufDecode2ChTo2ChRaw;
    1180                         pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChRawBlend : audioMixBufDecode2ChTo2ChRawBlend;
    1181                         break;
    1182                     default:
    1183                         AssertMsgFailedReturn(("%u bytes\n", PDMAudioPropsSampleSize(pProps)), VERR_OUT_OF_RANGE);
    1184                 }
     1611                pState->pfnDecode      = audioMixBufDecodeGenericU16;
     1612                pState->pfnDecodeBlend = audioMixBufDecodeGenericU16Blend;
     1613                break;
     1614            case 4:
     1615                pState->pfnDecode      = audioMixBufDecodeGenericU32;
     1616                pState->pfnDecodeBlend = audioMixBufDecodeGenericU32Blend;
    11851617                break;
    11861618            default:
    1187                 /* Note: We may have dedicated encoders for a few selected multichannel
    1188                          configurations, and generic ones that encodes channel by channel (i.e.
    1189                          add the mixer channel count, destination frame size, and an array of
    1190                          destination channel frame offsets to the state). */
    1191                 AssertMsgFailedReturn(("from %u to %u channels is not implemented yet\n", cSrcCh, cDstCh), VERR_OUT_OF_RANGE);
     1619                AssertMsgFailedReturn(("%u bytes\n", cbSample), VERR_OUT_OF_RANGE);
    11921620        }
    1193     }
    1194     else
    1195     {
     1621
     1622        /* Any specializations available? */
    11961623        switch (cDstCh)
    11971624        {
    11981625            case 1:
    1199                 AssertReturn(cSrcCh == 1 || cSrcCh == 2, VERR_OUT_OF_RANGE);
    1200                 switch (PDMAudioPropsSampleSize(pProps))
    1201                 {
    1202                     case 1:
    1203                         pState->pfnDecode      = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChU8       : audioMixBufDecode2ChTo1ChU8;
    1204                         pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChU8Blend  : audioMixBufDecode2ChTo1ChU8Blend;
    1205                         break;
    1206                     case 2:
    1207                         pState->pfnDecode      = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChU16      : audioMixBufDecode2ChTo1ChU16;
    1208                         pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChU16Blend : audioMixBufDecode2ChTo1ChU16Blend;
    1209                         break;
    1210                     case 4:
    1211                         pState->pfnDecode      = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChU32      : audioMixBufDecode2ChTo1ChU32;
    1212                         pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo1ChU32Blend : audioMixBufDecode2ChTo1ChU32Blend;
    1213                         break;
    1214                     default:
    1215                         AssertMsgFailedReturn(("%u bytes\n", PDMAudioPropsSampleSize(pProps)), VERR_OUT_OF_RANGE);
    1216                 }
     1626                if (cSrcCh == 1)
     1627                    switch (cbSample)
     1628                    {
     1629                        case 1:
     1630                            pState->pfnDecode      = audioMixBufDecode1ChTo1ChU8;
     1631                            pState->pfnDecodeBlend = audioMixBufDecode1ChTo1ChU8Blend;
     1632                            break;
     1633                        case 2:
     1634                            pState->pfnDecode      = audioMixBufDecode1ChTo1ChU16;
     1635                            pState->pfnDecodeBlend = audioMixBufDecode1ChTo1ChU16Blend;
     1636                            break;
     1637                        case 4:
     1638                            pState->pfnDecode      = audioMixBufDecode1ChTo1ChU32;
     1639                            pState->pfnDecodeBlend = audioMixBufDecode1ChTo1ChU32Blend;
     1640                            break;
     1641                    }
     1642                else if (cSrcCh == 2)
     1643                    switch (cbSample)
     1644                    {
     1645                        case 1:
     1646                            pState->pfnDecode      = audioMixBufDecode2ChTo1ChU8;
     1647                            pState->pfnDecodeBlend = audioMixBufDecode2ChTo1ChU8Blend;
     1648                            break;
     1649                        case 2:
     1650                            pState->pfnDecode      = audioMixBufDecode2ChTo1ChU16;
     1651                            pState->pfnDecodeBlend = audioMixBufDecode2ChTo1ChU16Blend;
     1652                            break;
     1653                        case 4:
     1654                            pState->pfnDecode      = audioMixBufDecode2ChTo1ChU32;
     1655                            pState->pfnDecodeBlend = audioMixBufDecode2ChTo1ChU32Blend;
     1656                            break;
     1657                    }
    12171658                break;
     1659
    12181660            case 2:
    1219                 AssertReturn(cSrcCh == 1 || cSrcCh == 2, VERR_OUT_OF_RANGE);
    1220                 switch (PDMAudioPropsSampleSize(pProps))
    1221                 {
    1222                     case 1:
    1223                         pState->pfnDecode      = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChU8       : audioMixBufDecode2ChTo2ChU8;
    1224                         pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChU8Blend  : audioMixBufDecode2ChTo2ChU8Blend;
    1225                         break;
    1226                     case 2:
    1227                         pState->pfnDecode      = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChU16      : audioMixBufDecode2ChTo2ChU16;
    1228                         pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChU16Blend : audioMixBufDecode2ChTo2ChU16Blend;
    1229                         break;
    1230                     case 4:
    1231                         pState->pfnDecode      = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChU32      : audioMixBufDecode2ChTo2ChU32;
    1232                         pState->pfnDecodeBlend = cSrcCh == 1 ? audioMixBufDecode1ChTo2ChU32Blend : audioMixBufDecode2ChTo2ChU32Blend;
    1233                         break;
    1234                     default:
    1235                         AssertMsgFailedReturn(("%u bytes\n", PDMAudioPropsSampleSize(pProps)), VERR_OUT_OF_RANGE);
    1236                 }
     1661                if (cSrcCh == 1)
     1662                    switch (cbSample)
     1663                    {
     1664                        case 1:
     1665                            pState->pfnDecode      = audioMixBufDecode1ChTo2ChU8;
     1666                            pState->pfnDecodeBlend = audioMixBufDecode1ChTo2ChU8Blend;
     1667                            break;
     1668                        case 2:
     1669                            pState->pfnDecode      = audioMixBufDecode1ChTo2ChU16;
     1670                            pState->pfnDecodeBlend = audioMixBufDecode1ChTo2ChU16Blend;
     1671                            break;
     1672                        case 4:
     1673                            pState->pfnDecode      = audioMixBufDecode1ChTo2ChU32;
     1674                            pState->pfnDecodeBlend = audioMixBufDecode1ChTo2ChU32Blend;
     1675                            break;
     1676                    }
     1677                else if (cSrcCh == 2)
     1678                    switch (cbSample)
     1679                    {
     1680                        case 1:
     1681                            pState->pfnDecode      = audioMixBufDecode2ChTo2ChU8;
     1682                            pState->pfnDecodeBlend = audioMixBufDecode2ChTo2ChU8Blend;
     1683                            break;
     1684                        case 2:
     1685                            pState->pfnDecode      = audioMixBufDecode2ChTo2ChU16;
     1686                            pState->pfnDecodeBlend = audioMixBufDecode2ChTo2ChU16Blend;
     1687                            break;
     1688                        case 4:
     1689                            pState->pfnDecode      = audioMixBufDecode2ChTo2ChU32;
     1690                            pState->pfnDecodeBlend = audioMixBufDecode2ChTo2ChU32Blend;
     1691                            break;
     1692                    }
    12371693                break;
    1238             default:
    1239                 /* Note: We may have dedicated encoders for a few selected multichannel
    1240                          configurations, and generic ones that encodes channel by channel (i.e.
    1241                          add an array of destination channel frame offsets to the state). */
    1242                 AssertMsgFailedReturn(("from %u to %u channels is not implemented yet\n", cSrcCh, cDstCh), VERR_OUT_OF_RANGE);
    12431694        }
    12441695    }
  • trunk/src/VBox/Devices/Audio/AudioMixBuffer.h

    r89378 r89382  
    105105    /** Destination frame size. */
    106106    uint8_t                     cbDstFrame;
     107    /** The destination frame layout described as indexes into the source frame.
     108     * This ASSUMES that all channels uses the same sample size, so one sample per
     109     * channel if you like.
     110     * Negative values are special: -1 for zero, -2 for silence.
     111     * @note Blending stereo into mono is not really expressible here. */
     112    int8_t                      aidxChannelMap[PDMAUDIO_MAX_CHANNELS];
    107113} AUDIOMIXBUFPEEKSTATE;
    108114/** Pointer to peek state & config. */
     
    128134    /** Source frame size. */
    129135    uint8_t                     cbSrcFrame;
     136    /** The destination frame layout described as indexes into the source frame.
     137     * This ASSUMES that all channels uses the same sample size, so one sample per
     138     * channel if you like.
     139     * Negative values are special: -1 for zero, -2 for silence.
     140     * @note Blending stereo into mono is not really expressible here. */
     141    int8_t                      aidxChannelMap[PDMAUDIO_MAX_CHANNELS];
    130142} AUDIOMIXBUFWRITESTATE;
    131143/** Pointer to write state & config. */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette