AudioMixer.cpp revision a3b592bbebcadf0cc7c1b9e295f4f8a032128ef0
/* $Id$ */
/** @file
* VBox audio: Mixing routines, mainly used by the various audio device
* devices LUNs.
*/
/*
* Copyright (C) 2014-2015 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include "AudioMixer.h"
#include "AudioMixBuffer.h"
#include <iprt/asm-math.h>
#ifdef LOG_GROUP
#endif
#define LOG_GROUP LOG_GROUP_DEV_AUDIO
int audioMixerUpdateSinkVolume(PAUDMIXSINK pSink, const PPDMAUDIOVOLUME pVolMaster, const PPDMAUDIOVOLUME pVolSink);
int audioMixerAddSink(PAUDIOMIXER pMixer, const char *pszName, AUDMIXSINKDIR enmDir, PAUDMIXSINK *ppSink)
{
/** ppSink is optional. */
int rc = VINF_SUCCESS;
if (pSink)
{
rc = VERR_NO_MEMORY;
if (RT_SUCCESS(rc))
{
/* Set initial volume to max. */
LogFlowFunc(("pMixer=%p, pSink=%p, cSinks=%RU8\n",
if (ppSink)
}
else
}
else
rc = VERR_NO_MEMORY;
return rc;
}
int audioMixerAddStreamIn(PAUDMIXSINK pSink, PPDMIAUDIOCONNECTOR pConnector, PPDMAUDIOGSTSTRMIN pStream,
{
/** @todo Add flag validation. */
/* ppStream is optional. */
int rc;
return VERR_TOO_MUCH_DATA;
if (pMixStream)
{
/** @todo Process flags. */
LogFlowFunc(("%s: pStream=%p, cStreams=%RU8\n",
if (ppStream)
*ppStream = pMixStream;
rc = VINF_SUCCESS;
}
else
rc = VERR_NO_MEMORY;
return rc;
}
int audioMixerAddStreamOut(PAUDMIXSINK pSink, PPDMIAUDIOCONNECTOR pConnector, PPDMAUDIOGSTSTRMOUT pStream,
{
/** @todo Add flag validation. */
/* ppStream is optional. */
int rc;
return VERR_TOO_MUCH_DATA;
if (pMixStream)
{
/** @todo Process flags. */
LogFlowFunc(("%s: pStream=%p, cStreams=%RU8\n",
if (ppStream)
*ppStream = pMixStream;
rc = VINF_SUCCESS;
}
else
rc = VERR_NO_MEMORY;
return rc;
}
{
return VERR_NOT_IMPLEMENTED;
}
{
/** @todo Add flag validation. */
int rc = VINF_SUCCESS;
if (pMixer)
{
rc = VERR_NO_MEMORY;
if (RT_SUCCESS(rc))
{
}
else
}
else
rc = VERR_NO_MEMORY;
return rc;
}
{
if (pMixer)
{
while (pSink)
{
if (fLast)
break;
}
}
}
{
if (!pSink)
return;
}
{
if (!pStream)
return;
}
{
AssertPtrReturn(pMixer, 0);
return cStreams;
}
{
/* Propagate new master volume to all connected sinks. */
{
}
}
int audioMixerProcessSinkIn(PAUDMIXSINK pSink, AUDMIXOP enmOp, void *pvBuf, uint32_t cbBuf, uint32_t *pcbProcessed)
{
/* pcbProcessed is optional. */
/** @todo Handle mixing operation enmOp! */
if (!pvMixBuf)
return VERR_NO_MEMORY;
int rc = VERR_NOT_FOUND;
uint32_t cbProcessed = 0;
{
/** @todo Support output sinks as well! */
continue;
uint32_t cbTotalRead = 0;
while (cbToRead)
{
if ( RT_FAILURE(rc)
|| !cbRead)
break;
cbTotalRead += cbRead;
}
if (RT_FAILURE(rc))
continue;
}
if (RT_SUCCESS(rc))
{
if (pcbProcessed)
}
return rc;
}
int audioMixerProcessSinkOut(PAUDMIXSINK pSink, AUDMIXOP enmOp, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbProcessed)
{
return VERR_NOT_IMPLEMENTED;
}
{
if (!pSink)
return;
while (pStream)
{
if (fLast)
break;
}
LogFlowFunc(("%s: pSink=%s, cSinks=%RU8\n",
}
{
if (!pStream)
return;
LogFlowFunc(("%s: pStream=%s, cStreams=%RU8\n",
}
{
/** @todo Perform a deep copy, if needed. */
return VINF_SUCCESS;
}
{
/* 0x00..0xff => 0x01..0x100 */
if (u32VolumeLeft)
if (u32VolumeRight)
return volOut;
}
static inline PDMAUDIOVOLUME audioMixerVolMix(const PPDMAUDIOVOLUME pVolMaster, PPDMAUDIOVOLUME pVol)
{
volOut.uLeft = ASMMultU64ByU32DivByU32(pVolMaster->uLeft, pVol->uLeft, 0x80000000U); /* Maximum is 0x80000000U */
volOut.uRight = ASMMultU64ByU32DivByU32(pVolMaster->uRight, pVol->uRight, 0x80000000U); /* Maximum is 0x80000000U */
LogFlowFunc(("pMaster=%p, fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n",
LogFlowFunc(("pVol=%p, fMuted=%RTbool, lVol=%RU32, rVol=%RU32 => fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n",
return volOut;
}
int audioMixerUpdateSinkVolume(PAUDMIXSINK pSink, const PPDMAUDIOVOLUME pVolMaster, const PPDMAUDIOVOLUME pVolSink)
{
LogFlowFunc(("Master fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n",
LogFlowFunc(("%s: fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n",
/** @todo Very crude implementation for now -- needs more work! */
LogFlowFunc(("\t-> fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n",
/* Propagate new sink volume to all streams in the sink. */
{
if (fOut)
else
}
return VINF_SUCCESS;
}
{
LogFlowFunc(("%s: lVol=%RU32, rVol=%RU32 => fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n",
return VINF_SUCCESS;
}
{
LogFlowFunc(("%s: fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n", pSink->pszName, pVol->fMuted, pVol->uLeft, pVol->uRight));
}