【发布时间】:2020-08-03 19:57:20
【问题描述】:
使用 Xamarin,我想使用 AVAudioSinkNode 来存储并最终以尽可能低的延迟从麦克风传输传入的音频数据(而不直接进入 AudioUnits 和已弃用的 AUGraphs)。请参阅下面的注释代码,其中 SinkNode 连接到默认 InputNode。这让我很伤心。我将 Xamarin.Forms 与一个简单的 iOS 依赖类一起使用。我可以通过 fx 节点(例如 Reverb)成功连接 InputNode,然后连接到 OutputNode。在这种情况下,我已将代码最小化以专注于手头的问题:
public unsafe class AudioEngine : IAudioEngine
{
AVAudioEngine engine;
AVAudioInputNode input;
AVAudioSinkNode sink;
public AudioEngine()
{
ActivateAudioSession();
}
protected void ActivateAudioSession()
{
var session = AVAudioSession.SharedInstance();
session.SetCategory(AVAudioSessionCategory.Playback, AVAudioSessionCategoryOptions.DuckOthers);
session.SetActive(true);
session.SetPreferredIOBufferDuration(0.0007, out error); // 32 byte buffer, if possible!
engine = new AVAudioEngine();
input = engine.InputNode; // to save on typing
input.Volume = 0.5f;
var format = input.GetBusInputFormat(0); // used for fx connections, but not used in this snippet. If I use this in the Input -> Sink connection, it crashes.
sink = new AVAudioSinkNode(sinkReceiverHandler);
engine.AttachNode(sink);
try
{
//-----------------------------------------------------
// Param #3 (format) is nil in all the Apple Documentation and multiple examples
// In place of nil, **NSNull.Null** isn't accepted.
// In place of nil, **null** throws a System.NullReferenceException. (see stack dump)
// In place of nil, using the **InputNode's format** crashes with
// something about missing the Trampolines.g.cs file... no clue...
engine.Connect(input, sink, **null**); // null doesn't work in place of nil.
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace); // Exception messages included below
}
engine.Prepare();
engine.StartAndReturnError(out error);
}
private unsafe int sinkReceiverHandler(AudioToolbox.AudioTimeStamp timeStamp, uint frames, ref AudioToolbox.AudioBuffers inputData)
{
// Do stuff with the data...
return 0;
}
}
我发现一篇关于在 Xamarin.iOS 中使用 nil 作为参数的帖子说库的作者需要包含 [NullAllowed] 参数:
How to assign something to nil using Xamarin.iOS
我的问题是:我是否遗漏了一些明显的东西,或者这是 Xamarin 库定义中的疏忽?我一直认为这是我缺乏专业知识,但如果这是一个错误,我该如何向 Xamarin 报告?
后续问题:如果这是小故障,是否有可行的解决方法?我可以手动调整 Xamarin 库定义吗? (我敢肯定,任何更新都会中断。)或者我可以使用 Swift 创建一个小库,然后将其导入到我的 Xamarin 项目中?
只是在想办法。谢谢阅读! 下面是我使用 null 代替 nil 时的堆栈转储(再次强调......在这种情况下,NSNull.Null 不被视为有效类型。它只是无法编译): p>
{System.NullReferenceException:对象引用未设置为对象的实例 在 /Library/Frameworks/Xamarin.iOS.framework/Versions/13.18.3.2/src/Xamarin.iOS/AVFoundation/AVAudioFormat.cs 中的 AVFoundation.AVAudioFormat.op_Equality (AVFoundation.AVAudioFormat a, AVFoundation.AVAudioFormat b) [0x00000]: 27 在/Library/Frameworks/Xamarin.iOS.framework/Versions/13.18.3.2/src/Xamarin.iOS/AVAudioEngine中的AVFoundation.AVAudioEngine.Connect(AVFoundation.AVAudioNode sourceNode,AVFoundation.AVAudioNode targetNode,AVFoundation.AVAudioFormat格式)[0x00024] .g.cs:120 在 /Users/eludema/dev/xamarin/udptest/udptest.iOS/AudioEngine.cs:43 中的 udptest.iOS.AudioEngine.ActivateAudioSession () [0x0009b] }
谢谢!
【问题讨论】:
-
1) 你应该创建一个新问题@@github.com/xamarin/xamarin-macios/issues 2) 我从来没有使用过
null音频格式,作为一种解决方法,如果你只传递一个new AVAudioFormat()而不是@,会发生什么情况987654327@ 3)如果这不起作用,那么合法的格式怎么样:new AVAudioFormat (44100.0, 2); -
感谢@SushiHangover 的建议!我也没有使用 null,但似乎这是 AVAudioSinkNode 的路线,因为它不允许任何格式转换。做一个空的新 AVAudioFormat 给了我一个不同的例外。并按照您的建议(以及从 InputNode 中获取格式)执行合法的实际格式并出现错误:找不到 Trampolines.g.cs 文件——我不知道那是什么:)。感谢您的建议!它给了我一些希望!任何其他解决方法表示赞赏。同时,我将在 github 上创建一个问题。
-
在document:
Connect(AVAudioNode, AVAudioNode, AVAudioFormat)中声明 AVAudioFormat 可以为空。 -
感谢@Jack Hua!但是 null 是否会转换为 iOS 的 nil?我读过这就是 NSNull.Null 的用途,但这并不能编译为类型不匹配......我只是很困惑为什么它不起作用。也许我处理接收器代表的方式有问题......
-
我稍后会尝试你的代码并更新你。
标签: xamarin xamarin.ios avfoundation core-audio avaudioengine