Skip to content

Commit 4fea4fd

Browse files
authoredFeb 9, 2020
Merge pull request #57 from ExistentialAudio/dev
0.2.5
2 parents e193991 + f9c6b24 commit 4fea4fd

File tree

7 files changed

+64
-39
lines changed

7 files changed

+64
-39
lines changed
 

‎BlackHole.xcodeproj/project.pbxproj

+11
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@
110110
isa = PBXProject;
111111
attributes = {
112112
LastUpgradeCheck = 1030;
113+
TargetAttributes = {
114+
2D7477A81578168D00412279 = {
115+
DevelopmentTeam = Q5C99V536K;
116+
};
117+
};
113118
};
114119
buildConfigurationList = 2D7477A01578162B00412279 /* Build configuration list for PBXProject "BlackHole" */;
115120
compatibilityVersion = "Xcode 3.2";
@@ -316,13 +321,15 @@
316321
buildSettings = {
317322
ALWAYS_SEARCH_USER_PATHS = NO;
318323
CLANG_ENABLE_OBJC_WEAK = YES;
324+
DEVELOPMENT_TEAM = Q5C99V536K;
319325
GCC_PREPROCESSOR_DEFINITIONS = (
320326
"$(inherited)",
321327
"DEBUG=0",
322328
);
323329
INFOPLIST_FILE = "$(SRCROOT)/BlackHole/BlackHole-Info.plist";
324330
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Audio/Plug-Ins/HAL";
325331
MACOSX_DEPLOYMENT_TARGET = 10.10;
332+
MARKETING_VERSION = 0.2.6;
326333
PRODUCT_BUNDLE_IDENTIFIER = audio.existential.BlackHole;
327334
PRODUCT_NAME = "$(TARGET_NAME)";
328335
WRAPPER_EXTENSION = driver;
@@ -334,13 +341,15 @@
334341
buildSettings = {
335342
ALWAYS_SEARCH_USER_PATHS = NO;
336343
CLANG_ENABLE_OBJC_WEAK = YES;
344+
DEVELOPMENT_TEAM = Q5C99V536K;
337345
GCC_PREPROCESSOR_DEFINITIONS = (
338346
"$(inherited)",
339347
"DEBUG=1",
340348
);
341349
INFOPLIST_FILE = "$(SRCROOT)/BlackHole/BlackHole-Info.plist";
342350
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Audio/Plug-Ins/HAL";
343351
MACOSX_DEPLOYMENT_TARGET = 10.10;
352+
MARKETING_VERSION = 0.2.6;
344353
PRODUCT_BUNDLE_IDENTIFIER = audio.existential.BlackHole;
345354
PRODUCT_NAME = "$(TARGET_NAME)";
346355
WRAPPER_EXTENSION = driver;
@@ -352,13 +361,15 @@
352361
buildSettings = {
353362
ALWAYS_SEARCH_USER_PATHS = NO;
354363
CLANG_ENABLE_OBJC_WEAK = YES;
364+
DEVELOPMENT_TEAM = Q5C99V536K;
355365
GCC_PREPROCESSOR_DEFINITIONS = (
356366
"$(inherited)",
357367
"DEBUG=1",
358368
);
359369
INFOPLIST_FILE = "$(SRCROOT)/BlackHole/BlackHole-Info.plist";
360370
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Audio/Plug-Ins/HAL";
361371
MACOSX_DEPLOYMENT_TARGET = 10.10;
372+
MARKETING_VERSION = 0.2.6;
362373
PRODUCT_BUNDLE_IDENTIFIER = audio.existential.BlackHole;
363374
PRODUCT_NAME = "$(TARGET_NAME)";
364375
WRAPPER_EXTENSION = driver;

‎BlackHole.xcodeproj/xcshareddata/xcschemes/BlackHole.xcscheme

-4
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
shouldUseLaunchSchemeArgsEnv = "YES">
3030
<Testables>
3131
</Testables>
32-
<AdditionalOptions>
33-
</AdditionalOptions>
3432
</TestAction>
3533
<LaunchAction
3634
buildConfiguration = "Debug"
@@ -51,8 +49,6 @@
5149
ReferencedContainer = "container:BlackHole.xcodeproj">
5250
</BuildableReference>
5351
</MacroExpansion>
54-
<AdditionalOptions>
55-
</AdditionalOptions>
5652
</LaunchAction>
5753
<ProfileAction
5854
buildConfiguration = "Release"

‎BlackHole/BlackHole-Info.plist

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<key>CFBundlePackageType</key>
1818
<string>BNDL</string>
1919
<key>CFBundleShortVersionString</key>
20-
<string>0.2.2</string>
20+
<string>$(MARKETING_VERSION)</string>
2121
<key>CFBundleSignature</key>
2222
<string>????</string>
2323
<key>CFBundleVersion</key>

‎BlackHole/BlackHole.c

+42-33
Original file line numberDiff line numberDiff line change
@@ -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
}

‎BlackHole/BlackHole.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,13 @@ static UInt32 gDataSource_Output_Master_Value = 0;
164164
#define BYTES_PER_CHANNEL (BITS_PER_CHANNEL / 8)
165165
#define BYTES_PER_FRAME (NUMBER_OF_CHANNELS * BYTES_PER_CHANNEL)
166166
#define RING_BUFFER_SIZE ((8192 + LATENCY_FRAME_SIZE) * NUMBER_OF_CHANNELS * BYTES_PER_CHANNEL)
167-
static char ringBuffer[RING_BUFFER_SIZE];
167+
static void* ringBuffer;
168168
static UInt64 ringBufferOffset = 0;
169169
static UInt64 inIOBufferByteSize = 0;
170170
static UInt64 remainingRingBufferByteSize = 0;
171171

172+
//kAudioHardwarePropertySleepingIsAllowed
173+
172174

173175
//==================================================================================================
174176
#pragma mark -

‎CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
66
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
77

8+
## [0.2.6] - 2020-02-08
9+
### Changed
10+
- Fixed BlackHole error when switching devices from DAW
11+
- Fixed BlackHole error when sleeping
12+
- Audio Midi Setup speaker configuration now saves preferences
13+
814
## [0.2.5] - 2019-11-29
915
### Changed
1016
- Set default volume to 1.0

‎README.md

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ Visit the [Wiki](https://github.com/ExistentialAudio/BlackHole/wiki) for applica
4949
3. Open DAW and set input device to "BlackHole"
5050
4. Set track to input from channel 1-2
5151
5. Play audio from another application and monitor or record in your DAW.
52+
NOTE: You will not be able to hear the audio with this method.
5253

5354
### Route Audio Between Applications
5455
1. Set output driver to "BlackHole" in sending application

0 commit comments

Comments
 (0)