Changeset 62071 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- Jul 6, 2016 4:01:01 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvHostCoreAudio.cpp
r61764 r62071 36 36 #include <AudioToolbox/AudioConverter.h> 37 37 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 38 48 /* TODO: 39 49 * - Maybe make sure the threads are immediately stopped if playing/recording stops. … … 67 77 ******************************************************************************/ 68 78 69 static void coreAudioPrintASBD esc(const char *pszDesc, const AudioStreamBasicDescription *pStreamDesc)79 static void coreAudioPrintASBD(const char *pszDesc, const AudioStreamBasicDescription *pASBD) 70 80 { 71 81 char pszSampleRate[32]; 72 82 LogRel2(("CoreAudio: %s description:\n", pszDesc)); 73 LogRel2(("CoreAudio: Format ID: %RU32 (%c%c%c%c)\n", p StreamDesc->mFormatID,74 RT_BYTE4(p StreamDesc->mFormatID), RT_BYTE3(pStreamDesc->mFormatID),75 RT_BYTE2(p StreamDesc->mFormatID), RT_BYTE1(pStreamDesc->mFormatID)));76 LogRel2(("CoreAudio: Flags: %RU32", p StreamDesc->mFormatFlags));77 if (p StreamDesc->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) 78 88 LogRel2((" Float")); 79 if (p StreamDesc->mFormatFlags & kAudioFormatFlagIsBigEndian)89 if (pASBD->mFormatFlags & kAudioFormatFlagIsBigEndian) 80 90 LogRel2((" BigEndian")); 81 if (p StreamDesc->mFormatFlags & kAudioFormatFlagIsSignedInteger)91 if (pASBD->mFormatFlags & kAudioFormatFlagIsSignedInteger) 82 92 LogRel2((" SignedInteger")); 83 if (p StreamDesc->mFormatFlags & kAudioFormatFlagIsPacked)93 if (pASBD->mFormatFlags & kAudioFormatFlagIsPacked) 84 94 LogRel2((" Packed")); 85 if (p StreamDesc->mFormatFlags & kAudioFormatFlagIsAlignedHigh)95 if (pASBD->mFormatFlags & kAudioFormatFlagIsAlignedHigh) 86 96 LogRel2((" AlignedHigh")); 87 if (p StreamDesc->mFormatFlags & kAudioFormatFlagIsNonInterleaved)97 if (pASBD->mFormatFlags & kAudioFormatFlagIsNonInterleaved) 88 98 LogRel2((" NonInterleaved")); 89 if (p StreamDesc->mFormatFlags & kAudioFormatFlagIsNonMixable)99 if (pASBD->mFormatFlags & kAudioFormatFlagIsNonMixable) 90 100 LogRel2((" NonMixable")); 91 if (p StreamDesc->mFormatFlags & kAudioFormatFlagsAreAllClear)101 if (pASBD->mFormatFlags & kAudioFormatFlagsAreAllClear) 92 102 LogRel2((" AllClear")); 93 103 LogRel2(("\n")); 94 snprintf(pszSampleRate, 32, "%.2f", (float)p StreamDesc->mSampleRate); /** @todo r=andy Use RTStrPrint*. */104 snprintf(pszSampleRate, 32, "%.2f", (float)pASBD->mSampleRate); /** @todo r=andy Use RTStrPrint*. */ 95 105 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 113 static 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; 115 130 } 116 131 … … 286 301 }; 287 302 } 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 */ 308 typedef 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; 288 325 289 326 /** @todo Unify COREAUDIOSTREAMOUT / COREAUDIOSTREAMIN. */ … … 302 339 AudioUnit audioUnit; 303 340 /** A ring buffer for transferring data to the playback thread. */ 304 PRTCIRCBUF p Buf;341 PRTCIRCBUF pCircBuf; 305 342 /** Initialization status tracker. Used when some of the device parameters 306 343 * or the device itself is changed during the runtime. */ … … 329 366 /** The AudioUnit used. */ 330 367 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. */ 332 371 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; 337 374 /** The ratio between the device & the stream sample rate. */ 338 375 Float64 sampleRatio; 339 /** A ring buffer for transferring data from the recording thread. */340 PRTCIRCBUF pBuf;341 376 /** Initialization status tracker. Used when some of the device parameters 342 377 * or the device itself is changed during the runtime. */ … … 366 401 367 402 /** 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 */ 410 static 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 */ 437 static 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. 369 449 * 370 450 * @return IPRT status code. … … 474 554 475 555 if (fIn) 476 LogRel2(("CoreAudio: Found %RU8 capturing device(s)\n", cDevs));556 LogRel2(("CoreAudio: Found %RU8 recording device(s)\n", cDevs)); 477 557 else 478 558 LogRel2(("CoreAudio: Found %RU8 playback device(s)\n", cDevs)); … … 624 704 UInt32 uResp; 625 705 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, pProperty, 0, NULL, &uSize, &uResp); 706 626 707 if (err == noErr) 627 708 { … … 652 733 UInt32 uResp; 653 734 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propAdr, 0, NULL, &uSize, &uResp); 735 654 736 if (err == noErr) 655 737 { … … 719 801 720 802 /* 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; 803 static 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; 730 819 731 820 /** @todo Check converter ID? */ 732 821 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; 773 875 } 774 876 775 877 /* Callback to feed audio input buffer. */ 776 static DECLCALLBACK(OSStatus) coreAudioRecordingCb(void *pvUser,878 static DECLCALLBACK(OSStatus) coreAudioRecordingCb(void *pvUser, 777 879 AudioUnitRenderActionFlags *pActionFlags, 778 880 const AudioTimeStamp *pAudioTS, … … 781 883 AudioBufferList *pBufData) 782 884 { 783 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pvUser;784 PPDMAUDIOSTREAM pStream = &pStreamIn->Stream;785 786 if (ASMAtomicReadU32(&pStreamIn->status) != CA_STATUS_INIT)787 return noErr;788 789 885 /* If nothing is pending return immediately. */ 790 886 if (cFrames == 0) 791 887 return noErr; 792 888 889 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pvUser; 890 891 if (ASMAtomicReadU32(&pStreamIn->status) != CA_STATUS_INIT) 892 return noErr; 893 894 PCOREAUDIOCONVCBCTX pConvCbCtx = &pStreamIn->convCbCtx; 895 793 896 OSStatus err = noErr; 794 897 int rc = VINF_SUCCESS; 795 898 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 796 910 do 797 911 { … … 799 913 if (pStreamIn->pConverter) 800 914 { 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) 807 919 { 808 920 rc = VERR_NO_MEMORY; … … 810 922 } 811 923 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); 813 926 if (err != noErr) 814 927 { … … 818 931 } 819 932 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) 855 975 { 856 LogF unc(("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))); 858 978 rc = VERR_IO_GEN_FAILURE; 859 979 break; 860 980 } 861 981 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) 873 983 break; 874 984 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; 877 1021 } 878 1022 } 879 1023 else /* No converter being used. */ 880 1024 { 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) 891 1034 { 892 1035 rc = VERR_NO_MEMORY; … … 894 1037 } 895 1038 896 err = AudioUnitRender(pStreamIn->audioUnit, pActionFlags, pAudioTS, uBusID, cFrames, &p StreamIn->bufferList);1039 err = AudioUnitRender(pStreamIn->audioUnit, pActionFlags, pAudioTS, uBusID, cFrames, &pConvCbCtx->bufLstSrc); 897 1040 if (err != noErr) 898 1041 { … … 902 1045 } 903 1046 904 const uint32_t cbDataSize = pS treamIn->bufferList.mBuffers[0].mDataByteSize;905 const size_t cbBufFree = RTCircBufFree(pStreamIn->p Buf);1047 const uint32_t cbDataSize = pSrcBuf->mDataByteSize; 1048 const size_t cbBufFree = RTCircBufFree(pStreamIn->pCircBuf); 906 1049 size_t cbAvail = RT_MIN(cbDataSize, cbBufFree); 907 1050 … … 915 1058 /* Try to acquire the necessary space from the ring buffer. */ 916 1059 size_t cbToWrite = 0; 917 RTCircBufAcquireWriteBlock(pStreamIn->p Buf, cbAvail, (void **)&puDst, &cbToWrite);1060 RTCircBufAcquireWriteBlock(pStreamIn->pCircBuf, cbAvail, (void **)&puDst, &cbToWrite); 918 1061 if (!cbToWrite) 919 1062 break; 920 1063 921 1064 /* Copy the data from the Core Audio buffer to the ring buffer. */ 922 memcpy(puDst, (uint8_t *)pS treamIn->bufferList.mBuffers[0].mData + cbWrittenTotal, cbToWrite);1065 memcpy(puDst, (uint8_t *)pSrcBuf->mData + cbWrittenTotal, cbToWrite); 923 1066 924 1067 /* Release the ring buffer, so the main thread could start reading this data. */ 925 RTCircBufReleaseWriteBlock(pStreamIn->p Buf, cbToWrite);1068 RTCircBufReleaseWriteBlock(pStreamIn->pCircBuf, cbToWrite); 926 1069 927 1070 cbWrittenTotal += cbToWrite; … … 936 1079 } while (0); 937 1080 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 } 946 1086 947 1087 return err; … … 960 1100 UInt32 cSamples = 0; 961 1101 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 962 1126 do 963 1127 { 964 1128 ASMAtomicXchgU32(&pStreamIn->status, CA_STATUS_IN_INIT); 965 1129 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; 988 1132 989 1133 /* … … 1122 1266 1123 1267 /* Fetch the current stream format of the device. */ 1268 RT_ZERO(pStreamIn->deviceFormat); 1124 1269 uSize = sizeof(pStreamIn->deviceFormat); 1125 1270 err = AudioUnitGetProperty(pStreamIn->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, … … 1132 1277 1133 1278 /* 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); 1138 1284 1139 1285 /* If the frequency of the device is different from the requested one we … … 1142 1288 || pStreamIn->deviceFormat.mChannelsPerFrame != pStreamIn->streamFormat.mChannelsPerFrame) 1143 1289 { 1144 LogRel (("CoreAudio: Input converter is active\n"));1290 LogRel2(("CoreAudio: Input converter is active\n")); 1145 1291 1146 1292 err = AudioConverterNew(&pStreamIn->deviceFormat, &pStreamIn->streamFormat, &pStreamIn->pConverter); … … 1154 1300 && pStreamIn->streamFormat.mChannelsPerFrame == 2 /* Stereo */) 1155 1301 { 1302 LogRel2(("CoreAudio: Mono to stereo conversion active\n")); 1303 1156 1304 /* 1157 1305 * If the channel count is different we have to tell this the converter … … 1161 1309 * cases. 1162 1310 */ 1163 const SInt32 channelMap[2] = {0, 0}; /* Channel map for mono -> stereo ,*/1311 const SInt32 channelMap[2] = {0, 0}; /* Channel map for mono -> stereo. */ 1164 1312 1165 1313 err = AudioConverterSetProperty(pStreamIn->pConverter, kAudioConverterChannelMap, sizeof(channelMap), channelMap); … … 1170 1318 } 1171 1319 } 1172 #if 0 1320 1173 1321 /* Set sample rate converter quality to maximum. */ 1174 1322 uFlag = kAudioConverterQuality_Max; 1175 err = AudioConverterSetProperty(pStreamIn-> converter, kAudioConverterSampleRateConverterQuality,1323 err = AudioConverterSetProperty(pStreamIn->pConverter, kAudioConverterSampleRateConverterQuality, 1176 1324 sizeof(uFlag), &uFlag); 1177 1325 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. */ 1181 1354 err = AudioUnitSetProperty(pStreamIn->audioUnit, 1182 1355 kAudioUnitProperty_StreamFormat, … … 1187 1360 if (RT_UNLIKELY(err != noErr)) 1188 1361 { 1189 LogRel(("CoreAudio: Failed to set inputstream output format (%RI32)\n", err));1362 LogRel(("CoreAudio: Failed to set stream output format (%RI32)\n", err)); 1190 1363 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED); 1191 1364 } 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 }1204 1365 } 1205 1366 else 1206 1367 { 1207 1208 1368 /* Set the new output format description for the input stream. */ 1209 1369 err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, … … 1261 1421 1262 1422 /* 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); 1268 1430 1269 1431 /* Calculate the ratio between the device and the stream sample rate. */ 1270 1432 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;1278 1433 1279 1434 /* … … 1294 1449 } 1295 1450 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 } 1298 1477 1299 1478 } while (0); … … 1312 1491 AudioUnitUninitialize(pStreamIn->audioUnit); 1313 1492 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); 1319 1500 1320 1501 ASMAtomicXchgU32(&pStreamIn->status, CA_STATUS_UNINIT); … … 1477 1658 1478 1659 /* Create an AudioStreamBasicDescription based on our required audio settings. */ 1479 coreAudioPCM InfoToASBDesc(&pStreamOut->Stream.Props, &pStreamOut->streamFormat);1480 1481 coreAudioPrintASBD esc("CoreAudio: playback device", &pStreamOut->deviceFormat);1482 coreAudioPrintASBD esc("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); 1483 1664 1484 1665 /* Set the new output format description for the stream. */ … … 1554 1735 1555 1736 /* Destroy any former internal ring buffer. */ 1556 if (pStreamOut->p Buf)1557 { 1558 RTCircBufDestroy(pStreamOut->p Buf);1559 pStreamOut->p Buf = NULL;1737 if (pStreamOut->pCircBuf) 1738 { 1739 RTCircBufDestroy(pStreamOut->pCircBuf); 1740 pStreamOut->pCircBuf = NULL; 1560 1741 } 1561 1742 1562 1743 /* Create the internal ring buffer. */ 1563 rc = RTCircBufCreate(&pStreamOut->p Buf, cSamples << pStream->Props.cShift);1744 rc = RTCircBufCreate(&pStreamOut->pCircBuf, cSamples << pStream->Props.cShift); 1564 1745 if (RT_SUCCESS(rc)) 1565 1746 { … … 1589 1770 ASMAtomicXchgU32(&pStreamOut->status, CA_STATUS_INIT); 1590 1771 1772 LogFunc(("cSamples=%RU32\n", cSamples)); 1773 1591 1774 if (pcSamples) 1592 1775 *pcSamples = cSamples; … … 1596 1779 AudioUnitUninitialize(pStreamOut->audioUnit); 1597 1780 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); 1603 1788 } 1604 1789 … … 1642 1827 1643 1828 /* How much space is used in the ring buffer? */ 1644 size_t cbToRead = RT_MIN(RTCircBufUsed(pStreamOut->p Buf), pBufData->mBuffers[0].mDataByteSize);1829 size_t cbToRead = RT_MIN(RTCircBufUsed(pStreamOut->pCircBuf), pBufData->mBuffers[0].mDataByteSize); 1645 1830 if (!cbToRead) 1646 1831 { … … 1656 1841 { 1657 1842 /* Try to acquire the necessary block from the ring buffer. */ 1658 RTCircBufAcquireReadBlock(pStreamOut->p Buf, cbLeft, (void **)&pbSrc, &cbToRead);1843 RTCircBufAcquireReadBlock(pStreamOut->pCircBuf, cbLeft, (void **)&pbSrc, &cbToRead); 1659 1844 1660 1845 /* Break if nothing is used anymore. */ … … 1666 1851 1667 1852 /* Release the read buffer, so it could be used for new data. */ 1668 RTCircBufReleaseReadBlock(pStreamOut->p Buf, cbToRead);1853 RTCircBufReleaseReadBlock(pStreamOut->pCircBuf, cbToRead); 1669 1854 1670 1855 /* Move offset. */ … … 1679 1864 pBufData->mBuffers[0].mDataByteSize = cbRead; 1680 1865 1681 Log FlowFunc(("Read %zu / %zu bytes\n", cbRead, cbToRead));1866 Log3Func(("Read %zu / %zu bytes\n", cbRead, cbToRead)); 1682 1867 1683 1868 return noErr; … … 1718 1903 { 1719 1904 size_t cbBuf = AudioMixBufSizeBytes(&pStream->MixBuf); 1720 size_t cbToWrite = RT_MIN(cbBuf, RTCircBufUsed(pStreamIn->p Buf));1905 size_t cbToWrite = RT_MIN(cbBuf, RTCircBufUsed(pStreamIn->pCircBuf)); 1721 1906 1722 1907 uint32_t cWritten, cbWritten; … … 1729 1914 { 1730 1915 /* Try to acquire the necessary block from the ring buffer. */ 1731 RTCircBufAcquireReadBlock(pStreamIn->p Buf, cbToWrite, (void **)&puBuf, &cbToRead);1916 RTCircBufAcquireReadBlock(pStreamIn->pCircBuf, cbToWrite, (void **)&puBuf, &cbToRead); 1732 1917 if (!cbToRead) 1733 1918 { 1734 RTCircBufReleaseReadBlock(pStreamIn->p Buf, cbToRead);1919 RTCircBufReleaseReadBlock(pStreamIn->pCircBuf, cbToRead); 1735 1920 break; 1736 1921 } … … 1740 1925 || !cWritten) 1741 1926 { 1742 RTCircBufReleaseReadBlock(pStreamIn->p Buf, cbToRead);1927 RTCircBufReleaseReadBlock(pStreamIn->pCircBuf, cbToRead); 1743 1928 break; 1744 1929 } … … 1747 1932 1748 1933 /* Release the read buffer, so it could be used for new data. */ 1749 RTCircBufReleaseReadBlock(pStreamIn->p Buf, cbWritten);1934 RTCircBufReleaseReadBlock(pStreamIn->pCircBuf, cbWritten); 1750 1935 1751 1936 Assert(cbToWrite >= cbWritten); … … 1802 1987 uint32_t cbReadTotal = 0; 1803 1988 1804 size_t cbToRead = RT_MIN(cbLive, RTCircBufFree(pStreamOut->p Buf));1805 Log FlowFunc(("cbToRead=%zu\n", cbToRead));1989 size_t cbToRead = RT_MIN(cbLive, RTCircBufFree(pStreamOut->pCircBuf)); 1990 Log3Func(("cbToRead=%zu\n", cbToRead)); 1806 1991 1807 1992 while (cbToRead) … … 1812 1997 1813 1998 /* Try to acquire the necessary space from the ring buffer. */ 1814 RTCircBufAcquireWriteBlock(pStreamOut->p Buf, cbToRead, (void **)&puBuf, &cbCopy);1999 RTCircBufAcquireWriteBlock(pStreamOut->pCircBuf, cbToRead, (void **)&puBuf, &cbCopy); 1815 2000 if (!cbCopy) 1816 2001 { 1817 RTCircBufReleaseWriteBlock(pStreamOut->p Buf, cbCopy);2002 RTCircBufReleaseWriteBlock(pStreamOut->pCircBuf, cbCopy); 1818 2003 break; 1819 2004 } … … 1827 2012 || !cRead) 1828 2013 { 1829 RTCircBufReleaseWriteBlock(pStreamOut->p Buf, 0);2014 RTCircBufReleaseWriteBlock(pStreamOut->pCircBuf, 0); 1830 2015 break; 1831 2016 } … … 1834 2019 1835 2020 /* Release the ring buffer, so the read thread could start reading this data. */ 1836 RTCircBufReleaseWriteBlock(pStreamOut->p Buf, cbRead);2021 RTCircBufReleaseWriteBlock(pStreamOut->pCircBuf, cbRead); 1837 2022 1838 2023 Assert(cbToRead >= cbRead); … … 1847 2032 AudioMixBufFinish(&pStream->MixBuf, cReadTotal); 1848 2033 1849 Log FlowFunc(("cReadTotal=%RU32 (%RU32 bytes)\n", cReadTotal, cbReadTotal));2034 Log3Func(("cReadTotal=%RU32 (%RU32 bytes)\n", cReadTotal, cbReadTotal)); 1850 2035 1851 2036 if (pcSamplesPlayed) … … 1887 2072 /* Keep going. */ 1888 2073 } 1889 RTCircBufReset(pStreamOut->p Buf);2074 RTCircBufReset(pStreamOut->pCircBuf); 1890 2075 1891 2076 err = AudioOutputUnitStart(pStreamOut->audioUnit); … … 1957 2142 if (!coreAudioIsRunning(pStreamIn->deviceID)) 1958 2143 { 1959 RTCircBufReset(pStreamIn->p Buf);2144 RTCircBufReset(pStreamIn->pCircBuf); 1960 2145 err = AudioOutputUnitStart(pStreamIn->audioUnit); 1961 2146 if (err != noErr) … … 2102 2287 pStreamIn->deviceID = kAudioDeviceUnknown; 2103 2288 pStreamIn->audioUnit = NULL; 2104 pStreamIn->offBufferRead = 0;2105 2289 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; 2110 2297 } 2111 2298 … … 2208 2395 pStreamOut->deviceID = kAudioDeviceUnknown; 2209 2396 pStreamOut->audioUnit = NULL; 2210 if (pStreamOut->p Buf)2211 { 2212 RTCircBufDestroy(pStreamOut->p Buf);2213 pStreamOut->p Buf = NULL;2397 if (pStreamOut->pCircBuf) 2398 { 2399 RTCircBufDestroy(pStreamOut->pCircBuf); 2400 pStreamOut->pCircBuf = NULL; 2214 2401 } 2215 2402 … … 2228 2415 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream; 2229 2416 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; 2240 2425 2241 2426 /* Set callback context. */ … … 2315 2500 LogFlowFuncEnter(); 2316 2501 2317 pStreamOut->deviceID 2318 pStreamOut->audioUnit 2319 pStreamOut->p Buf= NULL;2320 pStreamOut->status 2321 pStreamOut->fDefDevChgListReg 2322 pStreamOut->fDevStateChgListReg 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; 2323 2508 2324 2509 /* Set callback context. */
Note:
See TracChangeset
for help on using the changeset viewer.