在Mac上使用BlackHole捕捉系统输出音频时,如何解决虚拟音频设备BlackHole 2ch无声音输出?

问题描述

我有一个难题:

我正在使用 BlackHole 尝试在 macOS 上捕获系统输出音频,BlackHole 驱动器可以创建一个虚拟音频设备,例如支持 2 个通道的 BlackHole 2ch。
当我选择这个虚拟设备作为音频输出设备时,我确实可以通过BlockHole创建的相应虚拟输入设备与虚拟输出设备同时捕获系统输出音频。

但是,虚拟输出设备没有声音播放,我无法从扬声器或耳机听到任何声音。
我知道必须在 BlackHole_DoIOOperation() 函数中编写一些代码行,但我不知道任何方向,谁能给我一些建议? 谢谢

这是 BlackHole 创建的虚拟输出设备

This is virtual output device created by BlackHole

这是 BlackHole 创建的虚拟输入设备

This is virtual input device created by BlackHole


这里是 BlackHole_DoIOOperation() 函数代码
我怀疑是这行代码引起的,所以我把它删除了,但还是不行。
// memset(ioMainBuffer,inIOBufferFrameSize * NUMBER_OF_CHANNELS * sizeof(Float32));

static Osstatus BlackHole_DoIOOperation(AudioServerPlugInDriverRef          inDriver,AudioObjectID                       inDeviceObjectID,AudioObjectID                       inStreamObjectID,UInt32                              inClientID,UInt32                              inoperationID,UInt32                              inIOBufferFrameSize,const AudioServerPlugInIOCycleInfo* inIOCycleInfo,void*                               ioMainBuffer,void*                               ioSecondaryBuffer)
{
    //  This is called to actuall perform a given operation. For this device,all we need to do is
    //  clear the buffer for the ReadInput operation.
    DebugMsg("BlackHole DoIOOperation()");
    #pragma unused(inClientID,inIOCycleInfo,ioSecondaryBuffer)
    
    //  declare the local variables
    Osstatus theAnswer = 0;
    
    //  check the arguments
    FailWithAction(inDriver != gAudioServerPlugInDriverRef,theAnswer = kAudioHardwareBadobjectError,Done,"BlackHole_DoIOOperation: bad driver reference");
    FailWithAction(inDeviceObjectID != kObjectID_Device,"BlackHole_DoIOOperation: bad device ID");
    FailWithAction((inStreamObjectID != kObjectID_Stream_Input) && (inStreamObjectID != kObjectID_Stream_Output),"BlackHole_DoIOOperation: bad stream ID");
    
    // IO Lock
    pthread_mutex_lock(&gDevice_IOMutex);

    // From BlackHole to Application
    if(inoperationID == kAudioServerPlugInIOOperationReadInput)
    {

        Float32* buffer = (Float32*)ioMainBuffer;
        UInt64 mSampleTime = inIOCycleInfo->mInputTime.mSampleTime;

        for (UInt32 frame = 0; frame < inIOBufferFrameSize; frame++)
        {
            for (int channel = 0; channel < NUMBER_OF_CHANNELS; channeL++)
            {
                // don't do anything if muted
                if (!gMute_Output_Master_Value)
                {
                    // write to the ioMainBuffer
                    buffer[frame*NUMBER_OF_CHANNELS+channel] = ringBuffer[((mSampleTime+frame)%kDevice_RingBufferSize)*NUMBER_OF_CHANNELS+channel];
                }
                else
                {
                    buffer[frame*NUMBER_OF_CHANNELS+channel] = 0;
                }
                
                // clear ring buffer after 8192 samples.
                ringBuffer[((mSampleTime+frame-8192)%kDevice_RingBufferSize)*NUMBER_OF_CHANNELS+channel] = 0;

            }
        }
    }
    
    // From Application to BlackHole
    if(inoperationID == kAudioServerPlugInIOOperationWriteMix)
    {
        DebugMsg("output...");
        Float32* buffer = (Float32*) ioMainBuffer;
        UInt64 mSampleTime = inIOCycleInfo->mOutputTime.mSampleTime;
        for (UInt32 frame = 0; frame < inIOBufferFrameSize; frame++)
        {
            for (int channel = 0; channel < NUMBER_OF_CHANNELS; channeL++)
            {
                // don't do anything if muted
                if (!gMute_Output_Master_Value)
                {
                    // write to internal ring buffer
                    DebugMsg("channel: %d",channel);
                    ringBuffer[((mSampleTime + frame) % kDevice_RingBufferSize) * NUMBER_OF_CHANNELS + channel] += buffer[frame * NUMBER_OF_CHANNELS + channel] * gVolume_Output_Master_Value;
                }
                else
                {
                    buffer[frame * NUMBER_OF_CHANNELS + channel] = 0;
                }
                
                // clear ring buffer after 8192 samples.
                ringBuffer[((mSampleTime + frame - 8192) % kDevice_RingBufferSize) * NUMBER_OF_CHANNELS + channel] = 0;
            }
        }
        theAnswer = kAudioHardwareBadobjectError;
        
        // clear the io buffer
        // memset(ioMainBuffer,inIOBufferFrameSize * NUMBER_OF_CHANNELS * sizeof(Float32));
    }
    
    pthread_mutex_unlock(&gDevice_IOMutex);

Done:
    return theAnswer;
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)