@@ -221,9 +221,11 @@ static OSStatus BlackHole_Initialize(AudioServerPlugInDriverRef inDriver, AudioS
221
221
// calculate the host ticks per frame
222
222
struct mach_timebase_info theTimeBaseInfo ;
223
223
mach_timebase_info (& theTimeBaseInfo );
224
- Float64 theHostClockFrequency = theTimeBaseInfo .denom / theTimeBaseInfo .numer ;
224
+ Float64 theHostClockFrequency = ( Float64 ) theTimeBaseInfo .denom / ( Float64 ) theTimeBaseInfo .numer ;
225
225
theHostClockFrequency *= 1000000000.0 ;
226
226
gDevice_HostTicksPerFrame = theHostClockFrequency / gDevice_SampleRate ;
227
+
228
+ // DebugMsg("BlackHole theTimeBaseInfo.numer: %u \t theTimeBaseInfo.denom: %u", theTimeBaseInfo.numer, theTimeBaseInfo.denom);
227
229
228
230
Done :
229
231
return theAnswer ;
@@ -346,12 +348,14 @@ static OSStatus BlackHole_PerformDeviceConfigurationChange(AudioServerPlugInDriv
346
348
// recalculate the state that depends on the sample rate
347
349
struct mach_timebase_info theTimeBaseInfo ;
348
350
mach_timebase_info (& theTimeBaseInfo );
349
- Float64 theHostClockFrequency = theTimeBaseInfo .denom / theTimeBaseInfo .numer ;
351
+ Float64 theHostClockFrequency = ( Float64 ) theTimeBaseInfo .numer / ( Float64 ) theTimeBaseInfo .denom ;
350
352
theHostClockFrequency *= 1000000000.0 ;
351
353
gDevice_HostTicksPerFrame = theHostClockFrequency / gDevice_SampleRate ;
352
354
353
355
// unlock the state mutex
354
356
pthread_mutex_unlock (& gPlugIn_StateMutex );
357
+
358
+ // DebugMsg("BlackHole theTimeBaseInfo.numer: %u \t theTimeBaseInfo.denom: %u", theTimeBaseInfo.numer, theTimeBaseInfo.denom);
355
359
356
360
Done :
357
361
return theAnswer ;
@@ -412,9 +416,7 @@ static Boolean BlackHole_HasProperty(AudioServerPlugInDriverRef inDriver, AudioO
412
416
theAnswer = BlackHole_HasStreamProperty (inDriver , inObjectID , inClientProcessID , inAddress );
413
417
break ;
414
418
415
- case kObjectID_Volume_Input_Master :
416
419
case kObjectID_Volume_Output_Master :
417
- case kObjectID_Mute_Input_Master :
418
420
case kObjectID_Mute_Output_Master :
419
421
case kObjectID_DataSource_Input_Master :
420
422
case kObjectID_DataSource_Output_Master :
@@ -461,9 +463,7 @@ static OSStatus BlackHole_IsPropertySettable(AudioServerPlugInDriverRef inDriver
461
463
theAnswer = BlackHole_IsStreamPropertySettable (inDriver , inObjectID , inClientProcessID , inAddress , outIsSettable );
462
464
break ;
463
465
464
- case kObjectID_Volume_Input_Master :
465
466
case kObjectID_Volume_Output_Master :
466
- case kObjectID_Mute_Input_Master :
467
467
case kObjectID_Mute_Output_Master :
468
468
case kObjectID_DataSource_Input_Master :
469
469
case kObjectID_DataSource_Output_Master :
@@ -513,9 +513,7 @@ static OSStatus BlackHole_GetPropertyDataSize(AudioServerPlugInDriverRef inDrive
513
513
theAnswer = BlackHole_GetStreamPropertyDataSize (inDriver , inObjectID , inClientProcessID , inAddress , inQualifierDataSize , inQualifierData , outDataSize );
514
514
break ;
515
515
516
- case kObjectID_Volume_Input_Master :
517
516
case kObjectID_Volume_Output_Master :
518
- case kObjectID_Mute_Input_Master :
519
517
case kObjectID_Mute_Output_Master :
520
518
case kObjectID_DataSource_Input_Master :
521
519
case kObjectID_DataSource_Output_Master :
@@ -566,9 +564,7 @@ static OSStatus BlackHole_GetPropertyData(AudioServerPlugInDriverRef inDriver, A
566
564
theAnswer = BlackHole_GetStreamPropertyData (inDriver , inObjectID , inClientProcessID , inAddress , inQualifierDataSize , inQualifierData , inDataSize , outDataSize , outData );
567
565
break ;
568
566
569
- case kObjectID_Volume_Input_Master :
570
567
case kObjectID_Volume_Output_Master :
571
- case kObjectID_Mute_Input_Master :
572
568
case kObjectID_Mute_Output_Master :
573
569
case kObjectID_DataSource_Input_Master :
574
570
case kObjectID_DataSource_Output_Master :
@@ -617,9 +613,7 @@ static OSStatus BlackHole_SetPropertyData(AudioServerPlugInDriverRef inDriver, A
617
613
theAnswer = BlackHole_SetStreamPropertyData (inDriver , inObjectID , inClientProcessID , inAddress , inQualifierDataSize , inQualifierData , inDataSize , inData , & theNumberPropertiesChanged , theChangedAddresses );
618
614
break ;
619
615
620
- case kObjectID_Volume_Input_Master :
621
616
case kObjectID_Volume_Output_Master :
622
- case kObjectID_Mute_Input_Master :
623
617
case kObjectID_Mute_Output_Master :
624
618
case kObjectID_DataSource_Input_Master :
625
619
case kObjectID_DataSource_Output_Master :
@@ -915,7 +909,7 @@ static OSStatus BlackHole_GetPlugInPropertyData(AudioServerPlugInDriverRef inDri
915
909
FailWithAction (inDataSize < sizeof (AudioObjectID ), theAnswer = kAudioHardwareBadPropertySizeError , Done , "BlackHole_GetPlugInPropertyData: not enough space for the return value of kAudioPlugInPropertyTranslateUIDToBox" );
916
910
FailWithAction (inQualifierDataSize == sizeof (CFStringRef ), theAnswer = kAudioHardwareBadPropertySizeError , Done , "BlackHole_GetPlugInPropertyData: the qualifier is the wrong size for kAudioPlugInPropertyTranslateUIDToBox" );
917
911
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 )
919
913
{
920
914
* ((AudioObjectID * )outData ) = kObjectID_Box ;
921
915
}
@@ -958,7 +952,7 @@ static OSStatus BlackHole_GetPlugInPropertyData(AudioServerPlugInDriverRef inDri
958
952
FailWithAction (inDataSize < sizeof (AudioObjectID ), theAnswer = kAudioHardwareBadPropertySizeError , Done , "BlackHole_GetPlugInPropertyData: not enough space for the return value of kAudioPlugInPropertyTranslateUIDToDevice" );
959
953
FailWithAction (inQualifierDataSize == sizeof (CFStringRef ), theAnswer = kAudioHardwareBadPropertySizeError , Done , "BlackHole_GetPlugInPropertyData: the qualifier is the wrong size for kAudioPlugInPropertyTranslateUIDToDevice" );
960
954
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 )
962
956
{
963
957
* ((AudioObjectID * )outData ) = kObjectID_Device ;
964
958
}
@@ -1329,7 +1323,7 @@ static OSStatus BlackHole_GetBoxPropertyData(AudioServerPlugInDriverRef inDriver
1329
1323
case kAudioBoxPropertyBoxUID :
1330
1324
// Boxes have UIDs the same as devices
1331
1325
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 );
1333
1327
break ;
1334
1328
1335
1329
case kAudioBoxPropertyTransportType :
@@ -1910,7 +1904,7 @@ static OSStatus BlackHole_GetDevicePropertyData(AudioServerPlugInDriverRef inDri
1910
1904
// audio device across boot sessions. Note that two instances of the same
1911
1905
// device must have different values for this property.
1912
1906
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 );
1914
1908
* outDataSize = sizeof (CFStringRef );
1915
1909
break ;
1916
1910
@@ -1919,7 +1913,7 @@ static OSStatus BlackHole_GetDevicePropertyData(AudioServerPlugInDriverRef inDri
1919
1913
// devices that are the same kind of device. Note that two instances of the
1920
1914
// save device must have the same value for this property.
1921
1915
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 );
1923
1917
* outDataSize = sizeof (CFStringRef );
1924
1918
break ;
1925
1919
@@ -3693,7 +3687,7 @@ static OSStatus BlackHole_StartIO(AudioServerPlugInDriverRef inDriver, AudioObje
3693
3687
gDevice_AnchorHostTime = mach_absolute_time ();
3694
3688
3695
3689
// allocate ring buffer
3696
- ringBuffer = malloc ( RING_BUFFER_SIZE );
3690
+ ringBuffer = calloc ( RING_BUFFER_FRAME_SIZE * NUMBER_OF_CHANNELS , sizeof ( Float32 ) );
3697
3691
}
3698
3692
else
3699
3693
{
@@ -3799,6 +3793,8 @@ static OSStatus BlackHole_GetZeroTimeStamp(AudioServerPlugInDriverRef inDriver,
3799
3793
* outSampleTime = gDevice_NumberTimeStamps * kDevice_RingBufferSize ;
3800
3794
* outHostTime = gDevice_AnchorHostTime + (((Float64 )gDevice_NumberTimeStamps ) * theHostTicksPerRingBuffer );
3801
3795
* outSeed = 1 ;
3796
+
3797
+ // DebugMsg("SampleTime: %f \t HostTime: %llu", *outSampleTime, *outHostTime);
3802
3798
3803
3799
// unlock the state lock
3804
3800
pthread_mutex_unlock (& gDevice_IOMutex );
@@ -3887,81 +3883,65 @@ static OSStatus BlackHole_DoIOOperation(AudioServerPlugInDriverRef inDriver, Aud
3887
3883
3888
3884
// IO Lock
3889
3885
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
- }
3915
3886
3887
+ // From BlackHole to Application
3888
+ if (inOperationID == kAudioServerPlugInIOOperationReadInput )
3889
+ {
3916
3890
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 ;
3921
3910
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
+ }
3933
3912
}
3934
3913
}
3935
-
3936
- /* WRITE MIX */
3914
+
3915
+ // From Application to BlackHole
3937
3916
if (inOperationID == kAudioServerPlugInIOOperationWriteMix )
3938
3917
{
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 ;
3960
3939
}
3961
- }
3962
3940
3941
+ }
3942
+
3963
3943
// clear the io buffer
3964
- memset (ioMainBuffer , 0 , inIOBufferByteSize );
3944
+ memset (ioMainBuffer , 0 , inIOBufferFrameSize * NUMBER_OF_CHANNELS * sizeof ( Float32 ) );
3965
3945
}
3966
3946
3967
3947
pthread_mutex_unlock (& gDevice_IOMutex );
0 commit comments