swift - 使用 AVAudio 循环播放 mp3
问题描述
我尝试循环播放一个 mp3 文件,我可以在播放时更改它的音高。我可以更改音高,但无法循环播放文件。这是我的代码:
import AVKit
class ViewController: UIViewController {
@IBOutlet weak var speedSlider: UISlider!
@IBOutlet weak var speedLabel: UILabel!
let pitchControl = AVAudioUnitTimePitch()
let engine = AVAudioEngine()
override func viewDidLoad(){
super.viewDidLoad()
do{ try playSound(soundName: "audiSound1")} catch{}
}
@IBAction func speedSlided(_ sender: Any) {
pitchControl.pitch = speedSlider.value
speedLabel.text = String(speedSlider.value)
}
func playSound(soundName: String) throws{
guard let url = Bundle.main.url(forResource: soundName, withExtension: "mp3") else { return }
let file = try AVAudioFile(forReading: url)
let audioPlayer = AVAudioPlayerNode()
engine.attach(audioPlayer)
engine.attach(pitchControl)
engine.connect(audioPlayer, to: pitchControl, format: nil)
engine.connect(pitchControl, to: engine.mainMixerNode, format: nil)
audioPlayer.scheduleFile(try! AVAudioFile(forReading: url), at: nil)
try engine.start()
audioPlayer.play()
}
}
为了让它循环,我尝试使用 AVAudioPCMBuffer(),请参阅:
import AVKit
class ViewController: UIViewController {
@IBOutlet weak var speedSlider: UISlider!
@IBOutlet weak var speedLabel: UILabel!
let pitchControl = AVAudioUnitTimePitch()
let engine = AVAudioEngine()
override func viewDidLoad(){
super.viewDidLoad()
do{ try playSound(soundName: "audiSound1")} catch{}
}
@IBAction func speedSlided(_ sender: Any) {
pitchControl.pitch = speedSlider.value
speedLabel.text = String(speedSlider.value)
}
func playSound(soundName: String) throws{
guard let url = Bundle.main.url(forResource: soundName, withExtension: "mp3") else { return }
let file = try AVAudioFile(forReading: url)
let audioPlayer = AVAudioPlayerNode()
//New:
let audioFileBuffer = AVAudioPCMBuffer(pcmFormat: file.fileFormat, frameCapacity: AVAudioFrameCount(file.length))
try? file.read(into: audioFileBuffer!)
engine.attach(audioPlayer)
engine.attach(pitchControl)
engine.connect(audioPlayer, to: pitchControl, format: nil)
engine.connect(pitchControl, to: engine.mainMixerNode, format: nil)
audioPlayer.scheduleBuffer(audioFileBuffer!,at: nil, options: .loops, completionHandler: nil) //Changed
try engine.start()
audioPlayer.play()
}
}
但是当我运行项目时,它给了我一个线程 1:“必需条件为 false:isPCMFormat”错误:/ 确切的错误消息是:
2021-04-06 20:31:51.824454+0200 avas[67546:8825321] [avae] AVAEInternal.h:76 所需条件为假:[AVAudioBuffer.mm:175:-[AVAudioPCMBuffer initWithPCMFormat:frameCapacity:]: (isPCMFormat) ] 2021-04-06 20:31:51.832637+0200 avas[67546:8825321] *** 由于未捕获的异常“com.apple.coreaudio.avfaudio”而终止应用程序,原因:“必需条件为 false:isPCMFormat”
我不知道如何让它以另一种(工作)方式循环。有人能帮我吗?:)
太感谢了!
解决方案
这有效:
import AVKit
class ViewController: UIViewController {
@IBOutlet weak var speedSlider: UISlider!
@IBOutlet weak var speedLabel: UILabel!
let pitchControl = AVAudioUnitTimePitch()
let engine = AVAudioEngine()
override func viewDidLoad(){
super.viewDidLoad()
do{ try playSound(soundName: "audiSound1")} catch{}
}
@IBAction func speedSlided(_ sender: Any) {
pitchControl.pitch = speedSlider.value
speedLabel.text = String(speedSlider.value)
}
func playSound(soundName: String) throws{
guard let url = Bundle.main.url(forResource: soundName, withExtension: "mp3") else { return }
let file = try AVAudioFile(forReading: url)
let audioPlayer = AVAudioPlayerNode()
let audioFormat = file.processingFormat
let audioFrameCount = UInt32(file.length)
let audioFileBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: audioFrameCount)
try! file.read(into: audioFileBuffer!)
let mainMixer = engine.mainMixerNode
engine.attach(audioPlayer)
engine.attach(pitchControl)
engine.connect(audioPlayer, to: mainMixer, format: audioFileBuffer?.format)
engine.connect(audioPlayer, to: pitchControl, format:audioFileBuffer?.format)
engine.connect(pitchControl, to: engine.mainMixerNode, format: nil)
try engine.start()
audioPlayer.play()
audioPlayer.scheduleBuffer(audioFileBuffer!, at: nil, options: .loops, completionHandler: nil)
}
}
推荐阅读
- java - 如何在 Hibernate HSQL 数据库中创建视图
- c++ - 这个 Visual Studio 编译器错误“除以或除以零”是一个错误吗?
- macos - macOS 上的 Swiftui 表单标签对齐
- r - 将箱线图异常值放入表中
- java - Kafka Streams Initializer 对同一个键被多次调用
- javascript - 画布,画布弧,javascript
- ssis - SSIS条件拆分处理列中的空值和其他值
- python - 在 Python 中同时插入行
- c++ - 如何在 C++ 中同时写入文件(换句话说,写入文件的最快方法是什么)
- django - 从主要模型实例获取用户特定答案属性 - django