代码之家  ›  专栏  ›  技术社区  ›  Terry B

情节提要segue导致AVAudioEngine崩溃

  •  1
  • Terry B  · 技术社区  · 7 年前

    我正在使用应用程序中连接到AVAudioEngine的AvaudioInitSampler。我已经让一切都很好地工作了,除了我脱离了采样器在其中实例化的视图控制器。我遇到了一个崩溃,错误是:

    由于未捕获的异常“com”,正在终止应用程序。苹果coreaudio。avfaudio',原因:'所需条件为false:outputNode'

    我猜这是因为当我回到以前的VC时,引擎不知怎么被中断了,不确定!

    我试图停止引擎,视图中的序列器也将消失,但它仍然崩溃。

    如果我使用上一个VC的UIButton show segue,它可以正常工作,但我会在放松segue和当前导航栏segue时崩溃。

    我是个新手,希望我已经解释得足够好了!

    我从上一个VC上的表视图触发的一个序列中访问这个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 回复  |  直到 7 年前
        1
  •  0
  •   u84six    7 年前

    此代码与您的代码类似,在分段或展开时不会崩溃:

    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")
                        }
                    }
                }
            }
        }
    }