首页 > 解决方案 > AVAudioPlayer.play() 有效,但 AVAudioPlayerNode.play() 失败

问题描述

我有以下使用 AVAudioPlayerNode 播放音频文件的 Swift Playground 代码。

import AVFoundation
import Foundation

NSSetUncaughtExceptionHandler { exception in
    print("Exception thrown: \(exception)")
}

var filePath = "/Users/fractor/Desktop/TestFile.mp3"
let file : AVAudioFile
do {
    file = try AVAudioFile(forReading: URL(fileURLWithPath: filePath))
} catch let error {
    print(error.localizedDescription)
    throw error
}

let audioEngine = AVAudioEngine()
let playerNode = AVAudioPlayerNode()
audioEngine.attach(playerNode)
audioEngine.connect(playerNode, to: audioEngine.outputNode, format: file.processingFormat);

do {
    try audioEngine.start()
} catch let error {
    print(error.localizedDescription)
    throw error
}

playerNode.scheduleFile(file, at: nil){}
playerNode.play();

当使用内置扬声器或连接到 UE WONDERBOOM 蓝牙扬声器时,这在我的 mac mini 上运行良好。但是,当连接到 UE BOOM 2 蓝牙扬声器时,它会崩溃。

AVAudioPlayer我尝试过的所有扬声器都可以正常使用,包括 UE BOOM 2 。

异常消息是“当引擎未运行时播放器启动”但是插入打印命令显示引擎在playerNode.play()被调用之前正在运行。

这是堆栈跟踪的(部分)。

堆栈跟踪

在这种情况下,EXC_BAD_INSTRUCTION 表示什么?

为了消除由于使用 Swift 游乐场而引入错误行为的可能性,我还创建了一个 Swift macOS Cocoa 应用程序。这是代码:

class ViewController: NSViewController {

    let filePath = "/Users/fractor/Desktop/TestFile.mp3"
    var file : AVAudioFile?
    var audioEngine = AVAudioEngine()
    var playerNode = AVAudioPlayerNode()

    override func viewDidLoad() {
        super.viewDidLoad()

        do {
            file = try AVAudioFile(forReading: URL(fileURLWithPath: filePath))
        } catch let error {
            print(error.localizedDescription)
            return
        }

        audioEngine.attach(playerNode)
        audioEngine.connect(playerNode, to: audioEngine.outputNode, format: file!.processingFormat);

        do {
            try audioEngine.start()
        } catch let error {
            print(error.localizedDescription)
            return
        }

        playerNode.scheduleFile(file!, at: nil){}

        print("audioEngine.isRunning = \(audioEngine.isRunning)");
        playerNode.play();
        print("playerNode.isPlaying = \(playerNode.isPlaying)");
    }
}

当连接到 UE BOOM 2 扬声器时无法播放,并出现以下错误:

2019-07-23 13:32:50.784444+0100 AVAudioPlayerNodeSwiftTest[1757:29297] [AudioHAL_Client] HALC_ProxyIOContext.cpp:958:IOWorkLoop:  HALC_ProxyIOContext::IOWorkLoop: the server failed to start, Error: 0xE00002D6
2019-07-23 13:32:51.696089+0100 AVAudioPlayerNodeSwiftTest[1757:29249] Failed to set (contentViewController) user defined inspected property on (NSWindow): player started when engine not running
2019-07-23 13:32:53.815222+0100 AVAudioPlayerNodeSwiftTest[1757:29448] [AudioHAL_Client] HALC_ProxyIOContext.cpp:958:IOWorkLoop:  HALC_ProxyIOContext::IOWorkLoop: the server failed to start, Error: 0xE00002D6

这同样适用于 WONDERBOOM 扬声器和内置扬声器。

play如果我使用以下代码调用后台线程,我设法获得异常跟踪:

DispatchQueue.global(qos: .background).async {
    print("audioEngine.isRunning = \(self.audioEngine.isRunning)");
    self.playerNode.play();
    print("playerNode.isPlaying = \(self.playerNode.isPlaying)");
}

完整的输出是:

audioEngine.isRunning = true
2019-07-24 12:25:38.710647+0100 AVAudioPlayerNodeSwiftTest[1852:21353] [AudioHAL_Client] HALC_ProxyIOContext.cpp:958:IOWorkLoop:  HALC_ProxyIOContext::IOWorkLoop: the server failed to start, Error: 0xE00002D6
2019-07-24 12:25:40.717683+0100 AVAudioPlayerNodeSwiftTest[1852:21340] [General] An uncaught exception was raised
2019-07-24 12:25:40.717738+0100 AVAudioPlayerNodeSwiftTest[1852:21340] [General] player started when engine not running
2019-07-24 12:25:40.717865+0100 AVAudioPlayerNodeSwiftTest[1852:21340] [General] (
    0   CoreFoundation                      0x00007fff2d017cfd __exceptionPreprocess + 256
    1   libobjc.A.dylib                     0x00007fff576bea17 objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff2d032a1a +[NSException raise:format:arguments:] + 98
    3   AVFAudio                            0x00007fff291f2304 _Z19AVAE_RaiseExceptionP8NSStringz + 156
    4   AVFAudio                            0x00007fff29247d8c _ZN21AVAudioPlayerNodeImpl9StartImplEP11AVAudioTime + 1282
    5   AVFAudio                            0x00007fff29246b48 -[AVAudioPlayerNode play] + 75
    6   AVAudioPlayerNodeSwiftTest          0x0000000100002924 $s26AVAudioPlayerNodeSwiftTest14ViewControllerC11viewDidLoadyyFyycfU0_ + 644
    7   AVAudioPlayerNodeSwiftTest          0x0000000100002b8d $s26AVAudioPlayerNodeSwiftTest14ViewControllerC11viewDidLoadyyFyycfU0_TA + 13
    8   AVAudioPlayerNodeSwiftTest          0x00000001000025dd $sIeg_IeyB_TR + 45
    9   libdispatch.dylib                   0x000000010034fe7c _dispatch_call_block_and_release + 12
    10  libdispatch.dylib                   0x0000000100350f1b _dispatch_client_callout + 8
    11  libdispatch.dylib                   0x0000000100363a06 _dispatch_root_queue_drain + 816
    12  libdispatch.dylib                   0x00000001003642da _dispatch_worker_thread2 + 125
    13  libsystem_pthread.dylib             0x00000001003ca0b7 _pthread_wqthread + 583
    14  libsystem_pthread.dylib             0x00000001003c9e01 start_wqthread + 13
)
2019-07-24 12:25:40.718570+0100 AVAudioPlayerNodeSwiftTest[1852:21340] *** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'player started when engine not running'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff2d017cfd __exceptionPreprocess + 256
    1   libobjc.A.dylib                     0x00007fff576bea17 objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff2d032a1a +[NSException raise:format:arguments:] + 98
    3   AVFAudio                            0x00007fff291f2304 _Z19AVAE_RaiseExceptionP8NSStringz + 156
    4   AVFAudio                            0x00007fff29247d8c _ZN21AVAudioPlayerNodeImpl9StartImplEP11AVAudioTime + 1282
    5   AVFAudio                            0x00007fff29246b48 -[AVAudioPlayerNode play] + 75
    6   AVAudioPlayerNodeSwiftTest          0x0000000100002924 $s26AVAudioPlayerNodeSwiftTest14ViewControllerC11viewDidLoadyyFyycfU0_ + 644
    7   AVAudioPlayerNodeSwiftTest          0x0000000100002b8d $s26AVAudioPlayerNodeSwiftTest14ViewControllerC11viewDidLoadyyFyycfU0_TA + 13
    8   AVAudioPlayerNodeSwiftTest          0x00000001000025dd $sIeg_IeyB_TR + 45
    9   libdispatch.dylib                   0x000000010034fe7c _dispatch_call_block_and_release + 12
    10  libdispatch.dylib                   0x0000000100350f1b _dispatch_client_callout + 8
    11  libdispatch.dylib                   0x0000000100363a06 _dispatch_root_queue_drain + 816
    12  libdispatch.dylib                   0x00000001003642da _dispatch_worker_thread2 + 125
    13  libsystem_pthread.dylib             0x00000001003ca0b7 _pthread_wqthread + 583
    14  libsystem_pthread.dylib             0x00000001003c9e01 start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException

同样,如果使用 WONDERBOOM 或内置扬声器也没问题。

人们在这里也遇到了问题:https ://forums.developer.apple.com/thread/118459

AudioKit 也崩溃:AudioKit macOS HelloWorld 与 UE BOOM 2 扬声器崩溃

AVAudioPlayer对于我正在开发的应用程序来说是不够的。问题是什么?想必既然它抛出了一个异常,那就是Apple代码中的一个错误?

标签: swiftmacosavfoundationavaudioengineavaudioplayernode

解决方案


推荐阅读