gpt4 book ai didi

swift - AudioQueueBuffers 之间的爆音

转载 作者:行者123 更新时间:2023-11-28 08:32:51 25 4
gpt4 key购买 nike

我正在尝试使用 Core Audio AudioQueue (Swift 3) 播放纯正弦波音调。

它播放得很好,但每次调用我的 AudioQueueOutputCallback 以用音频数据填充新缓冲区时,我都会听到爆裂声。

我的 AudioStreamer 类如下所示:

let kNumberBuffers = 3

protocol AudioStreamerDelegate {
func requestAudioData() -> [Float]
}

let sampleRate = 48000.0
let bufferSize = Int(sampleRate) / 50
let bufferByteSize = UInt32(bufferSize * sizeof(Float)) // 20 mili sec of audio

class AudioStreamer {
var delegate: AudioStreamerDelegate

var outputQueue: AudioQueueRef?

var buffers = [AudioQueueBufferRef?](repeatElement(nil, count: kNumberBuffers))

var streamBasicDescription = AudioStreamBasicDescription(
mSampleRate: sampleRate,
mFormatID: kAudioFormatLinearPCM,
mFormatFlags: kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved,
mBytesPerPacket: UInt32(sizeof(Float)),
mFramesPerPacket: 1,
mBytesPerFrame: UInt32(sizeof(Float)),
mChannelsPerFrame: 1,
mBitsPerChannel: UInt32(8 * sizeof(Float)),
mReserved: 0
)

init(delegate: AudioStreamerDelegate) {
// create new output audio queue
self.delegate = delegate
}

func play() {
let queue = DispatchQueue.main

queue.async(execute: {
let selfPointer = unsafeBitCast(self, to: UnsafeMutablePointer<Void>.self)
AudioQueueNewOutput(
&self.streamBasicDescription,
AudioStreamerOuputCallback,
selfPointer,
nil,
nil,
0,
&self.outputQueue
)

// allocate buffers
for i in 0 ..< kNumberBuffers {
AudioQueueAllocateBuffer(
self.outputQueue!,
bufferByteSize,
&self.buffers[i]
)

if let bufferRef = self.buffers[i] {
// configure audio buffer
let selfPointer = unsafeBitCast(self, to: UnsafeMutablePointer<Void>.self)
bufferRef.pointee.mUserData = selfPointer
bufferRef.pointee.mAudioDataByteSize = bufferByteSize
}
}

AudioQueuePrime(self.outputQueue!, 0, nil)
for bufferRef in self.buffers {
AudioStreamerOuputCallback(userData: unsafeBitCast(self, to: UnsafeMutablePointer<Void>.self), queueRef: self.outputQueue!, buffer: bufferRef!)
}
AudioQueueStart(self.outputQueue!, nil)
})
}
}

func AudioStreamerOuputCallback(userData: Optional<UnsafeMutablePointer<Void>>, queueRef: AudioQueueRef, buffer: AudioQueueBufferRef) {
let this = Unmanaged<AudioStreamer>.fromOpaque(OpaquePointer(userData!)).takeUnretainedValue()
let audioData = this.delegate.requestAudioData()

memcpy(buffer.pointee.mAudioData, unsafeBitCast(audioData, to: UnsafeMutablePointer<Void>.self), Int(bufferByteSize))
AudioQueueEnqueueBuffer(queueRef, buffer, 0, nil)
}

只有一个“播放”按钮的 ViewController 类的音频数据生成器方法(theta 是该 ViewController 上的存储属性):

func generateAudioData(frequency: Double) {
semaphore.wait()

let amplitude: Double = 0.25

let theta_increment: Double = 2.0 * M_PI * frequency / sampleRate

for j in 0 ..< Int(bufferSize) {
audioData[j] = Float(sin(theta) * amplitude)
theta += theta_increment

if theta > 2.0 * M_PI {
theta -= 2.0 * M_PI
}
}
}

问题看起来与 this question 上的问题类似, 但没有人回答。

任何帮助将不胜感激。

最佳答案

在您的输出回调中,您没有生成一组新的音频数据,其中新缓冲区的第一个样本的相位是前一个缓冲区的最后一个样本的增量。

关于swift - AudioQueueBuffers 之间的爆音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38509920/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com