15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync/* $Id$ */
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync/** @file
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * Intermedia audio driver, common routines. These are also used
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * in the drivers which are bound to Main, e.g. the VRDE or the
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * video audio recording drivers.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync */
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync/*
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * Copyright (C) 2006-2014 Oracle Corporation
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync *
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * available from http://www.virtualbox.org. This file is free software;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * you can redistribute it and/or modify it under the terms of the GNU
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * General Public License (GPL) as published by the Free Software
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * --------------------------------------------------------------------
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync *
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * This code is based on: audio_template.h from QEMU AUDIO subsystem.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync *
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * QEMU Audio subsystem header
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync *
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * Copyright (c) 2005 Vassili Karpov (malc)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync *
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * Permission is hereby granted, free of charge, to any person obtaining a copy
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * of this software and associated documentation files (the "Software"), to deal
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * in the Software without restriction, including without limitation the rights
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * copies of the Software, and to permit persons to whom the Software is
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * furnished to do so, subject to the following conditions:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync *
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * The above copyright notice and this permission notice shall be included in
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * all copies or substantial portions of the Software.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync *
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * THE SOFTWARE.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync */
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#include <iprt/asm-math.h>
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#include <iprt/assert.h>
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#include <iprt/uuid.h>
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#include <iprt/string.h>
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#include <iprt/alloc.h>
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#include <VBox/vmm/pdmdev.h>
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#include <VBox/vmm/pdm.h>
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#include <VBox/err.h>
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#include <VBox/vmm/mm.h>
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#ifdef LOG_GROUP
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync# undef LOG_GROUP
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#endif
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#define LOG_GROUP LOG_GROUP_DEV_AUDIO
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#include <VBox/log.h>
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#include <ctype.h>
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#include <stdlib.h>
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#include "DrvAudio.h"
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#include "AudioMixBuffer.h"
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsyncbool drvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsyncconst char *drvAudioRecSourceToString(PDMAUDIORECSOURCE enmRecSource)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync{
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync switch (enmRecSource)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync {
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case PDMAUDIORECSOURCE_MIC: return "Microphone In";
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case PDMAUDIORECSOURCE_CD: return "CD";
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case PDMAUDIORECSOURCE_VIDEO: return "Video";
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case PDMAUDIORECSOURCE_AUX: return "AUX";
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case PDMAUDIORECSOURCE_LINE_IN: return "Line In";
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case PDMAUDIORECSOURCE_PHONE: return "Phone";
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync default:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync }
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync AssertMsgFailed(("Bogus recording source %ld\n", enmRecSource));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return "Unknown";
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync}
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsyncconst char *drvAudioHlpFormatToString(PDMAUDIOFMT enmFormat)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync{
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync switch (enmFormat)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync {
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_U8:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return "U8";
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_U16:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return "U16";
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_U32:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return "U32";
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_S8:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return "S8";
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_S16:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return "S16";
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_S32:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return "S32";
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync default:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync }
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync AssertMsgFailed(("Bogus audio format %ld\n", enmFormat));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return "Invalid";
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync}
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsyncPDMAUDIOFMT drvAudioHlpStringToFormat(const char *pszFormat)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync{
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync if (!RTStrICmp(pszFormat, "u8"))
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return AUD_FMT_U8;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync else if (!RTStrICmp(pszFormat, "u16"))
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return AUD_FMT_U16;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync else if (!RTStrICmp(pszFormat, "u32"))
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return AUD_FMT_U32;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync else if (!RTStrICmp(pszFormat, "s8"))
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return AUD_FMT_S8;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync else if (!RTStrICmp(pszFormat, "s16"))
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return AUD_FMT_S16;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync else if (!RTStrICmp(pszFormat, "s32"))
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return AUD_FMT_S32;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync AssertMsgFailed(("Bogus audio format \"%s\"\n", pszFormat));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return AUD_FMT_INVALID;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync}
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync/*********************************** In Stream Functions **********************************************/
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsyncvoid drvAudioGstInFreeRes(PPDMAUDIOGSTSTRMIN pGstStrmIn)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync{
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync AssertPtrReturnVoid(pGstStrmIn);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync if (pGstStrmIn->State.pszName)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync {
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync RTStrFree(pGstStrmIn->State.pszName);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync pGstStrmIn->State.pszName = NULL;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync }
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync audioMixBufDestroy(&pGstStrmIn->MixBuf);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync}
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsyncvoid drvAudioHstInFreeRes(PPDMAUDIOHSTSTRMIN pHstStrmIn)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync{
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync AssertPtrReturnVoid(pHstStrmIn);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync audioMixBufDestroy(&pHstStrmIn->MixBuf);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync}
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsyncvoid drvAudioGstOutFreeRes(PPDMAUDIOGSTSTRMOUT pGstStrmOut)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync{
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync if (!pGstStrmOut)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync if (pGstStrmOut->State.pszName)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync {
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync RTStrFree(pGstStrmOut->State.pszName);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync pGstStrmOut->State.pszName = NULL;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync }
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync audioMixBufDestroy(&pGstStrmOut->MixBuf);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync}
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#if 0
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync/**
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * Finds the minimum number of not yet captured samples of all
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * attached guest input streams for a certain host input stream.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync *
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * @return uint32_t Minimum number of not yet captured samples.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * UINT32_MAX if none found.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * @param pHstStrmIn Host input stream to check for.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync */
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsyncinline uint32_t drvAudioHstInFindMinCaptured(PPDMAUDIOHSTSTRMIN pHstStrmIn)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync{
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync AssertPtrReturn(pHstStrmIn, 0);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync uint32_t cMinSamples = UINT32_MAX;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync PPDMAUDIOGSTSTRMIN pGstStrmIn;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync RTListForEach(&pHstStrmIn->lstGstStrmIn, pGstStrmIn, PDMAUDIOGSTSTRMIN, Node)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync {
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync if (pGstStrmIn->State.fActive)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync cMinSamples = RT_MIN(cMinSamples, audioMixBufMixed(&pGstStrmIn->MixBuf));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync }
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#ifdef DEBUG_andy
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync LogFlowFunc(("cMinSamples=%RU32\n", cMinSamples));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#endif
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return cMinSamples;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync}
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsyncuint32_t drvAudioHstInGetFree(PPDMAUDIOHSTSTRMIN pHstStrmIn)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync{
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync AssertPtrReturn(pHstStrmIn, 0);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return audioMixBufSize(&pHstStrmIn->MixBuf) - drvAudioHstInGetLive(pHstStrmIn);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync}
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsyncuint32_t drvAudioHstInGetLive(PPDMAUDIOHSTSTRMIN pHstStrmIn)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync{
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync AssertPtrReturn(pHstStrmIn, 0);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync uint32_t cMinSamplesCaptured = drvAudioHstInFindMinCaptured(pHstStrmIn);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync uint32_t cSamplesCaptured = audioMixBufMixed(&pHstStrmIn->MixBuf);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync Assert(cSamplesCaptured >= cMinSamplesCaptured);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync uint32_t cSamplesLive = cSamplesCaptured - cMinSamplesCaptured;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync Assert(cSamplesLive <= audioMixBufSize(&pHstStrmIn->MixBuf));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#ifdef DEBUG_andy
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync LogFlowFunc(("cSamplesLive=%RU32\n", cSamplesLive));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#endif
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return cSamplesLive;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync}
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#endif
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsyncvoid drvAudioHstOutFreeRes(PPDMAUDIOHSTSTRMOUT pHstStrmOut)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync{
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync AssertPtrReturnVoid(pHstStrmOut);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync audioMixBufDestroy(&pHstStrmOut->MixBuf);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync}
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#if 0
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync/**
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * Returns the number of live sample data (in bytes) of a certain
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * guest input stream.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync *
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * @return uint32_t Live sample data (in bytes), 0 if none.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * @param pGstStrmIn Guest input stream to check for.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync */
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsyncuint32_t drvAudioGstInGetLiveBytes(PPDMAUDIOGSTSTRMIN pGstStrmIn)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync{
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync AssertPtrReturn(pGstStrmIn, 0);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync AssertPtrReturn(pGstStrmIn->pHstStrmIn, 0);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync Assert(pGstStrmIn->pHstStrmIn->cTotalSamplesCaptured >= pGstStrmIn->cTotalHostSamplesRead);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync uint32_t cSamplesLive = pGstStrmIn->pHstStrmIn->cTotalSamplesCaptured - pGstStrmIn->cTotalHostSamplesRead;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync if (!cSamplesLive)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return 0;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync Assert(cSamplesLive <= pGstStrmIn->pHstStrmIn->cSamples);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync /** @todo Document / refactor this! */
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return (((int64_t) cSamplesLive << 32) / pGstStrmIn->State.uFreqRatio) << pGstStrmIn->Props.cShift;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync}
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync/**
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * Returns the total number of unused sample data (in bytes) of a certain
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * guest output stream.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync *
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * @return uint32_t Number of unused sample data (in bytes), 0 if all used up.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * @param pGstStrmOut Guest output stream to check for.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync */
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsyncuint32_t drvAudioGstOutGetFreeBytes(PPDMAUDIOGSTSTRMOUT pGstStrmOut)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync{
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync AssertPtrReturn(pGstStrmOut, 0);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync Assert(pGstStrmOut->cTotalSamplesWritten <= pGstStrmOut->pHstStrmOut->cSamples);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync uint32_t cSamplesFree = pGstStrmOut->pHstStrmOut->cSamples
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync - pGstStrmOut->cTotalSamplesWritten;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync if (!cSamplesFree)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return 0;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync /** @todo Document / refactor this! */
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return (((int64_t) cSamplesFree << 32) / pGstStrmOut->State.uFreqRatio) << pGstStrmOut->Props.cShift;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync}
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync#endif
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsyncbool drvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync{
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync int cBits = 8;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync bool fSigned = false;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync switch (pCfg->enmFormat)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync {
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_S8:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync fSigned = true;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_U8:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_S16:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync fSigned = true;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_U16:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync cBits = 16;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_S32:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync fSigned = true;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_U32:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync cBits = 32;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync default:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync AssertMsgFailed(("Unknown format %ld\n", pCfg->enmFormat));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync }
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync bool fEqual = pProps->uHz == pCfg->uHz
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync && pProps->cChannels == pCfg->cChannels
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync && pProps->fSigned == fSigned
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync && pProps->cBits == cBits
10258d88c40d8254a2a0d89e9b6c1f3b487f5c2dvboxsync && pProps->fSwapEndian == !(pCfg->enmEndianness == PDMAUDIOHOSTENDIANNESS);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync LogFlowFunc(("fEqual=%RTbool\n", fEqual));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return fEqual;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync}
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsyncint drvAudioStreamCfgToProps(PPDMAUDIOSTREAMCFG pCfg, PPDMPCMPROPS pProps)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync{
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync int rc = VINF_SUCCESS;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync int cBits = 8, cShift = 0;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync bool fSigned = false;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync switch (pCfg->enmFormat)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync {
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_S8:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync fSigned = true;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_U8:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_S16:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync fSigned = true;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_U16:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync cBits = 16;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync cShift = 1;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_S32:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync fSigned = true;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_U32:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync cBits = 32;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync cShift = 2;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync default:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync AssertMsgFailed(("Unknown format %ld\n", pCfg->enmFormat));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync rc = VERR_NOT_SUPPORTED;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync }
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync if (RT_SUCCESS(rc))
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync {
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync pProps->uHz = pCfg->uHz;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync pProps->cBits = cBits;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync pProps->fSigned = fSigned;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync pProps->cChannels = pCfg->cChannels;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync pProps->cShift = (pCfg->cChannels == 2) + cShift;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync pProps->uAlign = (1 << pProps->cShift) - 1;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync pProps->cbPerSec = pProps->uHz << pProps->cShift;
10258d88c40d8254a2a0d89e9b6c1f3b487f5c2dvboxsync pProps->fSwapEndian = pCfg->enmEndianness != PDMAUDIOHOSTENDIANNESS;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync }
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
3ab9febd96202da54e2461400fa0b694a28f5707vboxsync#ifdef DEBUG
3ab9febd96202da54e2461400fa0b694a28f5707vboxsync drvAudioStreamCfgPrint(pCfg);
3ab9febd96202da54e2461400fa0b694a28f5707vboxsync#endif
3ab9febd96202da54e2461400fa0b694a28f5707vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync LogFlowFunc(("rc=%Rrc\n", rc));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return rc;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync}
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsyncvoid drvAudioStreamCfgPrint(PPDMAUDIOSTREAMCFG pCfg)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync{
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync LogFlowFunc(("uHz=%RU32, cChannels=%RU8, enmFormat=",
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync pCfg->uHz, pCfg->cChannels));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync switch (pCfg->enmFormat)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync {
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_S8:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync LogFlow(("S8"));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_U8:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync LogFlow(("U8"));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_S16:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync LogFlow(("S16"));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_U16:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync LogFlow(("U16"));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_S32:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync LogFlow(("S32"));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync case AUD_FMT_U32:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync LogFlow(("U32"));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync default:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync LogFlow(("invalid(%d)", pCfg->enmFormat));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync }
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync LogFlow((", endianness="));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync switch (pCfg->enmEndianness)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync {
10258d88c40d8254a2a0d89e9b6c1f3b487f5c2dvboxsync case PDMAUDIOENDIANNESS_LITTLE:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync LogFlow(("little\n"));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
10258d88c40d8254a2a0d89e9b6c1f3b487f5c2dvboxsync case PDMAUDIOENDIANNESS_BIG:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync LogFlow(("big\n"));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync default:
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync LogFlow(("invalid\n"));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync break;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync }
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync}
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync/**
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * Returns the minimum number of live samples already written to all associated
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * guest output streams of a specific host output stream.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync *
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * @return uint32_t Minimum number of total live samples already written to all
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * associated guest output streams, UINT32_MAX if none found.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * @param pHstStrmOut Host output stream to search in.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * @param pcStreamsLive Returns the number of live guest streams associated to
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * this host output stream. Optional.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync */
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsyncstatic uint32_t drvAudioHstOutMinSamplesMixed(PPDMAUDIOHSTSTRMOUT pHstStrmOut, uint32_t *pcStreamsLive)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync{
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync AssertPtrReturn(pHstStrmOut, 0);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync /* pcStreamsLive is optional. */
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync uint32_t cStreamsLive = 0;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync uint32_t cMinSamplesMixed = UINT32_MAX;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync uint32_t cSamples;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync PPDMAUDIOGSTSTRMOUT pGstStrmOut;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync RTListForEach(&pHstStrmOut->lstGstStrmOut, pGstStrmOut, PDMAUDIOGSTSTRMOUT, Node)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync {
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync if ( pGstStrmOut->State.fActive
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync || !pGstStrmOut->State.fEmpty)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync {
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync cSamples = audioMixBufMixed(&pGstStrmOut->MixBuf);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync cMinSamplesMixed = RT_MIN(cMinSamplesMixed, cSamples);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync cStreamsLive++;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync }
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync }
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync if (pcStreamsLive)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync *pcStreamsLive = cStreamsLive;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return cMinSamplesMixed;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync}
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync/**
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * Finds the number of live (guest) samples of a specific host output stream.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync *
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * @return uint32_t Minimum number of live host output samples processed
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * by all connected guest output streams.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * @param pHstStrmOut Host output stream to search in.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync * @param pcStreamsLive Number of associated guest live streams. Optional.
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync */
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsyncuint32_t drvAudioHstOutSamplesLive(PPDMAUDIOHSTSTRMOUT pHstStrmOut, uint32_t *pcStreamsLive)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync{
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync AssertPtrReturn(pHstStrmOut, 0);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync /* pcStreamsLive is optional. */
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync uint32_t cStreamsLive;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync uint32_t cSamplesMin = drvAudioHstOutMinSamplesMixed(pHstStrmOut, &cStreamsLive);
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync if (pcStreamsLive)
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync *pcStreamsLive = cStreamsLive;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync if (cStreamsLive) /* Any live streams at all? */
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync {
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync if ( cSamplesMin == UINT32_MAX
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync || cSamplesMin > audioMixBufSize(&pHstStrmOut->MixBuf))
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync {
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync LogFlowFunc(("Error: cSamplesMin=%RU32\n", cSamplesMin));
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return 0;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync }
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return cSamplesMin;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync }
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync return 0;
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync}
15c5e2945e3abf354a7d822904579c64f7a190c3vboxsync