我的AVAudioEngine设置如下:
fileprivate let player = AVAudioPlayerNode()
fileprivate let audioEngine = AVAudioEngine()
fileprivate var audioFileBuffer: AVAudioPCMBuffer?
fileprivate var EQNode: AVAudioUnitEQ?
fileprivate var audioFile: AVAudioFile?
fileprivate func setUpEngine(with name: String, frequencies: [Int], isDownloaded: Bool = false) {
// Load a music file
do {
var audioUrl: URL?
if isDownloaded {
// URL from Document Directory
guard let docDirecoryPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
audioUrl = docDirecoryPath.appendingPathComponent(name)
} else {
// URL from Main Bundle
audioUrl = Bundle.main.url(forResource: name, withExtension: "mp3")
}
guard let musicUrl = audioUrl else { return }
let audioFile = try AVAudioFile(forReading: musicUrl)
self.audioFile = audioFile
audioFileBuffer = AVAudioPCMBuffer(pcmFormat: audioFile.processingFormat, frameCapacity: UInt32(audioFile.length))
try audioFile.read(into: audioFileBuffer!)
} catch {
AppUtility.showAlert("", message: "failed to load the music. Error: \(error.localizedDescription)", delegate: nil)
//assertionFailure("failed to load the music. Error: \(error)")
return
}
// initial Equalizer.
EQNode = AVAudioUnitEQ(numberOfBands: frequencies.count)
EQNode!.globalGain = 1
for i in 0...(EQNode!.bands.count-1) {
EQNode!.bands[i].frequency = Float(frequencies[i])
EQNode!.bands[i].gain = 0
EQNode!.bands[i].bypass = false
EQNode!.bands[i].filterType = .parametric
}
// Attach nodes to an engine.
audioEngine.attach(EQNode!)
audioEngine.attach(player)
// Connect player to the EQNode.
let mixer = audioEngine.mainMixerNode
//
audioEngine.connect(player, to: EQNode!, format: mixer.outputFormat(forBus: 0))
// Connect the EQNode to the mixer.
audioEngine.connect(EQNode!, to: mixer, format: mixer.outputFormat(forBus: 0))
// For BackGround Play
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, mode: AVAudioSessionModeDefault, options: [.mixWithOthers, .allowAirPlay])
try AVAudioSession.sharedInstance().setActive(true)
} catch let error {
print(error.localizedDescription)
}
// Schedule player to play the buffer on a loop.
if let audioFileBuffer = audioFileBuffer {
player.scheduleBuffer(audioFileBuffer, at: nil, options: .loops, completionHandler: nil)
}
}
另外,我还配置了“耳机插入/插入通知”。在这两种情况下,我都需要暂停当前播放的音频。 因此,在插入/拔出耳机后,我会暂停音频。当我再次播放时,没有声音从电话扬声器或耳机都没有。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
UIApplication.shared.statusBarStyle = .lightContent
// Notification for output changed
NotificationCenter.default.addObserver(self, selector: #selector(audioHardwareRouteChanged), name: .AVAudioSessionRouteChange, object: nil)
return true
}
@objc func audioHardwareRouteChanged(notification: Notification) {
guard let userInfoDict = notification.userInfo, let routeChangeReason = userInfoDict[AVAudioSessionRouteChangeReasonKey] as? UInt, let audioManager = AppConstants.audioManager else {
return
}
switch routeChangeReason {
case AVAudioSessionRouteChangeReason.newDeviceAvailable.rawValue:
print("headphone plugged in")
self.changeNowPlayingSettings(audioManager: audioManager)
case AVAudioSessionRouteChangeReason.oldDeviceUnavailable.rawValue:
print("headphone pulled out")
self.changeNowPlayingSettings(audioManager: audioManager)
default:
break
}
}
func changeNowPlayingSettings(audioManager: AudioManager) {
// Now Playing
AppConstants.nowPlayingTrack?.isNowPlaying = false
AppConstants.nowPlayingTrack?.isPaused = false
// Root Controller
if let navController = self.window?.rootViewController as? UINavigationController, let nowPlayingVC = navController.topViewController as? NowPlayingViewController {
audioManager.pause()
}
}
答案 0 :(得分:0)
在两种情况下(插入和拔出)音频引擎都停止时,检查audioengine.isrunning,它将返回false。您需要重新启动/重新启动音频引擎