我目前看到的问题是,当我将初始缓冲区排队时,在播放这些缓冲区时,会有一点“点击”。然而,当缓冲区被重复使用时,什么也不会发生。我已经通过使用不合理的大量缓冲区(50000多个)证明了这一点,该缓冲区产生的1秒哔哔声大约是我预期的水平。这对于给定的采样率是正确的。但是,一旦所有初始缓冲区播放一次,样本将停止。
我尝试过使用内部循环以外的运行循环。我已经检查了我的回调是否被调用,是否接收到正确的对象,并且似乎正在为缓冲区的内容设置正确的值,但它只是停止工作。也没有任何AudioQueue函数返回任何异常OSStatus代码。我在基本描述中尝试了各种选项来解释数据格式和尾数。我只是想不出还有什么是错误的,因为我所拥有的与我所发现的大多数例子相似。
(注意:为了简洁起见,我省略了启动和停止音频队列的命令。我只想说一句
createAudioQueue()
这就是所谓的
func synthesizerCallback(userData: UnsafeMutableRawPointer?, audioQueue: AudioQueueRef, buffer: AudioQueueBufferRef) {
guard let rawSynth = userData else { return }
let synth = Unmanaged<Synthesizer>.fromOpaque(rawSynth).takeUnretainedValue()
synth.write(withAudioQueue: audioQueue, toBuffer: buffer)
}
class Synthesizer {
enum Errors: Error {
case coreAudioError(OSStatus)
case couldNotInitialiseAudioQueue
}
private var format: AudioStreamBasicDescription
private var outputQueue: AudioQueueRef?
private var outputBuffers: [AudioQueueBufferRef?]
private var offset: Double = 0
let sampleRate: Double
let channels: Int
init(sampleRate: Double = 44100, channels: Int = 2, bufferCount: Int = 3) {
assert(bufferCount > 2, "Need at least three buffers!")
self.sampleRate = sampleRate
self.channels = channels
self.outputBuffers = Array<AudioQueueBufferRef?>(repeating: nil, count: bufferCount)
let uChannels = UInt32(channels)
let channelBytes = UInt32(MemoryLayout<Int16>.size)
let bytesPerFrame = uChannels * channelBytes
self.format = AudioStreamBasicDescription(
mSampleRate: Float64(sampleRate),
mFormatID: kAudioFormatLinearPCM,
mFormatFlags: kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked,
mBytesPerPacket: bytesPerFrame,
mFramesPerPacket: 1,
mBytesPerFrame: bytesPerFrame,
mChannelsPerFrame: uChannels,
mBitsPerChannel: channelBytes * 8,
mReserved: 0
)
}
private func createAudioQueue() throws {
let selfPointer = unsafeBitCast(self, to: UnsafeMutableRawPointer.self)
let createOutputResult = AudioQueueNewOutput(&format, synthesizerCallback, selfPointer, nil, nil, 0, &outputQueue)
if createOutputResult != 0 { throw Errors.coreAudioError(createOutputResult) }
guard let outputQueue = outputQueue else { throw Errors.couldNotInitialiseAudioQueue }
for i in 0 ..< outputBuffers.count {
let createBufferResult = AudioQueueAllocateBuffer(outputQueue, format.mBytesPerFrame, &outputBuffers[i])
if createBufferResult != 0 { throw Errors.coreAudioError(createBufferResult) }
guard let outputBuffer = outputBuffers[i] else { throw Errors.couldNotInitialiseAudioQueue }
synthesizerCallback(userData: selfPointer, audioQueue: outputQueue, buffer: outputBuffer)
}
let primeQueueResult = AudioQueuePrime(outputQueue, 0, nil)
if primeQueueResult != 0 { throw Errors.coreAudioError(primeQueueResult) }
let startQueueResult = AudioQueueStart(outputQueue, nil)
if startQueueResult != 0 { throw Errors.coreAudioError(startQueueResult) }
}
func write(withAudioQueue audioQueue: AudioQueueRef, toBuffer buffer: AudioQueueBufferRef) {
let dataSize = MemoryLayout<Int16>.stride * channels
let phase = offset / sampleRate * 10000 * Double.pi * 2
let value = Int16(sin(phase) * Double(Int16.max))
var allChannels = Array<Int16>(repeatElement(value, count: channels))
buffer.pointee.mAudioData.copyMemory(from: &allChannels, byteCount: dataSize)
buffer.pointee.mAudioDataByteSize = UInt32(dataSize)
let enqueueResult = AudioQueueEnqueueBuffer(audioQueue, buffer, 0, nil)
if enqueueResult != 0 { print(enqueueResult) }
offset += 1
}
}
使现代化