@@ -221,9 +221,11 @@ static OSStatus BlackHole_Initialize(AudioServerPlugInDriverRef inDriver, AudioS
221221 // calculate the host ticks per frame
222222 struct mach_timebase_info theTimeBaseInfo ;
223223 mach_timebase_info (& theTimeBaseInfo );
224- Float64 theHostClockFrequency = theTimeBaseInfo .denom / theTimeBaseInfo .numer ;
224+ Float64 theHostClockFrequency = ( Float64 ) theTimeBaseInfo .denom / ( Float64 ) theTimeBaseInfo .numer ;
225225 theHostClockFrequency *= 1000000000.0 ;
226226 gDevice_HostTicksPerFrame = theHostClockFrequency / gDevice_SampleRate ;
227+
228+ // DebugMsg("BlackHole theTimeBaseInfo.numer: %u \t theTimeBaseInfo.denom: %u", theTimeBaseInfo.numer, theTimeBaseInfo.denom);
227229
228230Done :
229231 return theAnswer ;
@@ -346,12 +348,14 @@ static OSStatus BlackHole_PerformDeviceConfigurationChange(AudioServerPlugInDriv
346348 // recalculate the state that depends on the sample rate
347349 struct mach_timebase_info theTimeBaseInfo ;
348350 mach_timebase_info (& theTimeBaseInfo );
349- Float64 theHostClockFrequency = theTimeBaseInfo .denom / theTimeBaseInfo .numer ;
351+ Float64 theHostClockFrequency = ( Float64 ) theTimeBaseInfo .numer / ( Float64 ) theTimeBaseInfo .denom ;
350352 theHostClockFrequency *= 1000000000.0 ;
351353 gDevice_HostTicksPerFrame = theHostClockFrequency / gDevice_SampleRate ;
352354
353355 // unlock the state mutex
354356 pthread_mutex_unlock (& gPlugIn_StateMutex );
357+
358+ // DebugMsg("BlackHole theTimeBaseInfo.numer: %u \t theTimeBaseInfo.denom: %u", theTimeBaseInfo.numer, theTimeBaseInfo.denom);
355359
356360Done :
357361 return theAnswer ;
@@ -412,9 +416,7 @@ static Boolean BlackHole_HasProperty(AudioServerPlugInDriverRef inDriver, AudioO
412416 theAnswer = BlackHole_HasStreamProperty (inDriver , inObjectID , inClientProcessID , inAddress );
413417 break ;
414418
415- case kObjectID_Volume_Input_Master :
416419 case kObjectID_Volume_Output_Master :
417- case kObjectID_Mute_Input_Master :
418420 case kObjectID_Mute_Output_Master :
419421 case kObjectID_DataSource_Input_Master :
420422 case kObjectID_DataSource_Output_Master :
@@ -461,9 +463,7 @@ static OSStatus BlackHole_IsPropertySettable(AudioServerPlugInDriverRef inDriver
461463 theAnswer = BlackHole_IsStreamPropertySettable (inDriver , inObjectID , inClientProcessID , inAddress , outIsSettable );
462464 break ;
463465
464- case kObjectID_Volume_Input_Master :
465466 case kObjectID_Volume_Output_Master :
466- case kObjectID_Mute_Input_Master :
467467 case kObjectID_Mute_Output_Master :
468468 case kObjectID_DataSource_Input_Master :
469469 case kObjectID_DataSource_Output_Master :
@@ -513,9 +513,7 @@ static OSStatus BlackHole_GetPropertyDataSize(AudioServerPlugInDriverRef inDrive
513513 theAnswer = BlackHole_GetStreamPropertyDataSize (inDriver , inObjectID , inClientProcessID , inAddress , inQualifierDataSize , inQualifierData , outDataSize );
514514 break ;
515515
516- case kObjectID_Volume_Input_Master :
517516 case kObjectID_Volume_Output_Master :
518- case kObjectID_Mute_Input_Master :
519517 case kObjectID_Mute_Output_Master :
520518 case kObjectID_DataSource_Input_Master :
521519 case kObjectID_DataSource_Output_Master :
@@ -566,9 +564,7 @@ static OSStatus BlackHole_GetPropertyData(AudioServerPlugInDriverRef inDriver, A
566564 theAnswer = BlackHole_GetStreamPropertyData (inDriver , inObjectID , inClientProcessID , inAddress , inQualifierDataSize , inQualifierData , inDataSize , outDataSize , outData );
567565 break ;
568566
569- case kObjectID_Volume_Input_Master :
570567 case kObjectID_Volume_Output_Master :
571- case kObjectID_Mute_Input_Master :
572568 case kObjectID_Mute_Output_Master :
573569 case kObjectID_DataSource_Input_Master :
574570 case kObjectID_DataSource_Output_Master :
@@ -617,9 +613,7 @@ static OSStatus BlackHole_SetPropertyData(AudioServerPlugInDriverRef inDriver, A
617613 theAnswer = BlackHole_SetStreamPropertyData (inDriver , inObjectID , inClientProcessID , inAddress , inQualifierDataSize , inQualifierData , inDataSize , inData , & theNumberPropertiesChanged , theChangedAddresses );
618614 break ;
619615
620- case kObjectID_Volume_Input_Master :
621616 case kObjectID_Volume_Output_Master :
622- case kObjectID_Mute_Input_Master :
623617 case kObjectID_Mute_Output_Master :
624618 case kObjectID_DataSource_Input_Master :
625619 case kObjectID_DataSource_Output_Master :
@@ -915,7 +909,7 @@ static OSStatus BlackHole_GetPlugInPropertyData(AudioServerPlugInDriverRef inDri
915909 FailWithAction (inDataSize < sizeof (AudioObjectID ), theAnswer = kAudioHardwareBadPropertySizeError , Done , "BlackHole_GetPlugInPropertyData: not enough space for the return value of kAudioPlugInPropertyTranslateUIDToBox" );
916910 FailWithAction (inQualifierDataSize == sizeof (CFStringRef ), theAnswer = kAudioHardwareBadPropertySizeError , Done , "BlackHole_GetPlugInPropertyData: the qualifier is the wrong size for kAudioPlugInPropertyTranslateUIDToBox" );
917911 FailWithAction (inQualifierData == NULL , theAnswer = kAudioHardwareBadPropertySizeError , Done , "BlackHole_GetPlugInPropertyData: no qualifier for kAudioPlugInPropertyTranslateUIDToBox" );
918- if (CFStringCompare (* ((CFStringRef * )inQualifierData ), CFSTR (kBox_UID ), 0 ) == kCFCompareEqualTo )
912+ if (CFStringCompare (* ((CFStringRef * )inQualifierData ), CFStringCreateWithFormat ( NULL , NULL , CFSTR (kBox_UID ), NUMBER_OF_CHANNELS ), 0 ) == kCFCompareEqualTo )
919913 {
920914 * ((AudioObjectID * )outData ) = kObjectID_Box ;
921915 }
@@ -958,7 +952,7 @@ static OSStatus BlackHole_GetPlugInPropertyData(AudioServerPlugInDriverRef inDri
958952 FailWithAction (inDataSize < sizeof (AudioObjectID ), theAnswer = kAudioHardwareBadPropertySizeError , Done , "BlackHole_GetPlugInPropertyData: not enough space for the return value of kAudioPlugInPropertyTranslateUIDToDevice" );
959953 FailWithAction (inQualifierDataSize == sizeof (CFStringRef ), theAnswer = kAudioHardwareBadPropertySizeError , Done , "BlackHole_GetPlugInPropertyData: the qualifier is the wrong size for kAudioPlugInPropertyTranslateUIDToDevice" );
960954 FailWithAction (inQualifierData == NULL , theAnswer = kAudioHardwareBadPropertySizeError , Done , "BlackHole_GetPlugInPropertyData: no qualifier for kAudioPlugInPropertyTranslateUIDToDevice" );
961- if (CFStringCompare (* ((CFStringRef * )inQualifierData ), CFSTR (kDevice_UID ), 0 ) == kCFCompareEqualTo )
955+ if (CFStringCompare (* ((CFStringRef * )inQualifierData ), CFStringCreateWithFormat ( NULL , NULL , CFSTR (kDevice_UID ), NUMBER_OF_CHANNELS ), 0 ) == kCFCompareEqualTo )
962956 {
963957 * ((AudioObjectID * )outData ) = kObjectID_Device ;
964958 }
@@ -1329,7 +1323,7 @@ static OSStatus BlackHole_GetBoxPropertyData(AudioServerPlugInDriverRef inDriver
13291323 case kAudioBoxPropertyBoxUID :
13301324 // Boxes have UIDs the same as devices
13311325 FailWithAction (inDataSize < sizeof (CFStringRef ), theAnswer = kAudioHardwareBadPropertySizeError , Done , "BlackHole_GetBoxPropertyData: not enough space for the return value of kAudioObjectPropertyManufacturer for the box" );
1332- * ((CFStringRef * )outData ) = CFSTR (kBox_UID );
1326+ * ((CFStringRef * )outData ) = CFStringCreateWithFormat ( NULL , NULL , CFSTR (kBox_UID ), NUMBER_OF_CHANNELS );
13331327 break ;
13341328
13351329 case kAudioBoxPropertyTransportType :
@@ -1910,7 +1904,7 @@ static OSStatus BlackHole_GetDevicePropertyData(AudioServerPlugInDriverRef inDri
19101904 // audio device across boot sessions. Note that two instances of the same
19111905 // device must have different values for this property.
19121906 FailWithAction (inDataSize < sizeof (CFStringRef ), theAnswer = kAudioHardwareBadPropertySizeError , Done , "BlackHole_GetDevicePropertyData: not enough space for the return value of kAudioDevicePropertyDeviceUID for the device" );
1913- * ((CFStringRef * )outData ) = CFSTR (kDevice_UID );
1907+ * ((CFStringRef * )outData ) = CFStringCreateWithFormat ( NULL , NULL , CFSTR (kDevice_UID ), NUMBER_OF_CHANNELS );
19141908 * outDataSize = sizeof (CFStringRef );
19151909 break ;
19161910
@@ -1919,7 +1913,7 @@ static OSStatus BlackHole_GetDevicePropertyData(AudioServerPlugInDriverRef inDri
19191913 // devices that are the same kind of device. Note that two instances of the
19201914 // save device must have the same value for this property.
19211915 FailWithAction (inDataSize < sizeof (CFStringRef ), theAnswer = kAudioHardwareBadPropertySizeError , Done , "BlackHole_GetDevicePropertyData: not enough space for the return value of kAudioDevicePropertyModelUID for the device" );
1922- * ((CFStringRef * )outData ) = CFSTR (kDevice_ModelUID );
1916+ * ((CFStringRef * )outData ) = CFStringCreateWithFormat ( NULL , NULL , CFSTR (kDevice_ModelUID ), NUMBER_OF_CHANNELS );
19231917 * outDataSize = sizeof (CFStringRef );
19241918 break ;
19251919
@@ -3693,7 +3687,7 @@ static OSStatus BlackHole_StartIO(AudioServerPlugInDriverRef inDriver, AudioObje
36933687 gDevice_AnchorHostTime = mach_absolute_time ();
36943688
36953689 // allocate ring buffer
3696- ringBuffer = malloc ( RING_BUFFER_SIZE );
3690+ ringBuffer = calloc ( RING_BUFFER_FRAME_SIZE * NUMBER_OF_CHANNELS , sizeof ( Float32 ) );
36973691 }
36983692 else
36993693 {
@@ -3799,6 +3793,8 @@ static OSStatus BlackHole_GetZeroTimeStamp(AudioServerPlugInDriverRef inDriver,
37993793 * outSampleTime = gDevice_NumberTimeStamps * kDevice_RingBufferSize ;
38003794 * outHostTime = gDevice_AnchorHostTime + (((Float64 )gDevice_NumberTimeStamps ) * theHostTicksPerRingBuffer );
38013795 * outSeed = 1 ;
3796+
3797+ // DebugMsg("SampleTime: %f \t HostTime: %llu", *outSampleTime, *outHostTime);
38023798
38033799 // unlock the state lock
38043800 pthread_mutex_unlock (& gDevice_IOMutex );
@@ -3887,81 +3883,65 @@ static OSStatus BlackHole_DoIOOperation(AudioServerPlugInDriverRef inDriver, Aud
38873883
38883884 // IO Lock
38893885 pthread_mutex_lock (& gDevice_IOMutex );
3890-
3891- /* READ INPUT */
3892- if (inOperationID == kAudioServerPlugInIOOperationReadInput )
3893- {
3894- /* WRITE TO IOBUFFER */
3895- // calculate the ring buffer offset for the first sample INPUT
3896- ringBufferOffset = ((UInt64 )(inIOCycleInfo -> mInputTime .mSampleTime * BYTES_PER_FRAME ) % RING_BUFFER_SIZE );
3897-
3898- // calculate the size of the buffer
3899- inIOBufferByteSize = inIOBufferFrameSize * BYTES_PER_FRAME ;
3900- remainingRingBufferByteSize = RING_BUFFER_SIZE - ringBufferOffset ;
3901-
3902- if (remainingRingBufferByteSize > inIOBufferByteSize )
3903- {
3904- // copy whole buffer if we have space
3905- memcpy (ioMainBuffer , ringBuffer + ringBufferOffset , inIOBufferByteSize );
3906-
3907- }
3908- else
3909- {
3910- // copy 1st half
3911- memcpy (ioMainBuffer , ringBuffer + ringBufferOffset , remainingRingBufferByteSize );
3912- // copy 2nd half
3913- memcpy (ioMainBuffer + remainingRingBufferByteSize , ringBuffer , inIOBufferByteSize - remainingRingBufferByteSize );
3914- }
39153886
3887+ // From BlackHole to Application
3888+ if (inOperationID == kAudioServerPlugInIOOperationReadInput )
3889+ {
39163890
3917- /* CLEAR TO RINGBUFFER TRAILING BY 3072 SAMPLES */
3918- // calculate the ring buffer offset for the first sample INPUT
3919- ringBufferOffset = ((UInt64 )(inIOCycleInfo -> mInputTime .mSampleTime * BYTES_PER_FRAME - 3072 ) % RING_BUFFER_SIZE );
3920- remainingRingBufferByteSize = RING_BUFFER_SIZE - ringBufferOffset ;
3891+ Float32 * buffer = (Float32 * )ioMainBuffer ;
3892+ UInt64 mSampleTime = inIOCycleInfo -> mInputTime .mSampleTime ;
3893+
3894+ for (UInt32 frame = 0 ; frame < inIOBufferFrameSize ; frame ++ ){
3895+ for (int channel = 0 ; channel < NUMBER_OF_CHANNELS ; channel ++ ){
3896+
3897+ // don't do anything if muted
3898+ if (!gMute_Output_Master_Value )
3899+ {
3900+ // write to the ioMainBuffer
3901+ buffer [frame * NUMBER_OF_CHANNELS + channel ] = ringBuffer [((mSampleTime + frame )%kDevice_RingBufferSize )* NUMBER_OF_CHANNELS + channel ];
3902+ }
3903+ else
3904+ {
3905+ buffer [frame * NUMBER_OF_CHANNELS + channel ] = 0 ;
3906+ }
3907+
3908+ // clear ring buffer after 8192 samples.
3909+ ringBuffer [((mSampleTime + frame - 8192 )%kDevice_RingBufferSize )* NUMBER_OF_CHANNELS + channel ] = 0 ;
39213910
3922- if (remainingRingBufferByteSize > inIOBufferByteSize )
3923- {
3924- // clear the internal ring buffer
3925- memset (ringBuffer + ringBufferOffset , 0 , inIOBufferByteSize );
3926- }
3927- else
3928- {
3929- // clear the 1st half
3930- memset (ringBuffer + ringBufferOffset , 0 , remainingRingBufferByteSize );
3931- // clear the 2nd half
3932- memset (ringBuffer , 0 , inIOBufferByteSize - remainingRingBufferByteSize );
3911+ }
39333912 }
39343913 }
3935-
3936- /* WRITE MIX */
3914+
3915+ // From Application to BlackHole
39373916 if (inOperationID == kAudioServerPlugInIOOperationWriteMix )
39383917 {
3939- // don't do anything if muted
3940- if (!( gMute_Input_Master_Value || gMute_Output_Master_Value ))
3941- {
3942- /* WRITE MIX TO RINGBUFFER */
3943- // calculate the ring buffer offset for the first sample OUTPUT
3944- ringBufferOffset = (( UInt64 )( inIOCycleInfo -> mOutputTime . mSampleTime * BYTES_PER_FRAME ) % RING_BUFFER_SIZE );
3945-
3946- // calculate the size of the buffer
3947- inIOBufferByteSize = inIOBufferFrameSize * BYTES_PER_FRAME ;
3948-
3949- // mix the audio
3950- for ( UInt64 sample = 0 ; sample < inIOBufferByteSize ; sample += sizeof ( Float32 ))
3951- {
3952- // sample from ioMainBuffer
3953- Float32 * ioSample = ioMainBuffer + sample ;
3954-
3955- // sample from ring buffer
3956- Float32 * ringSample = ( Float32 * )( ringBuffer + ( ringBufferOffset + sample ) % RING_BUFFER_SIZE );
3957-
3958- // mix the two together scale by volume
3959- * ringSample += * ioSample * gVolume_Output_Master_Value * gVolume_Input_Master_Value ;
3918+
3919+ Float32 * buffer = ( Float32 * ) ioMainBuffer ;
3920+
3921+ UInt64 mSampleTime = inIOCycleInfo -> mOutputTime . mSampleTime ;
3922+
3923+ for ( UInt32 frame = 0 ; frame < inIOBufferFrameSize ; frame ++ ){
3924+ for ( int channel = 0 ; channel < NUMBER_OF_CHANNELS ; channel ++ ){
3925+
3926+ // don't do anything if muted
3927+ if (! gMute_Output_Master_Value )
3928+ {
3929+ // write to internal ring buffer
3930+ ringBuffer [(( mSampleTime + frame )% kDevice_RingBufferSize ) * NUMBER_OF_CHANNELS + channel ] += buffer [ frame * NUMBER_OF_CHANNELS + channel ] * gVolume_Output_Master_Value ;
3931+ }
3932+ else
3933+ {
3934+ buffer [ frame * NUMBER_OF_CHANNELS + channel ] = 0 ;
3935+ }
3936+
3937+ // clear ring buffer after 8192 samples.
3938+ ringBuffer [(( mSampleTime + frame - 8192 )% kDevice_RingBufferSize ) * NUMBER_OF_CHANNELS + channel ] = 0 ;
39603939 }
3961- }
39623940
3941+ }
3942+
39633943 // clear the io buffer
3964- memset (ioMainBuffer , 0 , inIOBufferByteSize );
3944+ memset (ioMainBuffer , 0 , inIOBufferFrameSize * NUMBER_OF_CHANNELS * sizeof ( Float32 ) );
39653945 }
39663946
39673947 pthread_mutex_unlock (& gDevice_IOMutex );
0 commit comments