故事板segue导致AVAudioEngine崩溃

时间:2018-05-14 17:56:42

标签: ios swift avfoundation avaudioengine

我正在使用AVAudioUnitSampler连接到我的应用程序中的AVAudioEngine。我已经完成了所有工作,除非我从视图控制器中取样实例化了采样器。我遇到了一个错误,说:

  

由于未捕获的异常终止应用' com.apple.coreaudio.avfaudio',原因:'必需条件为false:outputNode'

我猜这是因为当我回到我之前的VC时,引擎会以某种方式被打断,不确定!

我试图阻止引擎以及viewWillDisappear中的音序器,但它仍然崩溃。

如果我使用UIButton show segue到之前的VC,它有点工作,但是我得到一个带有展开segue和当前导航栏segue的崩溃。

我是新手,所以希望我已经解释得这么好了!

我从前一个VC的表视图触发的segue中获取此VC。

以下是相关VC的代码:

import UIKit
import AVFoundation

class PlayerViewController: UIViewController {
    @IBOutlet weak var descriptionLabel: UILabel!
    @IBOutlet weak var playPauseButton: UIButton!
    @IBOutlet weak var musicView: UIImageView!

    let allSounds = SoundBankOnAndOff()
    var currentSoundFile: OnandOff?
    var engine = AVAudioEngine()
    var sampler = AVAudioUnitSampler()

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(true)

        self.navigationController?.isNavigationBarHidden = false
        setupSequencer()
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(true)
        engine.stop()
        sequencer.stop()
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        descriptionLabel.text = exercises[myIndex]
        musicView.image = musicNotes[myIndex]
        engine = AVAudioEngine()
        sampler = AVAudioUnitSampler()

        engine.attach(sampler)
        engine.connect(sampler, to: engine.mainMixerNode, format: nil)
        loadSF2PresetIntoSampler(preset: 0)
        startEngine()
        setSessionPlayback()
    }

    func setSessionPlayback() {
        let audioSession = AVAudioSession.sharedInstance()
        do {
            try
                audioSession.setCategory(AVAudioSessionCategoryPlayback, with:
                    AVAudioSessionCategoryOptions.mixWithOthers)
        } catch {
            print("couldn't set category \(error)")
            return
        }

        do {
            try audioSession.setActive(true)
            print("category is active")
        } catch {
            print("couldn't set category to active \(error)")
            return
        }
    }

    func startEngine() {
        if engine.isRunning {
            print("audio engine has already started")
            return
        }

        do {
            try engine.start()
            print("audio engine started")
        } catch {
            print("oops \(error)")
            print("could not start audio engine")
        }
    }

    var sequencer:AVAudioSequencer!

    func setupSequencer() {
        let allSounds = SoundBankOnAndOff()
        let currentSoundFile = allSounds.list[myIndex]
        self.sequencer = AVAudioSequencer(audioEngine: engine)

        let options = AVMusicSequenceLoadOptions.smfChannelsToTracks

        if let fileURL = Bundle.main.urls(forResourcesWithExtension: "mid", subdirectory: "On & Off MIDI") {
            do {
                try sequencer.load(from: (currentSoundFile.soundFile), options: options)
                print("loaded \(fileURL)")
            } catch {
                print("something messed up \(error)")
                return
            }
        }
        sequencer.prepareToPlay()
    }


    func play() {
        if sequencer.isPlaying {
            stop()
        }

        sequencer.currentPositionInBeats = TimeInterval(0)

        do {
            try sequencer.start()


        } catch {
            print("cannot start \(error)")
        }
    }

    func stop() {
        sequencer.stop()
    }

    func loadSF2PresetIntoSampler(preset:UInt8)  {
        guard let bankURL = Bundle.main.url(forResource: "Pad Sounds", withExtension: "sf2") else {
            print("could not load sound font")
            return
        }

        do {
            try sampler.loadSoundBankInstrument(at: bankURL, program: preset,bankMSB: UInt8(kAUSampler_DefaultMelodicBankMSB),bankLSB: UInt8(kAUSampler_DefaultBankLSB))
        } catch {
            print("error loading sound bank instrument")
        }
    }



    @IBAction func playButtonPressed(sender: UIButton) {
        if sender.currentTitle == "PLAY"{
            play()
            sender.setTitle("STOP", for: .normal)
        } else if sender.currentTitle == "STOP" {
            sender.setTitle("PLAY", for: .normal)

            stop()
        }
    }

    @IBAction func BackButtonPressed(_ sender: Any) {
        performSegue(withIdentifier: "unwindToDetailVC", sender: self)
    }
}

1 个答案:

答案 0 :(得分:0)

此代码与您的代码相似,并且在进行分割或展开时不会崩溃:

class MP3PlayerVC: UIViewController {

    let audioEngine = AVAudioEngine()
    let audioPlayer = AVAudioPlayerNode()
    let distortion = AVAudioUnitDistortion()

    override func viewDidLoad() {
        super.viewDidLoad()

        audioEngine.attach(audioPlayer)
        audioEngine.attach(distortion)
        audioEngine.connect(audioPlayer, to: distortion, format: nil)
        audioEngine.connect(distortion, to: audioEngine.outputNode, format: nil)
    }

    @IBAction func buttonClicked(_ sender: UIButton) {

        if let filePath = Bundle.main.path(forResource: "test", ofType: "mp3") {

            let url = URL.init(fileURLWithPath: filePath)

            if let audioFile = try? AVAudioFile(forReading: url) {

                if audioPlayer.isPlaying {
                    audioPlayer.stop()
                    audioEngine.stop()
                } else {

                    audioPlayer.scheduleFile(audioFile, at: nil, completionHandler: nil)

                    do {
                        try audioEngine.start()

                        audioPlayer.play()

                    } catch {
                        print("something went wrong")
                    }
                }
            }
        }
    }
}