AudioMixBuffer.cpp revision 53aa5f00ecfc2d0e5ac355bc452b30cc1202c676
48N/A * available from http://www.virtualbox.org. This file is free software;
48N/A#ifdef DEBUG_DUMP_PCM_DATA
48N/A# define LOG_ENABLED
48N/A#include "AudioMixBuffer.h"
48N/A# define AUDMIXBUF_LOG(x) do {} while (0)
70N/Atypedef struct AUDMIXBUF_CONVOPTS
#ifdef TESTCASE
# define AUDMIXBUF_MACRO_FN
# define AUDMIXBUF_MACRO_FN static inline
#ifdef DEBUG
typedef uint32_t (AUDMIXBUF_FN_CONVFROM) (PPDMAUDIOSAMPLE paDst, const void *pvSrc, size_t cbSrc, const PAUDMIXBUF_CONVOPTS pOpts);
typedef void (AUDMIXBUF_FN_CONVTO) (void *pvDst, const PPDMAUDIOSAMPLE paSrc, const PAUDMIXBUF_CONVOPTS pOpts);
int rc;
if (!cSamplesToRead)
*pcSamplesRead = 0;
return VINF_SUCCESS;
return rc;
offClear = 0;
if (cLeft)
if (!pMixBuf)
return cFree;
if (!cbSamples)
return VERR_INVALID_PARAMETER;
return VERR_NO_MEMORY;
return VINF_SUCCESS;
#ifdef DEBUG_MACROS
# define AUDMIXBUF_MACRO_LOG(x) do {} while (0)
if (_aSigned) \
return _aMax; \
return _aMin; \
if (_aSigned) \
AUDMIXBUF_MACRO_FN uint32_t audioMixBufConvFrom##_aName##Stereo(PPDMAUDIOSAMPLE paDst, const void *pvSrc, size_t cbSrc, \
paDst->u64LSample = (ASMMult2xS32RetS64(audioMixBufClipFrom##_aName(*pSrc++), pOpts->Volume.uLeft ) >> 31); \
paDst->u64RSample = (ASMMult2xS32RetS64(audioMixBufClipFrom##_aName(*pSrc++), pOpts->Volume.uRight) >> 31); \
paDst++; \
return cSamples; \
AUDMIXBUF_MACRO_FN uint32_t audioMixBufConvFrom##_aName##Mono(PPDMAUDIOSAMPLE paDst, const void *pvSrc, size_t cbSrc, \
paDst->u64LSample = ASMMult2xS32RetS64(audioMixBufClipFrom##_aName(pSrc[0]), pOpts->Volume.uLeft); \
pSrc++; \
paDst++; \
return cSamples; \
AUDMIXBUF_MACRO_FN void audioMixBufConvTo##_aName##Stereo(void *pvDst, const PPDMAUDIOSAMPLE paSrc, \
_aType l, r; \
while (cSamples--) \
*pDst++ = l; \
*pDst++ = r; \
pSrc++; \
while (cSamples--) \
pSrc++; \
AUDMIXBUF_CONVERT(S8 /* Name */, int8_t, INT8_MIN /* Min */, INT8_MAX /* Max */, true /* fSigned */, 8 /* cShift */)
AUDMIXBUF_CONVERT(U8 /* Name */, uint8_t, 0 /* Min */, UINT8_MAX /* Max */, false /* fSigned */, 8 /* cShift */)
AUDMIXBUF_CONVERT(S16 /* Name */, int16_t, INT16_MIN /* Min */, INT16_MAX /* Max */, true /* fSigned */, 16 /* cShift */)
AUDMIXBUF_CONVERT(U16 /* Name */, uint16_t, 0 /* Min */, UINT16_MAX /* Max */, false /* fSigned */, 16 /* cShift */)
AUDMIXBUF_CONVERT(S32 /* Name */, int32_t, INT32_MIN /* Min */, INT32_MAX /* Max */, true /* fSigned */, 32 /* cShift */)
AUDMIXBUF_CONVERT(U32 /* Name */, uint32_t, 0 /* Min */, UINT32_MAX /* Max */, false /* fSigned */, 32 /* cShift */)
AUDMIXBUF_MACRO_LOG(("pRate=%p: srcOffset=0x%x (%RU32), dstOffset=0x%x (%RU32), dstInc=0x%x (%RU64)\n", \
if (pcDstWritten) \
if (pcSrcRead) \
AUDMIXBUF_MACRO_LOG(("Start: paDstEnd=%p - paDstStart=%p -> %zu\n", paDstEnd, paDst, paDstEnd - paDstStart)); \
AUDMIXBUF_MACRO_LOG(("Start: paSrcEnd=%p - paSrcStart=%p -> %zu\n", paSrcEnd, paSrc, paSrcEnd - paSrcStart)); \
lDelta = 0; \
lDelta++; \
samOut.u64LSample = (samLast.u64LSample * ((int64_t) UINT32_MAX - iDstOffInt) + samCur.u64LSample * iDstOffInt) >> 32; \
samOut.u64RSample = (samLast.u64RSample * ((int64_t) UINT32_MAX - iDstOffInt) + samCur.u64RSample * iDstOffInt) >> 32; \
paDst++; \
AUDMIXBUF_MACRO_LOG(("\tlDelta=0x%x (%RU64), iDstOffInt=0x%x (%RI64), l=%RI64, r=%RI64 (cur l=%RI64, r=%RI64)\n", \
AUDMIXBUF_MACRO_LOG(("\t\tpRate->dstOffset=0x%x (%RU32)\n", pRate->dstOffset, pRate->dstOffset >> 32)); \
AUDMIXBUF_MACRO_LOG(("End: paDst=%p - paDstStart=%p -> %zu\n", paDst, paDstStart, paDst - paDstStart)); \
AUDMIXBUF_MACRO_LOG(("End: paSrc=%p - paSrcStart=%p -> %zu\n", paSrc, paSrcStart, paSrc - paSrcStart)); \
if (pcDstWritten) \
if (pcSrcRead) \
/* audioMixBufOpAssign: Assigns values from source buffer to destination bufffer, overwriting the destination. */
/* audioMixBufOpBlend: Blends together the values from both, the source and the destination buffer. */
default: return NULL;
default: return NULL;
default: return NULL;
default: return NULL;
return NULL;
default: return NULL;
default: return NULL;
default: return NULL;
default: return NULL;
return NULL;
if (pMixBuf)
int audioMixBufInit(PPDMAUDIOMIXBUF pMixBuf, const char *pszName, PPDMPCMPROPS pProps, uint32_t cSamples)
return VERR_NO_MEMORY;
return VERR_ACCESS_DENIED;
if (!cSamples)
return VERR_NO_MEMORY;
AUDMIXBUF_LOG(("uThisHz=%RU32, uParentHz=%RU32, iFreqRatio=0x%x (%RI64), uRateInc=0x%x (%RU64), cSamples=%RU32 (%RU32 parent)\n",
return rc;
static int audioMixBufMixTo(PPDMAUDIOMIXBUF pDst, PPDMAUDIOMIXBUF pSrc, uint32_t cSamples, uint32_t *pcProcessed)
AUDMIXBUF_LOG(("pSrc=%s (%RU32 samples), pDst=%s (%RU32 samples), cLive=%RU32, cDead=%RU32, cToReadTotal=%RU32, offWrite=%RU32\n",
pSrc->pszName, pSrc->cSamples, pDst->pszName, pDst->cSamples, cLive, cDead, cToReadTotal, offWrite));
while (cToReadTotal)
if (!cToWrite)
AUDMIXBUF_LOG(("\t%RU32Hz -> %RU32Hz\n", AUDMIXBUF_FMT_SAMPLE_FREQ(pSrc->AudioFmt), AUDMIXBUF_FMT_SAMPLE_FREQ(pDst->AudioFmt)));
#ifdef DEBUG
if (pcProcessed)
AUDMIXBUF_LOG(("cReadTotal=%RU32 (pcProcessed), cWrittenTotal=%RU32, cSrcMixed=%RU32, cDstProc=%RU32\n",
return VINF_SUCCESS;
if (pcProcessed)
return rc;
#ifdef DEBUG_DISABLED
int rc;
if (cToProcess)
if (pConv)
if (pcbRead)
return rc;
if (!cbBuf)
return VINF_SUCCESS;
if (!cToRead)
if (pcRead)
*pcRead = 0;
return VINF_SUCCESS;
return VERR_NOT_SUPPORTED;
if (cLenSrc1)
&& cLenSrc2)
#ifdef DEBUG_DUMP_PCM_DATA
if (pcRead)
return rc;
return VERR_BUFFER_OVERFLOW;
if (!pConv)
return VERR_NOT_SUPPORTED;
int rc;
#ifdef DEBUG_DUMP_PCM_DATA
if (cToProcess)
cWritten = 0;
if (pcWritten)
return rc;
if (!cbBuf)
if (pcWritten)
*pcWritten = 0;
return VINF_SUCCESS;
if ( pParent
if (pcWritten)
*pcWritten = 0;
return VINF_SUCCESS;
if (!pConv)
return VERR_NOT_SUPPORTED;
if (cLenDst1)
&& cLenDst2)
cWrittenTotal += pConv(pSamplesDst2, (uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), cbBuf, &convOpts);
#ifdef DEBUG_DUMP_PCM_DATA
if (pcWritten)
return rc;