如何使用带有 Xamarin 的 AudioUnit 录制音频

Posted

技术标签:

【中文标题】如何使用带有 Xamarin 的 AudioUnit 录制音频【英文标题】:How to Record audio using AudioUnit with Xamarin 【发布时间】:2020-06-09 21:39:23 【问题描述】:

我正在尝试使用 AudioUnit 录制音频。

我有以下代码: 但是 SetFormat 方法返回 PropertyNotWritable。我已经能够使用这样的代码使用相同的格式参数播放音频。但不能让它用于录制音频。

(请注意,Xamarin 似乎缺少 RemoteIO 常量 :()

  const int AudioUnitSubTypeRemoteIO = ('r' << 24) + ('i' << 16) + ('o' << 8) + 'c';
  readonly AudioUnit.AudioUnit _audioUnit;

  public AudioRecorderios()
  
     var audioComponentDescription = new AudioComponentDescription()
     
        ComponentType = AudioComponentType.Output,
        ComponentSubType = AudioUnitSubTypeRemoteIO,
        ComponentManufacturer = AudioComponentManufacturerType.Apple,
        ComponentFlags = 0,
        ComponentFlagsMask = 0
     ;

     AudioComponent defaultOutput = AudioComponent.FindNextComponent(null, ref audioComponentDescription);
     _audioUnit = defaultOutput.CreateAudioUnit();

     const int sampleRate = 8000;
     const int channels = 1;
     const int bytesPerSample = 2;
     int framesPerPacket = 1;

     var streamFormat = new AudioStreamBasicDescription()
     
        SampleRate = sampleRate,
        Format = AudioFormatType.LinearPCM,
        FormatFlags = AudioFormatFlags.LinearPCMIsSignedInteger | AudioFormatFlags.IsPacked,
        ChannelsPerFrame = channels,
        BytesPerFrame = bytesPerSample * channels,
        BitsPerChannel = bytesPerSample * 8,
        BytesPerPacket = framesPerPacket * bytesPerSample * channels,
        FramesPerPacket = framesPerPacket,
        Reserved = 0
     ;

     AudioUnitStatus status = _audioUnit.SetFormat(streamFormat, AudioUnitScopeType.Output);
     if (status != AudioUnitStatus.OK)
     
        throw new ArgumentOutOfRangeException($"Failed to set Audio Format with error status");
     

     _audioUnit.SetRenderCallback(InputCallback, AudioUnitScopeType.Output);

     _audioUnit.Initialize();

更新: 如果我忽略 SetFormat 的输出,并在初始化后调用 GetFormat,那么我会得到非常不同的格式选项,如果我随后将我的格式请求更新为与它选择的相同,那么我仍然会得到 PropertyNotWritable。所以我认为这与我选择的格式值无关。我还在网上找到了使用与我完全相同的格式选项的人的示例。

【问题讨论】:

是否抛出异常?堆栈跟踪显示什么? 正如我的问题中所详述的,SetFormat 调用正在返回 PropertyNotWritable,(然后我抛出一个 ArgumentOutOfRangeException,您可以从阅读我的代码中看到) 我不知道如何解决它,但我发现问题是由AudioUnitSubTypeRemoteIO 引起的。如果我评论 ComponentSubType = AudioUnitSubTypeRemoteIO 那么一切正常。 【参考方案1】:

我需要调用 _audioUnit.SetEnableIO(true, AudioUnitScopeType.Input, 1) 来启用录音。以及在 Info.plist 中添加“隐私 - 麦克风使用说明”

并在 SetFormat 和 SetInputCallback 方法中将 audioUnitElement 参数设置为 1。

【讨论】:

以上是关于如何使用带有 Xamarin 的 AudioUnit 录制音频的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C#/Xamarin 中使用带有来自 android 钥匙串的私钥的 X.509 证书?

使用带有 Xamarin 表单的 Rg 插件弹出窗口

如何在 Xamarin Android 的 AlertDialog 中创建带有自定义适配器的列表视图

Xamarin:Android - 带有大位图的OutOfMemory异常 - 如何解决?

如何在 Visual Studio 中为带有 Windows 计算机的 Xamarin 应用程序设计用户界面?

如何在 Xamarin Forms iOS 中显示带有小型大写字体样式的标签?