VirtualBox

Changeset 61609 in vbox for trunk


Ignore:
Timestamp:
Jun 9, 2016 10:22:39 AM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
107952
Message:

Audio: Update.

Location:
trunk
Files:
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/pdmaudioifs.h

    r61523 r61609  
    174174     *  mixed together with data of other audio streams. */
    175175    PDMAUDIOSTREAMLAYOUT_INTERLEAVED,
     176    /** Complex layout, which does not fit into the
     177     *  interleaved / non-interleaved layouts. */
     178    PDMAUDIOSTREAMLAYOUT_COMPLEX,
    176179    /** Hack to blow the type up to 32-bit. */
    177180    PDMAUDIOSTREAMLAYOUT_32BIT_HACK = 0x7fffffff
     
    503506} PDMAUDIOSTREAMCTX;
    504507
     508/**
     509 * Structure for keeping audio input stream specifics.
     510 * Do not use directly. Instead, use PDMAUDIOSTREAM.
     511 */
    505512typedef struct PDMAUDIOSTREAMIN
    506513{
    507 
    508514} PDMAUDIOSTREAMIN, *PPDMAUDIOSTREAMIN;
    509515
     516/**
     517 * Structure for keeping audio output stream specifics.
     518 * Do not use directly. Instead, use PDMAUDIOSTREAM.
     519 */
    510520typedef struct PDMAUDIOSTREAMOUT
    511521{
    512 
    513522} PDMAUDIOSTREAMOUT, *PPDMAUDIOSTREAMOUT;
    514523
     
    516525typedef PDMAUDIOSTREAM *PPDMAUDIOSTREAM;
    517526
     527/**
     528 * Structure for maintaining an nput/output audio stream.
     529 */
    518530typedef struct PDMAUDIOSTREAM
    519531{
     
    538550    /** Context of this stream. */
    539551    PDMAUDIOSTREAMCTX      enmCtx;
    540     typedef union
     552    /** Union for input/output specifics. */
     553    union
    541554    {
    542555        PDMAUDIOSTREAMIN   In;
    543556        PDMAUDIOSTREAMOUT  Out;
    544     } InOut;
     557    };
    545558} PDMAUDIOSTREAM, *PPDMAUDIOSTREAM;
    546559
     
    699712
    700713    /**
    701      * Retrieves the status of a specific audio stream.
     714     * Returns the number of readable data (in bytes) of a specific audio input stream.
     715     *
     716     * @returns Number of readable data (in bytes).
     717     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     718     * @param   pStream         Pointer to audio stream.
     719     */
     720    DECLR3CALLBACKMEMBER(uint32_t, pfnStreamGetReadable, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream));
     721
     722    /**
     723     * Returns the number of writable data (in bytes) of a specific audio output stream.
     724     *
     725     * @returns Number of writable data (in bytes).
     726     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     727     * @param   pStream         Pointer to audio stream.
     728     */
     729    DECLR3CALLBACKMEMBER(uint32_t, pfnStreamGetWritable, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream));
     730
     731    /**
     732     * Returns the status of a specific audio stream.
    702733     *
    703734     * @returns Audio stream status
     
    743774
    744775/** PDMIAUDIOCONNECTOR interface ID. */
    745 #define PDMIAUDIOCONNECTOR_IID                  "D1B6465D-E3DD-455B-9E05-FB6D56F7D472"
     776#define PDMIAUDIOCONNECTOR_IID                  "C850CCE0-C5F4-42AB-BFC5-BACB41A8284D"
    746777
    747778
  • trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp

    r61523 r61609  
    191191
    192192/**
    193  * Returns available number of samples for processing.
    194  *
    195  * @return  uint32_t                Number of samples available for reading.
    196  * @param   pMixBuf                 Mixing buffer to return value for.
    197  */
    198 uint32_t AudioMixBufAvail(PPDMAUDIOMIXBUF pMixBuf)
    199 {
    200     AssertPtrReturn(pMixBuf, 0);
    201 
    202     uint32_t cAvail;
    203     if (pMixBuf->pParent) /* Is this a child buffer? */
    204         cAvail = pMixBuf->cMixed;
    205     else
    206         cAvail = pMixBuf->cUsed;
    207 
    208     Assert(cAvail <= pMixBuf->cSamples);
    209     return cAvail;
    210 }
    211 
    212 /**
    213193 * Clears the entire sample buffer.
    214194 *
     
    327307    AssertPtrReturn(pMixBuf, 0);
    328308
    329     uint32_t cSamplesFree;
     309    uint32_t cSamples, cSamplesFree;
    330310    if (pMixBuf->pParent)
    331311    {
     
    334314         * already have been consumed by the parent.
    335315         */
    336         Assert(pMixBuf->cMixed <= pMixBuf->pParent->cSamples);
    337         cSamplesFree = pMixBuf->pParent->cSamples - pMixBuf->cMixed;
     316        cSamples = pMixBuf->pParent->cSamples;
     317
     318        Assert(pMixBuf->cMixed <= cSamples);
     319        cSamplesFree = cSamples - pMixBuf->cMixed;
    338320    }
    339321    else /* As a parent. */
    340322    {
    341         Assert(pMixBuf->cSamples >= pMixBuf->cUsed);
     323        cSamples     = pMixBuf->cSamples;
     324        Assert(cSamples >= pMixBuf->cUsed);
    342325        cSamplesFree = pMixBuf->cSamples - pMixBuf->cUsed;
    343326    }
    344327
    345     AUDMIXBUF_LOG(("%s: cSamplesFree=%RU32\n", pMixBuf->pszName, cSamplesFree));
     328    AUDMIXBUF_LOG(("%s: %RU32 of %RU32\n", pMixBuf->pszName, cSamplesFree, cSamples));
    346329    return cSamplesFree;
    347330}
     
    920903
    921904/**
    922  * Returns the number of audio samples mixed (processed) by
    923  * the parent mixing buffer.
    924  *
    925  * @return  uint32_t                Number of audio samples mixed (processed).
    926  * @param   pMixBuf                 Mixing buffer to return number from.
    927  */
    928 uint32_t AudioMixBufMixed(PPDMAUDIOMIXBUF pMixBuf)
     905 * Returns number of available live samples.
     906 *
     907 * @return  uint32_t                Number of live samples available.
     908 * @param   pMixBuf                 Mixing buffer to return value for.
     909 */
     910uint32_t AudioMixBufLive(PPDMAUDIOMIXBUF pMixBuf)
    929911{
    930912    AssertPtrReturn(pMixBuf, 0);
    931913
    932     AssertMsgReturn(VALID_PTR(pMixBuf->pParent),
    933                               ("Buffer is not linked to a parent buffer\n"),
    934                               0);
    935 
    936     AUDMIXBUF_LOG(("%s: cMixed=%RU32\n", pMixBuf->pszName, pMixBuf->cMixed));
    937     return pMixBuf->cMixed;
     914    uint32_t cSamples, cAvail;
     915    if (pMixBuf->pParent) /* Is this a child buffer? */
     916    {
     917        /* Use the sample count from the parent, as
     918         * pMixBuf->cMixed specifies the sample count
     919         * in parent samples. */
     920        cSamples = pMixBuf->pParent->cSamples;
     921        cAvail   = pMixBuf->cMixed;
     922    }
     923    else
     924    {
     925        cSamples = pMixBuf->cSamples;
     926        cAvail   = pMixBuf->cUsed;
     927    }
     928
     929    Assert(cAvail <= cSamples);
     930    return cAvail;
    938931}
    939932
     
    944937 * @param   pDst                    Destination mixing buffer.
    945938 * @param   pSrc                    Source mixing buffer.
    946  * @param   cSamples                Number of source audio samples to mix.
     939 * @param   cSrcSamples             Number of source audio samples to mix.
    947940 * @param   pcProcessed             Number of audio samples successfully mixed.
    948941 */
    949 static int audioMixBufMixTo(PPDMAUDIOMIXBUF pDst, PPDMAUDIOMIXBUF pSrc, uint32_t cSamples, uint32_t *pcProcessed)
     942static int audioMixBufMixTo(PPDMAUDIOMIXBUF pDst, PPDMAUDIOMIXBUF pSrc, uint32_t cSrcSamples, uint32_t *pcProcessed)
    950943{
    951944    AssertPtrReturn(pDst,  VERR_INVALID_POINTER);
     
    969962    Assert(pSrc->cUsed >= pDst->cMixed);
    970963
    971     uint32_t cSrcAvail  = RT_MIN(cSamples, pSrc->cUsed - pDst->cMixed);
     964    uint32_t cSrcAvail  = RT_MIN(cSrcSamples, pSrc->cUsed - pDst->cMixed);
    972965    uint32_t offSrcRead = pSrc->offRead;
    973966    uint32_t cDstMixed  = pSrc->cMixed;
     
    985978    }
    986979
    987     AUDMIXBUF_LOG(("cSamples=%RU32, cSrcAvail=%RU32 -> cDstAvail=%RU32\n", cSamples,  cSrcAvail, cDstAvail));
     980    AUDMIXBUF_LOG(("cSrcSamples=%RU32, cSrcAvail=%RU32 -> cDstAvail=%RU32\n", cSrcSamples,  cSrcAvail, cDstAvail));
    988981
    989982#ifdef DEBUG
     
    10941087 * @return  IPRT status code.
    10951088 * @param   pMixBuf                 Mixing buffer to mix samples down to parent.
    1096  * @param   cSamples                Number of audio samples to mix down.
     1089 * @param   cSamples                Number of audio samples of specified mixing buffer to to mix
     1090 *                                  to its attached parent mixing buffer (if any).
    10971091 * @param   pcProcessed             Number of audio samples successfully processed. Optional.
    10981092 */
  • trunk/src/VBox/Devices/Audio/AudioMixBuffer.h

    r61320 r61609  
    5151
    5252int AudioMixBufAcquire(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamplesToRead, PPDMAUDIOSAMPLE *ppvSamples, uint32_t *pcSamplesRead);
    53 uint32_t AudioMixBufAvail(PPDMAUDIOMIXBUF pMixBuf);
    5453inline uint32_t AudioMixBufBytesToSamples(PPDMAUDIOMIXBUF pMixBuf);
    5554void AudioMixBufClear(PPDMAUDIOMIXBUF pMixBuf);
     
    6160bool AudioMixBufIsEmpty(PPDMAUDIOMIXBUF pMixBuf);
    6261int AudioMixBufLinkTo(PPDMAUDIOMIXBUF pMixBuf, PPDMAUDIOMIXBUF pParent);
    63 uint32_t AudioMixBufMixed(PPDMAUDIOMIXBUF pMixBuf);
     62uint32_t AudioMixBufLive(PPDMAUDIOMIXBUF pMixBuf);
    6463int AudioMixBufMixToParent(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples, uint32_t *pcProcessed);
    6564uint32_t AudioMixBufUsed(PPDMAUDIOMIXBUF pMixBuf);
  • trunk/src/VBox/Devices/Audio/AudioMixer.cpp

    r61523 r61609  
    5555static void audioMixerSinkRemoveAllStreamsInternal(PAUDMIXSINK pSink);
    5656static int audioMixerSinkRemoveStreamInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
     57static void audioMixerSinkReset(PAUDMIXSINK pSink);
    5758static int audioMixerSinkUpdateInternal(PAUDMIXSINK pSink);
    5859
     
    7879        {
    7980            pSink->pParent  = pMixer;
    80             pSink->cStreams = 0;
    8181            pSink->enmDir   = enmDir;
    8282            RTListInit(&pSink->lstStreams);
     
    479479        pSink->fStatus &= ~AUDMIXSINK_STS_RUNNING;
    480480
     481    /* Not running anymore? Reset. */
     482    if (!(pSink->fStatus & AUDMIXSINK_STS_RUNNING))
     483        audioMixerSinkReset(pSink);
     484
    481485    LogFlowFunc(("[%s]: enmCmd=%ld, fStatus=0x%x, rc=%Rrc\n", pSink->pszName, enmSinkCmd, pSink->fStatus, rc));
    482486    return rc;
     
    528532    RTMemFree(pSink);
    529533    pSink = NULL;
     534}
     535
     536/**
     537 * Returns the amount of bytes ready to be read from a sink since the last call
     538 * to AudioMixerSinkUpdate().
     539 *
     540 * @returns Amount of bytes ready to be read from the sink.
     541 * @param   pSink           Sink to return number of available samples for.
     542 */
     543uint32_t AudioMixerSinkGetReadable(PAUDMIXSINK pSink)
     544{
     545    AssertPtrReturn(pSink, 0);
     546
     547    AssertMsg(pSink->enmDir == AUDMIXSINKDIR_INPUT, ("Can't read from a non-input sink\n"));
     548
     549#ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
     550# error "Implement me!"
     551#else
     552    LogFlowFunc(("[%s]: cbReadable=%RU32\n", pSink->pszName, pSink->In.cbReadable));
     553    return pSink->In.cbReadable;
     554#endif
     555}
     556
     557/**
     558 * Returns the amount of bytes ready to be written to a sink since the last call
     559 * to AudioMixerSinkUpdate().
     560 *
     561 * @returns Amount of bytes ready to be written to the sink.
     562 * @param   pSink           Sink to return number of available samples for.
     563 */
     564uint32_t AudioMixerSinkGetWritable(PAUDMIXSINK pSink)
     565{
     566    AssertPtrReturn(pSink, 0);
     567
     568    AssertMsg(pSink->enmDir == AUDMIXSINKDIR_OUTPUT, ("Can't write to a non-output sink\n"));
     569
     570#ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
     571# error "Implement me!"
     572#else
     573    LogFlowFunc(("[%s]: cbWritable=%RU32\n", pSink->pszName, pSink->Out.cbWritable));
     574    return pSink->Out.cbWritable;
     575#endif
    530576}
    531577
     
    721767
    722768/**
     769 * Resets the sink's state.
     770 *
     771 * @param   pSink       Sink to reset.
     772 */
     773static void audioMixerSinkReset(PAUDMIXSINK pSink)
     774{
     775    if (!pSink)
     776        return;
     777
     778    LogFunc(("%s\n", pSink->pszName));
     779
     780    if (pSink->enmDir == AUDMIXSINKDIR_INPUT)
     781    {
     782#ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
     783        AudioMixBufReset(&pSink->MixBuf);
     784#else
     785        pSink->In.cbReadable = 0;
     786#endif
     787    }
     788    else if (pSink->enmDir == AUDMIXSINKDIR_OUTPUT)
     789    {
     790#ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
     791        AudioMixBufReset(&pSink->MixBuf);
     792#else
     793        pSink->Out.cbWritable = 0;
     794#endif
     795    }
     796}
     797
     798/**
    723799 * Removes all attached streams from a given sink.
    724800 *
     
    792868}
    793869
    794 void AudioMixerSinkTimerUpdate(PAUDMIXSINK pSink, uint64_t cTimerTicks, uint64_t cTicksElapsed)
    795 {
    796     AssertPtrReturnVoid(pSink);
    797 
    798     /* Note: cTimerTicks / cTicksElapsed = Hz elapsed. */
    799 
    800     LogFlowFunc(("[%s]: cTimerTicks=%RU64, cTicksElapsed=%RU64 -> %zuHz\n",
    801                  pSink->pszName, cTimerTicks, cTicksElapsed, cTimerTicks / cTicksElapsed));
    802 
    803     audioMixerSinkUpdateInternal(pSink);
    804 }
    805 
    806870static int audioMixerSinkUpdateInternal(PAUDMIXSINK pSink)
    807871{
     
    811875
    812876    Log3Func(("[%s]\n", pSink->pszName));
     877
     878    /* Update last updated timestamp. */
     879    pSink->tsLastUpdatedNS = RTTimeNanoTS();
    813880
    814881    PAUDMIXSTREAM pMixStream;
    815882    RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node)
    816883    {
    817         PPDMAUDIOSTREAM pStream = pMixStream->pStream;
     884        PPDMAUDIOSTREAM pStream   = pMixStream->pStream;
    818885        AssertPtr(pStream);
     886
     887        PPDMIAUDIOCONNECTOR pConn = pMixStream->pConn;
     888        AssertPtr(pConn);
    819889
    820890        uint32_t cPlayed   = 0;
    821891        uint32_t cCaptured = 0;
    822892
    823         int rc2 = pMixStream->pConn->pfnStreamIterate(pMixStream->pConn, pStream);
     893        int rc2 = pConn->pfnStreamIterate(pConn, pStream);
    824894        if (RT_SUCCESS(rc2))
    825895        {
    826             if (pStream->enmDir == PDMAUDIODIR_IN)
     896            if (pSink->enmDir == AUDMIXSINKDIR_INPUT)
    827897            {
    828                 rc = pMixStream->pConn->pfnStreamCapture(pMixStream->pConn, pMixStream->pStream, &cCaptured);
     898                rc = pConn->pfnStreamCapture(pConn, pMixStream->pStream, &cCaptured);
    829899                if (RT_FAILURE(rc2))
    830900                {
    831                     LogFlowFunc(("%s: Failed capture stream '%s': %Rrc\n", pSink->pszName, pMixStream->pStream->szName, rc2));
     901                    LogFlowFunc(("%s: Failed capturing stream '%s', rc=%Rrc\n", pSink->pszName, pMixStream->pStream->szName, rc2));
    832902                    if (RT_SUCCESS(rc))
    833903                        rc = rc2;
     904                    continue;
    834905                }
    835906
     
    837908                    pSink->fStatus |= AUDMIXSINK_STS_DIRTY;
    838909            }
    839             else if (pStream->enmDir == PDMAUDIODIR_OUT)
     910            else if (pSink->enmDir == AUDMIXSINKDIR_OUTPUT)
    840911            {
    841                 rc2 = pMixStream->pConn->pfnStreamPlay(pMixStream->pConn, pMixStream->pStream, &cPlayed);
     912                rc2 = pConn->pfnStreamPlay(pConn, pMixStream->pStream, NULL /* cPlayed */);
    842913                if (RT_FAILURE(rc2))
    843914                {
    844                     LogFlowFunc(("%s: Failed playing stream '%s': %Rrc\n", pSink->pszName, pMixStream->pStream->szName, rc2));
     915                    LogFlowFunc(("%s: Failed playing stream '%s', rc=%Rrc\n", pSink->pszName, pMixStream->pStream->szName, rc2));
    845916                    if (RT_SUCCESS(rc))
    846917                        rc = rc2;
     918                    continue;
    847919                }
    848920            }
    849921            else
     922            {
    850923                AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
     924                continue;
     925            }
     926
     927            rc2 = pConn->pfnStreamIterate(pConn, pStream);
     928            if (RT_FAILURE(rc2))
     929            {
     930                LogFlowFunc(("%s: Failed re-iterating stream '%s', rc=%Rrc\n", pSink->pszName, pMixStream->pStream->szName, rc2));
     931                if (RT_SUCCESS(rc))
     932                    rc = rc2;
     933                continue;
     934            }
     935
     936            if (pSink->enmDir == AUDMIXSINKDIR_INPUT)
     937            {
     938#ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
     939# error "Implement me!"
     940#else
     941                pSink->In.cbReadable = pConn->pfnStreamGetReadable(pConn, pMixStream->pStream);
     942#endif
     943            }
     944            else if (pSink->enmDir == AUDMIXSINKDIR_OUTPUT)
     945            {
     946#ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
     947# error "Implement me!"
     948#else
     949                pSink->Out.cbWritable = pConn->pfnStreamGetWritable(pConn, pMixStream->pStream);
     950#endif
     951            }
    851952        }
    852953
     
    862963int AudioMixerSinkUpdate(PAUDMIXSINK pSink)
    863964{
     965    AssertPtrReturn(pSink, VERR_INVALID_POINTER);
     966
     967    uint64_t tsElapsed = RTTimeNanoTS() - pSink->tsLastUpdatedNS;
     968
     969    /*
     970     * Note: Hz elapsed     = cTicksElapsed / cTimerTicks
     971     *       Bytes / second = Sample rate (Hz) * Audio channels * Bytes per sample
     972     */
     973//    uint32_t cSamples = (int)((pSink->PCMProps.cChannels * cTicksElapsed * pSink->PCMProps.uHz + cTimerTicks) / cTimerTicks / pSink->PCMProps.cChannels);
     974
     975//    LogFlowFunc(("[%s]: cTimerTicks=%RU64, cTicksElapsed=%RU64\n", pSink->pszName, cTimerTicks, cTicksElapsed));
     976//    LogFlowFunc(("\t%zuHz elapsed, %RU32 samples (%RU32 bytes)\n", cTicksElapsed / cTimerTicks, cSamples, cSamples << 1));
     977
    864978    return audioMixerSinkUpdateInternal(pSink);
    865979}
  • trunk/src/VBox/Devices/Audio/AudioMixer.h

    r61523 r61609  
    115115
    116116/**
     117 * Structure for keeping audio input sink specifics.
     118 * Do not use directly. Instead, use AUDMIXSINK.
     119 */
     120typedef struct AUDMIXSINKIN
     121{
     122#ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
     123    /** This sink's mixing buffer, acting as
     124     * a parent buffer for all streams this sink owns. */
     125    PDMAUDIOMIXBUF MixBuf;
     126#else
     127    /** Number of bytes available to read from the sink. */
     128    uint32_t       cbReadable;
     129#endif
     130} AUDMIXSINKIN;
     131
     132/**
     133 * Structure for keeping audio output sink specifics.
     134 * Do not use directly. Instead, use AUDMIXSINK.
     135 */
     136typedef struct AUDMIXSINKOUT
     137{
     138#ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
     139    /** This sink's mixing buffer, acting as
     140     * a parent buffer for all streams this sink owns. */
     141    PDMAUDIOMIXBUF MixBuf;
     142#else
     143    /** Number of bytes available to write to the sink. */
     144    uint32_t       cbWritable;
     145#endif
     146} AUDMIXSINKOUT;
     147
     148/**
    117149 * Structure for maintaining an audio mixer sink.
    118150 */
     
    127159     *  if this sink handles input or output. */
    128160    AUDMIXSINKDIR           enmDir;
     161    /** Union for input/output specifics. */
     162    union
     163    {
     164        AUDMIXSINKIN        In;
     165        AUDMIXSINKOUT       Out;
     166    };
    129167    /** Sink status of type AUDMIXSINK_STS_XXX. */
    130168    AUDMIXSINKSTS           fStatus;
     
    138176    /** @todo Use something faster -- vector maybe? */
    139177    RTLISTANCHOR            lstStreams;
    140 #ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
    141     /** This sink's mixing buffer, acting as
    142      *  a parent buffer for all streams this sink owns. */
    143     PDMAUDIOMIXBUF          MixBuf;
    144 #endif
    145178    /** The volume of this sink. The volume always will
    146179     *  be combined with the mixer's master volume. */
    147180    PDMAUDIOVOLUME          Volume;
     181    /** Timestamp (in ns) since last update. */
     182    uint64_t                tsLastUpdatedNS;
    148183} AUDMIXSINK, *PAUDMIXSINK;
    149184
     
    178213int AudioMixerSinkCtl(PAUDMIXSINK pSink, AUDMIXSINKCMD enmCmd);
    179214void AudioMixerSinkDestroy(PAUDMIXSINK pSink);
     215uint32_t AudioMixerSinkGetReadable(PAUDMIXSINK pSink);
     216uint32_t AudioMixerSinkGetWritable(PAUDMIXSINK pSink);
    180217AUDMIXSINKDIR AudioMixerSinkGetDir(PAUDMIXSINK pSink);
    181218PAUDMIXSTREAM AudioMixerSinkGetStream(PAUDMIXSINK pSink, uint8_t uIndex);
     
    187224int AudioMixerSinkSetFormat(PAUDMIXSINK pSink, PPDMPCMPROPS pPCMProps);
    188225int AudioMixerSinkSetVolume(PAUDMIXSINK pSink, PPDMAUDIOVOLUME pVol);
    189 void AudioMixerSinkTimerUpdate(PAUDMIXSINK pSink, uint64_t cTimerTicks, uint64_t cTicksElapsed);
     226void AudioMixerSinkTimerUpdate(PAUDMIXSINK pSink, uint64_t cTimerTicks, uint64_t cTicksElapsed, uint32_t *pcbToProcess);
    190227int AudioMixerSinkWrite(PAUDMIXSINK pSink, AUDMIXOP enmOp, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten);
    191228int AudioMixerSinkUpdate(PAUDMIXSINK pSink);
  • trunk/src/VBox/Devices/Audio/DevIchAc97.cpp

    r61529 r61609  
    424424static DECLCALLBACK(void) ichac97Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser);
    425425#endif
    426 static int ichac97TransferAudio(PAC97STATE pThis, PAC97STREAM pStream);
     426static int ichac97TransferAudio(PAC97STATE pThis, PAC97STREAM pStream, uint32_t cbToProcess, uint32_t *pcbProcessed);
    427427
    428428static void ichac97WarmReset(PAC97STATE pThis)
     
    530530static bool ichac97StreamIsActive(PAC97STATE pThis, PAC97STREAM pStream)
    531531{
    532     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    533     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    534 
    535     bool fActive = AudioMixerSinkGetStatus(ichac97IndexToSink(pThis, pStream->u8Strm));
     532    AssertPtrReturn(pThis,   false);
     533    AssertPtrReturn(pStream, false);
     534
     535    PAUDMIXSINK pSink = ichac97IndexToSink(pThis, pStream->u8Strm);
     536    bool fActive = RT_BOOL(AudioMixerSinkGetStatus(pSink) & AUDMIXSINK_STS_RUNNING);
    536537
    537538    LogFlowFunc(("SD=%RU8, fActive=%RTbool\n", pStream->u8Strm, fActive));
     
    13211322static void ichac97TimerMaybeStart(PAC97STATE pThis)
    13221323{
    1323     LogFlowFunc(("cStreamsActive=%RU8\n", pThis->cStreamsActive));
    1324 
    13251324    if (pThis->cStreamsActive == 0) /* Only start the timer if there are no active streams. */
    13261325        return;
     
    13291328        return;
    13301329
     1330    LogFlowFunc(("Starting timer\n"));
     1331
    13311332    /* Set timer flag. */
    13321333    ASMAtomicXchgBool(&pThis->fTimerActive, true);
     
    13411342static void ichac97TimerMaybeStop(PAC97STATE pThis)
    13421343{
    1343     LogFlowFunc(("cStreamsActive=%RU8\n", pThis->cStreamsActive));
    1344 
    13451344    if (pThis->cStreamsActive) /* Some streams still active? Bail out. */
    13461345        return;
     
    13481347    if (!pThis->pTimer)
    13491348        return;
     1349
     1350    LogFlowFunc(("Stopping timer\n"));
    13501351
    13511352    /* Set timer flag. */
     
    13741375    bool fKickTimer = false;
    13751376
    1376     AudioMixerSinkTimerUpdate(pThis->pSinkLineIn, pThis->cTimerTicks, cTicksPerSec);
    1377     ichac97TransferAudio(pThis, &pThis->StreamLineIn);
    1378 
    1379     fKickTimer = AudioMixerSinkGetStatus(pThis->pSinkLineIn) & AUDMIXSINK_STS_DIRTY;
    1380 
    1381     AudioMixerSinkTimerUpdate(pThis->pSinkMicIn , pThis->cTimerTicks, cTicksPerSec);
    1382     ichac97TransferAudio(pThis, &pThis->StreamMicIn);
    1383 
    1384     fKickTimer = AudioMixerSinkGetStatus(pThis->pSinkMicIn) & AUDMIXSINK_STS_DIRTY;
    1385 
    1386     AudioMixerSinkTimerUpdate(pThis->pSinkOutput, pThis->cTimerTicks, cTicksPerSec);
    1387     ichac97TransferAudio(pThis, &pThis->StreamOut);
    1388 
    1389     fKickTimer = AudioMixerSinkGetStatus(pThis->pSinkOutput) & AUDMIXSINK_STS_DIRTY;
     1377    uint32_t cbToProcess;
     1378
     1379    int rc = AudioMixerSinkUpdate(pThis->pSinkLineIn);
     1380    if (RT_SUCCESS(rc))
     1381    {
     1382        cbToProcess = AudioMixerSinkGetReadable(pThis->pSinkLineIn);
     1383        if (cbToProcess)
     1384        {
     1385            rc = ichac97TransferAudio(pThis, &pThis->StreamLineIn, cbToProcess, NULL /* pcbProcessed */);
     1386            fKickTimer |= RT_SUCCESS(rc);
     1387        }
     1388    }
     1389
     1390    rc = AudioMixerSinkUpdate(pThis->pSinkMicIn);
     1391    if (RT_SUCCESS(rc))
     1392    {
     1393        cbToProcess = AudioMixerSinkGetReadable(pThis->pSinkMicIn);
     1394        if (cbToProcess)
     1395        {
     1396            rc = ichac97TransferAudio(pThis, &pThis->StreamMicIn, cbToProcess, NULL /* pcbProcessed */);
     1397            fKickTimer |= RT_SUCCESS(rc);
     1398        }
     1399    }
     1400
     1401    rc = AudioMixerSinkUpdate(pThis->pSinkOutput);
     1402    if (RT_SUCCESS(rc))
     1403    {
     1404        cbToProcess = AudioMixerSinkGetReadable(pThis->pSinkOutput);
     1405        if (cbToProcess)
     1406        {
     1407            rc = ichac97TransferAudio(pThis, &pThis->StreamOut, cbToProcess, NULL /* pcbProcessed */);
     1408            fKickTimer |= RT_SUCCESS(rc);
     1409        }
     1410    }
    13901411
    13911412    if (   ASMAtomicReadBool(&pThis->fTimerActive)
     
    14031424#endif /* !VBOX_WITH_AUDIO_CALLBACKS */
    14041425
    1405 static int ichac97TransferAudio(PAC97STATE pThis, PAC97STREAM pStream)
    1406 {
     1426static int ichac97TransferAudio(PAC97STATE pThis, PAC97STREAM pStream, uint32_t cbToProcess, uint32_t *pcbProcessed)
     1427{
     1428    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     1429    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     1430    /* pcbProcessed is optional. */
     1431
    14071432    Log3Func(("SD=%RU8\n", pStream->u8Strm));
    14081433
     
    14161441            {
    14171442                case PO_INDEX:
    1418                     ichac97WriteBUP(pThis, (uint32_t)(pRegs->picb << 1));
     1443                    ichac97WriteBUP(pThis, cbToProcess);
    14191444                    break;
    14201445
     
    14241449        }
    14251450
     1451        if (pcbProcessed)
     1452            *pcbProcessed = 0;
    14261453        return VINF_SUCCESS;
    14271454    }
     
    14291456    /* BCIS flag still set? Skip iteration. */
    14301457    if (pRegs->sr & SR_BCIS)
     1458    {
     1459        if (pcbProcessed)
     1460            *pcbProcessed = 0;
    14311461        return VINF_SUCCESS;
     1462    }
    14321463
    14331464    int rc = VINF_SUCCESS;
    1434     uint32_t cbWrittenTotal = 0;
    1435 
    1436     do
     1465
     1466    uint32_t cbLeft  = cbToProcess;
     1467    uint32_t cbTotal = 0;
     1468
     1469    while (cbLeft)
    14371470    {
    14381471        if (!pRegs->bd_valid)
     
    14741507                    && cbTransferred)
    14751508                {
    1476                     cbWrittenTotal += cbTransferred;
    1477                     Assert((cbTransferred & 1) == 0); /* Else the following shift won't work */
    1478                     pRegs->picb    -= (cbTransferred >> 1); /** @todo r=andy Assumes 16bit samples. */
    1479                 }
    1480                 break;
    1481             }
    1482 
    1483             case PI_INDEX:
    1484             case MC_INDEX:
    1485             {
    1486                 cbToTransfer = (uint32_t)(pRegs->picb << 1);
    1487 
    1488                 rc = ichac97ReadAudio(pThis, pStream, cbToTransfer, &cbTransferred);
    1489                 if (   RT_SUCCESS(rc)
    1490                     && cbTransferred)
    1491                 {
     1509                    cbTotal     += cbTransferred;
     1510                    Assert(cbLeft >= cbTransferred);
     1511                    cbLeft      -= cbTransferred;
    14921512                    Assert((cbTransferred & 1) == 0); /* Else the following shift won't work */
    14931513                    pRegs->picb -= (cbTransferred >> 1); /** @todo r=andy Assumes 16bit samples. */
     
    14961516            }
    14971517
     1518            case PI_INDEX:
     1519            case MC_INDEX:
     1520            {
     1521                cbToTransfer = (uint32_t)(pRegs->picb << 1);
     1522
     1523                rc = ichac97ReadAudio(pThis, pStream, cbToTransfer, &cbTransferred);
     1524                if (   RT_SUCCESS(rc)
     1525                    && cbTransferred)
     1526                {
     1527                    cbTotal     += cbTransferred;
     1528                    Assert(cbLeft >= cbTransferred);
     1529                    cbLeft      -= cbTransferred;
     1530                    Assert((cbTransferred & 1) == 0); /* Else the following shift won't work */
     1531                    pRegs->picb -= (cbTransferred >> 1); /** @todo r=andy Assumes 16bit samples. */
     1532                }
     1533                break;
     1534            }
     1535
    14981536            default:
    14991537                AssertMsgFailed(("Stream #%RU8 not supported\n", pStream->u8Strm));
     
    15021540        }
    15031541
    1504         Log3Func(("PICB=%RU16 (%#x), cbTransferred=%RU32 (%zu samples), cbWrittenTotal=%RU32\n",
    1505                   pRegs->picb, pRegs->picb, cbTransferred, (cbTransferred >> 1), cbWrittenTotal));
     1542        LogFlowFunc(("[SD%RU8]: %RU32 / %RU32, rc=%Rrc\n", pStream->u8Strm, cbTotal, cbToProcess, rc));
    15061543
    15071544        if (!pRegs->picb)
     
    15361573        if (rc == VINF_EOF) /* All data processed? */
    15371574            break;
    1538 
    1539     } while (RT_SUCCESS(rc));
     1575    }
     1576
     1577    if (RT_SUCCESS(rc))
     1578    {
     1579        if (pcbProcessed)
     1580            *pcbProcessed = cbTotal;
     1581    }
    15401582
    15411583    LogFlowFuncLeaveRC(rc);
  • trunk/src/VBox/Devices/Audio/DevIchHda.cpp

    r61529 r61609  
    942942static int hdaStreamStop(PHDASTREAM pStream);
    943943static int hdaStreamWaitForStateChange(PHDASTREAM pStream, RTMSINTERVAL msTimeout);
    944 static int hdaTransfer(PHDASTATE pThis, PHDASTREAM pStream);
     944static int hdaTransfer(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToProcess, uint32_t *pcbProcessed);
    945945#endif
    946946
     
    966966static void hdaTimerMaybeStart(PHDASTATE pThis);
    967967static void hdaTimerMaybeStop(PHDASTATE pThis);
    968 static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser);
    969968#endif
    970969
     
    17651764static bool hdaStreamIsActive(PHDASTATE pThis, PHDASTREAM pStream)
    17661765{
     1766    AssertPtrReturn(pThis,   false);
     1767    AssertPtrReturn(pStream, false);
     1768
     1769    bool fActive = pStream->State.fActive;
     1770
     1771    LogFlowFunc(("SD=%RU8, fActive=%RTbool\n", pStream->u8SD, fActive));
     1772    return fActive;
     1773}
     1774
     1775static int hdaStreamSetActive(PHDASTATE pThis, PHDASTREAM pStream, bool fActive)
     1776{
    17671777    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    17681778    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    17691779
    1770     bool fActive = pStream->State.fActive;
    1771 
    1772     if (!fActive)
    1773     {
    1774         AssertPtr(pStream->pMixSink);
     1780    LogFlowFunc(("[SD%RU8]: fActive=%RTbool, pMixSink=%p\n", pStream->u8SD, fActive, pStream->pMixSink));
     1781
     1782    if (pStream->State.fActive == fActive) /* No change required? */
     1783    {
     1784        LogFlowFunc(("[SD%RU8]: No change\n", pStream->u8SD));
     1785        return VINF_SUCCESS;
     1786    }
     1787
     1788    int rc;
     1789
     1790    if (pStream->pMixSink) /* Stream attached to a sink? */
     1791    {
     1792        AUDMIXSINKCMD enmCmd = fActive
     1793                             ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE;
     1794
     1795        /* First, enable or disable the stream and the stream's sink, if any. */
    17751796        if (pStream->pMixSink->pMixSink)
    1776             fActive = AudioMixerSinkGetStatus(pStream->pMixSink->pMixSink) & AUDMIXSINK_STS_DIRTY;
    1777     }
    1778 
    1779     LogFlowFunc(("SD=%RU8, fActive=%RTbool\n", pStream->u8SD, fActive));
    1780     return fActive;
    1781 }
    1782 
    1783 static int hdaStreamSetActive(PHDASTATE pThis, PHDASTREAM pStream, bool fActive)
    1784 {
    1785     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    1786     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    1787 
    1788     if (!pStream->pMixSink) /* No mixer sink assigned? Bail out early. */
    1789     {
    1790         LogFlowFunc(("u8Strm=%RU8 has no mixer sink assigned\n", pStream->u8SD));
    1791         return VINF_SUCCESS;
    1792     }
    1793 
    1794     AUDMIXSINKCMD enmCmd = fActive
    1795                          ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE;
    1796 
    1797     /* First, enable or disable the stream and the stream's sink, if any. */
    1798     if (pStream->pMixSink->pMixSink)
    1799         AudioMixerSinkCtl(pStream->pMixSink->pMixSink, enmCmd);
     1797            rc = AudioMixerSinkCtl(pStream->pMixSink->pMixSink, enmCmd);
     1798    }
     1799    else
     1800        rc = VINF_SUCCESS;
     1801
     1802    if (RT_FAILURE(rc))
     1803    {
     1804        LogFlowFunc(("Failed with rc=%Rrc\n", rc));
     1805        return rc;
     1806    }
    18001807
    18011808    pStream->State.fActive = fActive;
     
    34823489 *       but "reports bytes" when all conditions are met (FIFOW).
    34833490 */
    3484 static int hdaReadAudio(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToProcess, uint32_t *pcbProcessed)
     3491static int hdaReadAudio(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead)
    34853492{
    34863493    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    34873494    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    3488     /* pcbProcessed is optional. */
     3495    /* pcbRead is optional. */
    34893496
    34903497    int rc;
     
    34953502        PHDABDLE pBDLE = &pStream->State.BDLE;
    34963503
    3497         if (!cbToProcess)
     3504        if (!cbToRead)
    34983505        {
    34993506            rc = VINF_EOF;
     
    35033510        AssertPtr(pStream->pMixSink);
    35043511        AssertPtr(pStream->pMixSink->pMixSink);
    3505         rc = AudioMixerSinkRead(pStream->pMixSink->pMixSink, AUDMIXOP_BLEND, pBDLE->State.au8FIFO, cbToProcess, &cbRead);
     3512        rc = AudioMixerSinkRead(pStream->pMixSink->pMixSink, AUDMIXOP_BLEND, pBDLE->State.au8FIFO, cbToRead, &cbRead);
    35063513        if (RT_FAILURE(rc))
    35073514            break;
     
    35143521
    35153522        /* Sanity checks. */
    3516         Assert(cbRead <= cbToProcess);
     3523        Assert(cbRead <= cbToRead);
    35173524        Assert(cbRead <= sizeof(pBDLE->State.au8FIFO));
    35183525        Assert(cbRead <= pBDLE->u32BufSize - pBDLE->State.u32BufOff);
     
    35483555    if (RT_SUCCESS(rc))
    35493556    {
    3550         if (pcbProcessed)
    3551             *pcbProcessed = cbRead;
     3557        if (pcbRead)
     3558            *pcbRead = cbRead;
    35523559    }
    35533560
     
    35583565}
    35593566
    3560 static int hdaWriteAudio(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToProcess, uint32_t *pcbProcessed)
     3567static int hdaWriteAudio(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToWrite, uint32_t *pcbWritten)
    35613568{
    35623569    AssertPtrReturn(pThis,      VERR_INVALID_POINTER);
     
    35733580     */
    35743581    int rc;
    3575     if (!cbToProcess)
     3582    if (!cbToWrite)
    35763583    {
    35773584        rc = VINF_EOF;
     
    35803587    {
    35813588        void    *pvBuf = pBDLE->State.au8FIFO + pBDLE->State.cbBelowFIFOW;
    3582         Assert(cbToProcess >= pBDLE->State.cbBelowFIFOW);
    3583         uint32_t cbBuf = cbToProcess - pBDLE->State.cbBelowFIFOW;
     3589        Assert(cbToWrite >= pBDLE->State.cbBelowFIFOW);
     3590        uint32_t cbBuf = cbToWrite - pBDLE->State.cbBelowFIFOW;
    35843591
    35853592        /*
     
    36743681            /* Always report all data as being written;
    36753682             * backends who were not able to catch up have to deal with it themselves. */
    3676             cbWritten = cbToProcess;
    3677 
    3678             hdaBDLEUpdate(pBDLE, cbToProcess, cbWritten);
     3683            cbWritten = cbToWrite;
     3684
     3685            hdaBDLEUpdate(pBDLE, cbToWrite, cbWritten);
    36793686        }
    36803687        else
     
    36953702    if (RT_SUCCESS(rc))
    36963703    {
    3697         if (pcbProcessed)
    3698             *pcbProcessed = cbWritten;
     3704        if (pcbWritten)
     3705            *pcbWritten = cbWritten;
    36993706    }
    37003707
     
    39383945            }
    39393946
    3940             AssertPtr(pMixStream);
    3941 
    3942             AudioMixerSinkRemoveStream(pSink->pMixSink, pMixStream);
    3943             AudioMixerStreamDestroy(pMixStream);
     3947            if (pMixStream)
     3948            {
     3949                AudioMixerSinkRemoveStream(pSink->pMixSink, pMixStream);
     3950                AudioMixerStreamDestroy(pMixStream);
     3951
     3952                pMixStream = NULL;
     3953            }
    39443954        }
    39453955
     
    40514061static void hdaTimerMaybeStart(PHDASTATE pThis)
    40524062{
    4053     LogFlowFunc(("cStreamsActive=%RU8\n", pThis->cStreamsActive));
    4054 
    40554063    if (pThis->cStreamsActive == 0) /* Only start the timer if there are no active streams. */
    40564064        return;
     
    40614069    LogFlowFuncEnter();
    40624070
     4071    LogFlowFunc(("Starting timer\n"));
     4072
    40634073    /* Set timer flag. */
    40644074    ASMAtomicXchgBool(&pThis->fTimerActive, true);
     
    40734083static void hdaTimerMaybeStop(PHDASTATE pThis)
    40744084{
    4075     LogFlowFunc(("cStreamsActive=%RU8\n", pThis->cStreamsActive));
    4076 
    40774085    if (pThis->cStreamsActive) /* Some streams still active? Bail out. */
    40784086        return;
     
    40814089        return;
    40824090
    4083     LogFlowFuncEnter();
     4091    LogFlowFunc(("Stopping timer\n"));
    40844092
    40854093    /* Set timer flag. */
     
    40954103    STAM_PROFILE_START(&pThis->StatTimer, a);
    40964104
    4097     uint32_t cbInMax  = 0;
    4098     uint32_t cbOutMin = UINT32_MAX;
    4099 
    41004105    uint64_t cTicksNow     = TMTimerGet(pTimer);
    41014106    uint64_t cTicksElapsed = cTicksNow - pThis->uTimerTS;
     
    41194124#endif
    41204125
    4121     AudioMixerSinkTimerUpdate(pThis->SinkLineIn.pMixSink, pThis->cTimerTicks, cTicksElapsed);
    4122     hdaTransfer(pThis, pStreamLineIn);
    4123 
    4124     if (AudioMixerSinkGetStatus(pThis->SinkLineIn.pMixSink) & AUDMIXSINK_STS_DIRTY)
    4125         fKickTimer = true;
     4126    uint32_t cbToProcess;
     4127    int rc = AudioMixerSinkUpdate(pThis->SinkLineIn.pMixSink);
     4128    if (RT_SUCCESS(rc))
     4129    {
     4130        cbToProcess = AudioMixerSinkGetReadable(pThis->SinkLineIn.pMixSink);
     4131        if (cbToProcess)
     4132        {
     4133            rc = hdaTransfer(pThis, pStreamLineIn, cbToProcess, NULL /* pcbProcessed */);
     4134            fKickTimer = RT_SUCCESS(rc);
     4135        }
     4136    }
    41264137
    41274138#ifdef VBOX_WITH_HDA_MIC_IN
    4128     AudioMixerSinkTimerUpdate(pThis->SinkMicIn.pMixSink, pThis->cTimerTicks, cTicksElapsed);
    4129     hdaTransfer(pThis, pStreamMicIn);
    4130 
    4131     if (AudioMixerSinkGetStatus(pThis->SinkLineIn.pMixSink) & AUDMIXSINK_STS_DIRTY)
    4132         fKickTimer = true;
    4133 #endif
    4134 
    4135     AudioMixerSinkTimerUpdate(pThis->SinkFront.pMixSink,     pThis->cTimerTicks, cTicksElapsed);
    4136     hdaTransfer(pThis, pStreamFront);
    4137 
    4138     if (AudioMixerSinkGetStatus(pThis->SinkFront.pMixSink) & AUDMIXSINK_STS_DIRTY)
    4139         fKickTimer = true;
     4139    rc = AudioMixerSinkUpdate(pThis->SinkMicIn.pMixSink);
     4140    if (RT_SUCCESS(rc))
     4141    {
     4142        cbToProcess = AudioMixerSinkGetReadable(pThis->SinkMicIn.pMixSink);
     4143        if (cbToProcess)
     4144        {
     4145            rc = hdaTransfer(pThis, pStreamMicIn, cbToProcess, NULL /* pcbProcessed */);
     4146            fKickTimer = RT_SUCCESS(rc);
     4147        }
     4148    }
     4149#endif
    41404150
    41414151#ifdef VBOX_WITH_HDA_51_SURROUND
    4142     AudioMixerSinkTimerUpdate(pThis->SinkCenterLFE.pMixSink, pThis->cTimerTicks, cTicksElapsed);
    4143     AudioMixerSinkTimerUpdate(pThis->SinkRear.pMixSink,      pThis->cTimerTicks, cTicksElapsed);
    4144 
     4152    rc = AudioMixerSinkUpdate(pThis->SinkCenterLFE.pMixSink);
     4153    if (RT_SUCCESS(rc))
     4154    {
     4155
     4156    }
     4157
     4158    rc = AudioMixerSinkUpdate(pThis->SinkRear.pMixSink);
     4159    if (RT_SUCCESS(rc))
     4160    {
     4161
     4162    }
    41454163    /** @todo Check for stream interleaving and only call hdaTransfer() if required! */
    4146 #endif
    4147 
    4148 #ifdef VBOX_WITH_HDA_51_SURROUND
     4164
    41494165    /*
    41504166     * Only call hdaTransfer if CenterLFE and/or Rear are on different SDs,
     
    41534169     */
    41544170#endif
     4171    rc = AudioMixerSinkUpdate(pThis->SinkFront.pMixSink);
     4172    if (RT_SUCCESS(rc))
     4173    {
     4174        cbToProcess = AudioMixerSinkGetWritable(pThis->SinkFront.pMixSink);
     4175        if (cbToProcess)
     4176        {
     4177            rc = hdaTransfer(pThis, pStreamFront, cbToProcess, NULL /* pcbProcessed */);
     4178            fKickTimer = RT_SUCCESS(rc);
     4179        }
     4180    }
    41554181
    41564182    if (   ASMAtomicReadBool(&pThis->fTimerActive)
     
    42184244#endif /* VBOX_WITH_AUDIO_CALLBACKS */
    42194245
    4220 static int hdaTransfer(PHDASTATE pThis, PHDASTREAM pStream)
     4246static int hdaTransfer(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToProcess, uint32_t *pcbProcessed)
    42214247{
    42224248    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    42234249    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     4250    /* pcbProcessed is optional. */
    42244251
    42254252    if (ASMAtomicReadBool(&pThis->fInReset)) /* HDA controller in reset mode? Bail out. */
    42264253    {
    42274254        LogFlowFunc(("HDA in reset mode, skipping\n"));
     4255
     4256        if (pcbProcessed)
     4257            *pcbProcessed = 0;
    42284258        return VINF_SUCCESS;
    42294259    }
     
    42504280    else if (!(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)))
    42514281        fProceed = false;
     4282    /* Nothing to process? */
     4283    else if (!cbToProcess)
     4284        fProceed = false;
    42524285
    42534286    if ((HDA_STREAM_REG(pThis, STS, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
     
    42644297        AssertRC(rc);
    42654298
     4299        if (pcbProcessed)
     4300            *pcbProcessed = 0;
    42664301        return VINF_SUCCESS;
    42674302    }
     
    42814316
    42824317#ifdef DEBUG_andy
    4283 # define DEBUG_SIMPLE
     4318//# define DEBUG_SIMPLE
    42844319#endif
    42854320
     
    42894324#endif
    42904325
    4291     uint32_t cbToProcess      = 0;
    4292     uint32_t cbProcessed      = 0;
    4293     uint32_t cbProcessedTotal = 0;
     4326    uint32_t cbLeft           = cbToProcess;
     4327    uint32_t cbTotal          = 0;
     4328    uint32_t cbChunk          = 0;
     4329    uint32_t cbChunkProcessed = 0;
    42944330
    42954331    /* Set the FIFORDY bit on the stream while doing the transfer. */
    42964332    HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
    42974333
    4298     do
     4334    while (cbLeft)
    42994335    {
    43004336        /* Do we need to fetch the next Buffer Descriptor Entry (BDLE)? */
     
    43064342        }
    43074343
    4308         cbToProcess = hdaStreamGetTransferSize(pThis, pStream, _4K /** @todo Fix this */);
    4309         cbProcessed = 0;
     4344        cbChunk          = hdaStreamGetTransferSize(pThis, pStream, cbLeft);
     4345        cbChunkProcessed = 0;
    43104346
    43114347        if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_IN)
    4312             rc = hdaReadAudio(pThis, pStream, cbToProcess, &cbProcessed);
     4348            rc = hdaReadAudio(pThis, pStream, cbChunk, &cbChunkProcessed);
    43134349        else
    43144350        {
    43154351#ifndef DEBUG_SIMPLE
    4316             rc = hdaWriteAudio(pThis, pStream, cbToProcess, &cbProcessed);
     4352            rc = hdaWriteAudio(pThis, pStream, cbChunk, &cbChunkProcessed);
    43174353#else
    4318             uint32_t cbToWrite = hdaStreamGetTransferSize(pThis, pStream, cbToProcess);
    4319 
    43204354            void    *pvBuf = u8FIFO + u8FIFOff;
    4321             int32_t cbBuf = cbToWrite;
     4355            int32_t cbBuf  = cbChunk;
    43224356
    43234357            PHDABDLE pBDLE = &pStream->State.BDLE;
    43244358
    4325             rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),
    4326                                pBDLE->u64BufAdr + pBDLE->State.u32BufOff,
    4327                                pvBuf, cbBuf);
    4328 
    4329             hdaBDLEUpdate(pBDLE, cbToWrite, cbToWrite);
    4330 
    4331             u8FIFOff += cbToWrite;
     4359            if (cbBuf)
     4360                rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),
     4361                                       pBDLE->u64BufAdr + pBDLE->State.u32BufOff,
     4362                                       pvBuf, cbBuf);
     4363
     4364            cbChunkProcessed = cbChunk;
     4365
     4366            hdaBDLEUpdate(pBDLE, cbChunkProcessed, cbChunkProcessed);
     4367
     4368            u8FIFOff += cbChunkProcessed;
    43324369            Assert((u8FIFOff & 1) == 0);
    43334370            Assert(u8FIFOff <= sizeof(u8FIFO));
    4334 
    4335             cbProcessed = cbToWrite;
    43364371#endif
    43374372        }
     
    43404375            break;
    43414376
    4342         hdaStreamTransferUpdate(pThis, pStream, cbProcessed);
    4343 
    4344         cbProcessedTotal += cbProcessed;
     4377        hdaStreamTransferUpdate(pThis, pStream, cbChunkProcessed);
     4378
     4379        Assert(cbLeft >= cbChunkProcessed);
     4380        cbLeft  -= cbChunkProcessed;
     4381        cbTotal += cbChunkProcessed;
    43454382
    43464383        if (rc == VINF_EOF)
     
    43494386        if (hdaStreamTransferIsComplete(pThis, pStream, &fInterrupt))
    43504387            break;
    4351 
    4352     } while (RT_SUCCESS(rc));
     4388    }
    43534389
    43544390    /* Remove the FIFORDY bit again. */
    43554391    HDA_STREAM_REG(pThis, STS, pStream->u8SD) &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
    43564392
    4357     LogFlowFunc(("[SD%RU8]: %RU32 / %RU32, rc=%Rrc\n", pStream->u8SD, cbProcessedTotal, cbToProcess, rc));
     4393    LogFlowFunc(("[SD%RU8]: %RU32 / %RU32, rc=%Rrc\n", pStream->u8SD, cbTotal, cbToProcess, rc));
    43584394
    43594395#ifdef DEBUG_SIMPLE
     
    43864422
    43874423        hdaProcessInterrupt(pThis);
     4424    }
     4425
     4426    if (RT_SUCCESS(rc))
     4427    {
     4428        if (pcbProcessed)
     4429            *pcbProcessed = cbTotal;
    43884430    }
    43894431
     
    50515093            if (pStream)
    50525094            {
     5095                /* Deactive first. */
     5096                int rc2 = hdaStreamSetActive(pThis, pStream, false);
     5097                AssertRC(rc2);
     5098
    50535099                bool fActive = RT_BOOL(HDA_STREAM_REG(pThis, CTL, i) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
    5054                 LogFlowFunc(("[SD%RU8]: fActive=%RTbool\n", i, fActive));
    5055                 int rc2 = hdaStreamSetActive(pThis, pStream, fActive);
     5100
     5101                /* Activate, if needed. */
     5102                rc2 = hdaStreamSetActive(pThis, pStream, fActive);
    50565103                AssertRC(rc2);
    50575104            }
     
    56995746#ifndef VBOX_WITH_AUDIO_CALLBACKS
    57005747    uint16_t uTimerHz;
    5701     rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 100 /* Hz */);
     5748    rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 200 /* Hz */);
    57025749    if (RT_FAILURE(rc))
    57035750        return PDMDEV_SET_ERROR(pDevIns, rc,
  • trunk/src/VBox/Devices/Audio/DevSB16.cpp

    r61386 r61609  
    17851785    pThis->uTimerTSIO = cTicksNow;
    17861786
    1787     bool fIsPlaying = false;
     1787    bool     fIsPlaying = false;
     1788    uint32_t cbWritable = UINT32_MAX;
    17881789
    17891790    LogFlowFuncEnter();
     
    17961797            continue;
    17971798
    1798         int rc2 = pDrv->pConnector->pfnStreamIterate(pDrv->pConnector, pStream);
     1799        PPDMIAUDIOCONNECTOR pConn = pDrv->pConnector;
     1800        if (!pConn)
     1801            continue;
     1802
     1803        int rc2 = pConn->pfnStreamIterate(pConn, pStream);
    17991804        if (RT_SUCCESS(rc2))
    18001805        {
    18011806            if (pStream->enmDir == PDMAUDIODIR_IN)
    18021807            {
    1803                 /** @todo Implement this! */
     1808                /** @todo Implement recording! */
    18041809            }
    18051810            else
    18061811            {
    1807                 rc2 = pDrv->pConnector->pfnStreamPlay(pDrv->pConnector, pStream, NULL /* cPlayed */);
     1812                rc2 = pConn->pfnStreamPlay(pConn, pStream, NULL /* cPlayed */);
    18081813                if (RT_FAILURE(rc2))
     1814                {
    18091815                    LogFlowFunc(("%s: Failed playing stream, rc=%Rrc\n", pStream->szName, rc2));
     1816                    continue;
     1817                }
     1818
     1819                rc2 = pConn->pfnStreamIterate(pConn, pStream);
     1820                if (RT_FAILURE(rc2))
     1821                {
     1822                    LogFlowFunc(("%s: Failed re-iterating stream, rc=%Rrc\n", pStream->szName, rc2));
     1823                    continue;
     1824                }
     1825
     1826                cbWritable = RT_MIN(pConn->pfnStreamGetWritable(pConn, pStream), cbWritable);
    18101827            }
    18111828        }
    18121829
    1813         PDMAUDIOSTRMSTS strmSts = pDrv->pConnector->pfnStreamGetStatus(pDrv->pConnector, pStream);
     1830        PDMAUDIOSTRMSTS strmSts = pConn->pfnStreamGetStatus(pConn, pStream);
    18141831        fIsPlaying |= (   (strmSts & PDMAUDIOSTRMSTS_FLAG_ENABLED)
    18151832                       || (strmSts & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE));
     
    18211838        || fIsPlaying)
    18221839    {
    1823         /* Schedule the next transfer. */
    1824         PDMDevHlpDMASchedule(pThis->pDevInsR3);
     1840        if (cbWritable)
     1841        {
     1842            /* Schedule the next transfer. */
     1843            PDMDevHlpDMASchedule(pThis->pDevInsR3);
     1844        }
    18251845
    18261846        /* Kick the timer again. */
  • trunk/src/VBox/Devices/Audio/DrvAudio.cpp

    r61568 r61609  
    581581    AssertPtr(pGstStream);
    582582
    583     int rc = VINF_SUCCESS;
     583    int rc;
    584584
    585585    do
     
    587587        uint32_t cSamplesMixed = 0;
    588588
    589         PDMAUDIOSTRMSTS hstStrmSts = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pHstStream);
     589        rc = pThis->pHostDrvAudio->pfnStreamIterate(pThis->pHostDrvAudio, pHstStream);
     590        if (RT_FAILURE(rc))
     591            break;
    590592
    591593        if (pHstStream->enmDir == PDMAUDIODIR_IN)
    592594        {
    593             uint32_t cSamplesToCapture = AudioMixBufFree(&pGstStream->MixBuf);
    594             if (cSamplesToCapture)
    595             {
    596                 if (hstStrmSts & PDMAUDIOSTRMSTS_FLAG_DATA_READABLE)
     595            /* Has the host captured any samples which were not mixed to the guest side yet? */
     596            uint32_t cSamplesCaptured = AudioMixBufUsed(&pHstStream->MixBuf);
     597
     598            LogFlowFunc(("[%s] %RU32 samples captured\n", pHstStream->szName, cSamplesCaptured));
     599
     600            if (cSamplesCaptured)
     601            {
     602                /* When capturing samples, the guest is the parent while the host is the child.
     603                 * So try mixing not yet mixed host-side samples to the guest-side buffer. */
     604                rc = AudioMixBufMixToParent(&pHstStream->MixBuf, cSamplesCaptured, &cSamplesMixed);
     605                if (   RT_SUCCESS(rc)
     606                    && cSamplesMixed)
    597607                {
    598                     uint32_t cSamplesCaptured = 0;
    599 
    600                     /* Call the host backend to capture the audio input data. */
    601                     rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pHstStream, &cSamplesCaptured);
    602                     if (RT_FAILURE(rc))
    603                         break;
    604 
    605                     LogFlowFunc(("%s: %RU32 samples captured, rc=%Rrc\n", pHstStream->szName, cSamplesCaptured, rc));
     608                    LogFlowFunc(("[%s] %RU32 captured samples mixed\n", pHstStream->szName, cSamplesMixed));
    606609                }
    607610            }
     
    609612        else if (pHstStream->enmDir == PDMAUDIODIR_OUT)
    610613        {
    611             uint32_t cSamplesToMix = AudioMixBufUsed(&pGstStream->MixBuf);
    612 
    613             if (cSamplesToMix)
    614             {
    615                 uint32_t cSamplesPlayed = 0;
    616                 if (hstStrmSts & PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE)
     614            uint32_t cSamplesLive = AudioMixBufLive(&pGstStream->MixBuf);
     615            if (!cSamplesLive) /* No live samples at the moment? */
     616            {
     617                /* When playing samples, the host is the parent while the guest is the child.
     618                 * So try mixing not yet mixed guest-side samples to the host-side buffer. */
     619                rc = AudioMixBufMixToParent(&pGstStream->MixBuf, AudioMixBufUsed(&pGstStream->MixBuf), &cSamplesMixed);
     620                if (   RT_SUCCESS(rc)
     621                    && cSamplesMixed)
    617622                {
    618                     rc = AudioMixBufMixToParent(&pGstStream->MixBuf, cSamplesToMix, &cSamplesMixed);
    619 
    620                     LogFlowFunc(("%s: %RU32/%RU32 playback samples mixed, rc=%Rrc\n",
    621                                  pHstStream->szName, cSamplesMixed, cSamplesToMix, rc));
     623                    LogFlowFunc(("[%s] %RU32 samples mixed\n", pHstStream->szName, cSamplesMixed));
    622624                }
     625
     626                if (RT_SUCCESS(rc))
     627                    cSamplesLive = AudioMixBufLive(&pGstStream->MixBuf);
     628            }
     629
     630            LogFlowFunc(("[%s] %RU32 live samples\n", pHstStream->szName, cSamplesLive));
     631
     632            if (!cSamplesLive) /* No live samples at the moment? */
     633            {
     634                /* Has the host stream marked as disabled but there still were guest streams relying
     635                 * on it? Check if the stream now can be closed and do so, if possible. */
     636                if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE)
     637                {
     638                    LogFunc(("[%s] Closing pending stream\n", pHstStream->szName));
     639                    rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
     640                    if (RT_SUCCESS(rc))
     641                    {
     642                        pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE;
     643                    }
     644                    else
     645                        LogFunc(("%s: Backend vetoed against closing output stream, rc=%Rrc\n", pHstStream->szName, rc));
     646                }
     647
     648                break;
    623649            }
    624650        }
    625651        else
    626652            AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
    627 
    628         if (RT_SUCCESS(rc))
    629             rc = pThis->pHostDrvAudio->pfnStreamIterate(pThis->pHostDrvAudio, pHstStream);
    630653
    631654    } while (0);
     
    656679    if (RT_FAILURE(rc))
    657680        return rc;
    658 
    659     LogFlowFunc(("[%s]\n", pStream->szName));
    660681
    661682    uint32_t cSamplesPlayed = 0;
     
    682703        AssertPtr(pGstStream);
    683704
    684         uint32_t cSamplesLive = AudioMixBufUsed(&pHstStream->MixBuf);
     705        uint32_t cSamplesLive = AudioMixBufLive(&pGstStream->MixBuf);
    685706        if (cSamplesLive)
    686707        {
     
    690711                rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pHstStream, &cSamplesPlayed);
    691712                if (RT_FAILURE(rc))
    692                     drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
    693             }
    694 
    695             LogFlowFunc(("[%s] strmSts=0x%x, cSamplesPlayed=%RU32, rc=%Rrc\n", pStream->szName, strmSts, cSamplesPlayed, rc));
    696 
    697             if (RT_SUCCESS(rc))
    698             {
    699                 rc = drvAudioStreamIterateInternal(pThis, pStream);
    700                 if (RT_SUCCESS(rc))
    701                     cSamplesLive = AudioMixBufUsed(&pHstStream->MixBuf);
    702             }
     713                {
     714                    int rc2 = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
     715                    AssertRC(rc2);
     716                }
     717            }
     718
     719            LogFlowFunc(("[%s] strmSts=0x%x, cSamplesPlayed=%RU32, rc=%Rrc\n", pHstStream->szName, strmSts, cSamplesPlayed, rc));
    703720        }
    704721
     
    709726            if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE)
    710727            {
    711                 LogFunc(("%s: Closing pending stream\n", pHstStream->szName));
     728                LogFunc(("[%s] Closing pending stream\n", pHstStream->szName));
    712729                rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
    713730                if (RT_SUCCESS(rc))
     
    716733                }
    717734                else
    718                     LogFunc(("%s: Backend vetoed against closing output stream, rc=%Rrc\n", pHstStream->szName, rc));
     735                    LogFunc(("[%s] Backend vetoed against closing output stream, rc=%Rrc\n", pHstStream->szName, rc));
    719736            }
    720737        }
     
    733750
    734751    if (RT_FAILURE(rc))
    735         LogFlowFuncLeaveRC(rc);
     752        LogFlowFunc(("[%s] Failed with %Rrc\n", rc));
    736753
    737754    return rc;
     
    779796        AssertPtr(pGstStream);
    780797
    781         uint32_t cSamplesLive = AudioMixBufUsed(&pHstStream->MixBuf);
    782         if (cSamplesLive)
     798        uint32_t cSamplesLive = AudioMixBufLive(&pGstStream->MixBuf);
     799        if (!cSamplesLive)
    783800        {
    784801            PDMAUDIOSTRMSTS strmSts = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pHstStream);
     
    787804                rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pHstStream, &cSamplesCaptured);
    788805                if (RT_FAILURE(rc))
    789                     drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
    790             }
    791 
    792             LogFlowFunc(("[%s] strmSts=0x%x, cSamplesCaptured=%RU32, rc=%Rrc\n", pStream->szName, strmSts, cSamplesCaptured, rc));
    793 
    794             if (RT_SUCCESS(rc))
    795             {
    796                 rc = drvAudioStreamIterateInternal(pThis, pStream);
    797                 if (RT_SUCCESS(rc))
    798                     cSamplesLive = AudioMixBufUsed(&pHstStream->MixBuf);
    799             }
    800         }
    801 
    802         if (!cSamplesLive)
    803         {
    804             /* Has the host stream marked as disabled but there still were guest streams relying
    805              * on it? Check if the stream now can be closed and do so, if possible. */
    806             if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE)
    807             {
    808                 LogFunc(("%s: Closing pending stream\n", pHstStream->szName));
    809                 rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
    810                 if (RT_SUCCESS(rc))
    811806                {
    812                     pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE;
     807                    int rc2 = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
     808                    AssertRC(rc2);
    813809                }
    814                 else
    815                     LogFunc(("%s: Backend vetoed against closing input stream, rc=%Rrc\n", pHstStream->szName, rc));
    816             }
     810            }
     811
     812            LogFlowFunc(("[%s] strmSts=0x%x, cSamplesCaptured=%RU32, rc=%Rrc\n", pHstStream->szName, strmSts, cSamplesCaptured, rc));
    817813        }
    818814
     
    13661362    LogFlowFuncLeaveRC(rc);
    13671363    return backendSts;
     1364}
     1365
     1366static DECLCALLBACK(uint32_t) drvAudioStreamGetReadable(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream)
     1367{
     1368    AssertPtrReturn(pInterface, 0);
     1369    AssertPtrReturn(pStream,    0);
     1370
     1371    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
     1372
     1373    int rc2 = RTCritSectEnter(&pThis->CritSect);
     1374    AssertRC(rc2);
     1375
     1376    AssertMsg(pStream->enmDir == PDMAUDIODIR_IN, ("Can't read from a non-input stream\n"));
     1377
     1378    PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
     1379    if (!pHstStream) /* No host stream available? Bail out early. */
     1380    {
     1381        rc2 = RTCritSectLeave(&pThis->CritSect);
     1382        AssertRC(rc2);
     1383
     1384        return 0;
     1385    }
     1386
     1387    uint32_t cbReadable = 0;
     1388
     1389    PPDMAUDIOSTREAM pGstStream = pHstStream->pPair;
     1390    if (pGstStream)
     1391        cbReadable = AudioMixBufLive(&pGstStream->MixBuf);
     1392
     1393    LogFlowFunc(("[%s] cbReadable=%RU32\n", pHstStream->szName, cbReadable));
     1394
     1395    rc2 = RTCritSectLeave(&pThis->CritSect);
     1396    AssertRC(rc2);
     1397
     1398    return cbReadable;
     1399}
     1400
     1401static DECLCALLBACK(uint32_t) drvAudioStreamGetWritable(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream)
     1402{
     1403    AssertPtrReturn(pInterface, 0);
     1404    AssertPtrReturn(pStream,    0);
     1405
     1406    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
     1407
     1408    int rc2 = RTCritSectEnter(&pThis->CritSect);
     1409    AssertRC(rc2);
     1410
     1411    AssertMsg(pStream->enmDir == PDMAUDIODIR_OUT, ("Can't write to a non-output stream\n"));
     1412
     1413    PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
     1414    if (!pHstStream) /* No host stream available? Bail out early. */
     1415    {
     1416        rc2 = RTCritSectLeave(&pThis->CritSect);
     1417        AssertRC(rc2);
     1418
     1419        return 0;
     1420    }
     1421
     1422    PPDMAUDIOSTREAM pGstStream = pHstStream->pPair;
     1423
     1424    uint32_t cbWritable = 0;
     1425
     1426    if (AudioMixBufLive(&pHstStream->MixBuf) == 0)
     1427        cbWritable = AudioMixBufFreeBytes(&pGstStream->MixBuf);
     1428
     1429    LogFlowFunc(("[%s] cWritable=%RU32\n", pHstStream->szName, cbWritable));
     1430
     1431    rc2 = RTCritSectLeave(&pThis->CritSect);
     1432    AssertRC(rc2);
     1433
     1434    return cbWritable;
    13681435}
    13691436
     
    16341701    pThis->IAudioConnector.pfnStreamWrite       = drvAudioStreamWrite;
    16351702    pThis->IAudioConnector.pfnStreamIterate     = drvAudioStreamIterate;
     1703    pThis->IAudioConnector.pfnStreamGetReadable = drvAudioStreamGetReadable;
     1704    pThis->IAudioConnector.pfnStreamGetWritable = drvAudioStreamGetWritable;
    16361705    pThis->IAudioConnector.pfnStreamGetStatus   = drvAudioStreamGetStatus;
    16371706    pThis->IAudioConnector.pfnStreamSetVolume   = drvAudioStreamSetVolume;
  • trunk/src/VBox/Devices/Audio/DrvHostALSAAudio.cpp

    r61523 r61609  
    11661166                                                 (uint32_t)cAvail), /* cAvail is always >= 0 */
    11671167                                 AUDIOMIXBUF_S2B(&pStream->MixBuf,
    1168                                                  AudioMixBufAvail(&pStream->MixBuf)));
     1168                                                 AudioMixBufLive(&pStream->MixBuf)));
    11691169        LogFlowFunc(("cbToRead=%zu, cbAvail=%zu\n",
    11701170                     cbToRead, AUDIOMIXBUF_S2B(&pStream->MixBuf, cAvail)));
  • trunk/src/VBox/Devices/Audio/DrvHostCoreAudio.cpp

    r61321 r61609  
    15611561    /* Not much else to do here. */
    15621562
    1563     uint32_t cLive = AudioMixBufAvail(&pStream->MixBuf);;
    1564     if (!cLive) /* Not samples to play? Bail out. */
     1563    uint32_t cLive = AudioMixBufLive(&pStream->MixBuf);
     1564    if (!cLive) /* Not live samples to play? Bail out. */
    15651565    {
    15661566        if (pcSamplesPlayed)
     
    15691569    }
    15701570
     1571    size_t cbLive  = AUDIOMIXBUF_S2B(&pStream->MixBuf, cLive);
     1572
    15711573    uint32_t cbReadTotal = 0;
    1572     uint32_t cAvail = AudioMixBufAvail(&pStream->MixBuf);
    1573     size_t cbAvail  = AUDIOMIXBUF_S2B(&pStream->MixBuf, cAvail);
    1574     size_t cbToRead = RT_MIN(cbAvail, RTCircBufFree(pStreamOut->pBuf));
     1574
     1575    size_t cbToRead = RT_MIN(cbLive, RTCircBufFree(pStreamOut->pBuf));
    15751576    LogFlowFunc(("cbToRead=%zu\n", cbToRead));
    15761577
  • trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp

    r61345 r61609  
    257257    AssertPtrReturn(pThis,         VERR_INVALID_POINTER);
    258258    AssertPtrReturn(pDSoundStream, VERR_INVALID_POINTER);
     259    /* pdwBuffer is optional. */
     260    /* pdwFree is optional. */
     261    /* pdwPlayPos is optional. */
    259262
    260263    LPDIRECTSOUNDBUFFER8 pDSB = pDSoundStream->pDSB;
     
    305308    }
    306309
    307     LogFlowFuncLeaveRC(rc);
     310    if (RT_FAILURE(rc))
     311        LogFlowFuncLeaveRC(rc);
    308312    return rc;
    309313}
     
    15401544        cbFree     -= cbSample;
    15411545
    1542         uint32_t csLive = AudioMixBufAvail(&pStream->MixBuf);
    1543         uint32_t cbLive = AUDIOMIXBUF_S2B(&pStream->MixBuf, csLive);
     1546        uint32_t cLive  = AudioMixBufLive(&pStream->MixBuf);
     1547        uint32_t cbLive = AUDIOMIXBUF_S2B(&pStream->MixBuf, cLive);
    15441548
    15451549        /* Do not write more than available space in the DirectSound playback buffer. */
     
    22372241        PDSOUNDSTREAMOUT pDSoundStream = (PDSOUNDSTREAMOUT)pStream;
    22382242        if (pDSoundStream->fEnabled)
    2239             strmSts |= PDMAUDIOSTRMSTS_FLAG_ENABLED | PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE;
     2243        {
     2244            strmSts |= PDMAUDIOSTRMSTS_FLAG_ENABLED;
     2245
     2246            DWORD cbFree;
     2247            int rc = dsoundGetPosOut(pThis, pDSoundStream, NULL /* cbBuffer */, &cbFree, NULL /* cbPlayPos */);
     2248            if (   RT_SUCCESS(rc)
     2249                && cbFree)
     2250            {
     2251                LogFlowFunc(("cbFree=%ld\n", cbFree));
     2252                strmSts |= PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE;
     2253            }
     2254        }
    22402255    }
    22412256
  • trunk/src/VBox/Devices/Audio/DrvHostNullAudio.cpp

    r61320 r61609  
    160160
    161161    /* Consume as many samples as would be played at the current frequency since last call. */
    162     uint32_t csLive          = AudioMixBufAvail(&pStream->MixBuf);
     162    uint32_t cLive           = AudioMixBufLive(&pStream->MixBuf);
     163
    163164    uint64_t u64TicksNow     = PDMDrvHlpTMGetVirtualTime(pDrv->pDrvIns);
    164165    uint64_t u64TicksElapsed = u64TicksNow  - pNullStream->u64TicksLast;
     
    175176
    176177    /* Don't play more than available. */
    177     if (cSamplesPlayed > csLive)
    178         cSamplesPlayed = csLive;
     178    if (cSamplesPlayed > cLive)
     179        cSamplesPlayed = cLive;
    179180
    180181    cSamplesPlayed = RT_MIN(cSamplesPlayed, pNullStream->csPlayBuffer);
  • trunk/src/VBox/Devices/Audio/DrvHostOSSAudio.cpp

    r61332 r61609  
    875875        size_t cbBuf = AudioMixBufSizeBytes(&pStream->MixBuf);
    876876
    877         uint32_t cLive = AudioMixBufAvail(&pStream->MixBuf);
     877        uint32_t cLive = AudioMixBufLive(&pStream->MixBuf);
    878878        uint32_t cToRead;
    879879
  • trunk/src/VBox/Devices/Audio/DrvHostPulseAudio.cpp

    r61523 r61609  
    772772    }
    773773
     774    LogFlowFunc(("cbAvail=%zu\n", cbAvail));
     775
    774776    if (!cbAvail) /* No data? Bail out. */
    775777    {
     
    853855    {
    854856        uint32_t cProcessed = 0;
    855         if (cWrittenTotal)
     857      /*  if (cWrittenTotal)
    856858            rc = AudioMixBufMixToParent(&pStream->MixBuf, cWrittenTotal,
    857                                         &cProcessed);
     859                                        &cProcessed);*/
    858860
    859861        if (pcSamplesCaptured)
     
    14241426        && pa_stream_get_state(pStrm->pPAStream) == PA_STREAM_READY)
    14251427    {
    1426         size_t cbSize;
    1427 
    14281428        if (pStream->enmDir == PDMAUDIODIR_IN)
    14291429        {
    1430             cbSize = pa_stream_readable_size(pStrm->pPAStream);
    1431 
    1432             if (cbSize)
    1433                 strmSts |= PDMAUDIOSTRMSTS_FLAG_DATA_READABLE;
     1430            strmSts |= PDMAUDIOSTRMSTS_FLAG_DATA_READABLE;
    14341431        }
    14351432        else
    14361433        {
    1437             cbSize = pa_stream_writable_size(pStrm->pPAStream);
     1434            size_t cbSize = pa_stream_writable_size(pStrm->pPAStream);
     1435            LogFlowFunc(("cbSize=%zu\n", cbSize));
    14381436
    14391437            if (cbSize >= pStrm->BufAttr.minreq)
    14401438                strmSts |= PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE;
    14411439        }
    1442 
    1443         LogFlowFunc(("cbSize=%zu\n", cbSize));
    14441440    }
    14451441
  • trunk/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp

    r61352 r61609  
    231231        RTTESTI_CHECK_MSG_BREAK(written == cSamplesChild1, ("Child1: Expected %RU32 written samples, got %RU32\n", cSamplesChild1, written));
    232232        RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufMixToParent(&child1, written, &mixed));
    233         RTTESTI_CHECK_MSG_BREAK(AudioMixBufMixed(&child1) == mixed, ("Child1: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child1), mixed));
    234         RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&child1) == AUDIOMIXBUF_S2S_RATIO(&parent, mixed), ("Child1: Expected %RU32 used samples, got %RU32\n", AudioMixBufMixed(&child1), AUDIOMIXBUF_S2S_RATIO(&parent, mixed)));
     233        RTTESTI_CHECK_MSG_BREAK(AudioMixBufLive(&child1) == mixed, ("Child1: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufLive(&child1), mixed));
     234        RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&child1) == AUDIOMIXBUF_S2S_RATIO(&parent, mixed), ("Child1: Expected %RU32 used samples, got %RU32\n", AudioMixBufLive(&child1), AUDIOMIXBUF_S2S_RATIO(&parent, mixed)));
    235235        RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&parent) == 0, ("Parent: Expected 0 used samples, got %RU32\n", AudioMixBufUsed(&parent)));
    236236
     
    238238        RTTESTI_CHECK_MSG_BREAK(written == cSamplesChild2, ("Child2: Expected %RU32 written samples, got %RU32\n", cSamplesChild2, written));
    239239        RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufMixToParent(&child2, written, &mixed));
    240         RTTESTI_CHECK_MSG_BREAK(AudioMixBufMixed(&child2) == mixed, ("Child2: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child2), AudioMixBufUsed(&parent)));
    241         RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&child2) == AUDIOMIXBUF_S2S_RATIO(&parent, mixed), ("Child2: Expected %RU32 used samples, got %RU32\n", AudioMixBufMixed(&child2), AUDIOMIXBUF_S2S_RATIO(&parent, mixed)));
     240        RTTESTI_CHECK_MSG_BREAK(AudioMixBufLive(&child2) == mixed, ("Child2: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufLive(&child2), AudioMixBufUsed(&parent)));
     241        RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&child2) == AUDIOMIXBUF_S2S_RATIO(&parent, mixed), ("Child2: Expected %RU32 used samples, got %RU32\n", AudioMixBufLive(&child2), AUDIOMIXBUF_S2S_RATIO(&parent, mixed)));
    242242        RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&parent) == 0, ("Parent2: Expected 0 used samples, got %RU32\n", AudioMixBufUsed(&parent)));
    243243    }
    244244
    245     RTTESTI_CHECK(AudioMixBufUsed(&parent) == AudioMixBufMixed(&child1) + AudioMixBufMixed(&child2));
     245    RTTESTI_CHECK(AudioMixBufUsed(&parent) == AudioMixBufLive(&child1) + AudioMixBufLive(&child2));
    246246
    247247    for (;;)
     
    254254
    255255    RTTESTI_CHECK(AudioMixBufUsed(&parent) == 0);
    256     RTTESTI_CHECK(AudioMixBufMixed(&child1) == 0);
    257     RTTESTI_CHECK(AudioMixBufMixed(&child2) == 0);
     256    RTTESTI_CHECK(AudioMixBufLive(&child1) == 0);
     257    RTTESTI_CHECK(AudioMixBufLive(&child2) == 0);
    258258
    259259    AudioMixBufDestroy(&parent);
     
    338338    RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, written, &mixed));
    339339    temp = AudioMixBufUsed(&parent);
    340     RTTESTI_CHECK_MSG(AudioMixBufMixed(&child) == temp, ("Child: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child), temp));
    341 
    342     RTTESTI_CHECK(AudioMixBufUsed(&parent) == AudioMixBufMixed(&child));
     340    RTTESTI_CHECK_MSG(AudioMixBufLive(&child) == temp, ("Child: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufLive(&child), temp));
     341
     342    RTTESTI_CHECK(AudioMixBufUsed(&parent) == AudioMixBufLive(&child));
    343343
    344344    for (;;)
     
    366366
    367367    RTTESTI_CHECK(AudioMixBufUsed(&parent) == 0);
    368     RTTESTI_CHECK(AudioMixBufMixed(&child) == 0);
     368    RTTESTI_CHECK(AudioMixBufLive(&child) == 0);
    369369
    370370    AudioMixBufDestroy(&parent);
     
    441441    RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, written, &mixed));
    442442    temp = AudioMixBufUsed(&parent);
    443     RTTESTI_CHECK_MSG(AudioMixBufMixed(&child) == temp, ("Child: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child), temp));
    444 
    445     RTTESTI_CHECK(AudioMixBufUsed(&parent) == AudioMixBufMixed(&child));
     443    RTTESTI_CHECK_MSG(AudioMixBufLive(&child) == temp, ("Child: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufLive(&child), temp));
     444
     445    RTTESTI_CHECK(AudioMixBufUsed(&parent) == AudioMixBufLive(&child));
    446446
    447447    for (;;)
     
    468468
    469469    RTTESTI_CHECK(AudioMixBufUsed(&parent) == 0);
    470     RTTESTI_CHECK(AudioMixBufMixed(&child) == 0);
     470    RTTESTI_CHECK(AudioMixBufLive(&child) == 0);
    471471
    472472    AudioMixBufDestroy(&parent);
  • trunk/src/VBox/Main/src-client/DrvAudioVRDE.cpp

    r61320 r61609  
    254254    AssertPtrReturn(pVRDEStrmOut, VERR_INVALID_POINTER);
    255255
    256     uint32_t live = AudioMixBufAvail(&pStream->MixBuf);
     256    uint32_t cLive = AudioMixBufLive(&pStream->MixBuf);
     257
    257258    uint64_t now = PDMDrvHlpTMGetVirtualTime(pDrv->pDrvIns);
    258259    uint64_t ticks = now  - pVRDEStrmOut->old_ticks;
     
    263264
    264265    /* Don't play more than available. */
    265     if (cSamplesPlayed > live)
    266         cSamplesPlayed = live;
     266    if (cSamplesPlayed > cLive)
     267        cSamplesPlayed = cLive;
    267268
    268269    /* Remember when samples were consumed. */
Note: See TracChangeset for help on using the changeset viewer.

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