首页 > 解决方案 > AVAudioEngine 插入/拔出耳机后没有声音

问题描述

我的 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()
    }
}

在此处输入图像描述

标签: iosiphoneswift

解决方案


在这两种情况下(插入和拔出)音频引擎都已停止,检查 audioengine.isrunning,它将返回 false。您需要重新启动/重新初始化音频引擎


推荐阅读