fixed: mic redirection not working on iOS 12

This commit is contained in:
TrueZhuanjia
2025-09-24 22:43:14 +08:00
parent 9124a1fee5
commit 9a053d9ed8
+58 -33
View File
@@ -23,7 +23,8 @@ public class MicHandler: NSObject {
private var isRecording = false
private var useBuiltinMic = false
private var pcm16Buffer = Deque<Int16>()
private var pcm16BufferDeque = Deque<Int16>()
private var pcm16BufferArray: [Int16] = []
private let bufferQueue = DispatchQueue(label: "pcm.buffer.queue")
private var timer: SafeTimer?
@@ -201,21 +202,38 @@ public class MicHandler: NSObject {
}
}
private func sendOpusFrame() {
private func sendOpusFrameFromDequeBuffer() {
bufferQueue.sync {
if pcm16Buffer.count >= 960 {
let chunk = Array(pcm16Buffer.prefix(960))
if pcm16BufferDeque.count >= 960 {
let chunk = Array(pcm16BufferDeque.prefix(960))
var packet = [UInt8](repeating: 0, count: 4000)
guard let enc = self.opusEncoder else {return}
let outBytes = opus_encode(enc, chunk, 960, &packet, Int32(packet.count))
sendMicrophoneData(packet, outBytes)
let removeCount = min(960, pcm16Buffer.count)
let removeCount = min(960, pcm16BufferDeque.count)
if removeCount > 0 {
pcm16Buffer.removeFirst(removeCount)
pcm16BufferDeque.removeFirst(removeCount)
}
}
}
}
private func sendOpusFrameFromArrayBuffer() {
bufferQueue.sync {
if pcm16BufferArray.count >= 960 {
let chunk = Array(pcm16BufferArray.prefix(960))
var packet = [UInt8](repeating: 0, count: 4000)
guard let enc = self.opusEncoder else {return}
let outBytes = opus_encode(enc, chunk, 960, &packet, Int32(packet.count))
sendMicrophoneData(packet, outBytes)
let removeCount = min(960, pcm16BufferArray.count)
if removeCount > 0 {
pcm16BufferArray.removeFirst(removeCount)
}
}
}
}
private func configureEngine() throws {
let input = engine.inputNode
@@ -232,9 +250,6 @@ public class MicHandler: NSObject {
try AVAudioSession.sharedInstance().setPreferredIOBufferDuration(0.02)
let sinkNode = AVAudioSinkNode { timestamp, frameCount, audioBufferList -> OSStatus in
// 访问 AudioBufferList 数据
// print("sink interval: \((CACurrentMediaTime()-self.globalTimestamp)*1000),frameCount: \(frameCount)")
// self.globalTimestamp = CACurrentMediaTime()
guard self.isRecording else { return noErr}
@@ -250,7 +265,7 @@ public class MicHandler: NSObject {
}
// 追加到缓冲区
self.pcm16Buffer.append(contentsOf: chunk)
self.pcm16BufferDeque.append(contentsOf: chunk)
return noErr
}
@@ -261,44 +276,54 @@ public class MicHandler: NSObject {
// 开定时器,每 20ms 触发一次
self.timer = SafeTimer(interval:0.02, delay: 0.05) {
self.sendOpusFrame()
self.sendOpusFrameFromDequeBuffer()
}
}
else{
engine.attach(playerNode)
engine.connect(playerNode, to: engine.mainMixerNode, format: micInputFormat)
input.installTap(onBus: 0, bufferSize: 5760, format: micInputFormat) { [weak self] buffer, _ in
guard let self = self, self.isRecording else { return }
DispatchQueue.global().async {
let pcm16Buffer = AVAudioPCMBuffer(pcmFormat: pcm16Format!, frameCapacity: buffer.frameCapacity)
try? converter?.convert(to: pcm16Buffer!, from: buffer)
// 处理转换后的 outputBuffer
// ===============================
// 🔹 改动 1:把 buffer 转成 PCM16 并保存
let frameLength = Int(buffer.frameLength)
let channels = Int(buffer.format.channelCount)
var pcm16InterleavedBuffer = [Int16](repeating: 0, count: frameLength * channels)
let pcm16Buffer = AVAudioPCMBuffer(pcmFormat: pcm16Format!, frameCapacity: buffer.frameCapacity)
try? converter?.convert(to: pcm16Buffer!, from: buffer)
// ===============================
// 把 buffer 转成 PCM16 并保存
let frameLength = Int(buffer.frameLength)
let channels = Int(buffer.format.channelCount)
var pcm16InterleavedBuffer = [Int16](repeating: 0, count: frameLength * channels)
if let floatPtrs = buffer.floatChannelData {
for ch in 0..<channels {
if let pcm16Data = pcm16Buffer?.int16ChannelData?[ch] {
for i in 0..<frameLength {
pcm16InterleavedBuffer[i * channels + ch] = pcm16Data[i]
let floatPtr = floatPtrs[ch]
for i in 0..<frameLength {
let f = floatPtr[i]
// 把 float 转到 Int16 范围:假设 float 在 -1…+1 之间
// 乘以 Int16.max (32767),再做裁剪
let scaled = f * Float(Int16.max)
let clipped: Float
if scaled > Float(Int16.max) {
clipped = Float(Int16.max)
} else if scaled < Float(Int16.min) {
clipped = Float(Int16.min)
} else {
clipped = scaled
}
pcm16InterleavedBuffer[i * channels + ch] = Int16(clipped)
}
}
// 🔹 新增:Opus 编码并存入缓存
if let enc = self.opusEncoder {
var packet = [UInt8](repeating: 0, count: 8000)
let outBytes = opus_encode(enc, pcm16InterleavedBuffer, Int32(frameLength), &packet, Int32(packet.count))
sendMicrophoneData(packet, outBytes)
}
}
// 现在 pcm16InterleavedBuffer 里就是转换后的 Int16 数据
self.pcm16BufferArray.append(contentsOf: pcm16InterleavedBuffer)
}
// 开定时器,每 20ms 触发一次
self.timer = SafeTimer(interval:0.02, delay: 0.05) {
self.sendOpusFrameFromArrayBuffer()
}
}
engine.prepare()
try engine.start()
}