我正在使用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)
}
}
答案 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")
}
}
}
}
}
}