VirtualBox

Changeset 62071 in vbox for trunk/src/VBox/Devices/Audio


Ignore:
Timestamp:
Jul 6, 2016 4:01:01 PM (9 years ago)
Author:
vboxsync
Message:

Forward ported r108511 (Audio/DrvHostCoreAudio.cpp: Improved recording with USB headsets and other devices which might need on-the-fly conversion of the input data).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DrvHostCoreAudio.cpp

    r61764 r62071  
    3636#include <AudioToolbox/AudioConverter.h>
    3737
     38#if 0
     39# include <iprt/file.h>
     40# define DEBUG_DUMP_PCM_DATA
     41# ifdef RT_OS_WINDOWS
     42#  define DEBUG_DUMP_PCM_DATA_PATH "c:\\temp\\"
     43# else
     44#  define DEBUG_DUMP_PCM_DATA_PATH "/tmp/"
     45# endif
     46#endif
     47
    3848/* TODO:
    3949 * - Maybe make sure the threads are immediately stopped if playing/recording stops.
     
    6777 ******************************************************************************/
    6878
    69 static void coreAudioPrintASBDesc(const char *pszDesc, const AudioStreamBasicDescription *pStreamDesc)
     79static void coreAudioPrintASBD(const char *pszDesc, const AudioStreamBasicDescription *pASBD)
    7080{
    7181    char pszSampleRate[32];
    7282    LogRel2(("CoreAudio: %s description:\n", pszDesc));
    73     LogRel2(("CoreAudio: Format ID: %RU32 (%c%c%c%c)\n", pStreamDesc->mFormatID,
    74              RT_BYTE4(pStreamDesc->mFormatID), RT_BYTE3(pStreamDesc->mFormatID),
    75              RT_BYTE2(pStreamDesc->mFormatID), RT_BYTE1(pStreamDesc->mFormatID)));
    76     LogRel2(("CoreAudio: Flags: %RU32", pStreamDesc->mFormatFlags));
    77     if (pStreamDesc->mFormatFlags & kAudioFormatFlagIsFloat)
     83    LogRel2(("CoreAudio: Format ID: %RU32 (%c%c%c%c)\n", pASBD->mFormatID,
     84             RT_BYTE4(pASBD->mFormatID), RT_BYTE3(pASBD->mFormatID),
     85             RT_BYTE2(pASBD->mFormatID), RT_BYTE1(pASBD->mFormatID)));
     86    LogRel2(("CoreAudio: Flags: %RU32", pASBD->mFormatFlags));
     87    if (pASBD->mFormatFlags & kAudioFormatFlagIsFloat)
    7888        LogRel2((" Float"));
    79     if (pStreamDesc->mFormatFlags & kAudioFormatFlagIsBigEndian)
     89    if (pASBD->mFormatFlags & kAudioFormatFlagIsBigEndian)
    8090        LogRel2((" BigEndian"));
    81     if (pStreamDesc->mFormatFlags & kAudioFormatFlagIsSignedInteger)
     91    if (pASBD->mFormatFlags & kAudioFormatFlagIsSignedInteger)
    8292        LogRel2((" SignedInteger"));
    83     if (pStreamDesc->mFormatFlags & kAudioFormatFlagIsPacked)
     93    if (pASBD->mFormatFlags & kAudioFormatFlagIsPacked)
    8494        LogRel2((" Packed"));
    85     if (pStreamDesc->mFormatFlags & kAudioFormatFlagIsAlignedHigh)
     95    if (pASBD->mFormatFlags & kAudioFormatFlagIsAlignedHigh)
    8696        LogRel2((" AlignedHigh"));
    87     if (pStreamDesc->mFormatFlags & kAudioFormatFlagIsNonInterleaved)
     97    if (pASBD->mFormatFlags & kAudioFormatFlagIsNonInterleaved)
    8898        LogRel2((" NonInterleaved"));
    89     if (pStreamDesc->mFormatFlags & kAudioFormatFlagIsNonMixable)
     99    if (pASBD->mFormatFlags & kAudioFormatFlagIsNonMixable)
    90100        LogRel2((" NonMixable"));
    91     if (pStreamDesc->mFormatFlags & kAudioFormatFlagsAreAllClear)
     101    if (pASBD->mFormatFlags & kAudioFormatFlagsAreAllClear)
    92102        LogRel2((" AllClear"));
    93103    LogRel2(("\n"));
    94     snprintf(pszSampleRate, 32, "%.2f", (float)pStreamDesc->mSampleRate); /** @todo r=andy Use RTStrPrint*. */
     104    snprintf(pszSampleRate, 32, "%.2f", (float)pASBD->mSampleRate); /** @todo r=andy Use RTStrPrint*. */
    95105    LogRel2(("CoreAudio: SampleRate      : %s\n", pszSampleRate));
    96     LogRel2(("CoreAudio: ChannelsPerFrame: %RU32\n", pStreamDesc->mChannelsPerFrame));
    97     LogRel2(("CoreAudio: FramesPerPacket : %RU32\n", pStreamDesc->mFramesPerPacket));
    98     LogRel2(("CoreAudio: BitsPerChannel  : %RU32\n", pStreamDesc->mBitsPerChannel));
    99     LogRel2(("CoreAudio: BytesPerFrame   : %RU32\n", pStreamDesc->mBytesPerFrame));
    100     LogRel2(("CoreAudio: BytesPerPacket  : %RU32\n", pStreamDesc->mBytesPerPacket));
    101 }
    102 
    103 static void coreAudioPCMInfoToASBDesc(PDMPCMPROPS *pPcmProperties, AudioStreamBasicDescription *pStreamDesc)
    104 {
    105     pStreamDesc->mFormatID         = kAudioFormatLinearPCM;
    106     pStreamDesc->mFormatFlags      = kAudioFormatFlagIsPacked;
    107     pStreamDesc->mFramesPerPacket  = 1;
    108     pStreamDesc->mSampleRate       = (Float64)pPcmProperties->uHz;
    109     pStreamDesc->mChannelsPerFrame = pPcmProperties->cChannels;
    110     pStreamDesc->mBitsPerChannel   = pPcmProperties->cBits;
    111     if (pPcmProperties->fSigned)
    112         pStreamDesc->mFormatFlags |= kAudioFormatFlagIsSignedInteger;
    113     pStreamDesc->mBytesPerFrame    = pStreamDesc->mChannelsPerFrame * (pStreamDesc->mBitsPerChannel / 8);
    114     pStreamDesc->mBytesPerPacket   = pStreamDesc->mFramesPerPacket * pStreamDesc->mBytesPerFrame;
     106    LogRel2(("CoreAudio: ChannelsPerFrame: %RU32\n", pASBD->mChannelsPerFrame));
     107    LogRel2(("CoreAudio: FramesPerPacket : %RU32\n", pASBD->mFramesPerPacket));
     108    LogRel2(("CoreAudio: BitsPerChannel  : %RU32\n", pASBD->mBitsPerChannel));
     109    LogRel2(("CoreAudio: BytesPerFrame   : %RU32\n", pASBD->mBytesPerFrame));
     110    LogRel2(("CoreAudio: BytesPerPacket  : %RU32\n", pASBD->mBytesPerPacket));
     111}
     112
     113static void coreAudioPCMPropsToASBD(PDMPCMPROPS *pPCMProps, AudioStreamBasicDescription *pASBD)
     114{
     115    AssertPtrReturnVoid(pPCMProps);
     116    AssertPtrReturnVoid(pASBD);
     117
     118    RT_BZERO(pASBD, sizeof(AudioStreamBasicDescription));
     119
     120    pASBD->mFormatID         = kAudioFormatLinearPCM;
     121    pASBD->mFormatFlags      = kAudioFormatFlagIsPacked;
     122    pASBD->mFramesPerPacket  = 1; /* For uncompressed audio, set this to 1. */
     123    pASBD->mSampleRate       = (Float64)pPCMProps->uHz;
     124    pASBD->mChannelsPerFrame = pPCMProps->cChannels;
     125    pASBD->mBitsPerChannel   = pPCMProps->cBits;
     126    if (pPCMProps->fSigned)
     127        pASBD->mFormatFlags |= kAudioFormatFlagIsSignedInteger;
     128    pASBD->mBytesPerFrame    = pASBD->mChannelsPerFrame * (pASBD->mBitsPerChannel / 8);
     129    pASBD->mBytesPerPacket   = pASBD->mFramesPerPacket * pASBD->mBytesPerFrame;
    115130}
    116131
     
    286301    };
    287302} COREAUDIOSTREAMCBCTX, *PCOREAUDIOSTREAMCBCTX;
     303
     304/**
     305 * Structure for keeping a conversion callback context.
     306 * This is needed when using an audio converter during input/output processing.
     307 */
     308typedef struct COREAUDIOCONVCBCTX
     309{
     310    /** Pointer to stream context this converter callback context
     311     *  is bound to. */
     312    /** @todo Remove this as soon as we have unified input/output streams in this backend. */
     313    COREAUDIOSTREAMCBCTX        pStream;
     314    /** Source stream description. */
     315    AudioStreamBasicDescription asbdSrc;
     316    /** Destination stream description. */
     317    AudioStreamBasicDescription asbdDst;
     318    /** Native buffer list used for rendering the source audio data into. */
     319    AudioBufferList             bufLstSrc;
     320    /** Total packet conversion count. */
     321    UInt32                      uPacketCnt;
     322    /** Current packet conversion index. */
     323    UInt32                      uPacketIdx;
     324} COREAUDIOCONVCBCTX, *PCOREAUDIOCONVCBCTX;
    288325
    289326/** @todo Unify COREAUDIOSTREAMOUT / COREAUDIOSTREAMIN. */
     
    302339    AudioUnit                   audioUnit;
    303340    /** A ring buffer for transferring data to the playback thread. */
    304     PRTCIRCBUF                  pBuf;
     341    PRTCIRCBUF                  pCircBuf;
    305342    /** Initialization status tracker. Used when some of the device parameters
    306343     *  or the device itself is changed during the runtime. */
     
    329366    /** The AudioUnit used. */
    330367    AudioUnit                   audioUnit;
    331     /** The audio converter if necessary. */
     368    /** A ring buffer for transferring data from the capturing thread. */
     369    PRTCIRCBUF                  pCircBuf;
     370    /** The audio converter if necessary. NULL if no converter is being used. */
    332371    AudioConverterRef           pConverter;
    333     /** Native buffer used for render the audio data in the recording thread. */
    334     AudioBufferList             bufferList;
    335     /** Reading offset for the bufferList's buffer. */
    336     uint32_t                    offBufferRead;
     372    /** Callback context for the audio converter. */
     373    COREAUDIOCONVCBCTX          convCbCtx;
    337374    /** The ratio between the device & the stream sample rate. */
    338375    Float64                     sampleRatio;
    339     /** A ring buffer for transferring data from the recording thread. */
    340     PRTCIRCBUF                  pBuf;
    341376    /** Initialization status tracker. Used when some of the device parameters
    342377     *  or the device itself is changed during the runtime. */
     
    366401
    367402/**
    368  * Does a (Re-)enumeration of the host's playback + capturing devices.
     403 * Initializes a conversion callback context.
     404 *
     405 * @return  IPRT status code.
     406 * @param   pConvCbCtx          Conversion callback context to initialize.
     407 * @param   pASBDSrc            Input (source) stream description to use.
     408 * @param   pASBDDst            Output (destination) stream description to use.
     409 */
     410static int coreAudioInitConvCbCtx(PCOREAUDIOCONVCBCTX pConvCbCtx,
     411                                  AudioStreamBasicDescription *pASBDSrc, AudioStreamBasicDescription *pASBDDst)
     412{
     413    AssertPtrReturn(pConvCbCtx, VERR_INVALID_POINTER);
     414    AssertPtrReturn(pASBDSrc,   VERR_INVALID_POINTER);
     415    AssertPtrReturn(pASBDDst,   VERR_INVALID_POINTER);
     416
     417    memcpy(&pConvCbCtx->asbdSrc, pASBDSrc, sizeof(AudioStreamBasicDescription));
     418    memcpy(&pConvCbCtx->asbdDst, pASBDDst, sizeof(AudioStreamBasicDescription));
     419
     420    /* Create the AudioBufferList structure with one buffer. */
     421    pConvCbCtx->bufLstSrc.mNumberBuffers              = 1;
     422
     423    /* Initialize the conversion buffer. */
     424    pConvCbCtx->bufLstSrc.mBuffers[0].mNumberChannels = pConvCbCtx->asbdSrc.mChannelsPerFrame;
     425    pConvCbCtx->bufLstSrc.mBuffers[0].mDataByteSize   = 0;
     426    pConvCbCtx->bufLstSrc.mBuffers[0].mData           = NULL;
     427
     428    return VINF_SUCCESS;
     429}
     430
     431/**
     432 * Uninitializes a conversion callback context.
     433 *
     434 * @return  IPRT status code.
     435 * @param   pConvCbCtx          Conversion callback context to uninitialize.
     436 */
     437static void coreAudioUninitConvCbCtx(PCOREAUDIOCONVCBCTX pConvCbCtx)
     438{
     439    AssertPtrReturnVoid(pConvCbCtx);
     440
     441    RT_ZERO(pConvCbCtx->asbdSrc);
     442    RT_ZERO(pConvCbCtx->asbdDst);
     443
     444    pConvCbCtx->bufLstSrc.mNumberBuffers = 0;
     445}
     446
     447/**
     448 * Does a (Re-)enumeration of the host's playback + recording devices.
    369449 *
    370450 * @return  IPRT status code.
     
    474554
    475555    if (fIn)
    476         LogRel2(("CoreAudio: Found %RU8 capturing device(s)\n", cDevs));
     556        LogRel2(("CoreAudio: Found %RU8 recording device(s)\n", cDevs));
    477557    else
    478558        LogRel2(("CoreAudio: Found %RU8 playback device(s)\n", cDevs));
     
    624704                UInt32 uResp;
    625705                err = AudioObjectGetPropertyData(kAudioObjectSystemObject, pProperty, 0, NULL, &uSize, &uResp);
     706
    626707                if (err == noErr)
    627708                {
     
    652733                UInt32 uResp;
    653734                err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propAdr, 0, NULL, &uSize, &uResp);
     735
    654736                if (err == noErr)
    655737                {
     
    719801
    720802/* Callback to convert audio input data from one format to another. */
    721 static DECLCALLBACK(OSStatus) coreAudioConverterCb(AudioConverterRef              converterID,
    722                                                    UInt32                        *pcPackets,
    723                                                    AudioBufferList               *pBufData,
    724                                                    AudioStreamPacketDescription **ppPacketDesc,
    725                                                    void                          *pvUser)
    726 {
    727     /** @todo Check incoming pointers. */
    728 
    729     PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pvUser;
     803static DECLCALLBACK(OSStatus) coreAudioConverterCallback(AudioConverterRef              inAudioConverter,
     804                                                         UInt32                        *ioNumberDataPackets,
     805                                                         AudioBufferList               *ioData,
     806                                                         AudioStreamPacketDescription **ppASPD,
     807                                                         void                          *pvUser)
     808{
     809    AssertPtrReturn(ioNumberDataPackets, caConverterEOFDErr);
     810    AssertPtrReturn(ioData,              caConverterEOFDErr);
     811
     812    PCOREAUDIOCONVCBCTX pConvCbCtx = (PCOREAUDIOCONVCBCTX)pvUser;
     813    AssertPtr(pConvCbCtx);
     814
     815    /* Initialize values. */
     816    ioData->mBuffers[0].mNumberChannels = 0;
     817    ioData->mBuffers[0].mDataByteSize   = 0;
     818    ioData->mBuffers[0].mData           = NULL;
    730819
    731820    /** @todo Check converter ID? */
    732821
    733     const AudioBufferList *pBufferList = &pStreamIn->bufferList;
    734 
    735     if (ASMAtomicReadU32(&pStreamIn->status) != CA_STATUS_INIT)
    736         return noErr;
    737 
    738     /** @todo In principle we had to check here if the source is non interleaved, and if so,
    739      *        so go through all buffers not only the first one like now. */
    740 
    741     /* Use the lower one of the packets to process & the available packets in the buffer. */
    742     Assert(pBufferList->mBuffers[0].mDataByteSize >= pStreamIn->offBufferRead);
    743     UInt32 cSize = RT_MIN(*pcPackets * pStreamIn->deviceFormat.mBytesPerPacket,
    744                           pBufferList->mBuffers[0].mDataByteSize - pStreamIn->offBufferRead);
    745 
    746     /* Set the new size on output, so the caller know what we have processed. */
    747     Assert(pStreamIn->deviceFormat.mBytesPerPacket);
    748     *pcPackets = cSize / pStreamIn->deviceFormat.mBytesPerPacket;
    749 
    750     OSStatus err;
    751 
    752     /* If no data is available anymore we return with an error code. This error code will be returned
    753      * from AudioConverterFillComplexBuffer. */
    754     if (*pcPackets == 0)
    755     {
    756         pBufData->mBuffers[0].mDataByteSize = 0;
    757         pBufData->mBuffers[0].mData         = NULL;
    758 
    759         err = caConverterEOFDErr;
    760     }
    761     else
    762     {
    763         pBufData->mBuffers[0].mNumberChannels = pBufferList->mBuffers[0].mNumberChannels;
    764         pBufData->mBuffers[0].mDataByteSize   = cSize;
    765         pBufData->mBuffers[0].mData           = (uint8_t *)pBufferList->mBuffers[0].mData + pStreamIn->offBufferRead;
    766 
    767         pStreamIn->offBufferRead += cSize;
    768 
    769         err = noErr;
    770     }
    771 
    772     return err;
     822    /** @todo Handled non-interleaved data by going through the full buffer list,
     823     *        not only through the first buffer like we do now. */
     824
     825    Log3Func(("ioNumberDataPackets=%RU32\n", *ioNumberDataPackets));
     826
     827    if (pConvCbCtx->uPacketIdx + *ioNumberDataPackets > pConvCbCtx->uPacketCnt)
     828    {
     829        Log3Func(("Limiting ioNumberDataPackets to %RU32\n", pConvCbCtx->uPacketCnt - pConvCbCtx->uPacketIdx));
     830        *ioNumberDataPackets = pConvCbCtx->uPacketCnt - pConvCbCtx->uPacketIdx;
     831    }
     832
     833    if (*ioNumberDataPackets)
     834    {
     835        Assert(pConvCbCtx->bufLstSrc.mNumberBuffers == 1); /* Only one buffer for the source supported atm. */
     836
     837        size_t cbOff   = pConvCbCtx->uPacketIdx * pConvCbCtx->asbdSrc.mBytesPerPacket;
     838
     839        size_t cbAvail = RT_MIN(*ioNumberDataPackets * pConvCbCtx->asbdSrc.mBytesPerPacket,
     840                                pConvCbCtx->bufLstSrc.mBuffers[0].mDataByteSize - cbOff);
     841
     842        void  *pvAvail = (uint8_t *)pConvCbCtx->bufLstSrc.mBuffers[0].mData + cbOff;
     843
     844        Log3Func(("cbOff=%zu, cbAvail=%zu\n", cbOff, cbAvail));
     845
     846        /* Set input data for the converter to use.
     847         * Note: For VBR (Variable Bit Rates) or interleaved data handling we need multiple buffers here. */
     848        ioData->mNumberBuffers = 1;
     849
     850        ioData->mBuffers[0].mNumberChannels = pConvCbCtx->bufLstSrc.mBuffers[0].mNumberChannels;
     851        ioData->mBuffers[0].mDataByteSize   = cbAvail;
     852        ioData->mBuffers[0].mData           = pvAvail;
     853
     854#ifdef DEBUG_DUMP_PCM_DATA
     855        RTFILE fh;
     856        int rc = RTFileOpen(&fh, DEBUG_DUMP_PCM_DATA_PATH "ca-converter-cb-input.pcm",
     857                            RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
     858        if (RT_SUCCESS(rc))
     859        {
     860            RTFileWrite(fh, pvAvail, cbAvail, NULL);
     861            RTFileClose(fh);
     862        }
     863        else
     864            AssertFailed();
     865#endif
     866
     867        pConvCbCtx->uPacketIdx += *ioNumberDataPackets;
     868        Assert(pConvCbCtx->uPacketIdx <= pConvCbCtx->uPacketCnt);
     869    }
     870
     871    Log3Func(("%RU32 / %RU32 -> ioNumberDataPackets=%RU32\n",
     872              pConvCbCtx->uPacketIdx, pConvCbCtx->uPacketCnt, *ioNumberDataPackets));
     873
     874    return noErr;
    773875}
    774876
    775877/* Callback to feed audio input buffer. */
    776 static DECLCALLBACK(OSStatus) coreAudioRecordingCb(void *pvUser,
     878static DECLCALLBACK(OSStatus) coreAudioRecordingCb(void                       *pvUser,
    777879                                                   AudioUnitRenderActionFlags *pActionFlags,
    778880                                                   const AudioTimeStamp       *pAudioTS,
     
    781883                                                   AudioBufferList            *pBufData)
    782884{
    783     PCOREAUDIOSTREAMIN pStreamIn  = (PCOREAUDIOSTREAMIN)pvUser;
    784     PPDMAUDIOSTREAM pStream = &pStreamIn->Stream;
    785 
    786     if (ASMAtomicReadU32(&pStreamIn->status) != CA_STATUS_INIT)
    787         return noErr;
    788 
    789885    /* If nothing is pending return immediately. */
    790886    if (cFrames == 0)
    791887        return noErr;
    792888
     889    PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pvUser;
     890
     891    if (ASMAtomicReadU32(&pStreamIn->status) != CA_STATUS_INIT)
     892        return noErr;
     893
     894    PCOREAUDIOCONVCBCTX pConvCbCtx = &pStreamIn->convCbCtx;
     895
    793896    OSStatus err = noErr;
    794897    int rc = VINF_SUCCESS;
    795898
     899    Assert(pConvCbCtx->bufLstSrc.mNumberBuffers == 1);
     900    AudioBuffer *pSrcBuf = &pConvCbCtx->bufLstSrc.mBuffers[0];
     901
     902    pConvCbCtx->uPacketCnt = cFrames / pConvCbCtx->asbdSrc.mFramesPerPacket;
     903    pConvCbCtx->uPacketIdx = 0;
     904
     905    AudioConverterReset(pStreamIn->pConverter);
     906
     907    Log3Func(("cFrames=%RU32 (%RU32 frames per packet) -> %RU32 packets\n",
     908               cFrames, pConvCbCtx->asbdSrc.mFramesPerPacket, pConvCbCtx->uPacketCnt));
     909
    796910    do
    797911    {
     
    799913        if (pStreamIn->pConverter)
    800914        {
    801             /* First, render the data as usual. */
    802             pStreamIn->bufferList.mBuffers[0].mNumberChannels = pStreamIn->deviceFormat.mChannelsPerFrame;
    803             pStreamIn->bufferList.mBuffers[0].mDataByteSize   = pStreamIn->deviceFormat.mBytesPerFrame * cFrames;
    804             AssertBreakStmt(pStreamIn->bufferList.mBuffers[0].mDataByteSize, rc = VERR_INVALID_PARAMETER);
    805             pStreamIn->bufferList.mBuffers[0].mData           = RTMemAlloc(pStreamIn->bufferList.mBuffers[0].mDataByteSize);
    806             if (!pStreamIn->bufferList.mBuffers[0].mData)
     915            pSrcBuf->mNumberChannels = pConvCbCtx->asbdSrc.mChannelsPerFrame;
     916            pSrcBuf->mDataByteSize   = pConvCbCtx->asbdSrc.mBytesPerFrame * cFrames;
     917            pSrcBuf->mData           = RTMemAllocZ(pSrcBuf->mDataByteSize);
     918            if (!pSrcBuf->mData)
    807919            {
    808920                rc = VERR_NO_MEMORY;
     
    810922            }
    811923
    812             err = AudioUnitRender(pStreamIn->audioUnit, pActionFlags, pAudioTS, uBusID, cFrames, &pStreamIn->bufferList);
     924            /* First, render the source data as usual. */
     925            err = AudioUnitRender(pStreamIn->audioUnit, pActionFlags, pAudioTS, uBusID, cFrames, &pConvCbCtx->bufLstSrc);
    813926            if (err != noErr)
    814927            {
     
    818931            }
    819932
    820             size_t cbAvail = RT_MIN(RTCircBufFree(pStreamIn->pBuf), pStreamIn->bufferList.mBuffers[0].mDataByteSize);
    821 
    822             /* Initialize the temporary output buffer */
    823             AudioBufferList tmpList;
    824             tmpList.mNumberBuffers = 1;
    825             tmpList.mBuffers[0].mNumberChannels = pStreamIn->streamFormat.mChannelsPerFrame;
    826 
    827             /* Set the read position to zero. */
    828             pStreamIn->offBufferRead = 0;
    829 
    830             /* Iterate as long as data is available. */
    831             uint8_t *puDst = NULL;
    832             while (cbAvail)
    833             {
    834                 /* Try to acquire the necessary space from the ring buffer. */
    835                 size_t cbToWrite = 0;
    836                 RTCircBufAcquireWriteBlock(pStreamIn->pBuf, cbAvail, (void **)&puDst, &cbToWrite);
    837                 if (!cbToWrite)
    838                     break;
    839 
    840                 /* Now set how much space is available for output. */
    841                 Assert(pStreamIn->streamFormat.mBytesPerPacket);
    842 
    843                 UInt32 ioOutputDataPacketSize = cbToWrite / pStreamIn->streamFormat.mBytesPerPacket;
    844 
    845                 /* Set our ring buffer as target. */
    846                 tmpList.mBuffers[0].mDataByteSize = cbToWrite;
    847                 tmpList.mBuffers[0].mData         = puDst;
    848 
    849                 AudioConverterReset(pStreamIn->pConverter);
    850 
    851                 err = AudioConverterFillComplexBuffer(pStreamIn->pConverter, coreAudioConverterCb, pStreamIn,
    852                                                       &ioOutputDataPacketSize, &tmpList, NULL);
    853                 if(   err != noErr
    854                    && err != caConverterEOFDErr)
     933            Log3Func(("cbSrcBufSize=%RU32\n", pSrcBuf->mDataByteSize));
     934
     935#ifdef DEBUG_DUMP_PCM_DATA
     936            RTFILE fh;
     937            rc = RTFileOpen(&fh, DEBUG_DUMP_PCM_DATA_PATH "ca-recording-cb-src.pcm",
     938                            RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
     939            if (RT_SUCCESS(rc))
     940            {
     941                RTFileWrite(fh, pSrcBuf->mData, pSrcBuf->mDataByteSize, NULL);
     942                RTFileClose(fh);
     943            }
     944            else
     945                AssertFailed();
     946#endif
     947            AudioBufferList dstBufList;
     948
     949            dstBufList.mNumberBuffers = 1; /* We only use one buffer at once. */
     950
     951            AudioBuffer *pDstBuf = &dstBufList.mBuffers[0];
     952            pDstBuf->mDataByteSize   = pConvCbCtx->asbdDst.mBytesPerFrame * cFrames;
     953            pDstBuf->mData           = RTMemAllocZ(pDstBuf->mDataByteSize);
     954            if (!pDstBuf->mData)
     955            {
     956                rc = VERR_NO_MEMORY;
     957                break;
     958            }
     959
     960            UInt32 cPacketsToWriteAndWritten = pConvCbCtx->uPacketCnt;
     961            Assert(cPacketsToWriteAndWritten);
     962
     963            Log3Func(("cPacketsToWrite=%RU32\n", cPacketsToWriteAndWritten));
     964
     965            do
     966            {
     967                err = AudioConverterFillComplexBuffer(pStreamIn->pConverter,
     968                                                      coreAudioConverterCallback, pConvCbCtx /* pvData */,
     969                                                      &cPacketsToWriteAndWritten, &dstBufList, NULL);
     970
     971                Log3Func(("cPacketsWritten=%RU32 (%zu bytes), err=%RI32\n",
     972                          cPacketsToWriteAndWritten, cPacketsToWriteAndWritten * pConvCbCtx->asbdDst.mBytesPerPacket, err));
     973
     974                if (err != noErr)
    855975                {
    856                     LogFunc(("Failed to convert audio data (%RI32:%c%c%c%c)\n", err,
    857                              RT_BYTE4(err), RT_BYTE3(err), RT_BYTE2(err), RT_BYTE1(err)));
     976                    LogFlowFunc(("Failed to convert audio data (%RI32:%c%c%c%c)\n", err,
     977                                 RT_BYTE4(err), RT_BYTE3(err), RT_BYTE2(err), RT_BYTE1(err)));
    858978                    rc = VERR_IO_GEN_FAILURE;
    859979                    break;
    860980                }
    861981
    862                 /* Check in any case what processed size is returned. It could be less than we expected. */
    863                 cbToWrite = ioOutputDataPacketSize * pStreamIn->streamFormat.mBytesPerPacket;
    864 
    865                 Log3Func(("cbToWrite=%RU32\n", cbToWrite));
    866 
    867                 /* Release the ring buffer, so the main thread could start reading this data. */
    868                 RTCircBufReleaseWriteBlock(pStreamIn->pBuf, cbToWrite);
    869 
    870                 /* If the error is "End of Data" it means there is no data anymore
    871                  * which could be converted. So end here now. */
    872                 if (err == caConverterEOFDErr)
     982                if (cPacketsToWriteAndWritten == 0)
    873983                    break;
    874984
    875                 Assert(cbAvail >= cbToWrite);
    876                 cbAvail -= cbToWrite;
     985                size_t cbDst = cPacketsToWriteAndWritten * pConvCbCtx->asbdDst.mBytesPerPacket;
     986
     987#ifdef DEBUG_DUMP_PCM_DATA
     988                rc = RTFileOpen(&fh, DEBUG_DUMP_PCM_DATA_PATH "ca-recording-cb-dst.pcm",
     989                                RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
     990                if (RT_SUCCESS(rc))
     991                {
     992                    RTFileWrite(fh, pDstBuf->mData, cbDst, NULL);
     993                    RTFileClose(fh);
     994                }
     995                else
     996                    AssertFailed();
     997#endif
     998                size_t cbFree = RTCircBufFree(pStreamIn->pCircBuf);
     999                if (cbFree < cbDst)
     1000                {
     1001                    LogRel2(("CoreAudio: Capturing is lagging behind (%zu bytes available but only %zu bytes free)\n",
     1002                             cbDst, cbFree));
     1003                    break;
     1004                }
     1005
     1006                size_t cbDstChunk;
     1007                void  *puDst;
     1008                RTCircBufAcquireWriteBlock(pStreamIn->pCircBuf, cbDst, (void **)&puDst, &cbDstChunk);
     1009
     1010                if (cbDstChunk)
     1011                    memcpy(puDst, pDstBuf->mData, cbDstChunk);
     1012
     1013                RTCircBufReleaseWriteBlock(pStreamIn->pCircBuf, cbDstChunk);
     1014
     1015            } while (1);
     1016
     1017            if (pDstBuf->mData)
     1018            {
     1019                RTMemFree(pDstBuf->mData);
     1020                pDstBuf->mData = NULL;
    8771021            }
    8781022        }
    8791023        else /* No converter being used. */
    8801024        {
    881             AssertBreakStmt(pStreamIn->streamFormat.mChannelsPerFrame >= 1,    rc = VERR_INVALID_PARAMETER);
    882             AssertBreakStmt(pStreamIn->streamFormat.mBytesPerFrame >= 1,       rc = VERR_INVALID_PARAMETER);
    883 
    884             AssertBreakStmt(pStreamIn->bufferList.mNumberBuffers >= 1,         rc = VERR_INVALID_PARAMETER);
    885             AssertBreakStmt(pStreamIn->bufferList.mBuffers[0].mNumberChannels, rc = VERR_INVALID_PARAMETER);
    886 
    887             pStreamIn->bufferList.mBuffers[0].mNumberChannels = pStreamIn->streamFormat.mChannelsPerFrame;
    888             pStreamIn->bufferList.mBuffers[0].mDataByteSize   = pStreamIn->streamFormat.mBytesPerFrame * cFrames;
    889             pStreamIn->bufferList.mBuffers[0].mData           = RTMemAlloc(pStreamIn->bufferList.mBuffers[0].mDataByteSize);
    890             if (!pStreamIn->bufferList.mBuffers[0].mData)
     1025            AssertBreakStmt(pStreamIn->streamFormat.mChannelsPerFrame >= 1, rc = VERR_INVALID_PARAMETER);
     1026            AssertBreakStmt(pStreamIn->streamFormat.mBytesPerFrame >= 1,    rc = VERR_INVALID_PARAMETER);
     1027
     1028            AssertBreakStmt(pSrcBuf->mNumberChannels, rc = VERR_INVALID_PARAMETER);
     1029
     1030            pSrcBuf->mNumberChannels = pStreamIn->streamFormat.mChannelsPerFrame;
     1031            pSrcBuf->mDataByteSize   = pStreamIn->streamFormat.mBytesPerFrame * cFrames;
     1032            pSrcBuf->mData           = RTMemAlloc(pSrcBuf->mDataByteSize);
     1033            if (!pSrcBuf->mData)
    8911034            {
    8921035                rc = VERR_NO_MEMORY;
     
    8941037            }
    8951038
    896             err = AudioUnitRender(pStreamIn->audioUnit, pActionFlags, pAudioTS, uBusID, cFrames, &pStreamIn->bufferList);
     1039            err = AudioUnitRender(pStreamIn->audioUnit, pActionFlags, pAudioTS, uBusID, cFrames, &pConvCbCtx->bufLstSrc);
    8971040            if (err != noErr)
    8981041            {
     
    9021045            }
    9031046
    904             const uint32_t cbDataSize = pStreamIn->bufferList.mBuffers[0].mDataByteSize;
    905             const size_t   cbBufFree  = RTCircBufFree(pStreamIn->pBuf);
     1047            const uint32_t cbDataSize = pSrcBuf->mDataByteSize;
     1048            const size_t   cbBufFree  = RTCircBufFree(pStreamIn->pCircBuf);
    9061049                  size_t   cbAvail    = RT_MIN(cbDataSize, cbBufFree);
    9071050
     
    9151058                /* Try to acquire the necessary space from the ring buffer. */
    9161059                size_t cbToWrite = 0;
    917                 RTCircBufAcquireWriteBlock(pStreamIn->pBuf, cbAvail, (void **)&puDst, &cbToWrite);
     1060                RTCircBufAcquireWriteBlock(pStreamIn->pCircBuf, cbAvail, (void **)&puDst, &cbToWrite);
    9181061                if (!cbToWrite)
    9191062                    break;
    9201063
    9211064                /* Copy the data from the Core Audio buffer to the ring buffer. */
    922                 memcpy(puDst, (uint8_t *)pStreamIn->bufferList.mBuffers[0].mData + cbWrittenTotal, cbToWrite);
     1065                memcpy(puDst, (uint8_t *)pSrcBuf->mData + cbWrittenTotal, cbToWrite);
    9231066
    9241067                /* Release the ring buffer, so the main thread could start reading this data. */
    925                 RTCircBufReleaseWriteBlock(pStreamIn->pBuf, cbToWrite);
     1068                RTCircBufReleaseWriteBlock(pStreamIn->pCircBuf, cbToWrite);
    9261069
    9271070                cbWrittenTotal += cbToWrite;
     
    9361079    } while (0);
    9371080
    938     if (pStreamIn->bufferList.mBuffers[0].mData)
    939     {
    940         RTMemFree(pStreamIn->bufferList.mBuffers[0].mData);
    941         pStreamIn->bufferList.mBuffers[0].mData = NULL;
    942     }
    943 
    944     if (RT_FAILURE(rc))
    945         LogFunc(("Failed with rc=%Rrc\n", rc));
     1081    if (pSrcBuf->mData)
     1082    {
     1083        RTMemFree(pSrcBuf->mData);
     1084        pSrcBuf->mData = NULL;
     1085    }
    9461086
    9471087    return err;
     
    9601100    UInt32 cSamples = 0;
    9611101
     1102    OSStatus err = noErr;
     1103    AudioDeviceID deviceID = pStreamIn->deviceID;
     1104
     1105    UInt32 uSize = 0;
     1106    if (deviceID == kAudioDeviceUnknown)
     1107    {
     1108        /* Fetch the default audio recording device currently in use. */
     1109        AudioObjectPropertyAddress propAdr = { kAudioHardwarePropertyDefaultInputDevice,
     1110                                               kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
     1111        uSize = sizeof(deviceID);
     1112        err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propAdr, 0, NULL, &uSize,  &deviceID);
     1113        if (err != noErr)
     1114        {
     1115            LogFlowFunc(("CoreAudio: Unable to determine default recording device (%RI32)\n", err));
     1116            return VERR_AUDIO_NO_FREE_INPUT_STREAMS;
     1117        }
     1118    }
     1119
     1120    if (deviceID == kAudioDeviceUnknown)
     1121    {
     1122        LogFlowFunc(("No default recording device found\n"));
     1123        return VERR_AUDIO_NO_FREE_INPUT_STREAMS;
     1124    }
     1125
    9621126    do
    9631127    {
    9641128        ASMAtomicXchgU32(&pStreamIn->status, CA_STATUS_IN_INIT);
    9651129
    966         OSStatus err;
    967 
    968         UInt32 uSize = 0;
    969         if (pStreamIn->deviceID == kAudioDeviceUnknown)
    970         {
    971             /* Fetch the default audio recording device currently in use. */
    972             AudioObjectPropertyAddress propAdr = { kAudioHardwarePropertyDefaultInputDevice,
    973                                                    kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
    974             uSize = sizeof(pStreamIn->deviceID);
    975             err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propAdr, 0, NULL, &uSize, &pStreamIn->deviceID);
    976             if (err != noErr)
    977             {
    978                 LogRel2(("CoreAudio: Unable to determine default recording device (%RI32)\n", err));
    979                 return VERR_AUDIO_NO_FREE_INPUT_STREAMS;
    980             }
    981         }
    982 
    983         if (pStreamIn->deviceID == kAudioDeviceUnknown)
    984         {
    985             LogFlowFunc(("No default recording device found\n"));
    986             return VERR_AUDIO_NO_FREE_INPUT_STREAMS;
    987         }
     1130        /* Assign device ID. */
     1131        pStreamIn->deviceID = deviceID;
    9881132
    9891133        /*
     
    11221266
    11231267        /* Fetch the current stream format of the device. */
     1268        RT_ZERO(pStreamIn->deviceFormat);
    11241269        uSize = sizeof(pStreamIn->deviceFormat);
    11251270        err = AudioUnitGetProperty(pStreamIn->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input,
     
    11321277
    11331278        /* Create an AudioStreamBasicDescription based on our required audio settings. */
    1134         coreAudioPCMInfoToASBDesc(&pStreamIn->Stream.Props, &pStreamIn->streamFormat);
    1135 
    1136         coreAudioPrintASBDesc("CoreAudio: Recording device", &pStreamIn->deviceFormat);
    1137         coreAudioPrintASBDesc("CoreAudio: Recording stream", &pStreamIn->streamFormat);
     1279        RT_ZERO(pStreamIn->streamFormat);
     1280        coreAudioPCMPropsToASBD(&pStreamIn->Stream.Props, &pStreamIn->streamFormat);
     1281
     1282        coreAudioPrintASBD("Recording device", &pStreamIn->deviceFormat);
     1283        coreAudioPrintASBD("Recording stream", &pStreamIn->streamFormat);
    11381284
    11391285        /* If the frequency of the device is different from the requested one we
     
    11421288            || pStreamIn->deviceFormat.mChannelsPerFrame != pStreamIn->streamFormat.mChannelsPerFrame)
    11431289        {
    1144             LogRel(("CoreAudio: Input converter is active\n"));
     1290            LogRel2(("CoreAudio: Input converter is active\n"));
    11451291
    11461292            err = AudioConverterNew(&pStreamIn->deviceFormat, &pStreamIn->streamFormat, &pStreamIn->pConverter);
     
    11541300                && pStreamIn->streamFormat.mChannelsPerFrame == 2 /* Stereo */)
    11551301            {
     1302                LogRel2(("CoreAudio: Mono to stereo conversion active\n"));
     1303
    11561304                /*
    11571305                 * If the channel count is different we have to tell this the converter
     
    11611309                 * cases.
    11621310                 */
    1163                 const SInt32 channelMap[2] = {0, 0}; /* Channel map for mono -> stereo, */
     1311                const SInt32 channelMap[2] = {0, 0}; /* Channel map for mono -> stereo. */
    11641312
    11651313                err = AudioConverterSetProperty(pStreamIn->pConverter, kAudioConverterChannelMap, sizeof(channelMap), channelMap);
     
    11701318                }
    11711319            }
    1172 #if 0
     1320
    11731321            /* Set sample rate converter quality to maximum. */
    11741322            uFlag = kAudioConverterQuality_Max;
    1175             err = AudioConverterSetProperty(pStreamIn->converter, kAudioConverterSampleRateConverterQuality,
     1323            err = AudioConverterSetProperty(pStreamIn->pConverter, kAudioConverterSampleRateConverterQuality,
    11761324                                            sizeof(uFlag), &uFlag);
    11771325            if (err != noErr)
    1178                 LogRel(("CoreAudio: Failed to set input audio converter quality to the maximum (%RI32)\n", err));
    1179 #endif
    1180             /* Set the new format description for the stream. */
     1326                LogRel2(("CoreAudio: Failed to set input audio converter quality to the maximum (%RI32)\n", err));
     1327
     1328            uSize = sizeof(UInt32);
     1329            UInt32 maxOutputSize;
     1330            err = AudioConverterGetProperty(pStreamIn->pConverter, kAudioConverterPropertyMaximumOutputPacketSize,
     1331                                            &uSize, &maxOutputSize);
     1332            if (RT_UNLIKELY(err != noErr))
     1333            {
     1334                LogRel(("CoreAudio: Failed to retrieve converter's maximum output size (%RI32)\n", err));
     1335                CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1336            }
     1337
     1338            LogFunc(("Maximum converter packet output size is: %RI32\n", maxOutputSize));
     1339
     1340            /* Set the input (source) format, that is, the format the device is recording data with. */
     1341            err = AudioUnitSetProperty(pStreamIn->audioUnit,
     1342                                       kAudioUnitProperty_StreamFormat,
     1343                                       kAudioUnitScope_Input,
     1344                                       1,
     1345                                       &pStreamIn->deviceFormat,
     1346                                       sizeof(pStreamIn->deviceFormat));
     1347            if (RT_UNLIKELY(err != noErr))
     1348            {
     1349                LogRel(("CoreAudio: Failed to set device input format (%RI32)\n", err));
     1350                CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1351            }
     1352
     1353            /* Set the output (target) format, that is, the format we created the input stream with. */
    11811354            err = AudioUnitSetProperty(pStreamIn->audioUnit,
    11821355                                       kAudioUnitProperty_StreamFormat,
     
    11871360            if (RT_UNLIKELY(err != noErr))
    11881361            {
    1189                 LogRel(("CoreAudio: Failed to set input stream output format (%RI32)\n", err));
     1362                LogRel(("CoreAudio: Failed to set stream output format (%RI32)\n", err));
    11901363                CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
    11911364            }
    1192 
    1193             err = AudioUnitSetProperty(pStreamIn->audioUnit,
    1194                                        kAudioUnitProperty_StreamFormat,
    1195                                        kAudioUnitScope_Input,
    1196                                        1,
    1197                                        &pStreamIn->deviceFormat,
    1198                                        sizeof(pStreamIn->deviceFormat));
    1199             if (RT_UNLIKELY(err != noErr))
    1200             {
    1201                 LogRel(("CoreAudio: Failed to set stream input format (%RI32)\n", err));
    1202                 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
    1203             }
    12041365        }
    12051366        else
    12061367        {
    1207 
    12081368            /* Set the new output format description for the input stream. */
    12091369            err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output,
     
    12611421
    12621422        /* Destroy any former internal ring buffer. */
    1263         if (pStreamIn->pBuf)
    1264         {
    1265             RTCircBufDestroy(pStreamIn->pBuf);
    1266             pStreamIn->pBuf = NULL;
    1267         }
     1423        if (pStreamIn->pCircBuf)
     1424        {
     1425            RTCircBufDestroy(pStreamIn->pCircBuf);
     1426            pStreamIn->pCircBuf = NULL;
     1427        }
     1428
     1429        coreAudioUninitConvCbCtx(&pStreamIn->convCbCtx);
    12681430
    12691431        /* Calculate the ratio between the device and the stream sample rate. */
    12701432        pStreamIn->sampleRatio = pStreamIn->streamFormat.mSampleRate / pStreamIn->deviceFormat.mSampleRate;
    1271 
    1272         /* Create the AudioBufferList structure with one buffer. */
    1273         pStreamIn->bufferList.mNumberBuffers = 1;
    1274         /* Initialize the buffer to nothing. */
    1275         pStreamIn->bufferList.mBuffers[0].mNumberChannels = pStreamIn->streamFormat.mChannelsPerFrame;
    1276         pStreamIn->bufferList.mBuffers[0].mDataByteSize = 0;
    1277         pStreamIn->bufferList.mBuffers[0].mData = NULL;
    12781433
    12791434        /*
     
    12941449        }
    12951450
    1296         /* Create the internal ring buffer. */
    1297         rc = RTCircBufCreate(&pStreamIn->pBuf, cSamples << pStream->Props.cShift);
     1451        if (RT_SUCCESS(rc))
     1452            rc = RTCircBufCreate(&pStreamIn->pCircBuf, cSamples << pStreamIn->Stream.Props.cShift);
     1453
     1454        /* Init the converter callback context. */
     1455        if (RT_SUCCESS(rc))
     1456            rc = coreAudioInitConvCbCtx(&pStreamIn->convCbCtx,
     1457                                        &pStreamIn->deviceFormat /* Source */, &pStreamIn->streamFormat /* Dest */);
     1458
     1459        if (RT_SUCCESS(rc))
     1460        {
     1461#ifdef DEBUG
     1462            propAdr.mSelector = kAudioDeviceProcessorOverload;
     1463            propAdr.mScope    = kAudioUnitScope_Global;
     1464            err = AudioObjectAddPropertyListener(pStreamIn->deviceID, &propAdr,
     1465                                                 coreAudioRecordingAudioDevicePropertyChanged, (void *)pStreamIn);
     1466            if (RT_UNLIKELY(err != noErr))
     1467                LogRel2(("CoreAudio: Failed to add the processor overload listener for input stream (%RI32)\n", err));
     1468#endif /* DEBUG */
     1469            propAdr.mSelector = kAudioDevicePropertyNominalSampleRate;
     1470            propAdr.mScope    = kAudioUnitScope_Global;
     1471            err = AudioObjectAddPropertyListener(pStreamIn->deviceID, &propAdr,
     1472                                                 coreAudioRecordingAudioDevicePropertyChanged, (void *)pStreamIn);
     1473            /* Not fatal. */
     1474            if (RT_UNLIKELY(err != noErr))
     1475                LogRel2(("CoreAudio: Failed to register sample rate changed listener for input stream (%RI32)\n", err));
     1476        }
    12981477
    12991478    } while (0);
     
    13121491        AudioUnitUninitialize(pStreamIn->audioUnit);
    13131492
    1314         if (pStreamIn->pBuf)
    1315         {
    1316             RTCircBufDestroy(pStreamIn->pBuf);
    1317             pStreamIn->pBuf = NULL;
    1318         }
     1493        if (pStreamIn->pCircBuf)
     1494        {
     1495            RTCircBufDestroy(pStreamIn->pCircBuf);
     1496            pStreamIn->pCircBuf = NULL;
     1497        }
     1498
     1499        coreAudioUninitConvCbCtx(&pStreamIn->convCbCtx);
    13191500
    13201501        ASMAtomicXchgU32(&pStreamIn->status, CA_STATUS_UNINIT);
     
    14771658
    14781659    /* Create an AudioStreamBasicDescription based on our required audio settings. */
    1479     coreAudioPCMInfoToASBDesc(&pStreamOut->Stream.Props, &pStreamOut->streamFormat);
    1480 
    1481     coreAudioPrintASBDesc("CoreAudio: playback device", &pStreamOut->deviceFormat);
    1482     coreAudioPrintASBDesc("CoreAudio: Output format", &pStreamOut->streamFormat);
     1660    coreAudioPCMPropsToASBD(&pStreamOut->Stream.Props, &pStreamOut->streamFormat);
     1661
     1662    coreAudioPrintASBD("CoreAudio: playback device", &pStreamOut->deviceFormat);
     1663    coreAudioPrintASBD("CoreAudio: Output format", &pStreamOut->streamFormat);
    14831664
    14841665    /* Set the new output format description for the stream. */
     
    15541735
    15551736    /* Destroy any former internal ring buffer. */
    1556     if (pStreamOut->pBuf)
    1557     {
    1558         RTCircBufDestroy(pStreamOut->pBuf);
    1559         pStreamOut->pBuf = NULL;
     1737    if (pStreamOut->pCircBuf)
     1738    {
     1739        RTCircBufDestroy(pStreamOut->pCircBuf);
     1740        pStreamOut->pCircBuf = NULL;
    15601741    }
    15611742
    15621743    /* Create the internal ring buffer. */
    1563     rc = RTCircBufCreate(&pStreamOut->pBuf, cSamples << pStream->Props.cShift);
     1744    rc = RTCircBufCreate(&pStreamOut->pCircBuf, cSamples << pStream->Props.cShift);
    15641745    if (RT_SUCCESS(rc))
    15651746    {
     
    15891770        ASMAtomicXchgU32(&pStreamOut->status, CA_STATUS_INIT);
    15901771
     1772        LogFunc(("cSamples=%RU32\n", cSamples));
     1773
    15911774        if (pcSamples)
    15921775            *pcSamples = cSamples;
     
    15961779        AudioUnitUninitialize(pStreamOut->audioUnit);
    15971780
    1598         if (pStreamOut->pBuf)
    1599         {
    1600             RTCircBufDestroy(pStreamOut->pBuf);
    1601             pStreamOut->pBuf = NULL;
    1602         }
     1781        if (pStreamOut->pCircBuf)
     1782        {
     1783            RTCircBufDestroy(pStreamOut->pCircBuf);
     1784            pStreamOut->pCircBuf = NULL;
     1785        }
     1786
     1787        ASMAtomicXchgU32(&pStreamOut->status, CA_STATUS_UNINIT);
    16031788    }
    16041789
     
    16421827
    16431828    /* How much space is used in the ring buffer? */
    1644     size_t cbToRead = RT_MIN(RTCircBufUsed(pStreamOut->pBuf), pBufData->mBuffers[0].mDataByteSize);
     1829    size_t cbToRead = RT_MIN(RTCircBufUsed(pStreamOut->pCircBuf), pBufData->mBuffers[0].mDataByteSize);
    16451830    if (!cbToRead)
    16461831    {
     
    16561841    {
    16571842        /* Try to acquire the necessary block from the ring buffer. */
    1658         RTCircBufAcquireReadBlock(pStreamOut->pBuf, cbLeft, (void **)&pbSrc, &cbToRead);
     1843        RTCircBufAcquireReadBlock(pStreamOut->pCircBuf, cbLeft, (void **)&pbSrc, &cbToRead);
    16591844
    16601845        /* Break if nothing is used anymore. */
     
    16661851
    16671852        /* Release the read buffer, so it could be used for new data. */
    1668         RTCircBufReleaseReadBlock(pStreamOut->pBuf, cbToRead);
     1853        RTCircBufReleaseReadBlock(pStreamOut->pCircBuf, cbToRead);
    16691854
    16701855        /* Move offset. */
     
    16791864    pBufData->mBuffers[0].mDataByteSize = cbRead;
    16801865
    1681     LogFlowFunc(("Read %zu / %zu bytes\n", cbRead, cbToRead));
     1866    Log3Func(("Read %zu / %zu bytes\n", cbRead, cbToRead));
    16821867
    16831868    return noErr;
     
    17181903    {
    17191904        size_t cbBuf = AudioMixBufSizeBytes(&pStream->MixBuf);
    1720         size_t cbToWrite = RT_MIN(cbBuf, RTCircBufUsed(pStreamIn->pBuf));
     1905        size_t cbToWrite = RT_MIN(cbBuf, RTCircBufUsed(pStreamIn->pCircBuf));
    17211906
    17221907        uint32_t cWritten, cbWritten;
     
    17291914        {
    17301915            /* Try to acquire the necessary block from the ring buffer. */
    1731             RTCircBufAcquireReadBlock(pStreamIn->pBuf, cbToWrite, (void **)&puBuf, &cbToRead);
     1916            RTCircBufAcquireReadBlock(pStreamIn->pCircBuf, cbToWrite, (void **)&puBuf, &cbToRead);
    17321917            if (!cbToRead)
    17331918            {
    1734                 RTCircBufReleaseReadBlock(pStreamIn->pBuf, cbToRead);
     1919                RTCircBufReleaseReadBlock(pStreamIn->pCircBuf, cbToRead);
    17351920                break;
    17361921            }
     
    17401925                || !cWritten)
    17411926            {
    1742                 RTCircBufReleaseReadBlock(pStreamIn->pBuf, cbToRead);
     1927                RTCircBufReleaseReadBlock(pStreamIn->pCircBuf, cbToRead);
    17431928                break;
    17441929            }
     
    17471932
    17481933            /* Release the read buffer, so it could be used for new data. */
    1749             RTCircBufReleaseReadBlock(pStreamIn->pBuf, cbWritten);
     1934            RTCircBufReleaseReadBlock(pStreamIn->pCircBuf, cbWritten);
    17501935
    17511936            Assert(cbToWrite >= cbWritten);
     
    18021987    uint32_t cbReadTotal = 0;
    18031988
    1804     size_t cbToRead = RT_MIN(cbLive, RTCircBufFree(pStreamOut->pBuf));
    1805     LogFlowFunc(("cbToRead=%zu\n", cbToRead));
     1989    size_t cbToRead = RT_MIN(cbLive, RTCircBufFree(pStreamOut->pCircBuf));
     1990    Log3Func(("cbToRead=%zu\n", cbToRead));
    18061991
    18071992    while (cbToRead)
     
    18121997
    18131998        /* Try to acquire the necessary space from the ring buffer. */
    1814         RTCircBufAcquireWriteBlock(pStreamOut->pBuf, cbToRead, (void **)&puBuf, &cbCopy);
     1999        RTCircBufAcquireWriteBlock(pStreamOut->pCircBuf, cbToRead, (void **)&puBuf, &cbCopy);
    18152000        if (!cbCopy)
    18162001        {
    1817             RTCircBufReleaseWriteBlock(pStreamOut->pBuf, cbCopy);
     2002            RTCircBufReleaseWriteBlock(pStreamOut->pCircBuf, cbCopy);
    18182003            break;
    18192004        }
     
    18272012            || !cRead)
    18282013        {
    1829             RTCircBufReleaseWriteBlock(pStreamOut->pBuf, 0);
     2014            RTCircBufReleaseWriteBlock(pStreamOut->pCircBuf, 0);
    18302015            break;
    18312016        }
     
    18342019
    18352020        /* Release the ring buffer, so the read thread could start reading this data. */
    1836         RTCircBufReleaseWriteBlock(pStreamOut->pBuf, cbRead);
     2021        RTCircBufReleaseWriteBlock(pStreamOut->pCircBuf, cbRead);
    18372022
    18382023        Assert(cbToRead >= cbRead);
     
    18472032            AudioMixBufFinish(&pStream->MixBuf, cReadTotal);
    18482033
    1849         LogFlowFunc(("cReadTotal=%RU32 (%RU32 bytes)\n", cReadTotal, cbReadTotal));
     2034        Log3Func(("cReadTotal=%RU32 (%RU32 bytes)\n", cReadTotal, cbReadTotal));
    18502035
    18512036        if (pcSamplesPlayed)
     
    18872072                    /* Keep going. */
    18882073                }
    1889                 RTCircBufReset(pStreamOut->pBuf);
     2074                RTCircBufReset(pStreamOut->pCircBuf);
    18902075
    18912076                err = AudioOutputUnitStart(pStreamOut->audioUnit);
     
    19572142            if (!coreAudioIsRunning(pStreamIn->deviceID))
    19582143            {
    1959                 RTCircBufReset(pStreamIn->pBuf);
     2144                RTCircBufReset(pStreamIn->pCircBuf);
    19602145                err = AudioOutputUnitStart(pStreamIn->audioUnit);
    19612146                if (err != noErr)
     
    21022287        pStreamIn->deviceID      = kAudioDeviceUnknown;
    21032288        pStreamIn->audioUnit     = NULL;
    2104         pStreamIn->offBufferRead = 0;
    21052289        pStreamIn->sampleRatio   = 1;
    2106         if (pStreamIn->pBuf)
    2107         {
    2108             RTCircBufDestroy(pStreamIn->pBuf);
    2109             pStreamIn->pBuf = NULL;
     2290
     2291        coreAudioUninitConvCbCtx(&pStreamIn->convCbCtx);
     2292
     2293        if (pStreamIn->pCircBuf)
     2294        {
     2295            RTCircBufDestroy(pStreamIn->pCircBuf);
     2296            pStreamIn->pCircBuf = NULL;
    21102297        }
    21112298
     
    22082395        pStreamOut->deviceID  = kAudioDeviceUnknown;
    22092396        pStreamOut->audioUnit = NULL;
    2210         if (pStreamOut->pBuf)
    2211         {
    2212             RTCircBufDestroy(pStreamOut->pBuf);
    2213             pStreamOut->pBuf = NULL;
     2397        if (pStreamOut->pCircBuf)
     2398        {
     2399            RTCircBufDestroy(pStreamOut->pCircBuf);
     2400            pStreamOut->pCircBuf = NULL;
    22142401        }
    22152402
     
    22282415    PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream;
    22292416
    2230     pStreamIn->deviceID                  = kAudioDeviceUnknown;
    2231     pStreamIn->audioUnit                 = NULL;
    2232     pStreamIn->pConverter                = NULL;
    2233     pStreamIn->bufferList.mNumberBuffers = 0;
    2234     pStreamIn->offBufferRead             = 0;
    2235     pStreamIn->sampleRatio               = 1;
    2236     pStreamIn->pBuf                      = NULL;
    2237     pStreamIn->status                    = CA_STATUS_UNINIT;
    2238     pStreamIn->fDefDevChgListReg         = false;
    2239     pStreamIn->fDevStateChgListReg       = false;
     2417    pStreamIn->deviceID            = kAudioDeviceUnknown;
     2418    pStreamIn->audioUnit           = NULL;
     2419    pStreamIn->pConverter          = NULL;
     2420    pStreamIn->sampleRatio         = 1;
     2421    pStreamIn->pCircBuf            = NULL;
     2422    pStreamIn->status              = CA_STATUS_UNINIT;
     2423    pStreamIn->fDefDevChgListReg   = false;
     2424    pStreamIn->fDevStateChgListReg = false;
    22402425
    22412426    /* Set callback context. */
     
    23152500    LogFlowFuncEnter();
    23162501
    2317     pStreamOut->deviceID                  = kAudioDeviceUnknown;
    2318     pStreamOut->audioUnit                 = NULL;
    2319     pStreamOut->pBuf                      = NULL;
    2320     pStreamOut->status                    = CA_STATUS_UNINIT;
    2321     pStreamOut->fDefDevChgListReg         = false;
    2322     pStreamOut->fDevStateChgListReg       = false;
     2502    pStreamOut->deviceID            = kAudioDeviceUnknown;
     2503    pStreamOut->audioUnit           = NULL;
     2504    pStreamOut->pCircBuf            = NULL;
     2505    pStreamOut->status              = CA_STATUS_UNINIT;
     2506    pStreamOut->fDefDevChgListReg   = false;
     2507    pStreamOut->fDevStateChgListReg = false;
    23232508
    23242509    /* Set callback context. */
Note: See TracChangeset for help on using the changeset viewer.

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