swift - 重置 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.
}
}
解决方案
看起来您可能只需将attach
、connect
和engine.start
函数移出 sound1Play 函数,并将它们放入 viewDidLoad 中。目前,您正在连接每个操作的节点,并多次重新启动引擎。
推荐阅读
- html - 如何解决:“社交媒体精灵在纵向模式下无法正确显示”
- excel - 如果单元格在 VBA 中不是数字,如何删除整行?我的代码删除了所有内容
- jquery - Jquery Ajax 不通过发布请求发送多个数据
- django - http 响应标头中的 WCDN 缓存策略
- javascript - 带有属性+数组的Json对象,如何移动数组内的属性?
- c# - 按索引循环遍历三个 List(Of T)
- netflix - Netflix 技术背景下的事件是什么?
- laravel - 在 Laravel-Excel 3.1 中具有多个工作表的 Excel 文件 -> 在单元格验证后导入原始并存储 + 存储单个工作表
- vue.js - 无法使用 vuejs v-for 在 html 中显示数组
- javascript - 如何使用 if 语句使用 JavaScript 更改 CSS?