我正在为 iOS 制作音乐应用程序。我想同时播放 5 个文件。这已经在这个线程的帮助下工作了:如何使用连接到 AVAudioEngine 混音器的节点同时从缓冲区播放多个声音
现在我需要使用 AVAudioUnitVarispeed 更快地播放所有文件。我不能让它工作。
这是代码:
import AVFoundation
class Audio {
// MARK: AUDIO VARIABLEN
var engineFirst: AVAudioEngine = AVAudioEngine()
var audioFilePlayer = [AVAudioPlayerNode]()
var noteFilePath = [String]()
// Speed
var speedControl = [AVAudioUnitVarispeed]()
var noteFileURL = [URL]()
var noteAudioFile = [AVAudioFile]()
var noteAudioFileBuffer = [AVAudioPCMBuffer]()
let tonAnzahl = 5
let latency = 0.03
var playing = false
// MARK: PLAY SOUND
func playSound() {
playing = true
for i in 0...tonAnzahl - 1 {
audioFilePlayer[i].scheduleBuffer(noteAudioFileBuffer[i], at: nil, completionHandler: nil)
audioFilePlayer[i].play()
}
}
// MARK: STOP SOUND
func stopSound() {
playing = false
for i in 0...tonAnzahl - 1 {
audioFilePlayer[i].volume = 0
}
DispatchQueue.main.asyncAfter(deadline: .now() + latency, execute: {
for i in 0...self.tonAnzahl - 1 {
self.audioFilePlayer[i].stop()
}
})
}
// MARK: SETUP AUDIO ENGINE
func setupAudioEngine(bassFile: String, terzFile: String, septimeFile: String, tensionOneFile: String, tensionTwoFile: String) {
do {
noteAudioFile.removeAll()
noteFileURL.removeAll()
// For each note, read the note URL into an AVAudioFile,
// setup the AVAudioPCMBuffer using data read from the file,
// and read the AVAudioFile into the corresponding buffer
for i in 0...tonAnzahl - 1 {
noteFilePath = [
Bundle.main.path(forResource: bassFile, ofType: "mp3")!,
Bundle.main.path(forResource: terzFile, ofType: "mp3")!,
Bundle.main.path(forResource: septimeFile, ofType: "mp3")!,
Bundle.main.path(forResource: tensionOneFile, ofType: "mp3")!,
Bundle.main.path(forResource: tensionTwoFile, ofType: "mp3")!]
noteFileURL.append(URL(fileURLWithPath: noteFilePath[i]))
try noteAudioFile.append(AVAudioFile(forReading: noteFileURL[i]))
let noteAudioFormat = noteAudioFile[i].processingFormat
let noteAudioFrameCount = UInt32(noteAudioFile[i].length)
noteAudioFileBuffer.append(AVAudioPCMBuffer(pcmFormat: noteAudioFormat, frameCapacity: noteAudioFrameCount)!)
try noteAudioFile[i].read(into: noteAudioFileBuffer[i])
}
// For each note, attach the corresponding node to the engineFirst, and connect the node to the engineFirst's mixer.
for i in 0...tonAnzahl - 1 {
audioFilePlayer.append(AVAudioPlayerNode())
engineFirst.attach(audioFilePlayer[i])
// HERE IS THE PROBLEM
speedControl.append(AVAudioUnitVarispeed())
speedControl[i].rate = 2
engineFirst.attach(speedControl[i])
engineFirst.connect(audioFilePlayer[i], to: speedControl[i], fromBus: 0, toBus: i, format: noteAudioFileBuffer[i].format)
engineFirst.connect(speedControl[i], to: engineFirst.mainMixerNode, fromBus: 0, toBus: i, format: noteAudioFileBuffer[i].format)
}
// Audio Engine Start
try engineFirst.start()
// Setup the audio session to play sound in the app, and activate the audio session
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.soloAmbient)
try AVAudioSession.sharedInstance().setMode(AVAudioSession.Mode.default)
try AVAudioSession.sharedInstance().setActive(true)
}
catch let error {
print(error.localizedDescription)
}
}
}
如果我替换此代码同时播放 5 个音符
// HERE IS THE PROBLEM
speedControl.append(AVAudioUnitVarispeed())
speedControl[i].rate = 2
engineFirst.attach(speedControl[i])
engineFirst.connect(audioFilePlayer[i], to: speedControl[i], fromBus: 0, toBus: i, format: noteAudioFileBuffer[i].format)
engineFirst.connect(speedControl[i], to: engineFirst.mainMixerNode, fromBus: 0, toBus: i, format: noteAudioFileBuffer[i].format)
和
engineFirst.connect(audioFilePlayer[i], to: engineFirst.mainMixerNode, fromBus: 0, toBus: i, format: noteAudioFileBuffer[i].format)
...并调用 playSound()。
但后来我没有实现 AVAudioUnitVarispeed (speedControl) ......
那么,如何添加 AVAudioUnitVarispeed 的代码呢?
谢谢您的帮助。