如何启用/禁用聚合 CoreAudio 设备的输入或输出通道?

2024-06-25

我已经仔细阅读了该主题中的问题和答案:如何从聚合 CoreAudio 设备中排除输入或输出通道? https://stackoverflow.com/questions/60445512/how-to-exclude-input-or-output-channels-from-an-aggregate-coreaudio-device/67668430#67668430

并且似乎缺少有关解决方案的信息: 我创建了一个包含多个音频设备的聚合设备。当调用核心音频来接收流的数量(使用kAudioDevicePropertyStreams)时,返回值始终为1。我还尝试了CoreAudio实用程序类中的实现:CAHALAudioDevice::GetIOProcStreamUsage。我仍然看不到如何访问子流并禁用/启用它们,如此处所述。 需要做什么才能实现子流的禁用/启用?

EDIT

这里是 CAHALAudioDevice::GetIOProcStreamUsage 供参考:

void    CAHALAudioDevice::GetIOProcStreamUsage(AudioDeviceIOProcID 
inIOProcID, bool inIsInput, bool* outStreamUsage) const
{
    //  make an AudioHardwareIOProcStreamUsage the right size
    UInt32 theNumberStreams = GetNumberStreams(inIsInput);
    UInt32 theSize = SizeOf32(void*) + SizeOf32(UInt32) + (theNumberStreams * SizeOf32(UInt32));
    CAAutoFree<AudioHardwareIOProcStreamUsage> theStreamUsage(theSize);

    //  set it up
    theStreamUsage->mIOProc = reinterpret_cast<void*>(inIOProcID);
    theStreamUsage->mNumberStreams = theNumberStreams;

    //  get the property
    CAPropertyAddress theAddress(kAudioDevicePropertyIOProcStreamUsage, inIsInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput);
    GetPropertyData(theAddress, 0, NULL, theSize, theStreamUsage);

    //  fill out the return value
    for(UInt32 theIndex = 0; theIndex < theNumberStreams; ++theIndex)
    {
        outStreamUsage[theIndex] = (theStreamUsage->mStreamIsOn[theIndex] != 0);
    }
}

作为参考,这里是我的程序使用的函数来完成中描述的结果链接问题 https://stackoverflow.com/questions/60445512/how-to-exclude-input-or-output-channels-from-an-aggregate-coreaudio-device:

// Tell CoreAudio which input (or output) streams we actually want to use in our device
// @param devID the CoreAudio audio device ID of the aggregate device to modify
// @param ioProc the rendering callback-function (as was passed to AudioDeviceCreateIOProcID()'s second argument)
// @param scope either kAudioObjectPropertyScopeInput or kAudioObjectPropertyScopeOutput depending on which type of channels we want to modify
// @param numValidChannels how many audio channels in the aggregate device we want to actually use
// @param rightJustify if true, we want to use the last (numValidChannels) in the device; if false we want to use the first (numValidChannels) in the device
// @returns 0 on success or -1 on error
// @note this function doesn't change the layout of the audio-sample data in the audio-render callback; rather it causes some channels of audio in the callback to become zero'd out/unused.
int SetProcStreamUsage(AudioDeviceID devID, void * ioProc, AudioObjectPropertyScope scope, int numValidChannels, bool rightJustify)
{  
   const AudioObjectPropertyAddress sizesAddress =
   {                    
       kAudioDevicePropertyStreamConfiguration, 
       scope, 
       kAudioObjectPropertyElementMaster
   };    
   Uint32 streamSizesDataSize = 0;
   OSStatus err = AudioObjectGetPropertyDataSize(devID, &sizesAddress, 0, NULL, &streamSizesDataSize);
   if (err != noErr)
   {        
      printf("SetProcStreamUsage(%u,%i,%i):  AudioObjectGetPropertyDataSize(kAudioDevicePropertyStreamConfiguration) failed!\n", (unsigned int) devID, scope, rightJustify);
      return -1;  // ("AudioObjectGetPropertyDataSize(kAudioDevicePropertyStreamConfiguration) failed");
   }           
               
   const AudioObjectPropertyAddress usageAddress = 
   {              
       kAudioDevicePropertyIOProcStreamUsage,
       scope,        
       kAudioObjectPropertyElementMaster 
   };                
                        
   Uint32 streamUsageDataSize = 0;
   err = AudioObjectGetPropertyDataSize(devID, &usageAddress, 0, NULL, &streamUsageDataSize);
   if (err != noErr)
   {              
      printf("SetProcStreamUsage(%u,%i,%i):  AudioObjectGetPropertyDataSize(kAudioDevicePropertyIOProcStreamUsage) failed!\n", (unsigned int) devID, scope, rightJustify);
      return -1;  // ("AudioObjectGetPropertyDataSize(kAudioDevicePropertyIOProcStreamUsage) failed");
   }                 
                     
   AudioBufferList * bufList = (AudioBufferList*) malloc(streamSizesDataSize);  // using malloc() because the object-size is variable
   if (bufList)         
   {                 
      int ret;    
      
      err = AudioObjectGetPropertyData(devID, &sizesAddress, 0, NULL, &streamSizesDataSize, bufList);
      if (err == noErr) 
      {           
         AudioHardwareIOProcStreamUsage * streamUsage = (AudioHardwareIOProcStreamUsage *) malloc(streamUsageDataSize);  // using malloc() because the object-size is variable
         if (streamUsage)
         {           
            streamUsage->mIOProc = ioProc;
            err = AudioObjectGetPropertyData(devID, &usageAddress, 0, NULL, &streamUsageDataSize, streamUsage);
            if (err == noErr)
            {  
               if (bufList->mNumberBuffers == streamUsage->mNumberStreams)
               {  
                  Int32 numChannelsLeft = numValidChannels;
                  if (rightJustify)
                  {
                     // We only want streams corresponding to the last (N) channels to be enabled
                     for (Int32 i=streamUsage->mNumberStreams-1; i>=0; i--) 
                     {
                        streamUsage->mStreamIsOn[i] = (numChannelsLeft > 0);
                        numChannelsLeft -= bufList->mBuffers[i].mNumberChannels;
                     }
                  }
                  else
                  {
                     // We only want streams corresponding to the first (N) channels to be enabled
                     for (Uint32 i=0; i<streamUsage->mNumberStreams; i++)
                     {
                        streamUsage->mStreamIsOn[i] = (numChannelsLeft > 0);
                        numChannelsLeft -= bufList->mBuffers[i].mNumberChannels;
                     }
                  }

                  // Now set the stream-usage per our update, above
                  err = AudioObjectSetPropertyData(devID, &usageAddress, 0, NULL, streamUsageDataSize, streamUsage);
                  if (err != noErr)
                  {
                     printf("SetProcStreamUsage(%u,%i,%i):  AudioObjectSetPropertyData(kAudioDevicePropertyIOProcStreamUsage) failed!\n", (unsigned int) devID, scope, rightJustify);
                     ret = -1;  // ("AudioObjectSetPropertyData(kAudioDevicePropertyIOProcStreamUsage) failed");
                  }
               }
               else
               {
                  printf("SetProcStreamUsage(%u,%i,%i):  #Buffers (%u) doesn't match #Streams (%u)!\n", (unsigned int) devID, scope, rightJustify, bufList->mNumberBuffers, streamUsage->mNumberStreams);
                  ret = -1;
               }
            }
            else
            {
               printf("SetProcStreamUsage(%u,%i,%i):  AudioObjectSetPropertyData(kAudioDevicePropertyIOProcStreamUsage) failed!\n", (unsigned int) devID, scope, rightJustify);
               ret = -1;  // ("AudioObjectGetPropertyData(kAudioDevicePropertyIOProcStreamUsage) failed");
            }

            free(streamUsage);
         }
         else ret = -1;  // out of memory?
      }
      else
      {
         printf("SetProcStreamUsage(%u,%i,%i):  AudioObjectGetPropertyData(kAudioDevicePropertyStreamConfiguration) failed!\n", (unsigned int) devID, scope, rightJustify);
         ret = -1;  // ("AudioObjectGetPropertyData(kAudioDevicePropertyStreamConfiguration) failed");
      }

      free(bufList);
      return ret;
   }
   else return -1; // out of memory?
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何启用/禁用聚合 CoreAudio 设备的输入或输出通道? 的相关文章

随机推荐

  • 仅当列不为 NULL 时才连接列

    我有一个像这样的 SQL Server 表 PERSON NAME PHONE PHONE1 PHONE2 PHONE CONCAT Name1 12345 Null Null Null
  • Lua userdata数组访问及方法

    我正在用 C 编写一个用户数据类型 以便在 Lua 中使用 它有一些数组类型的属性和各种方法 现在如果你是这种类型 我使用u set k v resp u get k 访问数据 例如u sort 作为方法 为此我设置了 index到包含这些
  • Haskell - 让函数返回空字符

    我正在尝试创建一个函数来删除字符串中的每个第 n 个元素 dropEvery String gt Int gt String dropEvery str n map char indx gt if indx mod n 0 then cha
  • 使用 Chrome 扩展程序截取整页屏幕截图

    是否可以在 Chrome 扩展程序中捕获整个页面的屏幕截图 包括首屏以下的内容 The 捕获可见选项卡 http code google com chrome extensions tabs html似乎仅限于可见区域内显示的内容 标准方法
  • 方法被重写后,类不可序列化

    我重写一个createSocket 我的测试用例中的方法传递到模拟的套接字中 执行此操作后 对象将不再可序列化 这是一个不起作用的示例 Foo java import java io Serializable public class Fo
  • 如何在 C++ 中打印 Unicode 字符

    我正在尝试打印俄语 U 0444 http www unicode org charts PDF U0400 pdf西里尔小写字母 EF 字符 给出十进制代码1092 http en wikipedia org wiki D0 A4 使用C
  • 基于团体成员资格的额外输出

    我希望你们都度过愉快的一天 如果这是一个糟糕的问题尝试 我提前道歉 我不太擅长这个 介绍 首先 我想介绍一下我实际正在创作的内容 我为 MSP 工作 我的任务是创建一个供我们的一位客户使用的用户管理 Powershell 脚本 以便我们可以
  • 重置 Angular 7 Reactive 验证

    我使用 Angular Reactive 表单作为搜索表单 我希望能够重置表格 我用以下代码做到了这一点
  • 用于显示昨天日期和今天日期的 JavaScript 代码

    如何在我的文本框中显示昨天的日期 同时显示今天的日期 我有这个 home php 其中显示昨天的日期 用户无法修改此只读 和今天的日期 用户必须输入今天的日期 当明天到来并且用户访问主页 php 时 他 她将看到昨天输入的日期 并将再次输入
  • 抽象类型与类型参数

    在什么情况下抽象类型应该优先于类型参数 添加到我的之前关于抽象类型与参数的回答 https stackoverflow com questions 1154571 scala abstract types vs generics 11547
  • ssl.SSLError:[SSL:CERTIFICATE_VERIFY_FAILED]证书验证失败(_ssl.c:777)

    我目前正在使用 websocket client 将 python 与 QlikSense 服务器连接 对于身份验证 我使用了 Qlik sense 服务器生成的证书 即使我遵循这里提到的相同代码逻辑link https help qlik
  • Google App Engine 数据存储中最有效的一对多关系?

    抱歉 如果这个问题太简单了 我才刚上九年级 我正在尝试学习 NoSQL 数据库设计 我想设计一个谷歌数据存储模型 最大限度地减少读 写次数 以下是一对多关系中的博客文章和评论的玩具示例 将所有评论存储在 StructuredProperty
  • 如何在 Django 模型中使用枚举作为选择字段?

    我有一个模型类 我希望其中两个字段成为选择字段 因此为了填充这些选择 我使用了如下列出的枚举 models py class Transaction models Model transaction status models CharFi
  • MySQL - 将字段的默认值设置为字符串连接函数

    我有一个看起来有点像这个的表 actor forename surname stage name 我想将 stage name 更新为默认值 forename surname So that insert into actors foren
  • 删除 JSON 根

    我在 JavaScript 变量上有以下字符串 my Variable Domini cod domini 1 nom domini Sant Esteve de Palautordera cod domini 2 nom domini P
  • 对多个 Maven 项目运行 Fortify 扫描

    我有多个项目由单个父 pom 绑定 如果我使用 Maven fortify 插件在父 pom 上运行 fortify 扫描 则会生成每个项目的 fpr 文件 我希望为所有项目生成一个 fpr 文件 是否可以 感谢致敬 绍拉夫 您想要做的是聚
  • char 的符号是接口问题吗?

    假设我有一个函数 void foo char 它在内部需要将其输入视为以 NUL 结尾的字节块 例如 它是字符串上的哈希函数 我可以把论点转为unsigned char 在函数中 我还可以将声明更改为 void foo unsigned c
  • 何时在 JavaScript 中使用柯里化和偏函数

    我读了这个post http drdobbs com open source 231001821Dobb 博士关于 JavaScript 中的柯里化和部分函数的文章 它看起来很有用 但我想知道 作为 JavaScript 的临时开发人员 是
  • 如何处理 ASP.NET 中未处理的线程异常?

    ASP NET 应用程序应该如何处理非请求后台线程上发生的未处理的异常 由于错误 默认情况下 此类异常会导致进程终止 这在 ASP NET 工作进程的设置中是不可接受的因为并发运行的请求会不可预测地中止 这也是一个性能问题 请求线程上的异常
  • 如何启用/禁用聚合 CoreAudio 设备的输入或输出通道?

    我已经仔细阅读了该主题中的问题和答案 如何从聚合 CoreAudio 设备中排除输入或输出通道 https stackoverflow com questions 60445512 how to exclude input or outpu