问题
I have the following Swift playground code that plays an audio file using AVAudioPlayerNode.
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();
This works fine on my mac mini when using the inbuilt speaker or when connected to a UE WONDERBOOM bluetooth speaker. However it crashes when connected to a UE BOOM 2 bluetooth speaker.
Using AVAudioPlayer
works fine with all speakers I have tried including the UE BOOM 2.
The exception message is "player started when engine not running" however inserting print commands shows that the engine is running prior to playerNode.play()
being called.
Here's (part of) the stack trace.
What does EXC_BAD_INSTRUCTION indicate in this case?
To remove the possibility of erroneous behaviour being introduced due to using a Swift playground, I have also created a Swift macOS Cocoa app. Here is the code:
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)");
}
}
This fails to play when connected to the UE BOOM 2 speaker with the following errors:
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
Again this works fine with the WONDERBOOM speaker and the inbuilt speaker.
I manage to get an exception trace if I call play
on a background thread using the following code:
DispatchQueue.global(qos: .background).async {
print("audioEngine.isRunning = \(self.audioEngine.isRunning)");
self.playerNode.play();
print("playerNode.isPlaying = \(self.playerNode.isPlaying)");
}
The full output being:
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
Again, no problem if using the WONDERBOOM or built in speaker.
People are also having a problem here: https://forums.developer.apple.com/thread/118459
AudioKit also crashes: AudioKit macOS HelloWorld crashes with UE BOOM 2 speaker
AVAudioPlayer
is not sufficient for the application I am developing. What is the problem? Presumably since it throws an exception, it is a bug in Apple code?
来源:https://stackoverflow.com/questions/57092434/avaudioplayer-play-works-but-avaudioplayernode-play-fails