Swift:AVAudioPCMBuffer的触发器函数



我正在为iOS开发Metronome应用程序。引擎正在工作,目前非常准确,但它只提供音频反馈,而我也想提供视觉反馈。

我制作了一个AVAudioPCMBuffer来以设定的间隔播放节拍,如何在播放音频时触发函数?

这是我现在的代码:

"private func generateBuffer(bpm:Double,beats:Int(->AVAudioPCM缓冲区{

audioFileMainClick.framePosition = 0
audioFileAccentedClick.framePosition = 0

let beatLength = AVAudioFrameCount(audioFileMainClick.processingFormat.sampleRate * 60 / bpm)
let bufferMainClick = AVAudioPCMBuffer(pcmFormat: audioFileMainClick.processingFormat, frameCapacity: beatLength)!
try! audioFileMainClick.read(into: bufferMainClick)
bufferMainClick.frameLength = beatLength

let bufferAccentedClick = AVAudioPCMBuffer(pcmFormat: audioFileMainClick.processingFormat, frameCapacity: beatLength)!
try! audioFileAccentedClick.read(into: bufferAccentedClick)

let bufferBar = AVAudioPCMBuffer(pcmFormat: audioFileMainClick.processingFormat, frameCapacity: UInt32(beats) * beatLength)!
bufferBar.frameLength = UInt32(beats) * beatLength

let channelCount = Int(audioFileMainClick.processingFormat.channelCount)
let accentedClickArray = Array(
UnsafeBufferPointer(start: bufferAccentedClick.floatChannelData![0],
count: channelCount * Int(beatLength))
)
let mainClickArray = Array(
UnsafeBufferPointer(start: bufferMainClick.floatChannelData![0],
count: channelCount * Int(beatLength))
)

var barArray = [Float]()
// one time for first beat
barArray.append(contentsOf: accentedClickArray)
// n times for regular clicks
for _ in 1...(beats - 1) {
barArray.append(contentsOf: mainClickArray)
}
bufferBar.floatChannelData!.pointee.assign(from: barArray,
count: channelCount * Int(bufferBar.frameLength))
return bufferBar

}
func play(bpm: Double, beats: Int) {

let buffer = generateBuffer(bpm: bpm, beats: beats)

if audioPlayerNode.isPlaying {
audioPlayerNode.scheduleBuffer(buffer, at: nil, options: .interruptsAtLoop, completionHandler: nil)
} else {
self.audioPlayerNode.play()
}

self.audioPlayerNode.scheduleBuffer(buffer, at: nil, options: .loops, completionHandler: nil)

}

''

提前谢谢。

Filippo

尝试而不是使用scheduleBuffer的循环函数。请使用一个completionHandler来重新触发play((函数。这为您提供了向play((函数添加代码的选项,以获得视觉反馈,如显示当前节拍。请记住,对于UI内容,请始终使用DispatchQueue.main.async{…}。

最新更新