gpt4 book ai didi

ios - 低延迟输入/输出音频队列

转载 作者:可可西里 更新时间:2023-11-01 01:06:02 25 4
gpt4 key购买 nike

我有两个 iOS AudioQueues - 一个输入将样本直接馈送到一个输出。不幸的是,回声效果非常明显:(

是否可以使用 AudioQueues 制作低延迟音频,或者我真的需要使用 AudioUnits 吗? (我已经尝试过使用 AudioUnits 的 Novocaine 框架,这里的延迟要小得多。我还注意到这个框架似乎使用更少的 CPU 资源。不幸的是,如果不对它进行重大更改,我无法在我的 Swift 项目中使用这个框架.)

这里是我的一些代码摘录,主要是在Swift中完成的,除了那些需要在C中实现的回调。

private let audioStreamBasicDescription = AudioStreamBasicDescription(
mSampleRate: 16000,
mFormatID: AudioFormatID(kAudioFormatLinearPCM),
mFormatFlags: AudioFormatFlags(kAudioFormatFlagsNativeFloatPacked),
mBytesPerPacket: 4,
mFramesPerPacket: 1,
mBytesPerFrame: 4,
mChannelsPerFrame: 1,
mBitsPerChannel: 32,
mReserved: 0)

private let numberOfBuffers = 80
private let bufferSize: UInt32 = 256

private var active = false

private var inputQueue: AudioQueueRef = nil
private var outputQueue: AudioQueueRef = nil

private var inputBuffers = [AudioQueueBufferRef]()
private var outputBuffers = [AudioQueueBufferRef]()
private var headOfFreeOutputBuffers: AudioQueueBufferRef = nil

// callbacks implemented in Swift
private func audioQueueInputCallback(inputBuffer: AudioQueueBufferRef) {
if active {
if headOfFreeOutputBuffers != nil {
let outputBuffer = headOfFreeOutputBuffers
headOfFreeOutputBuffers = AudioQueueBufferRef(outputBuffer.memory.mUserData)
outputBuffer.memory.mAudioDataByteSize = inputBuffer.memory.mAudioDataByteSize
memcpy(outputBuffer.memory.mAudioData, inputBuffer.memory.mAudioData, Int(inputBuffer.memory.mAudioDataByteSize))
assert(AudioQueueEnqueueBuffer(outputQueue, outputBuffer, 0, nil) == 0)
} else {
println(__FUNCTION__ + ": out-of-output-buffers!")
}

assert(AudioQueueEnqueueBuffer(inputQueue, inputBuffer, 0, nil) == 0)
}
}

private func audioQueueOutputCallback(outputBuffer: AudioQueueBufferRef) {
if active {
outputBuffer.memory.mUserData = UnsafeMutablePointer<Void>(headOfFreeOutputBuffers)
headOfFreeOutputBuffers = outputBuffer
}
}

func start() {
var error: NSError?
audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, withOptions: .allZeros, error: &error)
dumpError(error, functionName: "AVAudioSessionCategoryPlayAndRecord")
audioSession.setPreferredSampleRate(16000, error: &error)
dumpError(error, functionName: "setPreferredSampleRate")
audioSession.setPreferredIOBufferDuration(0.005, error: &error)
dumpError(error, functionName: "setPreferredIOBufferDuration")

audioSession.setActive(true, error: &error)
dumpError(error, functionName: "setActive(true)")

assert(active == false)
active = true

// cannot provide callbacks to AudioQueueNewInput/AudioQueueNewOutput from Swift and so need to interface C functions
assert(MyAudioQueueConfigureInputQueueAndCallback(audioStreamBasicDescription, &inputQueue, audioQueueInputCallback) == 0)
assert(MyAudioQueueConfigureOutputQueueAndCallback(audioStreamBasicDescription, &outputQueue, audioQueueOutputCallback) == 0)

for (var i = 0; i < numberOfBuffers; i++) {
var audioQueueBufferRef: AudioQueueBufferRef = nil
assert(AudioQueueAllocateBuffer(inputQueue, bufferSize, &audioQueueBufferRef) == 0)
assert(AudioQueueEnqueueBuffer(inputQueue, audioQueueBufferRef, 0, nil) == 0)
inputBuffers.append(audioQueueBufferRef)

assert(AudioQueueAllocateBuffer(outputQueue, bufferSize, &audioQueueBufferRef) == 0)
outputBuffers.append(audioQueueBufferRef)

audioQueueBufferRef.memory.mUserData = UnsafeMutablePointer<Void>(headOfFreeOutputBuffers)
headOfFreeOutputBuffers = audioQueueBufferRef
}

assert(AudioQueueStart(inputQueue, nil) == 0)
assert(AudioQueueStart(outputQueue, nil) == 0)
}

然后我的 C 代码将回调设置回 Swift:

static void MyAudioQueueAudioInputCallback(void * inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, const AudioTimeStamp * inStartTime,
UInt32 inNumberPacketDescriptions, const AudioStreamPacketDescription * inPacketDescs) {
void(^block)(AudioQueueBufferRef) = (__bridge void(^)(AudioQueueBufferRef))inUserData;
block(inBuffer);
}

static void MyAudioQueueAudioOutputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {
void(^block)(AudioQueueBufferRef) = (__bridge void(^)(AudioQueueBufferRef))inUserData;
block(inBuffer);
}

OSStatus MyAudioQueueConfigureInputQueueAndCallback(AudioStreamBasicDescription inFormat, AudioQueueRef *inAQ, void(^callback)(AudioQueueBufferRef)) {
return AudioQueueNewInput(&inFormat, MyAudioQueueAudioInputCallback, (__bridge_retained void *)([callback copy]), nil, nil, 0, inAQ);
}

OSStatus MyAudioQueueConfigureOutputQueueAndCallback(AudioStreamBasicDescription inFormat, AudioQueueRef *inAQ, void(^callback)(AudioQueueBufferRef)) {
return AudioQueueNewOutput(&inFormat, MyAudioQueueAudioOutputCallback, (__bridge_retained void *)([callback copy]), nil, nil, 0, inAQ);
}

最佳答案

过了好一会儿我找到了this使用 AudioUnits 而不是 AudioQueues 的好帖子。我只是将它移植到 Swift,然后简单地添加:

audioSession.setPreferredIOBufferDuration(0.005, error: &error)

关于ios - 低延迟输入/输出音频队列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30011730/

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