使用AVAudioEngine在Swift 4中使用重音器的节拍器

时间:2017-12-05 05:34:24

标签: ios swift avaudioengine

我试图创建一个可以播放重音音符的固体节拍器(即每个小节开头的不同音符)。在对这个主题进行了研究之后,我了解到使用Timer(以前的NSTimer)不是因为它的不准确而走的路。

我遇到的一个解决方案是使用AVAudioEngine,它非常适合稳定的节拍器,但是我还没有弄清楚如何跟踪你在哪个酒吧,并因此发表声明根据你的位置改变你播放的音频文件似乎很棘手。这是节拍器类的代码。

import Foundation
import UIKit
import AVFoundation

class Metronome {

var audioPlayerNode:AVAudioPlayerNode
var audioFile:AVAudioFile
var audioEngine:AVAudioEngine

init (fileURL: URL) {

    audioFile = try! AVAudioFile(forReading: fileURL)

    audioPlayerNode = AVAudioPlayerNode()

    audioEngine = AVAudioEngine()
    audioEngine.attach(self.audioPlayerNode)

    audioEngine.connect(audioPlayerNode, to: audioEngine.mainMixerNode, format: audioFile.processingFormat)
    try! audioEngine.start()
}

func generateBuffer(forBpm bpm: Int) -> AVAudioPCMBuffer {
    audioFile.framePosition = 0
    let periodLength = AVAudioFrameCount(audioFile.processingFormat.sampleRate * 60 / Double(bpm))
    let buffer = AVAudioPCMBuffer(pcmFormat: audioFile.processingFormat, frameCapacity: periodLength)
    try! audioFile.read(into: buffer!)
    buffer?.frameLength = periodLength
    return buffer!
}

func play(bpm: Int) {

    let buffer = generateBuffer(forBpm: bpm)

    self.audioPlayerNode.play()

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

func stop() {
    audioPlayerNode.stop()
}
}

要实际播放声音,在ViewController中我有以下代码:

required init?(coder aDecoder: NSCoder) {

let fileUrl = Bundle.main.url(forResource: "tone", withExtension: "wav")

metronome = Metronome(fileURL: fileUrl!)

super.init(coder: aDecoder)
}

使用以下代码启动和停止我放入@IBAction按钮。

 metronome.play(bpm: 120)
 metronome.stop()

正如你所看到的,它不能直接计算节拍的数量,因为文件实际上是在重复播放之间设置缓冲时间(据我所知)。

感谢任何帮助/建议,因为我对Swift很新。

谢谢!

0 个答案:

没有答案