VirtualBox

Changeset 89395 in vbox for trunk/src/VBox/Devices


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

AudioMixBuffer: Converting AUDMIXBUF_CONVERT into a template file to simplify debugging (can't step macro template code in windbg). bugref:9890

File:
1 copied

Legend:

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

    r89394 r89395  
    11/* $Id$ */
    22/** @file
    3  * Audio mixing buffer for converting reading/writing audio data.
     3 * Audio mixing buffer for converting template.
    44 */
    55
    66/*
    7  * Copyright (C) 2014-2020 Oracle Corporation
     7 * Copyright (C) 2014-2021 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1616 */
    1717
    18 /** @page pg_audio_mix_buffer   Audio Mixer Buffer
    19  *
    20  * @section sec_audio_mix_buffer_volume     Soft Volume Control
    21  *
    22  * The external code supplies an 8-bit volume (attenuation) value in the
    23  * 0 .. 255 range. This represents 0 to -96dB attenuation where an input
    24  * value of 0 corresponds to -96dB and 255 corresponds to 0dB (unchanged).
    25  *
    26  * Each step thus corresponds to 96 / 256 or 0.375dB. Every 6dB (16 steps)
    27  * represents doubling the sample value.
    28  *
    29  * For internal use, the volume control needs to be converted to a 16-bit
    30  * (sort of) exponential value between 1 and 65536. This is used with fixed
    31  * point arithmetic such that 65536 means 1.0 and 1 means 1/65536.
    32  *
    33  * For actual volume calculation, 33.31 fixed point is used. Maximum (or
    34  * unattenuated) volume is represented as 0x40000000; conveniently, this
    35  * value fits into a uint32_t.
    36  *
    37  * To enable fast processing, the maximum volume must be a power of two
    38  * and must not have a sign when converted to int32_t. While 0x80000000
    39  * violates these constraints, 0x40000000 does not.
    40  */
    41 
    42 
    43 /*********************************************************************************************************************************
    44 *   Header Files                                                                                                                 *
    45 *********************************************************************************************************************************/
    46 #define LOG_GROUP LOG_GROUP_AUDIO_MIXER_BUFFER
    47 #if defined(VBOX_AUDIO_MIX_BUFFER_TESTCASE) && !defined(RT_STRICT)
    48 # define RT_STRICT /* Run the testcase with assertions because the main functions doesn't return on invalid input. */
    49 #endif
    50 #include <VBox/log.h>
    51 
    52 #if 0
    53 /*
    54  * AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA enables dumping the raw PCM data
    55  * to a file on the host. Be sure to adjust AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH
    56  * to your needs before using this!
    57  */
    58 # define AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA
    59 # ifdef RT_OS_WINDOWS
    60 #  define AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "c:\\temp\\"
    61 # else
    62 #  define AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "/tmp/"
    63 # endif
    64 /* Warning: Enabling this will generate *huge* logs! */
    65 //# define AUDIOMIXBUF_DEBUG_MACROS
    66 #endif
    67 
    68 #include <iprt/asm-math.h>
    69 #include <iprt/assert.h>
    70 #ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA
    71 # include <iprt/file.h>
    72 #endif
    73 #include <iprt/mem.h>
    74 #include <iprt/string.h> /* For RT_BZERO. */
    75 
    76 #ifdef VBOX_AUDIO_TESTCASE
    77 # define LOG_ENABLED
    78 # include <iprt/stream.h>
    79 #endif
    80 #include <iprt/errcore.h>
    81 #include <VBox/vmm/pdmaudioinline.h>
    82 
    83 #include "AudioMixBuffer.h"
    84 
    85 
    86 /*********************************************************************************************************************************
    87 *   Defined Constants And Macros                                                                                                 *
    88 *********************************************************************************************************************************/
    89 #ifndef VBOX_AUDIO_TESTCASE
    90 # ifdef DEBUG
    91 #  define AUDMIXBUF_LOG(x) LogFlowFunc(x)
    92 #  define AUDMIXBUF_LOG_ENABLED
    93 # else
    94 #  define AUDMIXBUF_LOG(x) do {} while (0)
    95 # endif
    96 #else /* VBOX_AUDIO_TESTCASE */
    97 # define AUDMIXBUF_LOG(x) RTPrintf x
    98 # define AUDMIXBUF_LOG_ENABLED
    99 #endif
    100 
    101 
    102 /** Bit shift for fixed point conversion.
    103  * @sa @ref sec_audio_mix_buffer_volume */
    104 #define AUDIOMIXBUF_VOL_SHIFT       30
    105 
    106 /** Internal representation of 0dB volume (1.0 in fixed point).
    107  * @sa @ref sec_audio_mix_buffer_volume */
    108 #define AUDIOMIXBUF_VOL_0DB         (1 << AUDIOMIXBUF_VOL_SHIFT)
    109 AssertCompile(AUDIOMIXBUF_VOL_0DB <= 0x40000000);   /* Must always hold. */
    110 AssertCompile(AUDIOMIXBUF_VOL_0DB == 0x40000000);   /* For now -- when only attenuation is used. */
    111 
    112 
    113 /*********************************************************************************************************************************
    114 *   Global Variables                                                                                                             *
    115 *********************************************************************************************************************************/
    116 /** Logarithmic/exponential volume conversion table.
    117  * @sa @ref sec_audio_mix_buffer_volume
    118  */
    119 static uint32_t const s_aVolumeConv[256] =
    120 {
    121         1,     1,     1,     1,     1,     1,     1,     1, /*   7 */
    122         1,     2,     2,     2,     2,     2,     2,     2, /*  15 */
    123         2,     2,     2,     2,     2,     3,     3,     3, /*  23 */
    124         3,     3,     3,     3,     4,     4,     4,     4, /*  31 */
    125         4,     4,     5,     5,     5,     5,     5,     6, /*  39 */
    126         6,     6,     6,     7,     7,     7,     8,     8, /*  47 */
    127         8,     9,     9,    10,    10,    10,    11,    11, /*  55 */
    128        12,    12,    13,    13,    14,    15,    15,    16, /*  63 */
    129        17,    17,    18,    19,    20,    21,    22,    23, /*  71 */
    130        24,    25,    26,    27,    28,    29,    31,    32, /*  79 */
    131        33,    35,    36,    38,    40,    41,    43,    45, /*  87 */
    132        47,    49,    52,    54,    56,    59,    61,    64, /*  95 */
    133        67,    70,    73,    76,    79,    83,    87,    91, /* 103 */
    134        95,    99,   103,   108,   112,   117,   123,   128, /* 111 */
    135       134,   140,   146,   152,   159,   166,   173,   181, /* 119 */
    136       189,   197,   206,   215,   225,   235,   245,   256, /* 127 */
    137       267,   279,   292,   304,   318,   332,   347,   362, /* 135 */
    138       378,   395,   412,   431,   450,   470,   490,   512, /* 143 */
    139       535,   558,   583,   609,   636,   664,   693,   724, /* 151 */
    140       756,   790,   825,   861,   899,   939,   981,  1024, /* 159 */
    141      1069,  1117,  1166,  1218,  1272,  1328,  1387,  1448, /* 167 */
    142      1512,  1579,  1649,  1722,  1798,  1878,  1961,  2048, /* 175 */
    143      2139,  2233,  2332,  2435,  2543,  2656,  2774,  2896, /* 183 */
    144      3025,  3158,  3298,  3444,  3597,  3756,  3922,  4096, /* 191 */
    145      4277,  4467,  4664,  4871,  5087,  5312,  5547,  5793, /* 199 */
    146      6049,  6317,  6597,  6889,  7194,  7512,  7845,  8192, /* 207 */
    147      8555,  8933,  9329,  9742, 10173, 10624, 11094, 11585, /* 215 */
    148     12098, 12634, 13193, 13777, 14387, 15024, 15689, 16384, /* 223 */
    149     17109, 17867, 18658, 19484, 20347, 21247, 22188, 23170, /* 231 */
    150     24196, 25268, 26386, 27554, 28774, 30048, 31379, 32768, /* 239 */
    151     34219, 35734, 37316, 38968, 40693, 42495, 44376, 46341, /* 247 */
    152     48393, 50535, 52773, 55109, 57549, 60097, 62757, 65536, /* 255 */
    153 };
    154 
    155 
    156 
    157 #ifdef VBOX_STRICT
    158 # ifdef UNUSED
    159 
    160 /**
    161  * Prints a single mixing buffer.
    162  * Internal helper function for debugging. Do not use directly.
    163  *
    164  * @returns VBox status code.
    165  * @param   pMixBuf                 Mixing buffer to print.
    166  * @param   pszFunc                 Function name to log this for.
    167  * @param   uIdtLvl                 Indention level to use.
    168  */
    169 static void audioMixBufDbgPrintSingle(PAUDIOMIXBUF pMixBuf, const char *pszFunc, uint16_t uIdtLvl)
    170 {
    171     Log(("%s: %*s %s: offRead=%RU32, offWrite=%RU32 -> %RU32/%RU32\n",
    172          pszFunc, uIdtLvl * 4, "",
    173          pMixBuf->pszName, pMixBuf->offRead, pMixBuf->offWrite, pMixBuf->cUsed, pMixBuf->cFrames));
    174 }
    175 
    176 static void audioMixBufDbgPrintInternal(PAUDIOMIXBUF pMixBuf, const char *pszFunc)
    177 {
    178     audioMixBufDbgPrintSingle(pMixBuf, pszFunc, 0 /* iIdtLevel */);
    179 }
    180 
    181 /**
    182  * Validates a single mixing buffer.
    183  *
    184  * @return  @true if the buffer state is valid or @false if not.
    185  * @param   pMixBuf                 Mixing buffer to validate.
    186  */
    187 static bool audioMixBufDbgValidate(PAUDIOMIXBUF pMixBuf)
    188 {
    189     //const uint32_t offReadEnd  = (pMixBuf->offRead + pMixBuf->cUsed) % pMixBuf->cFrames;
    190     //const uint32_t offWriteEnd = (pMixBuf->offWrite + (pMixBuf->cFrames - pMixBuf->cUsed)) % pMixBuf->cFrames;
    191 
    192     bool fValid = true;
    193 
    194     AssertStmt(pMixBuf->offRead  <= pMixBuf->cFrames, fValid = false);
    195     AssertStmt(pMixBuf->offWrite <= pMixBuf->cFrames, fValid = false);
    196     AssertStmt(pMixBuf->cUsed    <= pMixBuf->cFrames, fValid = false);
    197 
    198     if (pMixBuf->offWrite > pMixBuf->offRead)
    199     {
    200         if (pMixBuf->offWrite - pMixBuf->offRead != pMixBuf->cUsed)
    201             fValid = false;
    202     }
    203     else if (pMixBuf->offWrite < pMixBuf->offRead)
    204     {
    205         if (pMixBuf->offWrite + pMixBuf->cFrames - pMixBuf->offRead != pMixBuf->cUsed)
    206             fValid = false;
    207     }
    208 
    209     if (!fValid)
    210     {
    211         audioMixBufDbgPrintInternal(pMixBuf, __FUNCTION__);
    212         AssertFailed();
    213     }
    214 
    215     return fValid;
    216 }
    217 
    218 # endif /* UNUSED */
    219 #endif /* VBOX_STRICT */
    220 
    221 
    222 /**
    223  * Merges @a i32Src into the value stored at @a pi32Dst.
    224  *
    225  * @param   pi32Dst     The value to merge @a i32Src into.
    226  * @param   i32Src      The new value to add.
    227  */
    228 DECL_FORCE_INLINE(void) audioMixBufBlendSample(int32_t *pi32Dst, int32_t i32Src)
    229 {
    230     if (i32Src)
    231     {
    232         int64_t const i32Dst = *pi32Dst;
    233         if (!i32Dst)
    234             *pi32Dst = i32Src;
    235         else
    236             *pi32Dst = (int32_t)(((int64_t)i32Dst + i32Src) / 2);
    237     }
    238 }
    239 
    240 
    241 /**
    242  * Variant of audioMixBufBlendSample that returns the result rather than storing it.
    243  *
    244  * This is used for stereo -> mono.
    245  */
    246 DECL_FORCE_INLINE(int32_t) audioMixBufBlendSampleRet(int32_t i32Sample1, int32_t i32Sample2)
    247 {
    248     if (!i32Sample1)
    249         return i32Sample2;
    250     if (!i32Sample2)
    251         return i32Sample1;
    252     return (int32_t)(((int64_t)i32Sample1 + i32Sample2) / 2);
    253 }
    254 
    255 
    256 /**
    257  * Blends (merges) the source buffer into the destination buffer.
    258  *
    259  * We're taking a very simple approach here, working sample by sample:
    260  *  - if one is silent, use the other one.
    261  *  - otherwise sum and divide by two.
    262  *
    263  * @param   pi32Dst     The destination stream buffer (input and output).
    264  * @param   pi32Src     The source stream buffer.
    265  * @param   cFrames     Number of frames to process.
    266  * @param   cChannels   Number of channels.
    267  */
    268 static void audioMixBufBlendBuffer(int32_t *pi32Dst, int32_t const *pi32Src, uint32_t cFrames, uint8_t cChannels)
    269 {
    270     switch (cChannels)
    271     {
    272         case 2:
    273             while (cFrames-- > 0)
    274             {
    275                 audioMixBufBlendSample(&pi32Dst[0], pi32Src[0]);
    276                 audioMixBufBlendSample(&pi32Dst[1], pi32Src[1]);
    277                 pi32Dst += 2;
    278                 pi32Src += 2;
    279             }
    280             break;
    281 
    282         default:
    283             cFrames *= cChannels;
    284             RT_FALL_THROUGH();
    285         case 1:
    286             while (cFrames-- > 0)
    287             {
    288                 audioMixBufBlendSample(pi32Dst, pi32Src[0]);
    289                 pi32Dst++;
    290                 pi32Src++;
    291             }
    292             break;
    293     }
    294 }
    295 
    296 
    297 #ifdef AUDIOMIXBUF_DEBUG_MACROS
    298 # define AUDMIXBUF_MACRO_LOG(x) AUDMIXBUF_LOG(x)
    299 #elif defined(VBOX_AUDIO_TESTCASE_VERBOSE) /* Warning: VBOX_AUDIO_TESTCASE_VERBOSE will generate huge logs! */
    300 # define AUDMIXBUF_MACRO_LOG(x) RTPrintf x
    301 #else
    302 # define AUDMIXBUF_MACRO_LOG(x) do {} while (0)
    303 #endif
    30418
    30519/**
     
    587301    }
    588302
    589 
    590 /* audioMixBufConvXXXS8: 8-bit, signed. */
    591 AUDMIXBUF_CONVERT(S8 /* Name */,  int8_t,   INT8_MIN  /* Min */, INT8_MAX   /* Max */, true  /* fSigned */, 8  /* cShift */)
    592 /* audioMixBufConvXXXU8: 8-bit, unsigned. */
    593 AUDMIXBUF_CONVERT(U8 /* Name */,  uint8_t,  0         /* Min */, UINT8_MAX  /* Max */, false /* fSigned */, 8  /* cShift */)
    594 /* audioMixBufConvXXXS16: 16-bit, signed. */
    595 AUDMIXBUF_CONVERT(S16 /* Name */, int16_t,  INT16_MIN /* Min */, INT16_MAX  /* Max */, true  /* fSigned */, 16 /* cShift */)
    596 /* audioMixBufConvXXXU16: 16-bit, unsigned. */
    597 AUDMIXBUF_CONVERT(U16 /* Name */, uint16_t, 0         /* Min */, UINT16_MAX /* Max */, false /* fSigned */, 16 /* cShift */)
    598 /* audioMixBufConvXXXS32: 32-bit, signed. */
    599 AUDMIXBUF_CONVERT(S32 /* Name */, int32_t,  INT32_MIN /* Min */, INT32_MAX  /* Max */, true  /* fSigned */, 32 /* cShift */)
    600 /* audioMixBufConvXXXU32: 32-bit, unsigned. */
    601 AUDMIXBUF_CONVERT(U32 /* Name */, uint32_t, 0         /* Min */, UINT32_MAX /* Max */, false /* fSigned */, 32 /* cShift */)
    602 /* audioMixBufConvXXXRaw: 32-bit stored as 64-bit, signed. */
    603 AUDMIXBUF_CONVERT(Raw /* Name */, int64_t,  INT32_MIN /* Min */, INT32_MAX  /* Max */, true  /* fSigned */, 32 /* cShift */)
    604 
    605 #undef AUDMIXBUF_CONVERT
    606 #undef AUDMIXBUF_MACRO_LOG
    607 
    608 
    609 /*
    610  * Resampling core.
    611  */
    612 /** @todo Separate down- and up-sampling, borrow filter code from RDP. */
    613 #define COPY_LAST_FRAME_1CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
    614         (a_pi32Dst)[0] = (a_pi32Src)[0]; \
    615     } while (0)
    616 #define COPY_LAST_FRAME_2CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
    617         (a_pi32Dst)[0] = (a_pi32Src)[0]; \
    618         (a_pi32Dst)[1] = (a_pi32Src)[1]; \
    619     } 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)
    715 
    716 #define INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_iCh) \
    717         (a_pi32Dst)[a_iCh] = ((a_pi32Last)[a_iCh] * a_i64FactorLast + (a_pi32Src)[a_iCh] * a_i64FactorCur) >> 32
    718 #define INTERPOLATE_1CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
    719         INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
    720     } while (0)
    721 #define INTERPOLATE_2CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
    722         INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
    723         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); \
    819     } while (0)
    820 
    821 #define AUDIOMIXBUF_RESAMPLE(a_cChannels, a_Suffix) \
    822     /** @returns Number of destination frames written. */ \
    823     static DECLCALLBACK(uint32_t) \
    824     audioMixBufResample##a_cChannels##Ch##a_Suffix(int32_t *pi32Dst, uint32_t cDstFrames, \
    825                                                    int32_t const *pi32Src, uint32_t cSrcFrames, uint32_t *pcSrcFramesRead, \
    826                                                    PAUDIOSTREAMRATE pRate) \
    827     { \
    828         Log5(("Src: %RU32 L %RU32;  Dst: %RU32 L%RU32; uDstInc=%#RX64\n", \
    829               pRate->offSrc, cSrcFrames, RT_HI_U32(pRate->offDst), cDstFrames, pRate->uDstInc)); \
    830         int32_t * const       pi32DstStart = pi32Dst; \
    831         int32_t const * const pi32SrcStart = pi32Src; \
    832         \
    833         int32_t ai32LastFrame[a_cChannels]; \
    834         COPY_LAST_FRAME_##a_cChannels##CH(ai32LastFrame, pRate->SrcLast.ai32Samples, a_cChannels); \
    835         \
    836         while (cDstFrames > 0 && cSrcFrames > 0) \
    837         { \
    838             int32_t const cSrcNeeded = RT_HI_U32(pRate->offDst) - pRate->offSrc + 1; \
    839             if (cSrcNeeded > 0) \
    840             { \
    841                 if ((uint32_t)cSrcNeeded + 1 < cSrcFrames) \
    842                 { \
    843                     pRate->offSrc += (uint32_t)cSrcNeeded; \
    844                     cSrcFrames    -= (uint32_t)cSrcNeeded; \
    845                     pi32Src       += (uint32_t)cSrcNeeded * a_cChannels; \
    846                     COPY_LAST_FRAME_##a_cChannels##CH(ai32LastFrame, &pi32Src[-a_cChannels], a_cChannels); \
    847                 } \
    848                 else \
    849                 { \
    850                     pi32Src       += cSrcFrames * a_cChannels; \
    851                     pRate->offSrc += cSrcFrames; \
    852                     COPY_LAST_FRAME_##a_cChannels##CH(pRate->SrcLast.ai32Samples, &pi32Src[-a_cChannels], a_cChannels); \
    853                     *pcSrcFramesRead = (pi32Src - pi32SrcStart) / a_cChannels; \
    854                     return (pi32Dst - pi32DstStart) / a_cChannels; \
    855                 } \
    856             } \
    857             \
    858             /* Interpolate. */ \
    859             int64_t const offFactorCur  = pRate->offDst & UINT32_MAX; \
    860             int64_t const offFactorLast = (int64_t)_4G - offFactorCur; \
    861             INTERPOLATE_##a_cChannels##CH(pi32Dst, pi32Src, ai32LastFrame, offFactorCur, offFactorLast, a_cChannels); \
    862             \
    863             /* Advance. */ \
    864             pRate->offDst += pRate->uDstInc; \
    865             pi32Dst       += a_cChannels; \
    866             cDstFrames    -= 1; \
    867         } \
    868         \
    869         COPY_LAST_FRAME_##a_cChannels##CH(pRate->SrcLast.ai32Samples, ai32LastFrame, a_cChannels); \
    870         *pcSrcFramesRead = (pi32Src - pi32SrcStart) / a_cChannels; \
    871         return (pi32Dst - pi32DstStart) / a_cChannels; \
    872     }
    873 
    874 AUDIOMIXBUF_RESAMPLE(1,Generic)
    875 AUDIOMIXBUF_RESAMPLE(2,Generic)
    876 AUDIOMIXBUF_RESAMPLE(3,Generic)
    877 AUDIOMIXBUF_RESAMPLE(4,Generic)
    878 AUDIOMIXBUF_RESAMPLE(5,Generic)
    879 AUDIOMIXBUF_RESAMPLE(6,Generic)
    880 AUDIOMIXBUF_RESAMPLE(7,Generic)
    881 AUDIOMIXBUF_RESAMPLE(8,Generic)
    882 AUDIOMIXBUF_RESAMPLE(9,Generic)
    883 AUDIOMIXBUF_RESAMPLE(10,Generic)
    884 AUDIOMIXBUF_RESAMPLE(11,Generic)
    885 AUDIOMIXBUF_RESAMPLE(12,Generic)
    886 
    887 
    888 /**
    889  * Resets the resampling state unconditionally.
    890  *
    891  * @param   pRate   The state to reset.
    892  */
    893 static void audioMixBufRateResetAlways(PAUDIOSTREAMRATE pRate)
    894 {
    895     pRate->offDst = 0;
    896     pRate->offSrc = 0;
    897     for (uintptr_t i = 0; i < RT_ELEMENTS(pRate->SrcLast.ai32Samples); i++)
    898         pRate->SrcLast.ai32Samples[0] = 0;
    899 }
    900 
    901 
    902 /**
    903  * Resets the resampling state.
    904  *
    905  * @param   pRate   The state to reset.
    906  */
    907 DECLINLINE(void) audioMixBufRateReset(PAUDIOSTREAMRATE pRate)
    908 {
    909     if (pRate->offDst == 0)
    910     { /* likely */ }
    911     else
    912     {
    913         Assert(!pRate->fNoConversionNeeded);
    914         audioMixBufRateResetAlways(pRate);
    915     }
    916 }
    917 
    918 
    919 /**
    920  * Initializes the frame rate converter state.
    921  *
    922  * @returns VBox status code.
    923  * @param   pRate       The state to initialize.
    924  * @param   uSrcHz      The source frame rate.
    925  * @param   uDstHz      The destination frame rate.
    926  * @param   cChannels   The number of channels in a frame.
    927  */
    928 DECLINLINE(int) audioMixBufRateInit(PAUDIOSTREAMRATE pRate, uint32_t uSrcHz, uint32_t uDstHz, uint8_t cChannels)
    929 {
    930     /*
    931      * Do we need to set up frequency conversion?
    932      *
    933      * Some examples to get an idea of what uDstInc holds:
    934      *   44100 to 44100 -> (44100<<32) / 44100 = 0x01'00000000 (4294967296)
    935      *   22050 to 44100 -> (22050<<32) / 44100 = 0x00'80000000 (2147483648)
    936      *   44100 to 22050 -> (44100<<32) / 22050 = 0x02'00000000 (8589934592)
    937      *   44100 to 48000 -> (44100<<32) / 48000 = 0x00'EB333333 (3946001203.2)
    938      *   48000 to 44100 -> (48000<<32) / 44100 = 0x01'16A3B35F (4674794335.7823129251700680272109)
    939      */
    940     audioMixBufRateResetAlways(pRate);
    941     if (uSrcHz == uDstHz)
    942     {
    943         pRate->fNoConversionNeeded = true;
    944         pRate->uDstInc             = RT_BIT_64(32);
    945         pRate->pfnResample         = NULL;
    946     }
    947     else
    948     {
    949         pRate->fNoConversionNeeded = false;
    950         pRate->uDstInc             = ((uint64_t)uSrcHz << 32) / uDstHz;
    951         AssertReturn(uSrcHz != 0, VERR_INVALID_PARAMETER);
    952         switch (cChannels)
    953         {
    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;
    966             default:
    967                 AssertMsgFailedReturn(("resampling %u changes is not implemented yet\n", cChannels), VERR_OUT_OF_RANGE);
    968         }
    969     }
    970     return VINF_SUCCESS;
    971 }
    972 
    973 
    974 /**
    975  * Initializes a mixing buffer.
    976  *
    977  * @returns VBox status code.
    978  * @param   pMixBuf                 Mixing buffer to initialize.
    979  * @param   pszName                 Name of mixing buffer for easier identification. Optional.
    980  * @param   pProps                  PCM audio properties to use for the mixing buffer.
    981  * @param   cFrames                 Maximum number of audio frames the mixing buffer can hold.
    982  */
    983 int AudioMixBufInit(PAUDIOMIXBUF pMixBuf, const char *pszName, PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)
    984 {
    985     AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER);
    986     AssertPtrReturn(pszName, VERR_INVALID_POINTER);
    987     AssertPtrReturn(pProps,  VERR_INVALID_POINTER);
    988     Assert(PDMAudioPropsAreValid(pProps));
    989 
    990     /*
    991      * Initialize all members, setting the volume to max (0dB).
    992      */
    993     pMixBuf->cFrames        = 0;
    994     pMixBuf->pi32Samples    = NULL;
    995     pMixBuf->cChannels      = 0;
    996     pMixBuf->cbFrame        = 0;
    997     pMixBuf->offRead        = 0;
    998     pMixBuf->offWrite       = 0;
    999     pMixBuf->cUsed          = 0;
    1000     pMixBuf->Props          = *pProps;
    1001     pMixBuf->Volume.fMuted  = false;
    1002     pMixBuf->Volume.fAllMax = true;
    1003     for (uintptr_t i = 0; i < RT_ELEMENTS(pMixBuf->Volume.auChannels); i++)
    1004         pMixBuf->Volume.auChannels[i] = AUDIOMIXBUF_VOL_0DB;
    1005 
    1006     int rc;
    1007     uint8_t const cChannels = PDMAudioPropsChannels(pProps);
    1008     if (cChannels >= 1 && cChannels <= PDMAUDIO_MAX_CHANNELS)
    1009     {
    1010         pMixBuf->pszName = RTStrDup(pszName);
    1011         if (pMixBuf->pszName)
    1012         {
    1013             pMixBuf->pi32Samples = (int32_t *)RTMemAllocZ(cFrames * cChannels * sizeof(pMixBuf->pi32Samples[0]));
    1014             if (pMixBuf->pi32Samples)
    1015             {
    1016                 pMixBuf->cFrames    = cFrames;
    1017                 pMixBuf->cChannels  = cChannels;
    1018                 pMixBuf->cbFrame    = cChannels * sizeof(pMixBuf->pi32Samples[0]);
    1019                 pMixBuf->uMagic     = AUDIOMIXBUF_MAGIC;
    1020 #ifdef AUDMIXBUF_LOG_ENABLED
    1021                 char szTmp[PDMAUDIOPROPSTOSTRING_MAX];
    1022                 AUDMIXBUF_LOG(("%s: %s - cFrames=%#x (%d)\n",
    1023                                pMixBuf->pszName, PDMAudioPropsToString(pProps, szTmp, sizeof(szTmp)), cFrames, cFrames));
    1024 #endif
    1025                 return VINF_SUCCESS;
    1026             }
    1027             RTStrFree(pMixBuf->pszName);
    1028             pMixBuf->pszName = NULL;
    1029             rc = VERR_NO_MEMORY;
    1030         }
    1031         else
    1032             rc = VERR_NO_STR_MEMORY;
    1033     }
    1034     else
    1035     {
    1036         LogRelMaxFunc(64, ("cChannels=%d pszName=%s\n", cChannels, pszName));
    1037         rc = VERR_OUT_OF_RANGE;
    1038     }
    1039     pMixBuf->uMagic = AUDIOMIXBUF_MAGIC_DEAD;
    1040     return rc;
    1041 }
    1042 
    1043 /**
    1044  * Terminates (uninitializes) a mixing buffer.
    1045  *
    1046  * @param   pMixBuf     The mixing buffer.  Uninitialized mixer buffers will be
    1047  *                      quietly ignored.  As will NULL.
    1048  */
    1049 void AudioMixBufTerm(PAUDIOMIXBUF pMixBuf)
    1050 {
    1051     if (!pMixBuf)
    1052         return;
    1053 
    1054     /* Ignore calls for an uninitialized (zeroed) or already destroyed instance.  Happens a lot. */
    1055     if (   pMixBuf->uMagic == 0
    1056         || pMixBuf->uMagic == AUDIOMIXBUF_MAGIC_DEAD)
    1057     {
    1058         Assert(!pMixBuf->pszName);
    1059         Assert(!pMixBuf->pi32Samples);
    1060         Assert(!pMixBuf->cFrames);
    1061         return;
    1062     }
    1063 
    1064     Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
    1065     pMixBuf->uMagic = ~AUDIOMIXBUF_MAGIC;
    1066 
    1067     if (pMixBuf->pszName)
    1068     {
    1069         AUDMIXBUF_LOG(("%s\n", pMixBuf->pszName));
    1070 
    1071         RTStrFree(pMixBuf->pszName);
    1072         pMixBuf->pszName = NULL;
    1073     }
    1074 
    1075     if (pMixBuf->pi32Samples)
    1076     {
    1077         Assert(pMixBuf->cFrames);
    1078         RTMemFree(pMixBuf->pi32Samples);
    1079         pMixBuf->pi32Samples = NULL;
    1080     }
    1081 
    1082     pMixBuf->cFrames   = 0;
    1083     pMixBuf->cChannels = 0;
    1084 }
    1085 
    1086 
    1087 /**
    1088  * Drops all the frames in the given mixing buffer
    1089  *
    1090  * This will reset the read and write offsets to zero.
    1091  *
    1092  * @param   pMixBuf     The mixing buffer.  Uninitialized mixer buffers will be
    1093  *                      quietly ignored.
    1094  */
    1095 void AudioMixBufDrop(PAUDIOMIXBUF pMixBuf)
    1096 {
    1097     AssertPtrReturnVoid(pMixBuf);
    1098 
    1099     /* Ignore uninitialized (zeroed) mixer sink buffers (happens with AC'97 during VM construction). */
    1100     if (   pMixBuf->uMagic == 0
    1101         || pMixBuf->uMagic == AUDIOMIXBUF_MAGIC_DEAD)
    1102         return;
    1103 
    1104     AUDMIXBUF_LOG(("%s\n", pMixBuf->pszName));
    1105 
    1106     pMixBuf->offRead  = 0;
    1107     pMixBuf->offWrite = 0;
    1108     pMixBuf->cUsed    = 0;
    1109 }
    1110 
    1111 
    1112 /**
    1113  * Gets the maximum number of audio frames this buffer can hold.
    1114  *
    1115  * @returns Number of frames.
    1116  * @param   pMixBuf     The mixing buffer.
    1117  */
    1118 uint32_t AudioMixBufSize(PCAUDIOMIXBUF pMixBuf)
    1119 {
    1120     AssertPtrReturn(pMixBuf, 0);
    1121     Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
    1122     return pMixBuf->cFrames;
    1123 }
    1124 
    1125 
    1126 /**
    1127  * Gets the maximum number of bytes this buffer can hold.
    1128  *
    1129  * @returns Number of bytes.
    1130  * @param   pMixBuf     The mixing buffer.
    1131  */
    1132 uint32_t AudioMixBufSizeBytes(PCAUDIOMIXBUF pMixBuf)
    1133 {
    1134     AssertPtrReturn(pMixBuf, 0);
    1135     AssertReturn(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC, 0);
    1136     return AUDIOMIXBUF_F2B(pMixBuf, pMixBuf->cFrames);
    1137 }
    1138 
    1139 
    1140 /**
    1141  * Worker for AudioMixBufUsed and AudioMixBufUsedBytes.
    1142  */
    1143 DECLINLINE(uint32_t) audioMixBufUsedInternal(PCAUDIOMIXBUF pMixBuf)
    1144 {
    1145     uint32_t const cFrames = pMixBuf->cFrames;
    1146     uint32_t       cUsed   = pMixBuf->cUsed;
    1147     AssertStmt(cUsed <= cFrames, cUsed = cFrames);
    1148     return cUsed;
    1149 }
    1150 
    1151 
    1152 /**
    1153  * Get the number of used (readable) frames in the buffer.
    1154  *
    1155  * @returns Number of frames.
    1156  * @param   pMixBuf     The mixing buffer.
    1157  */
    1158 uint32_t AudioMixBufUsed(PCAUDIOMIXBUF pMixBuf)
    1159 {
    1160     AssertPtrReturn(pMixBuf, 0);
    1161     Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
    1162     return audioMixBufUsedInternal(pMixBuf);
    1163 }
    1164 
    1165 
    1166 /**
    1167  * Get the number of (readable) bytes in the buffer.
    1168  *
    1169  * @returns Number of bytes.
    1170  * @param   pMixBuf     The mixing buffer.
    1171  */
    1172 uint32_t AudioMixBufUsedBytes(PCAUDIOMIXBUF pMixBuf)
    1173 {
    1174     AssertPtrReturn(pMixBuf, 0);
    1175     Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
    1176     return AUDIOMIXBUF_F2B(pMixBuf, audioMixBufUsedInternal(pMixBuf));
    1177 }
    1178 
    1179 
    1180 /**
    1181  * Worker for AudioMixBufFree and AudioMixBufFreeBytes.
    1182  */
    1183 DECLINLINE(uint32_t) audioMixBufFreeInternal(PCAUDIOMIXBUF pMixBuf)
    1184 {
    1185     uint32_t const cFrames = pMixBuf->cFrames;
    1186     uint32_t       cUsed   = pMixBuf->cUsed;
    1187     AssertStmt(cUsed <= cFrames, cUsed = cFrames);
    1188     uint32_t const cFramesFree = cFrames - cUsed;
    1189 
    1190     AUDMIXBUF_LOG(("%s: %RU32 of %RU32\n", pMixBuf->pszName, cFramesFree, cFrames));
    1191     return cFramesFree;
    1192 }
    1193 
    1194 
    1195 /**
    1196  * Gets the free buffer space in frames.
    1197  *
    1198  * @return  Number of frames.
    1199  * @param   pMixBuf     The mixing buffer.
    1200  */
    1201 uint32_t AudioMixBufFree(PCAUDIOMIXBUF pMixBuf)
    1202 {
    1203     AssertPtrReturn(pMixBuf, 0);
    1204     Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
    1205     return audioMixBufFreeInternal(pMixBuf);
    1206 }
    1207 
    1208 
    1209 /**
    1210  * Gets the free buffer space in bytes.
    1211  *
    1212  * @return  Number of bytes.
    1213  * @param   pMixBuf     The mixing buffer.
    1214  */
    1215 uint32_t AudioMixBufFreeBytes(PCAUDIOMIXBUF pMixBuf)
    1216 {
    1217     AssertPtrReturn(pMixBuf, 0);
    1218     Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
    1219     return AUDIOMIXBUF_F2B(pMixBuf, audioMixBufFreeInternal(pMixBuf));
    1220 }
    1221 
    1222 
    1223 /**
    1224  * Checks if the buffer is empty.
    1225  *
    1226  * @retval  true if empty buffer.
    1227  * @retval  false if not empty and there are frames to be processed.
    1228  * @param   pMixBuf     The mixing buffer.
    1229  */
    1230 bool AudioMixBufIsEmpty(PCAUDIOMIXBUF pMixBuf)
    1231 {
    1232     AssertPtrReturn(pMixBuf, true);
    1233     Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
    1234     return pMixBuf->cUsed == 0;
    1235 }
    1236 
    1237 
    1238 /**
    1239  * Get the current read position.
    1240  *
    1241  * This is for the testcase.
    1242  *
    1243  * @returns Frame number.
    1244  * @param   pMixBuf     The mixing buffer.
    1245  */
    1246 uint32_t AudioMixBufReadPos(PCAUDIOMIXBUF pMixBuf)
    1247 {
    1248     AssertPtrReturn(pMixBuf, 0);
    1249     Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
    1250     return pMixBuf->offRead;
    1251 }
    1252 
    1253 
    1254 /**
    1255  * Gets the current write position.
    1256  *
    1257  * This is for the testcase.
    1258  *
    1259  * @returns Frame number.
    1260  * @param   pMixBuf     The mixing buffer.
    1261  */
    1262 uint32_t AudioMixBufWritePos(PCAUDIOMIXBUF pMixBuf)
    1263 {
    1264     AssertPtrReturn(pMixBuf, 0);
    1265     Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
    1266     return pMixBuf->offWrite;
    1267 }
    1268 
    1269 
    1270 /**
    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  */
    1279 static 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 /**
    1323  * Initializes the peek state, setting up encoder and (if necessary) resampling.
    1324  *
    1325  * @returns VBox status code.
    1326  */
    1327 int AudioMixBufInitPeekState(PCAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFPEEKSTATE pState, PCPDMAUDIOPCMPROPS pProps)
    1328 {
    1329     AssertPtr(pMixBuf);
    1330     AssertPtr(pState);
    1331     AssertPtr(pProps);
    1332 
    1333     /*
    1334      * Pick the encoding function first.
    1335      */
    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 
    1346     if (PDMAudioPropsIsSigned(pProps))
    1347     {
    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? */
    1363         switch (cDstCh)
    1364         {
    1365             case 1:
    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                     }
    1382                 break;
    1383 
    1384             case 2:
    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                     }
    1401                 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;
    1412             default:
    1413                 AssertMsgFailedReturn(("%u bytes\n", cbSample), VERR_OUT_OF_RANGE);
    1414         }
    1415 
    1416         /* Any specializations available? */
    1417         switch (cDstCh)
    1418         {
    1419             case 1:
    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                     }
    1434                 break;
    1435 
    1436             case 2:
    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                     }
    1451                 break;
    1452         }
    1453     }
    1454 
    1455     int rc = audioMixBufRateInit(&pState->Rate, PDMAudioPropsHz(&pMixBuf->Props), PDMAudioPropsHz(pProps), cSrcCh);
    1456     AUDMIXBUF_LOG(("%s: %RU32 Hz to %RU32 Hz => uDstInc=0x%'RX64\n", pMixBuf->pszName, PDMAudioPropsHz(&pMixBuf->Props),
    1457                    PDMAudioPropsHz(pProps), pState->Rate.uDstInc));
    1458     return rc;
    1459 }
    1460 
    1461 
    1462 /**
    1463  * Initializes the write/blend state, setting up decoders and (if necessary)
    1464  * resampling.
    1465  *
    1466  * @returns VBox status code.
    1467  */
    1468 int AudioMixBufInitWriteState(PCAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, PCPDMAUDIOPCMPROPS pProps)
    1469 {
    1470     AssertPtr(pMixBuf);
    1471     AssertPtr(pState);
    1472     AssertPtr(pProps);
    1473 
    1474     /*
    1475      * Pick the encoding function first.
    1476      */
    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 
    1485     if (PDMAudioPropsIsSigned(pProps))
    1486     {
    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? */
    1512         switch (cDstCh)
    1513         {
    1514             case 1:
    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;
    1609                 break;
    1610             case 2:
    1611                 pState->pfnDecode      = audioMixBufDecodeGenericU16;
    1612                 pState->pfnDecodeBlend = audioMixBufDecodeGenericU16Blend;
    1613                 break;
    1614             case 4:
    1615                 pState->pfnDecode      = audioMixBufDecodeGenericU32;
    1616                 pState->pfnDecodeBlend = audioMixBufDecodeGenericU32Blend;
    1617                 break;
    1618             default:
    1619                 AssertMsgFailedReturn(("%u bytes\n", cbSample), VERR_OUT_OF_RANGE);
    1620         }
    1621 
    1622         /* Any specializations available? */
    1623         switch (cDstCh)
    1624         {
    1625             case 1:
    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                     }
    1658                 break;
    1659 
    1660             case 2:
    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                     }
    1693                 break;
    1694         }
    1695     }
    1696 
    1697     int rc = audioMixBufRateInit(&pState->Rate, PDMAudioPropsHz(pProps), PDMAudioPropsHz(&pMixBuf->Props), cDstCh);
    1698     AUDMIXBUF_LOG(("%s: %RU32 Hz to %RU32 Hz => uDstInc=0x%'RX64\n", pMixBuf->pszName, PDMAudioPropsHz(pProps),
    1699                    PDMAudioPropsHz(&pMixBuf->Props), pState->Rate.uDstInc));
    1700     return rc;
    1701 }
    1702 
    1703 
    1704 /**
    1705  * Worker for AudioMixBufPeek that handles the rate conversion case.
    1706  */
    1707 DECL_NO_INLINE(static, void)
    1708 AudioMixBufPeekResampling(PCAUDIOMIXBUF pMixBuf, uint32_t offSrcFrame, uint32_t cMaxSrcFrames, uint32_t *pcSrcFramesPeeked,
    1709                           PAUDIOMIXBUFPEEKSTATE pState, void *pvDst, uint32_t cbDst, uint32_t *pcbDstPeeked)
    1710 {
    1711     *pcSrcFramesPeeked = 0;
    1712     *pcbDstPeeked      = 0;
    1713     while (cMaxSrcFrames > 0 && cbDst >= pState->cbDstFrame)
    1714     {
    1715         /* Rate conversion into temporary buffer. */
    1716         int32_t  ai32DstRate[1024];
    1717         uint32_t cSrcFrames    = RT_MIN(pMixBuf->cFrames - offSrcFrame, cMaxSrcFrames);
    1718         uint32_t cMaxDstFrames = RT_MIN(RT_ELEMENTS(ai32DstRate) / pState->cDstChannels, cbDst / pState->cbDstFrame);
    1719         uint32_t const cDstFrames = pState->Rate.pfnResample(ai32DstRate, cMaxDstFrames,
    1720                                                              &pMixBuf->pi32Samples[offSrcFrame * pMixBuf->cChannels],
    1721                                                              cSrcFrames, &cSrcFrames, &pState->Rate);
    1722         *pcSrcFramesPeeked += cSrcFrames;
    1723         cMaxSrcFrames      -= cSrcFrames;
    1724         offSrcFrame         = (offSrcFrame + cSrcFrames) % pMixBuf->cFrames;
    1725 
    1726         /* Encode the converted frames. */
    1727         uint32_t const cbDstEncoded = cDstFrames * pState->cbDstFrame;
    1728         pState->pfnEncode(pvDst, ai32DstRate, cDstFrames, pState);
    1729         *pcbDstPeeked      += cbDstEncoded;
    1730         cbDst              -= cbDstEncoded;
    1731         pvDst               = (uint8_t *)pvDst + cbDstEncoded;
    1732     }
    1733 }
    1734 
    1735 
    1736 /**
    1737  * Copies data out of the mixing buffer, converting it if needed, but leaves the
    1738  * read offset untouched.
    1739  *
    1740  * @param   pMixBuf             The mixing buffer.
    1741  * @param   offSrcFrame         The offset to start reading at relative to
    1742  *                              current read position (offRead).  The caller has
    1743  *                              made sure there is at least this number of
    1744  *                              frames available in the buffer before calling.
    1745  * @param   cMaxSrcFrames       Maximum number of frames to read.
    1746  * @param   pcSrcFramesPeeked   Where to return the actual number of frames read
    1747  *                              from the mixing buffer.
    1748  * @param   pState              Output configuration & conversion state.
    1749  * @param   pvDst               The destination buffer.
    1750  * @param   cbDst               The size of the destination buffer in bytes.
    1751  * @param   pcbDstPeeked        Where to put the actual number of bytes
    1752  *                              returned.
    1753  */
    1754 void AudioMixBufPeek(PCAUDIOMIXBUF pMixBuf, uint32_t offSrcFrame, uint32_t cMaxSrcFrames, uint32_t *pcSrcFramesPeeked,
    1755                      PAUDIOMIXBUFPEEKSTATE pState, void *pvDst, uint32_t cbDst, uint32_t *pcbDstPeeked)
    1756 {
    1757     /*
    1758      * Check inputs.
    1759      */
    1760     AssertPtr(pMixBuf);
    1761     Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
    1762     AssertPtr(pState);
    1763     AssertPtr(pState->pfnEncode);
    1764     Assert(pState->cSrcChannels == PDMAudioPropsChannels(&pMixBuf->Props));
    1765     Assert(cMaxSrcFrames > 0);
    1766     Assert(cMaxSrcFrames <= pMixBuf->cFrames);
    1767     Assert(offSrcFrame <= pMixBuf->cFrames);
    1768     Assert(offSrcFrame + cMaxSrcFrames <= pMixBuf->cUsed);
    1769     AssertPtr(pcSrcFramesPeeked);
    1770     AssertPtr(pvDst);
    1771     Assert(cbDst >= pState->cbDstFrame);
    1772     AssertPtr(pcbDstPeeked);
    1773 
    1774     /*
    1775      * Make start frame absolute.
    1776      */
    1777     offSrcFrame = (pMixBuf->offRead + offSrcFrame) % pMixBuf->cFrames;
    1778 
    1779     /*
    1780      * Hopefully no sample rate conversion is necessary...
    1781      */
    1782     if (pState->Rate.fNoConversionNeeded)
    1783     {
    1784         /* Figure out how much we should convert. */
    1785         cMaxSrcFrames      = RT_MIN(cMaxSrcFrames, cbDst / pState->cbDstFrame);
    1786         *pcSrcFramesPeeked = cMaxSrcFrames;
    1787         *pcbDstPeeked      = cMaxSrcFrames * pState->cbDstFrame;
    1788 
    1789         /* First chunk. */
    1790         uint32_t const cSrcFrames1 = RT_MIN(pMixBuf->cFrames - offSrcFrame, cMaxSrcFrames);
    1791         pState->pfnEncode(pvDst, &pMixBuf->pi32Samples[offSrcFrame * pMixBuf->cChannels], cSrcFrames1, pState);
    1792 
    1793         /* Another chunk from the start of the mixing buffer? */
    1794         if (cMaxSrcFrames > cSrcFrames1)
    1795             pState->pfnEncode((uint8_t *)pvDst + cSrcFrames1 * pState->cbDstFrame,
    1796                               &pMixBuf->pi32Samples[0], cMaxSrcFrames - cSrcFrames1, pState);
    1797     }
    1798     else
    1799         AudioMixBufPeekResampling(pMixBuf, offSrcFrame, cMaxSrcFrames, pcSrcFramesPeeked, pState, pvDst, cbDst, pcbDstPeeked);
    1800 }
    1801 
    1802 
    1803 /**
    1804  * Worker for AudioMixBufWrite that handles the rate conversion case.
    1805  */
    1806 DECL_NO_INLINE(static, void)
    1807 audioMixBufWriteResampling(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, const void *pvSrcBuf, uint32_t cbSrcBuf,
    1808                            uint32_t offDstFrame, uint32_t cMaxDstFrames, uint32_t *pcDstFramesWritten)
    1809 {
    1810     *pcDstFramesWritten = 0;
    1811     while (cMaxDstFrames > 0 && cbSrcBuf >= pState->cbSrcFrame)
    1812     {
    1813         /* Decode into temporary buffer. */
    1814         int32_t  ai32SrcDecoded[1024];
    1815         uint32_t cFramesDecoded = RT_MIN(RT_ELEMENTS(ai32SrcDecoded) / pState->cSrcChannels, cbSrcBuf / pState->cbSrcFrame);
    1816         pState->pfnDecode(ai32SrcDecoded, pvSrcBuf, cFramesDecoded, pState);
    1817         cbSrcBuf -= cFramesDecoded * pState->cbSrcFrame;
    1818         pvSrcBuf  = (uint8_t const *)pvSrcBuf + cFramesDecoded * pState->cbSrcFrame;
    1819 
    1820         /* Rate convert that into the mixer. */
    1821         uint32_t iFrameDecoded = 0;
    1822         while (iFrameDecoded < cFramesDecoded)
    1823         {
    1824             uint32_t cDstMaxFrames    = RT_MIN(pMixBuf->cFrames - offDstFrame, cMaxDstFrames);
    1825             uint32_t cSrcFrames       = cFramesDecoded - iFrameDecoded;
    1826             uint32_t const cDstFrames = pState->Rate.pfnResample(&pMixBuf->pi32Samples[offDstFrame * pMixBuf->cChannels],
    1827                                                                  cDstMaxFrames,
    1828                                                                  &ai32SrcDecoded[iFrameDecoded * pState->cSrcChannels],
    1829                                                                  cSrcFrames, &cSrcFrames, &pState->Rate);
    1830 
    1831             iFrameDecoded       += cSrcFrames;
    1832             *pcDstFramesWritten += cDstFrames;
    1833             offDstFrame          = (offDstFrame + cDstFrames) % pMixBuf->cFrames;
    1834         }
    1835     }
    1836 
    1837     /** @todo How to squeeze odd frames out of 22050 => 44100 conversion?   */
    1838 }
    1839 
    1840 
    1841 /**
    1842  * Writes @a cbSrcBuf bytes to the mixer buffer starting at @a offDstFrame,
    1843  * converting it as needed, leaving the write offset untouched.
    1844  *
    1845  * @param   pMixBuf             The mixing buffer.
    1846  * @param   pState              Source configuration & conversion state.
    1847  * @param   pvSrcBuf            The source frames.
    1848  * @param   cbSrcBuf            Number of bytes of source frames.  This will be
    1849  *                              convered in full.
    1850  * @param   offDstFrame         Mixing buffer offset relative to the write
    1851  *                              position.
    1852  * @param   cMaxDstFrames       Max number of frames to write.
    1853  * @param   pcDstFramesWritten  Where to return the number of frames actually
    1854  *                              written.
    1855  *
    1856  * @note    Does not advance the write position, please call AudioMixBufCommit()
    1857  *          to do that.
    1858  */
    1859 void AudioMixBufWrite(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, const void *pvSrcBuf, uint32_t cbSrcBuf,
    1860                       uint32_t offDstFrame, uint32_t cMaxDstFrames, uint32_t *pcDstFramesWritten)
    1861 {
    1862     /*
    1863      * Check inputs.
    1864      */
    1865     AssertPtr(pMixBuf);
    1866     Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
    1867     AssertPtr(pState);
    1868     AssertPtr(pState->pfnDecode);
    1869     AssertPtr(pState->pfnDecodeBlend);
    1870     Assert(pState->cDstChannels == PDMAudioPropsChannels(&pMixBuf->Props));
    1871     Assert(cMaxDstFrames > 0);
    1872     Assert(cMaxDstFrames <= pMixBuf->cFrames - pMixBuf->cUsed);
    1873     Assert(offDstFrame <= pMixBuf->cFrames);
    1874     AssertPtr(pvSrcBuf);
    1875     Assert(!(cbSrcBuf % pState->cbSrcFrame));
    1876     AssertPtr(pcDstFramesWritten);
    1877 
    1878     /*
    1879      * Make start frame absolute.
    1880      */
    1881     offDstFrame = (pMixBuf->offWrite + offDstFrame) % pMixBuf->cFrames;
    1882 
    1883     /*
    1884      * Hopefully no sample rate conversion is necessary...
    1885      */
    1886     if (pState->Rate.fNoConversionNeeded)
    1887     {
    1888         /* Figure out how much we should convert. */
    1889         Assert(cMaxDstFrames >= cbSrcBuf / pState->cbSrcFrame);
    1890         cMaxDstFrames       = RT_MIN(cMaxDstFrames, cbSrcBuf / pState->cbSrcFrame);
    1891         *pcDstFramesWritten = cMaxDstFrames;
    1892 
    1893         /* First chunk. */
    1894         uint32_t const cDstFrames1 = RT_MIN(pMixBuf->cFrames - offDstFrame, cMaxDstFrames);
    1895         pState->pfnDecode(&pMixBuf->pi32Samples[offDstFrame * pMixBuf->cChannels], pvSrcBuf, cDstFrames1, pState);
    1896 
    1897         /* Another chunk from the start of the mixing buffer? */
    1898         if (cMaxDstFrames > cDstFrames1)
    1899             pState->pfnDecode(&pMixBuf->pi32Samples[0], (uint8_t *)pvSrcBuf + cDstFrames1 * pState->cbSrcFrame,
    1900                               cMaxDstFrames - cDstFrames1, pState);
    1901     }
    1902     else
    1903         audioMixBufWriteResampling(pMixBuf, pState, pvSrcBuf, cbSrcBuf, offDstFrame, cMaxDstFrames, pcDstFramesWritten);
    1904 }
    1905 
    1906 
    1907 /**
    1908  * Worker for AudioMixBufBlend that handles the rate conversion case.
    1909  */
    1910 DECL_NO_INLINE(static, void)
    1911 audioMixBufBlendResampling(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, const void *pvSrcBuf, uint32_t cbSrcBuf,
    1912                            uint32_t offDstFrame, uint32_t cMaxDstFrames, uint32_t *pcDstFramesBlended)
    1913 {
    1914     *pcDstFramesBlended = 0;
    1915     while (cMaxDstFrames > 0 && cbSrcBuf >= pState->cbSrcFrame)
    1916     {
    1917         /* Decode into temporary buffer. */
    1918         int32_t  ai32SrcDecoded[1024];
    1919         uint32_t cFramesDecoded = RT_MIN(RT_ELEMENTS(ai32SrcDecoded) / pState->cSrcChannels, cbSrcBuf / pState->cbSrcFrame);
    1920         pState->pfnDecode(ai32SrcDecoded, pvSrcBuf, cFramesDecoded, pState);
    1921         cbSrcBuf -= cFramesDecoded * pState->cbSrcFrame;
    1922         pvSrcBuf  = (uint8_t const *)pvSrcBuf + cFramesDecoded * pState->cbSrcFrame;
    1923 
    1924         /* Rate convert that into another temporary buffer and then blend that into the mixer. */
    1925         uint32_t iFrameDecoded = 0;
    1926         while (iFrameDecoded < cFramesDecoded)
    1927         {
    1928             int32_t  ai32SrcRate[1024];
    1929             uint32_t cDstMaxFrames    = RT_MIN(RT_ELEMENTS(ai32SrcRate), cMaxDstFrames);
    1930             uint32_t cSrcFrames       = cFramesDecoded - iFrameDecoded;
    1931             uint32_t const cDstFrames = pState->Rate.pfnResample(&ai32SrcRate[0], cDstMaxFrames,
    1932                                                                  &ai32SrcDecoded[iFrameDecoded * pState->cSrcChannels],
    1933                                                                  cSrcFrames, &cSrcFrames, &pState->Rate);
    1934 
    1935             /* First chunk.*/
    1936             uint32_t const cDstFrames1 = RT_MIN(pMixBuf->cFrames - offDstFrame, cDstFrames);
    1937             audioMixBufBlendBuffer(&pMixBuf->pi32Samples[offDstFrame * pMixBuf->cChannels],
    1938                                    ai32SrcRate, cDstFrames1, pState->cSrcChannels);
    1939 
    1940             /* Another chunk from the start of the mixing buffer? */
    1941             if (cDstFrames > cDstFrames1)
    1942                 audioMixBufBlendBuffer(&pMixBuf->pi32Samples[0], &ai32SrcRate[cDstFrames1 * pState->cSrcChannels],
    1943                                        cDstFrames - cDstFrames1, pState->cSrcChannels);
    1944 
    1945             /* Advance */
    1946             iFrameDecoded       += cSrcFrames;
    1947             *pcDstFramesBlended += cDstFrames;
    1948             offDstFrame          = (offDstFrame + cDstFrames) % pMixBuf->cFrames;
    1949         }
    1950     }
    1951 
    1952     /** @todo How to squeeze odd frames out of 22050 => 44100 conversion?   */
    1953 }
    1954 
    1955 
    1956 /**
    1957  * @todo not sure if 'blend' is the appropriate term here, but you know what
    1958  *       we mean.
    1959  */
    1960 void AudioMixBufBlend(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, const void *pvSrcBuf, uint32_t cbSrcBuf,
    1961                       uint32_t offDstFrame, uint32_t cMaxDstFrames, uint32_t *pcDstFramesBlended)
    1962 {
    1963     /*
    1964      * Check inputs.
    1965      */
    1966     AssertPtr(pMixBuf);
    1967     Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
    1968     AssertPtr(pState);
    1969     AssertPtr(pState->pfnDecode);
    1970     AssertPtr(pState->pfnDecodeBlend);
    1971     Assert(pState->cDstChannels == PDMAudioPropsChannels(&pMixBuf->Props));
    1972     Assert(cMaxDstFrames > 0);
    1973     Assert(cMaxDstFrames <= pMixBuf->cFrames - pMixBuf->cUsed);
    1974     Assert(offDstFrame <= pMixBuf->cFrames);
    1975     AssertPtr(pvSrcBuf);
    1976     Assert(!(cbSrcBuf % pState->cbSrcFrame));
    1977     AssertPtr(pcDstFramesBlended);
    1978 
    1979     /*
    1980      * Make start frame absolute.
    1981      */
    1982     offDstFrame = (pMixBuf->offWrite + offDstFrame) % pMixBuf->cFrames;
    1983 
    1984     /*
    1985      * Hopefully no sample rate conversion is necessary...
    1986      */
    1987     if (pState->Rate.fNoConversionNeeded)
    1988     {
    1989         /* Figure out how much we should convert. */
    1990         Assert(cMaxDstFrames >= cbSrcBuf / pState->cbSrcFrame);
    1991         cMaxDstFrames       = RT_MIN(cMaxDstFrames, cbSrcBuf / pState->cbSrcFrame);
    1992         *pcDstFramesBlended = cMaxDstFrames;
    1993 
    1994         /* First chunk. */
    1995         uint32_t const cDstFrames1 = RT_MIN(pMixBuf->cFrames - offDstFrame, cMaxDstFrames);
    1996         pState->pfnDecodeBlend(&pMixBuf->pi32Samples[offDstFrame * pMixBuf->cChannels], pvSrcBuf, cDstFrames1, pState);
    1997 
    1998         /* Another chunk from the start of the mixing buffer? */
    1999         if (cMaxDstFrames > cDstFrames1)
    2000             pState->pfnDecodeBlend(&pMixBuf->pi32Samples[0], (uint8_t *)pvSrcBuf + cDstFrames1 * pState->cbSrcFrame,
    2001                                    cMaxDstFrames - cDstFrames1, pState);
    2002     }
    2003     else
    2004         audioMixBufBlendResampling(pMixBuf, pState, pvSrcBuf, cbSrcBuf, offDstFrame, cMaxDstFrames, pcDstFramesBlended);
    2005 }
    2006 
    2007 
    2008 /**
    2009  * Writes @a cFrames of silence at @a offFrame relative to current write pos.
    2010  *
    2011  * This will also adjust the resampling state.
    2012  *
    2013  * @param   pMixBuf     The mixing buffer.
    2014  * @param   pState      The write state.
    2015  * @param   offFrame    Where to start writing silence relative to the current
    2016  *                      write position.
    2017  * @param   cFrames     Number of frames of silence.
    2018  * @sa      AudioMixBufWrite
    2019  *
    2020  * @note    Does not advance the write position, please call AudioMixBufCommit()
    2021  *          to do that.
    2022  */
    2023 void AudioMixBufSilence(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, uint32_t offFrame, uint32_t cFrames)
    2024 {
    2025     /*
    2026      * Check inputs.
    2027      */
    2028     AssertPtr(pMixBuf);
    2029     Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
    2030     AssertPtr(pState);
    2031     AssertPtr(pState->pfnDecode);
    2032     AssertPtr(pState->pfnDecodeBlend);
    2033     Assert(pState->cDstChannels == PDMAudioPropsChannels(&pMixBuf->Props));
    2034     Assert(cFrames > 0);
    2035 #ifdef VBOX_STRICT
    2036     uint32_t const cMixBufFree = pMixBuf->cFrames - pMixBuf->cUsed;
    2037 #endif
    2038     Assert(cFrames <= cMixBufFree);
    2039     Assert(offFrame < cMixBufFree);
    2040     Assert(offFrame + cFrames <= cMixBufFree);
    2041 
    2042     /*
    2043      * Make start frame absolute.
    2044      */
    2045     offFrame = (pMixBuf->offWrite + offFrame) % pMixBuf->cFrames;
    2046 
    2047     /*
    2048      * First chunk.
    2049      */
    2050     uint32_t const cFramesChunk1 = RT_MIN(pMixBuf->cFrames - offFrame, cFrames);
    2051     RT_BZERO(&pMixBuf->pi32Samples[offFrame * pMixBuf->cChannels], cFramesChunk1 * pMixBuf->cbFrame);
    2052 
    2053     /*
    2054      * Second chunk, if needed.
    2055      */
    2056     if (cFrames > cFramesChunk1)
    2057     {
    2058         cFrames -= cFramesChunk1;
    2059         AssertStmt(cFrames <= pMixBuf->cFrames, cFrames = pMixBuf->cFrames);
    2060         RT_BZERO(&pMixBuf->pi32Samples[0], cFrames * pMixBuf->cbFrame);
    2061     }
    2062 
    2063     /*
    2064      * Reset the resampling state.
    2065      */
    2066     audioMixBufRateReset(&pState->Rate);
    2067 }
    2068 
    2069 
    2070 /**
    2071  * Records a blending gap (silence) of @a cFrames.
    2072  *
    2073  * This is used to adjust or reset the resampling state so we start from a
    2074  * silence state the next time we need to blend or write using @a pState.
    2075  *
    2076  * @param   pMixBuf     The mixing buffer.
    2077  * @param   pState      The write state.
    2078  * @param   cFrames     Number of frames of silence.
    2079  * @sa      AudioMixBufSilence
    2080  */
    2081 void AudioMixBufBlendGap(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, uint32_t cFrames)
    2082 {
    2083     /*
    2084      * For now we'll just reset the resampling state regardless of how many
    2085      * frames of silence there is.
    2086      */
    2087     audioMixBufRateReset(&pState->Rate);
    2088     RT_NOREF(pMixBuf, cFrames);
    2089 }
    2090 
    2091 
    2092 /**
    2093  * Advances the read position of the buffer.
    2094  *
    2095  * For use after done peeking with AudioMixBufPeek().
    2096  *
    2097  * @param   pMixBuf     The mixing buffer.
    2098  * @param   cFrames     Number of frames to advance.
    2099  * @sa      AudioMixBufCommit
    2100  */
    2101 void AudioMixBufAdvance(PAUDIOMIXBUF pMixBuf, uint32_t cFrames)
    2102 {
    2103     AssertPtrReturnVoid(pMixBuf);
    2104     AssertReturnVoid(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
    2105 
    2106     AssertStmt(cFrames <= pMixBuf->cUsed, cFrames = pMixBuf->cUsed);
    2107     pMixBuf->cUsed   -= cFrames;
    2108     pMixBuf->offRead  = (pMixBuf->offRead + cFrames) % pMixBuf->cFrames;
    2109     LogFlowFunc(("%s: Advanced %u frames: offRead=%u cUsed=%u\n", pMixBuf->pszName, cFrames, pMixBuf->offRead, pMixBuf->cUsed));
    2110 }
    2111 
    2112 
    2113 /**
    2114  * Worker for audioMixAdjustVolume that adjust one contiguous chunk.
    2115  */
    2116 static void audioMixAdjustVolumeWorker(PAUDIOMIXBUF pMixBuf, uint32_t off, uint32_t cFrames)
    2117 {
    2118     int32_t       *pi32Samples = &pMixBuf->pi32Samples[off * pMixBuf->cChannels];
    2119     switch (pMixBuf->cChannels)
    2120     {
    2121         case 1:
    2122         {
    2123             uint32_t const uFactorCh0 = pMixBuf->Volume.auChannels[0];
    2124             while (cFrames-- > 0)
    2125             {
    2126                 *pi32Samples = (int32_t)(ASMMult2xS32RetS64(*pi32Samples, uFactorCh0) >> AUDIOMIXBUF_VOL_SHIFT);
    2127                 pi32Samples++;
    2128             }
    2129             break;
    2130         }
    2131 
    2132         case 2:
    2133         {
    2134             uint32_t const uFactorCh0 = pMixBuf->Volume.auChannels[0];
    2135             uint32_t const uFactorCh1 = pMixBuf->Volume.auChannels[1];
    2136             while (cFrames-- > 0)
    2137             {
    2138                 pi32Samples[0] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[0], uFactorCh0) >> AUDIOMIXBUF_VOL_SHIFT);
    2139                 pi32Samples[1] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[1], uFactorCh1) >> AUDIOMIXBUF_VOL_SHIFT);
    2140                 pi32Samples += 2;
    2141             }
    2142             break;
    2143         }
    2144 
    2145         case 3:
    2146         {
    2147             uint32_t const uFactorCh0 = pMixBuf->Volume.auChannels[0];
    2148             uint32_t const uFactorCh1 = pMixBuf->Volume.auChannels[1];
    2149             uint32_t const uFactorCh2 = pMixBuf->Volume.auChannels[2];
    2150             while (cFrames-- > 0)
    2151             {
    2152                 pi32Samples[0] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[0], uFactorCh0) >> AUDIOMIXBUF_VOL_SHIFT);
    2153                 pi32Samples[1] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[1], uFactorCh1) >> AUDIOMIXBUF_VOL_SHIFT);
    2154                 pi32Samples[2] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[2], uFactorCh2) >> AUDIOMIXBUF_VOL_SHIFT);
    2155                 pi32Samples += 3;
    2156             }
    2157             break;
    2158         }
    2159 
    2160         case 4:
    2161         {
    2162             uint32_t const uFactorCh0 = pMixBuf->Volume.auChannels[0];
    2163             uint32_t const uFactorCh1 = pMixBuf->Volume.auChannels[1];
    2164             uint32_t const uFactorCh2 = pMixBuf->Volume.auChannels[2];
    2165             uint32_t const uFactorCh3 = pMixBuf->Volume.auChannels[3];
    2166             while (cFrames-- > 0)
    2167             {
    2168                 pi32Samples[0] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[0], uFactorCh0) >> AUDIOMIXBUF_VOL_SHIFT);
    2169                 pi32Samples[1] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[1], uFactorCh1) >> AUDIOMIXBUF_VOL_SHIFT);
    2170                 pi32Samples[2] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[2], uFactorCh2) >> AUDIOMIXBUF_VOL_SHIFT);
    2171                 pi32Samples[3] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[3], uFactorCh3) >> AUDIOMIXBUF_VOL_SHIFT);
    2172                 pi32Samples += 4;
    2173             }
    2174             break;
    2175         }
    2176 
    2177         case 5:
    2178         {
    2179             uint32_t const uFactorCh0 = pMixBuf->Volume.auChannels[0];
    2180             uint32_t const uFactorCh1 = pMixBuf->Volume.auChannels[1];
    2181             uint32_t const uFactorCh2 = pMixBuf->Volume.auChannels[2];
    2182             uint32_t const uFactorCh3 = pMixBuf->Volume.auChannels[3];
    2183             uint32_t const uFactorCh4 = pMixBuf->Volume.auChannels[4];
    2184             while (cFrames-- > 0)
    2185             {
    2186                 pi32Samples[0] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[0], uFactorCh0) >> AUDIOMIXBUF_VOL_SHIFT);
    2187                 pi32Samples[1] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[1], uFactorCh1) >> AUDIOMIXBUF_VOL_SHIFT);
    2188                 pi32Samples[2] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[2], uFactorCh2) >> AUDIOMIXBUF_VOL_SHIFT);
    2189                 pi32Samples[3] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[3], uFactorCh3) >> AUDIOMIXBUF_VOL_SHIFT);
    2190                 pi32Samples[4] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[4], uFactorCh4) >> AUDIOMIXBUF_VOL_SHIFT);
    2191                 pi32Samples += 5;
    2192             }
    2193             break;
    2194         }
    2195 
    2196         case 6:
    2197         {
    2198             uint32_t const uFactorCh0 = pMixBuf->Volume.auChannels[0];
    2199             uint32_t const uFactorCh1 = pMixBuf->Volume.auChannels[1];
    2200             uint32_t const uFactorCh2 = pMixBuf->Volume.auChannels[2];
    2201             uint32_t const uFactorCh3 = pMixBuf->Volume.auChannels[3];
    2202             uint32_t const uFactorCh4 = pMixBuf->Volume.auChannels[4];
    2203             uint32_t const uFactorCh5 = pMixBuf->Volume.auChannels[5];
    2204             while (cFrames-- > 0)
    2205             {
    2206                 pi32Samples[0] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[0], uFactorCh0) >> AUDIOMIXBUF_VOL_SHIFT);
    2207                 pi32Samples[1] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[1], uFactorCh1) >> AUDIOMIXBUF_VOL_SHIFT);
    2208                 pi32Samples[2] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[2], uFactorCh2) >> AUDIOMIXBUF_VOL_SHIFT);
    2209                 pi32Samples[3] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[3], uFactorCh3) >> AUDIOMIXBUF_VOL_SHIFT);
    2210                 pi32Samples[4] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[4], uFactorCh4) >> AUDIOMIXBUF_VOL_SHIFT);
    2211                 pi32Samples[5] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[5], uFactorCh5) >> AUDIOMIXBUF_VOL_SHIFT);
    2212                 pi32Samples += 6;
    2213             }
    2214             break;
    2215         }
    2216 
    2217         default:
    2218             while (cFrames-- > 0)
    2219                 for (uint32_t iCh = 0; iCh < pMixBuf->cChannels; iCh++, pi32Samples++)
    2220                     *pi32Samples = ASMMult2xS32RetS64(*pi32Samples, pMixBuf->Volume.auChannels[iCh]) >> AUDIOMIXBUF_VOL_SHIFT;
    2221             break;
    2222     }
    2223 }
    2224 
    2225 
    2226 /**
    2227  * Does volume adjustments for the given stretch of the buffer.
    2228  *
    2229  * @param   pMixBuf     The mixing buffer.
    2230  * @param   offFirst    Where to start (validated).
    2231  * @param   cFrames     How many frames (validated).
    2232  */
    2233 static void audioMixAdjustVolume(PAUDIOMIXBUF pMixBuf, uint32_t offFirst, uint32_t cFrames)
    2234 {
    2235     /* Caller has already validated these, so we don't need to repeat that in non-strict builds. */
    2236     Assert(offFirst < pMixBuf->cFrames);
    2237     Assert(cFrames <= pMixBuf->cFrames);
    2238 
    2239     /*
    2240      * Muted?
    2241      */
    2242     if (pMixBuf->Volume.fMuted)
    2243     {
    2244         /* first chunk */
    2245         uint32_t const cFramesChunk1 = RT_MIN(pMixBuf->cFrames - offFirst, cFrames);
    2246         RT_BZERO(&pMixBuf->pi32Samples[offFirst * pMixBuf->cChannels], pMixBuf->cbFrame * cFramesChunk1);
    2247 
    2248         /* second chunk */
    2249         if (cFramesChunk1 < cFrames)
    2250             RT_BZERO(&pMixBuf->pi32Samples[0], pMixBuf->cbFrame * (cFrames - cFramesChunk1));
    2251     }
    2252     /*
    2253      * Less than max volume?
    2254      */
    2255     else if (!pMixBuf->Volume.fAllMax)
    2256     {
    2257         /* first chunk */
    2258         uint32_t const cFramesChunk1 = RT_MIN(pMixBuf->cFrames - offFirst, cFrames);
    2259         audioMixAdjustVolumeWorker(pMixBuf, offFirst, cFramesChunk1);
    2260 
    2261         /* second chunk */
    2262         if (cFramesChunk1 < cFrames)
    2263             audioMixAdjustVolumeWorker(pMixBuf, 0, cFrames - cFramesChunk1);
    2264     }
    2265 }
    2266 
    2267 
    2268 /**
    2269  * Adjust for volume settings and advances the write position of the buffer.
    2270  *
    2271  * For use after done peeking with AudioMixBufWrite(), AudioMixBufSilence(),
    2272  * AudioMixBufBlend() and AudioMixBufBlendGap().
    2273  *
    2274  * @param   pMixBuf     The mixing buffer.
    2275  * @param   cFrames     Number of frames to advance.
    2276  * @sa      AudioMixBufAdvance, AudioMixBufSetVolume
    2277  */
    2278 void AudioMixBufCommit(PAUDIOMIXBUF pMixBuf, uint32_t cFrames)
    2279 {
    2280     AssertPtrReturnVoid(pMixBuf);
    2281     AssertReturnVoid(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
    2282 
    2283     AssertStmt(cFrames <= pMixBuf->cFrames - pMixBuf->cUsed, cFrames = pMixBuf->cFrames - pMixBuf->cUsed);
    2284 
    2285     audioMixAdjustVolume(pMixBuf, pMixBuf->offWrite, cFrames);
    2286 
    2287     pMixBuf->cUsed   += cFrames;
    2288     pMixBuf->offWrite = (pMixBuf->offWrite + cFrames) % pMixBuf->cFrames;
    2289     LogFlowFunc(("%s: Advanced %u frames: offWrite=%u cUsed=%u\n", pMixBuf->pszName, cFrames, pMixBuf->offWrite, pMixBuf->cUsed));
    2290 }
    2291 
    2292 
    2293 /**
    2294  * Sets the volume.
    2295  *
    2296  * The volume adjustments are applied by AudioMixBufCommit().
    2297  *
    2298  * @param   pMixBuf     Mixing buffer to set volume for.
    2299  * @param   pVol        Pointer to volume structure to set.
    2300  */
    2301 void AudioMixBufSetVolume(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOVOLUME pVol)
    2302 {
    2303     AssertPtrReturnVoid(pMixBuf);
    2304     AssertPtrReturnVoid(pVol);
    2305 
    2306     LogFlowFunc(("%s: lVol=%RU8, rVol=%RU8, fMuted=%RTbool\n", pMixBuf->pszName, pVol->uLeft, pVol->uRight, pVol->fMuted));
    2307 
    2308     /*
    2309      * Convert PDM audio volume to the internal format.
    2310      */
    2311     if (!pVol->fMuted)
    2312     {
    2313         pMixBuf->Volume.fMuted  = false;
    2314 
    2315         AssertCompileSize(pVol->uLeft, sizeof(uint8_t));
    2316         pMixBuf->Volume.auChannels[0] = s_aVolumeConv[pVol->uLeft ] * (AUDIOMIXBUF_VOL_0DB >> 16);
    2317         pMixBuf->Volume.auChannels[1] = s_aVolumeConv[pVol->uRight] * (AUDIOMIXBUF_VOL_0DB >> 16);
    2318         for (uintptr_t i = 2; i < pMixBuf->cChannels; i++)
    2319             pMixBuf->Volume.auChannels[i] = pMixBuf->Volume.auChannels[1];
    2320 
    2321         pMixBuf->Volume.fAllMax = true;
    2322         for (uintptr_t i = 0; i < pMixBuf->cChannels; i++)
    2323             if (pMixBuf->Volume.auChannels[i] != AUDIOMIXBUF_VOL_0DB)
    2324             {
    2325                 pMixBuf->Volume.fAllMax = false;
    2326                 break;
    2327             }
    2328     }
    2329     else
    2330     {
    2331         pMixBuf->Volume.fMuted  = true;
    2332         pMixBuf->Volume.fAllMax = false;
    2333         for (uintptr_t i = 0; i < RT_ELEMENTS(pMixBuf->Volume.auChannels); i++)
    2334             pMixBuf->Volume.auChannels[i] = 0;
    2335     }
    2336 }
    2337 
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