sha*_*yan 0 core-audio audiounit ios opus swift
我正在 IOS 中从 audioUnit 录制音频,用 opus 编码字节并通过 UDP 将其发送到 android 端。问题是播放的声音有点削波。我还通过将原始数据从 IOS 发送到 Android 来测试声音,效果非常完美。
我的 AudioSession 代码是
try audioSession.setCategory(.playAndRecord, mode: .voiceChat, options: [.defaultToSpeaker])
try audioSession.setPreferredIOBufferDuration(0.02)
try audioSession.setActive(true)
Run Code Online (Sandbox Code Playgroud)
我的录音回调代码是:
func performRecording(
_ ioActionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>,
inTimeStamp: UnsafePointer<AudioTimeStamp>,
inBufNumber: UInt32,
inNumberFrames: UInt32,
ioData: UnsafeMutablePointer<AudioBufferList>) -> OSStatus
{
var err: OSStatus = noErr
err = AudioUnitRender(audioUnit!, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData)
if let mData = ioData[0].mBuffers.mData {
let ptrData = mData.bindMemory(to: Int16.self, capacity: Int(inNumberFrames))
let bufferPtr = UnsafeBufferPointer(start: ptrData, count: Int(inNumberFrames))
count += 1
addedBuffer += Array(bufferPtr)
if count == 2 {
let _ = TPCircularBufferProduceBytes(&circularBuffer, addedBuffer, UInt32(addedBuffer.count * 2))
count = 0
addedBuffer = []
let buffer = TPCircularBufferTail(&circularBuffer, &availableBytes)
memcpy(&targetBuffer, buffer, Int(min(bytesToCopy, Int(availableBytes))))
TPCircularBufferConsume(&circularBuffer, UInt32(min(bytesToCopy, Int(availableBytes))))
self.audioRecordingDelegate(inTimeStamp.pointee.mSampleTime / Double(16000), targetBuffer)
}
}
return err;
}
Run Code Online (Sandbox Code Playgroud)
这里我得到的NumberOfFrames几乎是 341,我将 2 个数组附加在一起以获得更大的 Android 帧大小(需要 640),但我仅在 TPCircularBuffer 的帮助下编码 640。
func gotSomeAudio(timeStamp: Double, samples: [Int16]) {
samples.count))
let encodedData = opusHelper?.encodeStream(of: samples)
OPUS_SET_BITRATE_REQUEST)
let myData = encodedData!.withUnsafeBufferPointer {
Data(buffer: $0)
}
var protoModel = ProtoModel()
seqNumber += 1
protoModel.sequenceNumber = seqNumber
protoModel.timeStamp = Date().currentTimeInMillis()
protoModel.payload = myData
DispatchQueue.global().async {
do {
try self.tcpClient?.send(data: protoModel)
} catch {
print(error.localizedDescription)
}
}
let diff = CFAbsoluteTimeGetCurrent() - start
print("Time diff is \(diff)")
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,我对 640 帧大小进行了 opus 编码,并将其添加到 ProtoBuf 有效负载中,并通过 UDP 发送。
在Android端,我正在解析Protobuf并解码640帧大小并使用AudioTrack播放它。Android端没有问题,因为我仅使用Android录制和播放声音,但当我通过IOS录制声音并播放时出现问题安卓端。
请不要建议通过设置首选 IO 缓冲区持续时间来增加帧大小。我想在不改变这个的情况下做到这一点。
/sf/answers/4051144471/这很有帮助。
/sf/answers/4126310681/ 我已经根据您的建议更新了我的代码,删除了委托和数组连接,但 android 端仍然存在裁剪。我还计算出编码字节所需的时间约为 2-3 毫秒。
更新后的回调代码是
var err: OSStatus = noErr
// we are calling AudioUnitRender on the input bus of AURemoteIO
// this will store the audio data captured by the microphone in ioData
err = AudioUnitRender(audioUnit!, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData)
if let mData = ioData[0].mBuffers.mData {
_ = TPCircularBufferProduceBytes(&circularBuffer, mData, inNumberFrames * 2)
print("mDataByteSize: \(ioData[0].mBuffers.mDataByteSize)")
count += 1
if count == 2 {
count = 0
let buffer = TPCircularBufferTail(&circularBuffer, &availableBytes)
memcpy(&targetBuffer, buffer, min(bytesToCopy, Int(availableBytes)))
TPCircularBufferConsume(&circularBuffer, UInt32(min(bytesToCopy, Int(availableBytes))))
let encodedData = opusHelper?.encodeStream(of: targetBuffer)
let myData = encodedData!.withUnsafeBufferPointer {
Data(buffer: $0)
}
var protoModel = ProtoModel()
seqNumber += 1
protoModel.sequenceNumber = seqNumber
protoModel.timeStamp = Date().currentTimeInMillis()
protoModel.payload = myData
do {
try self.udpClient?.send(data: protoModel)
} catch {
print(error.localizedDescription)
}
}
}
return err;
Run Code Online (Sandbox Code Playgroud)
您的代码正在音频回调中执行 Swift 内存分配(数组串联)和 Swift 方法调用(您的录音委托)。Apple(在有关音频的 WWDC 会议中)建议不要在实时音频回调上下文中执行任何内存分配或方法调用(特别是在请求较短的首选 IO 缓冲区持续时间时)。坚持使用 C 函数调用,例如 memcpy 和 TPCircularBuffer。
补充:另外,不要丢弃样品。如果您获得 680 个样本,但一个数据包只需要 640 个样本,请保留 40 个“剩余”样本,并将它们附加在后面的数据包前面。循环缓冲区将为您保存它们。冲洗并重复。当您积累了足够的数据包时,发送从音频回调中获得的所有样本,或者当您最终积累了 1280 (2*640) 或更多时,发送另一个数据包。
| 归档时间: |
|
| 查看次数: |
529 次 |
| 最近记录: |