CoreAudio错误并在AVAudioEngine.connect上崩溃

时间:2019-08-06 15:27:34

标签: ios swift audiounit avaudioengine

我试图像这样将AVAudioUnitEffect连接到AVAudioEngine的实例:

required init(inputFormat: AVAudioFormat, outputFormat: AVAudioFormat, andAVAudioEngine avAudioEngine:AVAudioEngine) {
    self.inputFormat = inputFormat
    self.outputFormat = outputFormat

    self.avAudioEngine = avAudioEngine
    self.myAudioUnit = MyAVAudioUnit()

    super.init()

    avAudioEngine.attach(myAudioUnit)
    avAudioEngine.connect(myAudioUnit, to: avAudioEngine.outputNode, format: self.inputFormat)
}

总体类只是NSObject的子类,而MyAudioUnitAVAudioUnitEffect的子类。

在看似随机的时间,此初始化程序的最后一行(对connect的调用)将引发SIGABRT,并出现以下错误:com.apple.coreaudio.avfaudio: error -10875

等于kAudioUnitErr_FailedInitialization

任何人都可以弄清楚这个错误,这里可能会发生什么?我以为MyAVAudioUnit的初始化程序可能失败了,但是它的内部初始化程序(init(audioComponentDescription: AudioComponentDescription))不会引发任何错误,并且具有非可选的返回类型。其他人是否有处理此特定错误的经验?

更新

这是inputFormat的初始化:

guard let stereoFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32,
                                        sampleRate: 44100,
                                        channels: 2,
                                        interleaved: false) else {
                                            return                                             
}

let numChannels = UInt32(10)
guard let multiChannelLayout = AVAudioChannelLayout(layoutTag: kAudioChannelLayoutTag_Unknown | numChannels) else {
    return
}

inputFormat = AVAudioFormat(commonFormat: stereoFormat.commonFormat,
                                   sampleRate: stereoFormat.sampleRate,
                                   interleaved: stereoFormat.isInterleaved,
                                   channelLayout: multiChannelLayout)

MyAVAudioUnit包含一个附加的自定义参数(volumeParameter)并按以下方式初始化:

required override init() {
    var componentDescription = AudioComponentDescription()
    componentDescription.componentType = kAudioUnitType_Effect
    componentDescription.componentSubType = xxxxx
    componentDescription.componentManufacturer = xxxxx
    componentDescription.componentFlags = 0
    componentDescription.componentFlagsMask = 0

    AUAudioUnit.registerSubclass(MyAVAudioUnit.self,
                                 as: componentDescription,
                                 name:"MyAVAudioUnit",
                                 version: UInt32.max)

    super.init(audioComponentDescription: componentDescription)

    guard let paramTree = self.auAudioUnit.parameterTree else { return }
    volumeParameter = paramTree.value(forKey: "volumeParameter") as? AUParameter
}

2 个答案:

答案 0 :(得分:2)

这就是最终解决此问题的原因。我从崩溃日志中注意到,在尝试连接音频单元之前,音频图的打印输出显示如下:

“ ________ GraphDescription ________ AVAudioEngineGraph 0x101538ba0: initialized = 1, running = 0, number of nodes = 23 ”

有趣的是,尽管running为假,initialized true 。关于initialized这条信息的含义的文档并不多,但是我发现当AVAudioEngine之前已经启动但被暂停时,它显示为true。现在,我没有从任何地方显式调用avAudioEngine.pause(),但我认为系统可能是AVAudioSessionRouteChangeNotification的一部分开始暂停(这是我在整个事件系列中所要响应的)

很多是推测,但是很明显,在引擎的打印输出显示avAudioEngine.connect()时调用initialized = 1(或者推断引擎已暂停)会导致此崩溃。 / p>

在尝试连接音频单元之前,必须将音频引擎完全停止。我的问题是我尝试调用avAudioEngine.stop()的过程被包裹在if语句中,如下所示:

if avAudioEngine.isRunning {
    avAudioEngine.stop()
}

当然,此if语句被跳过了,因为音频引擎实际上没有运行。因此stop()从未被调用。毫无疑问,删除if语句并调用stop()会在引擎上设置initialized = 0并允许连接而不会发生崩溃。

希望这对其他人有帮助。花了我很长时间才能解散。

答案 1 :(得分:1)

您说这是在“随机时间”复数下发生的。这可能意味着您经常这样做,并且可能在释放或取消初始化设备后不久。请注意,音频单元子系统在不同的完全异步线程中运行,因此在您的应用停止并释放该单元后,操作系统可能仍会在短时间内使用该单元。如果您在任何停止/释放调用与任何(重新)初始化之间放置足够长的延迟(例如大约一秒钟或两秒钟),则可以避免此问题。

相关问题