Using AVAudioEngine to schedule sounds for low-latency metronome

后端 未结 3 2053
我寻月下人不归
我寻月下人不归 2021-02-05 19:49

I am creating a metronome as part of a larger app and I have a few very short wav files to use as the individual sounds. I would like to use AVAudioEngine because NSTimer has si

3条回答
  •  北海茫月
    2021-02-05 20:18

    I was able to make a buffer containing sound from file and silence of required length. Hope this will help:

    // audioFile here – an instance of AVAudioFile initialized with wav-file
    func tickBuffer(forBpm bpm: Int) -> AVAudioPCMBuffer {
        audioFile.framePosition = 0 // position in file from where to read, required if you're read several times from one AVAudioFile
        let periodLength = AVAudioFrameCount(audioFile.processingFormat.sampleRate * 60 / Double(bpm)) // tick's length for given bpm (sound length + silence length)
        let buffer = AVAudioPCMBuffer(PCMFormat: audioFile.processingFormat, frameCapacity: periodLength)
        try! audioFile.readIntoBuffer(buffer) // sorry for forcing try
        buffer.frameLength = periodLength // key to success. This will append silcence to sound
        return buffer
    }
    
    // player – instance of AVAudioPlayerNode within your AVAudioEngine
    func startLoop() {
        player.stop()
        let buffer = tickBuffer(forBpm: bpm)
        player.scheduleBuffer(buffer, atTime: nil, options: .Loops, completionHandler: nil)
        player.play()
    }
    

提交回复
热议问题