Seguboard Segue вызывает сбой AVAudioEngine - PullRequest
0 голосов
/ 14 мая 2018

Я работаю с AVAudioUnitSampler, который подключен к AVAudioEngine в моем приложении.Я получил все, чтобы работать хорошо, за исключением, когда я выхожу из контроллера представления, в котором создается экземпляр сэмплера. Я получаю сбой с ошибкой, которая говорит:

Завершение приложения из-за необработанного исключения 'com.apple.coreaudio.avfaudio ', reason:' обязательное условие: false: outputNode '

Я предполагаю, что это происходит из-за того, что двигатель прерывается, когда я возвращаюсь к своему предыдущему VC, Точно сказать не могу!

Я пытался остановить движок, а также секвенсор внутри viewWillDisappear, но он все еще не работает.

Если я использую UIButton show segue для предыдущего VC, это вроде работает,но я получаю сбой с раскруткой 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 Ответ

0 голосов
/ 15 мая 2018

Этот код похож на ваш и не вылетает при переходе или раскручивании:

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