美文网首页
实时音频处理

实时音频处理

作者: EnjoyWT | 来源:发表于2023-07-24 17:55 被阅读0次

    使用 AVAudioEngine 进行音频处理。 对音频格式进行二次处理,已满足数据处理音频格式要求

    import AVFoundation
    import Foundation
    
    class MicrophoneAudioStream {
        private var audioEngine: AVAudioEngine!
        var audioInputNode: AVAudioInputNode!
        private var audioFile: AVAudioFile?
    
        // 定义处理音频缓冲区数据的闭包类型
        typealias AudioBufferHandler = (AVAudioPCMBuffer, AVAudioTime) -> Void
        init() {
            setupAudioEngine()
        }
    
        private func setupAudioEngine() {
            audioEngine = AVAudioEngine()
            audioInputNode = audioEngine.inputNode
            let audioFormat = audioInputNode.inputFormat(forBus: 0)
    
            guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
                return
            }
            let audioFileURL = documentsDirectory.appendingPathComponent("audio.wav")
    
            // 创建AVAudioFile对象
            do {
                audioFile = try AVAudioFile(forWriting: audioFileURL, settings: audioFormat.settings, commonFormat: audioFormat.commonFormat, interleaved: audioFormat.isInterleaved)
            } catch {
                print("Error creating audio file: \(error.localizedDescription)")
            }
        }
    
        func start() {
            // Start the audio engine
            do {
                try audioEngine.start()
            } catch {
                print("Error starting audio engine: \(error.localizedDescription)")
            }
        }
    
        // 提供外部方法,接收闭包作为参数
        func startAudioStream(withBufferHandler handler: @escaping AudioBufferHandler) {
            audioInputNode = audioEngine.inputNode
    
            // 在设置音频格式之前先停止音频引擎
            audioEngine.stop()
            audioInputNode.removeTap(onBus: 0)
    
    
            let inputNodeOutputFormat = audioInputNode.outputFormat(forBus: 0)
            let targetFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: Double(16000), channels: 1, interleaved: false)
            let formatConverter =  AVAudioConverter(from:inputNodeOutputFormat, to: targetFormat!)
            
            
            
            
            audioInputNode.installTap(onBus: 0, bufferSize: 1024, format: inputNodeOutputFormat) { (buffer, time) in
                    let pcmBuffer = AVAudioPCMBuffer(pcmFormat: targetFormat!, frameCapacity: AVAudioFrameCount(targetFormat!.sampleRate) / 10)
                    var error: NSError? = nil
                
                    let inputBlock: AVAudioConverterInputBlock = { inNumPackets, outStatus in
                        outStatus.pointee = AVAudioConverterInputStatus.haveData
                        return buffer
                    }
                    formatConverter!.convert(to: pcmBuffer!, error: &error, withInputFrom: inputBlock)
                 guard let pcmBuffer = pcmBuffer else {return}
                 handler(pcmBuffer, time)
    
            }
            
            // 启动音频引擎
            do {
                audioEngine.prepare()
                try audioEngine.start()
            } catch {
                print("Error starting audio engine: \(error.localizedDescription)")
            }
        }
        
    
        func stopAudioEngine() {
            audioEngine.stop()
            audioInputNode.removeTap(onBus: 0)
        }
    
        private func writeAudioBuffer(_ audioBuffer: AVAudioPCMBuffer) {
    
            // 将音频数据写入文件
            if let audioFile = audioFile {
                do {
                    try audioFile.write(from: audioBuffer)
                } catch {
                    print("Error writing to audio file: \(error.localizedDescription)")
                }
            }
        }
    }
    
    

    相关文章

      网友评论

          本文标题:实时音频处理

          本文链接:https://www.haomeiwen.com/subject/nxkcpdtx.html