From 024bcaa2715b93ffcf45d01a24bc2fe8aecfdc84 Mon Sep 17 00:00:00 2001 From: fdp <1286779656@qq.com> Date: Sun, 24 Aug 2025 19:49:17 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=8C=89=E4=BD=8F=E8=AF=B4?= =?UTF-8?q?=E8=AF=9D=E8=AF=B4=E8=AF=9D=E4=BD=93=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/tools/SimpleAudioReceiver.swift | 101 ++++++++---------- 1 file changed, 42 insertions(+), 59 deletions(-) diff --git a/local_plugins/azure_speech/ios/azure_speech/Sources/tools/SimpleAudioReceiver.swift b/local_plugins/azure_speech/ios/azure_speech/Sources/tools/SimpleAudioReceiver.swift index bf79cb7cb..439a3cf83 100644 --- a/local_plugins/azure_speech/ios/azure_speech/Sources/tools/SimpleAudioReceiver.swift +++ b/local_plugins/azure_speech/ios/azure_speech/Sources/tools/SimpleAudioReceiver.swift @@ -93,7 +93,7 @@ public class SimpleAudioReceiver: NSObject { let frameCount = buffer.frameLength // print("麦克风启动: \(frameCount)") // print("🎵 音频数据: 帧数=\(frameCount), 声道数据=\(channelData != nil ? "有效" : "无效")") - self.writeQueue.put(self.audioBufferToData(buffer)) + self.writeQueue.put(self.audioBufferToDataOptimized(buffer)) // 分析或传输数据... } } catch { @@ -360,6 +360,7 @@ private func enableVoiceProcessingIfAvailable(inputNode: AVAudioInputNode) { } } } + // 修改 runMicrophoneCapture 方法 private func runMicrophoneCapture() { do { print("🎤 开始配置麦克风捕获") @@ -369,27 +370,24 @@ private func enableVoiceProcessingIfAvailable(inputNode: AVAudioInputNode) { print("🔧 创建新的音频引擎") } - // 如果音频引擎正在运行,先停止 if audioEngine?.isRunning == true { audioEngine?.stop() print("⏹️ 停止现有音频引擎") } try startCapture { buffer in - // 处理实时音频数据 - let channelData = buffer.floatChannelData?[0] - let frameCount = buffer.frameLength - // print("麦克风启动: \(frameCount)") - // print("🎵 音频数据: 帧数=\(frameCount), 声道数据=\(channelData != nil ? "有效" : "无效")") - self.writeQueue.put(self.audioBufferToData(buffer)) - // 分析或传输数据... + // 将音频处理移到专用队列,避免阻塞音频线程 + self.conversionQueue.async { + let audioData = self.audioBufferToDataOptimized(buffer) + self.writeQueue.put(audioData) + } } - try audioEngine?.start() + + try audioEngine?.start() print("✅ 麦克风捕获配置完成") } catch { print("麦克风启动失败: \(error)") - // 【新增】添加详细错误处理 if let nsError = error as NSError? { print("错误域: \(nsError.domain), 错误代码: \(nsError.code)") print("错误描述: \(nsError.localizedDescription)") @@ -462,63 +460,46 @@ private func enableVoiceProcessingIfAvailable(inputNode: AVAudioInputNode) { * @param buffer 音频缓冲区 * @return 转换后的音频数据 */ -private func audioBufferToData(_ buffer: AVAudioPCMBuffer) -> Data { +/** + * 优化的音频缓冲区转换方法 + * 减少内存分配,提高转换效率 + */ +// 在类属性中添加 +private var reusableDataBuffer: Data? +private let bufferReuseQueue = DispatchQueue(label: "buffer.reuse", qos: .userInitiated) + +/** + * 带缓冲区复用的音频转换方法 + */ +private func audioBufferToDataOptimized(_ buffer: AVAudioPCMBuffer) -> Data { guard let floatChannelData = buffer.floatChannelData else { return Data() } let frameLength = Int(buffer.frameLength) - let channelCount = Int(buffer.format.channelCount) - let inputSampleRate = buffer.format.sampleRate - let targetSampleRate: Double = 16000 + let requiredSize = frameLength * 2 + + // 复用或创建缓冲区 + if reusableDataBuffer == nil || reusableDataBuffer!.count < requiredSize { + reusableDataBuffer = Data(count: requiredSize) + } - // 统一处理:只使用第一个声道(单声道),确保一致性 + var outputData = reusableDataBuffer! let firstChannelData = floatChannelData[0] - // 如果采样率不是16kHz,进行降采样 - if inputSampleRate != targetSampleRate { - let ratio = inputSampleRate / targetSampleRate - let outputFrameCount = Int(Double(frameLength) / ratio) - - var outputData = Data() - outputData.reserveCapacity(outputFrameCount * 2) // 16位 = 2字节 - - for outputIndex in 0.. \(targetSampleRate)Hz, 帧数: \(frameLength) -> \(outputFrameCount)") - return outputData - } else { - // 采样率已经是16kHz,直接转换格式(只处理第一个声道) - var data = Data() - data.reserveCapacity(frameLength * 2) // 单声道,16位 + outputData.withUnsafeMutableBytes { rawBytes in + let int16Ptr = rawBytes.bindMemory(to: Int16.self) for frame in 0..