首页 > 解决方案 > 重置 AVAudioEngine

问题描述

我正在创建一个基本的音板应用程序。我有两个开关。一种在激活时会使音频变慢并降低音调,另一种会使其更快和更高。我有一个if else if if声明,查看这些开关,然后相应地播放音频,但是当我尝试第二次按下它时,无论是相同的声音还是不同的声音,它都会崩溃。

我大约 99% 确定这是由于需要重置 AVAudioEngine 或让节点本身重置,但我已经超越了我的联盟。我搜索了高低,但我似乎找到的答案与使用不同按钮发出高或低声音时重置播放器有关。有什么想法吗?

class ViewController: UIViewController {

@IBOutlet weak var sassSwitch: UISwitch!
@IBOutlet weak var chipSwitch: UISwitch!

@IBAction func sassAction(_ sender: UISwitch) {
    chipSwitch.setOn(false, animated: true)
}
@IBAction func chipSwitch(_ sender: UISwitch) {
    sassSwitch.setOn(false, animated: true)
}


///Playback Engine
private let audioEngine = AVAudioEngine()

///Player's Nodes
private let pitchPlayer = AVAudioPlayerNode()
private let timePitch = AVAudioUnitTimePitch()

///Audio Files to be played
private var audioFile1 = AVAudioFile()
private var audioFile2 = AVAudioFile()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    if let filePath = Bundle.main.path(forResource: "PeteNope", ofType:
        "mp3") {
        let filePathURL = URL(fileURLWithPath: filePath)

        setPlayerFile(filePathURL)

    }

    if let filePath2 = Bundle.main.path(forResource: "Law_WOW", ofType:
        "mp3") {
        let filePath2URL = URL(fileURLWithPath: filePath2)

        setPlayerFile2(filePath2URL)

    }
}

private func setPlayerFile(_ fileURL: URL) {
    do {
        let file = try AVAudioFile(forReading: fileURL)

        self.audioFile1 = file


    } catch {
        fatalError("Could not create AVAudioFile instance. error: \(error).")
    }
}

private func setPlayerFile2(_ fileURL: URL) {
    do {
        let file = try AVAudioFile(forReading: fileURL)

        self.audioFile2 = file


    } catch {
        fatalError("Could not create AVAudioFile instance. error: \(error).")
    }
}


@IBAction func sound1Play(_ sender: UIButton) {
    if sassSwitch.isOn {
        timePitch.pitch = -300
        timePitch.rate = 0.5
        audioEngine.attach(pitchPlayer)
        audioEngine.attach(timePitch)

        audioEngine.connect(pitchPlayer, to: timePitch, format: audioFile1.processingFormat)
        audioEngine.connect(timePitch, to: audioEngine.outputNode, format: audioFile1.processingFormat)
        pitchPlayer.scheduleFile(audioFile1, at: nil, completionHandler: nil)

        // Start the engine.
        do {
            try audioEngine.start()
        } catch {
            fatalError("Could not start engine. error: \(error).")
        }

        pitchPlayer.play()

    } else if chipSwitch.isOn {
        timePitch.pitch = +500
        timePitch.rate = 2.0
        audioEngine.attach(pitchPlayer)
        audioEngine.attach(timePitch)

        audioEngine.connect(pitchPlayer, to: timePitch, format: audioFile1.processingFormat)
        audioEngine.connect(timePitch, to: audioEngine.outputNode, format: audioFile1.processingFormat)
        pitchPlayer.scheduleFile(audioFile1, at: nil, completionHandler: nil)

        // Start the engine.
        do {
            try audioEngine.start()
        } catch {
            fatalError("Could not start engine. error: \(error).")
        }

        pitchPlayer.play()

    } else {
        timePitch.pitch = +0
        timePitch.rate = 1.0
        audioEngine.attach(pitchPlayer)
        audioEngine.attach(timePitch)

        audioEngine.connect(pitchPlayer, to: timePitch, format: audioFile1.processingFormat)
        audioEngine.connect(timePitch, to: audioEngine.outputNode, format: audioFile1.processingFormat)
        pitchPlayer.scheduleFile(audioFile1, at: nil, completionHandler: nil)

        // Start the engine.
        do {
            try audioEngine.start()
        } catch {
            fatalError("Could not start engine. error: \(error).")
        }
        pitchPlayer.play()
    }

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}

标签: swiftxcodeavaudioplayeravaudioengine

解决方案


看起来您可能只需将attachconnectengine.start函数移出 sound1Play 函数,并将它们放入 viewDidLoad 中。目前,您正在连接每个操作的节点,并多次重新启动引擎。


推荐阅读