I'm trying to play a sine sound for as long as the user wants it. So my plan is to use two buffers. Fill one buffer, play it and while it plays fill the second buffer and then switch between those two. But I always get audio jumps when switching the buffers, I can't get a continuous sound. Could someone look at my code and tell me what I'm doing wrong? The audio data is correct, when I schedule a bunch of buffers in a row a get a smooth sound.
import Foundation
import AVFoundation
var engine = AVAudioEngine()
var player = AVAudioPlayerNode()
var mixer = engine.mainMixerNode;
var dq = DispatchQueue(label: "Sine")
let sampleRate = mixer.outputFormat(forBus: 0).sampleRate
let samplesOfAudio = UInt32 (10000)
var buffer1 = AVAudioPCMBuffer(pcmFormat: (player.outputFormat(forBus: 0)), frameCapacity: samplesOfAudio)!
var buffer2 = AVAudioPCMBuffer(pcmFormat: (player.outputFormat(forBus: 0)), frameCapacity: samplesOfAudio)!
var f = 440.0
var s = UInt32(0) //current sample
let s2t = 2.0 * Double.pi / sampleRate //sample number to time conversion factor
func fillBuffer(buffer: AVAudioPCMBuffer) {
let leftChannel = buffer.floatChannelData![0]
let rightChannel = buffer.floatChannelData![1]
for i in 0 ..< samplesOfAudio {
let v = sin(f * Double(s) * s2t) * 0.2
leftChannel[Int(i)] = Float(v)
rightChannel[Int(i)] = Float(v)
s = s + 1
}
}
func playSine() {
engine.attach(player)
engine.connect(player, to: mixer, format: player.outputFormat(forBus: 0))
do{
try engine.start()
} catch {
}
buffer1.frameLength = samplesOfAudio
buffer2.frameLength = samplesOfAudio
fillBuffer(buffer: buffer1)
var nextBuffer = buffer1
let semaphore = DispatchSemaphore(value: 0)
dq.async {
while true {
player.scheduleBuffer(nextBuffer) {
semaphore.signal()
}
if(nextBuffer == buffer1) {
nextBuffer = buffer2
} else {
nextBuffer = buffer1
}
fillBuffer(buffer: nextBuffer)
semaphore.wait()
}
}
player.play()
}