@@ -1741,7 +1741,7 @@ static OSStatus BlackHole_GetDevicePropertyDataSize(AudioServerPlugInDriverRef i
17411741 break ;
17421742
17431743 case kAudioDevicePropertyPreferredChannelLayout :
1744- * outDataSize = offsetof(AudioChannelLayout , mChannelDescriptions ) + (2 * sizeof (AudioChannelDescription ));
1744+ * outDataSize = offsetof(AudioChannelLayout , mChannelDescriptions ) + (NUMBER_OF_CHANNELS * sizeof (AudioChannelDescription ));
17451745 break ;
17461746
17471747 case kAudioDevicePropertyZeroTimeStampPeriod :
@@ -2170,12 +2170,12 @@ static OSStatus BlackHole_GetDevicePropertyData(AudioServerPlugInDriverRef inDri
21702170 // by default. For this device, we return a stereo ACL.
21712171 {
21722172 // calcualte how big the
2173- UInt32 theACLSize = offsetof(AudioChannelLayout , mChannelDescriptions ) + (2 * sizeof (AudioChannelDescription ));
2173+ UInt32 theACLSize = offsetof(AudioChannelLayout , mChannelDescriptions ) + (NUMBER_OF_CHANNELS * sizeof (AudioChannelDescription ));
21742174 FailWithAction (inDataSize < theACLSize , theAnswer = kAudioHardwareBadPropertySizeError , Done , "BlackHole_GetDevicePropertyData: not enough space for the return value of kAudioDevicePropertyPreferredChannelLayout for the device" );
21752175 ((AudioChannelLayout * )outData )-> mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions ;
21762176 ((AudioChannelLayout * )outData )-> mChannelBitmap = 0 ;
2177- ((AudioChannelLayout * )outData )-> mNumberChannelDescriptions = 2 ;
2178- for (theItemIndex = 0 ; theItemIndex < 2 ; ++ theItemIndex )
2177+ ((AudioChannelLayout * )outData )-> mNumberChannelDescriptions = NUMBER_OF_CHANNELS ;
2178+ for (theItemIndex = 0 ; theItemIndex < NUMBER_OF_CHANNELS ; ++ theItemIndex )
21792179 {
21802180 ((AudioChannelLayout * )outData )-> mChannelDescriptions [theItemIndex ].mChannelLabel = kAudioChannelLabel_Left + theItemIndex ;
21812181 ((AudioChannelLayout * )outData )-> mChannelDescriptions [theItemIndex ].mChannelFlags = 0 ;
@@ -2538,14 +2538,14 @@ static OSStatus BlackHole_GetStreamPropertyData(AudioServerPlugInDriverRef inDri
25382538 // format has to be the same as the physical format.
25392539 FailWithAction (inDataSize < sizeof (AudioStreamBasicDescription ), theAnswer = kAudioHardwareBadPropertySizeError , Done , "BlackHole_GetStreamPropertyData: not enough space for the return value of kAudioStreamPropertyVirtualFormat for the stream" );
25402540 pthread_mutex_lock (& gPlugIn_StateMutex );
2541- ((AudioStreamBasicDescription * )outData )-> mSampleRate = gDevice_SampleRate ;
2542- ((AudioStreamBasicDescription * )outData )-> mFormatID = kAudioFormatLinearPCM ;
2543- ((AudioStreamBasicDescription * )outData )-> mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked ;
2544- ((AudioStreamBasicDescription * )outData )-> mBytesPerPacket = BYTES_PER_CHANNEL * NUMBER_OF_CHANNELS ;
2545- ((AudioStreamBasicDescription * )outData )-> mFramesPerPacket = 1 ;
2546- ((AudioStreamBasicDescription * )outData )-> mBytesPerFrame = BYTES_PER_CHANNEL * NUMBER_OF_CHANNELS ;
2547- ((AudioStreamBasicDescription * )outData )-> mChannelsPerFrame = NUMBER_OF_CHANNELS ;
2548- ((AudioStreamBasicDescription * )outData )-> mBitsPerChannel = BITS_PER_CHANNEL ;
2541+ ((AudioStreamBasicDescription * )outData )-> mSampleRate = gDevice_SampleRate ;
2542+ ((AudioStreamBasicDescription * )outData )-> mFormatID = kAudioFormatLinearPCM ;
2543+ ((AudioStreamBasicDescription * )outData )-> mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked ;
2544+ ((AudioStreamBasicDescription * )outData )-> mBytesPerPacket = BYTES_PER_CHANNEL * NUMBER_OF_CHANNELS ;
2545+ ((AudioStreamBasicDescription * )outData )-> mFramesPerPacket = 1 ;
2546+ ((AudioStreamBasicDescription * )outData )-> mBytesPerFrame = BYTES_PER_CHANNEL * NUMBER_OF_CHANNELS ;
2547+ ((AudioStreamBasicDescription * )outData )-> mChannelsPerFrame = NUMBER_OF_CHANNELS ;
2548+ ((AudioStreamBasicDescription * )outData )-> mBitsPerChannel = BITS_PER_CHANNEL ;
25492549 pthread_mutex_unlock (& gPlugIn_StateMutex );
25502550 * outDataSize = sizeof (AudioStreamBasicDescription );
25512551 break ;
@@ -2569,16 +2569,16 @@ static OSStatus BlackHole_GetStreamPropertyData(AudioServerPlugInDriverRef inDri
25692569 // fill out the return array
25702570 if (theNumberItemsToFetch > 0 )
25712571 {
2572- ((AudioStreamRangedDescription * )outData )[0 ].mFormat .mSampleRate = 44100.0 ;
2573- ((AudioStreamRangedDescription * )outData )[0 ].mFormat .mFormatID = kAudioFormatLinearPCM ;
2574- ((AudioStreamRangedDescription * )outData )[0 ].mFormat .mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked ;
2572+ ((AudioStreamRangedDescription * )outData )[0 ].mFormat .mSampleRate = 44100.0 ;
2573+ ((AudioStreamRangedDescription * )outData )[0 ].mFormat .mFormatID = kAudioFormatLinearPCM ;
2574+ ((AudioStreamRangedDescription * )outData )[0 ].mFormat .mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked ;
25752575 ((AudioStreamRangedDescription * )outData )[0 ].mFormat .mBytesPerPacket = BYTES_PER_FRAME ;
2576- ((AudioStreamRangedDescription * )outData )[0 ].mFormat .mFramesPerPacket = 1 ;
2577- ((AudioStreamRangedDescription * )outData )[0 ].mFormat .mBytesPerFrame = BYTES_PER_FRAME ;
2578- ((AudioStreamRangedDescription * )outData )[0 ].mFormat .mChannelsPerFrame = NUMBER_OF_CHANNELS ;
2579- ((AudioStreamRangedDescription * )outData )[0 ].mFormat .mBitsPerChannel = BITS_PER_CHANNEL ;
2580- ((AudioStreamRangedDescription * )outData )[0 ].mSampleRateRange .mMinimum = 44100.0 ;
2581- ((AudioStreamRangedDescription * )outData )[0 ].mSampleRateRange .mMaximum = 44100.0 ;
2576+ ((AudioStreamRangedDescription * )outData )[0 ].mFormat .mFramesPerPacket = 1 ;
2577+ ((AudioStreamRangedDescription * )outData )[0 ].mFormat .mBytesPerFrame = BYTES_PER_FRAME ;
2578+ ((AudioStreamRangedDescription * )outData )[0 ].mFormat .mChannelsPerFrame = NUMBER_OF_CHANNELS ;
2579+ ((AudioStreamRangedDescription * )outData )[0 ].mFormat .mBitsPerChannel = BITS_PER_CHANNEL ;
2580+ ((AudioStreamRangedDescription * )outData )[0 ].mSampleRateRange .mMinimum = 44100.0 ;
2581+ ((AudioStreamRangedDescription * )outData )[0 ].mSampleRateRange .mMaximum = 44100.0 ;
25822582 }
25832583 if (theNumberItemsToFetch > 1 )
25842584 {
@@ -3642,6 +3642,8 @@ static OSStatus BlackHole_StartIO(AudioServerPlugInDriverRef inDriver, AudioObje
36423642 // important to note that multiple clients can have IO running on the device at the same time.
36433643 // So, work only needs to be done when the first client starts. All subsequent starts simply
36443644 // increment the counter.
3645+
3646+ DebugMsg ("BlackHole Start IO" );
36453647
36463648 #pragma unused(inClientID)
36473649
@@ -3668,6 +3670,9 @@ static OSStatus BlackHole_StartIO(AudioServerPlugInDriverRef inDriver, AudioObje
36683670 gDevice_NumberTimeStamps = 0 ;
36693671 gDevice_AnchorSampleTime = 0 ;
36703672 gDevice_AnchorHostTime = mach_absolute_time ();
3673+
3674+ // allocate ring buffer
3675+ ringBuffer = malloc (RING_BUFFER_SIZE );
36713676 }
36723677 else
36733678 {
@@ -3686,6 +3691,8 @@ static OSStatus BlackHole_StopIO(AudioServerPlugInDriverRef inDriver, AudioObjec
36863691{
36873692 // This call tells the device that the client has stopped IO. The driver can stop the hardware
36883693 // once all clients have stopped.
3694+
3695+ DebugMsg ("BlackHole Stop IO" );
36893696
36903697 #pragma unused(inClientID)
36913698
@@ -3709,6 +3716,7 @@ static OSStatus BlackHole_StopIO(AudioServerPlugInDriverRef inDriver, AudioObjec
37093716 {
37103717 // We need to stop the hardware, which in this case means that there's nothing to do.
37113718 gDevice_IOIsRunning = 0 ;
3719+ free (ringBuffer );
37123720 }
37133721 else
37143722 {
@@ -3755,7 +3763,9 @@ static OSStatus BlackHole_GetZeroTimeStamp(AudioServerPlugInDriverRef inDriver,
37553763
37563764 // calculate the next host time
37573765 theHostTicksPerRingBuffer = gDevice_HostTicksPerFrame * ((Float64 )kDevice_RingBufferSize );
3766+
37583767 theHostTickOffset = ((Float64 )(gDevice_NumberTimeStamps + 1 )) * theHostTicksPerRingBuffer ;
3768+
37593769 theNextHostTime = gDevice_AnchorHostTime + ((UInt64 )theHostTickOffset );
37603770
37613771 // go to the next time if the next host time is less than the current time
@@ -3854,18 +3864,17 @@ static OSStatus BlackHole_DoIOOperation(AudioServerPlugInDriverRef inDriver, Aud
38543864 FailWithAction (inDeviceObjectID != kObjectID_Device , theAnswer = kAudioHardwareBadObjectError , Done , "BlackHole_DoIOOperation: bad device ID" );
38553865 FailWithAction ((inStreamObjectID != kObjectID_Stream_Input ) && (inStreamObjectID != kObjectID_Stream_Output ), theAnswer = kAudioHardwareBadObjectError , Done , "BlackHole_DoIOOperation: bad stream ID" );
38563866
3857-
38583867 /* READ INPUT */
38593868 if (inOperationID == kAudioServerPlugInIOOperationReadInput )
38603869 {
38613870 /* WRITE TO IOBUFFER */
38623871 // calculate the ring buffer offset for the first sample INPUT
38633872 ringBufferOffset = ((UInt64 )(inIOCycleInfo -> mInputTime .mSampleTime * BYTES_PER_FRAME ) % RING_BUFFER_SIZE );
3864-
3873+
38653874 // calculate the size of the buffer
38663875 inIOBufferByteSize = inIOBufferFrameSize * BYTES_PER_FRAME ;
38673876 remainingRingBufferByteSize = RING_BUFFER_SIZE - ringBufferOffset ;
3868-
3877+
38693878 if (remainingRingBufferByteSize > inIOBufferByteSize )
38703879 {
38713880 // copy whole buffer if we have space
@@ -3879,13 +3888,13 @@ static OSStatus BlackHole_DoIOOperation(AudioServerPlugInDriverRef inDriver, Aud
38793888 // copy 2nd half
38803889 memcpy (ioMainBuffer + remainingRingBufferByteSize , ringBuffer , inIOBufferByteSize - remainingRingBufferByteSize );
38813890 }
3882-
3883-
3891+
3892+
38843893 /* CLEAR TO RINGBUFFER TRAILING BY 3072 SAMPLES */
38853894 // calculate the ring buffer offset for the first sample INPUT
38863895 ringBufferOffset = ((UInt64 )(inIOCycleInfo -> mInputTime .mSampleTime * BYTES_PER_FRAME - 3072 ) % RING_BUFFER_SIZE );
38873896 remainingRingBufferByteSize = RING_BUFFER_SIZE - ringBufferOffset ;
3888-
3897+
38893898 if (remainingRingBufferByteSize > inIOBufferByteSize )
38903899 {
38913900 // clear the internal ring buffer
@@ -3899,7 +3908,7 @@ static OSStatus BlackHole_DoIOOperation(AudioServerPlugInDriverRef inDriver, Aud
38993908 memset (ringBuffer , 0 , inIOBufferByteSize - remainingRingBufferByteSize );
39003909 }
39013910 }
3902-
3911+
39033912 /* WRITE MIX */
39043913 if (inOperationID == kAudioServerPlugInIOOperationWriteMix )
39053914 {
@@ -3909,24 +3918,24 @@ static OSStatus BlackHole_DoIOOperation(AudioServerPlugInDriverRef inDriver, Aud
39093918 /* WRITE MIX TO RINGBUFFER */
39103919 // calculate the ring buffer offset for the first sample OUTPUT
39113920 ringBufferOffset = ((UInt64 )(inIOCycleInfo -> mOutputTime .mSampleTime * BYTES_PER_FRAME ) % RING_BUFFER_SIZE );
3912-
3921+
39133922 // calculate the size of the buffer
39143923 inIOBufferByteSize = inIOBufferFrameSize * BYTES_PER_FRAME ;
3915-
3924+
39163925 // mix the audio
39173926 for (UInt64 sample = 0 ; sample < inIOBufferByteSize ; sample += sizeof (Float32 ))
39183927 {
39193928 // sample from ioMainBuffer
39203929 Float32 * ioSample = ioMainBuffer + sample ;
3921-
3930+
39223931 // sample from ring buffer
39233932 Float32 * ringSample = (Float32 * )(ringBuffer + (ringBufferOffset + sample ) % RING_BUFFER_SIZE );
3924-
3933+
39253934 // mix the two together scale by volume
39263935 * ringSample += * ioSample * gVolume_Output_Master_Value * gVolume_Input_Master_Value ;
39273936 }
39283937 }
3929-
3938+
39303939 // clear the io buffer
39313940 memset (ioMainBuffer , 0 , inIOBufferByteSize );
39323941 }
0 commit comments