如何通过OutputStream发送NSData
你可以在github上查看这个项目: https : //github.com/Lkember/MotoIntercom/
重要的类是PhoneViewController.swift
我有一个AVAudioPCMBuffer。 然后使用这个函数将缓冲区转换为NSData:
func audioBufferToNSData(PCMBuffer: AVAudioPCMBuffer) -> NSData { let channelCount = 1 let channels = UnsafeBufferPointer(start: PCMBuffer.floatChannelData, count: channelCount) let data = NSData(bytes: channels[0], length:Int(PCMBuffer.frameCapacity * PCMBuffer.format.streamDescription.pointee.mBytesPerFrame)) return data }
根据OutputStream.write的文档,需要将这些数据转换为UnsafePointer <UInt8>。
https://developer.apple.com/reference/foundation/outputstream/1410720-write
这是我迄今为止:
let data = self.audioBufferToNSData(PCMBuffer: buffer) let output = self.outputStream!.write(UnsafePointer<UInt8>(data.bytes.assumingMemoryBound(to: UInt8.self)), maxLength: data.length)
当收到这个数据时,使用这个方法将它转换回AVAudioPCMBuffer:
func dataToPCMBuffer(data: NSData) -> AVAudioPCMBuffer { let audioFormat = AVAudioFormat(commonFormat: AVAudioCommonFormat.pcmFormatFloat32, sampleRate: 8000, channels: 1, interleaved: false) // given NSData audio format let audioBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: UInt32(data.length) / audioFormat.streamDescription.pointee.mBytesPerFrame) audioBuffer.frameLength = audioBuffer.frameCapacity let channels = UnsafeBufferPointer(start: audioBuffer.floatChannelData, count: Int(audioBuffer.format.channelCount)) data.getBytes(UnsafeMutableRawPointer(channels[0]) , length: data.length) return audioBuffer }
不幸的是,当我播放这个audioBuffer的时候,我只能听到静止的声音。 我不相信这是从AVAudioPCMBuffer转换到NSData或从NSData转换回AVAudioPCMBuffer的问题。 我想这是我写NSData到stream的方式。
我不相信这是我的转换的原因是因为我创build了一个示例项目(可以下载并尝试),将audiologging到AVAudioPCMBuffer,将其转换为NSData,将NSData转换回AVAudioPCMBuffer并播放audio。 在这种情况下播放audio没有问题。
编辑:
我从来没有展示过如何从stream中获取数据。 这是如何完成的:
func stream(_ aStream: Stream, handle eventCode: Stream.Event) { switch (eventCode) { case Stream.Event.hasBytesAvailable: DispatchQueue.global().async { var buffer = [UInt8](repeating: 0, count: 8192) let length = self.inputStream!.read(&buffer, maxLength: buffer.count) let data = NSData.init(bytes: buffer, length: buffer.count) print("\(#file) > \(#function) > \(length) bytes read on queue \(self.currentQueueName()!) buffer.count \(data.length)") if (length > 0) { let audioBuffer = self.dataToPCMBuffer(data: data) self.audioPlayerQueue.async { self.peerAudioPlayer.scheduleBuffer(audioBuffer) if (!self.peerAudioPlayer.isPlaying && self.localAudioEngine.isRunning) { self.peerAudioPlayer.play() } } } else if (length == 0) { print("\(#file) > \(#function) > Reached end of stream") } }
一旦我有这个数据,我使用dataToPCMBuffer方法将其转换为AVAudioPCMBuffer。
编辑1:
这里是我使用的AVAudioFormat:
self.localInputFormat = AVAudioFormat.init(commonFormat: .pcmFormatFloat32, sampleRate: 44100, channels: 1, interleaved: false)
本来我是用这个:
self.localInputFormat = self.localInput?.inputFormat(forBus: 0)
但是,如果通道数量不等于预期的通道数量,那么比我遇到崩溃。 所以我把它切换到上面。
我正在使用的实际AVAudioPCMBuffer是在installTap方法(其中localInput是一个AVAudioInputNode):
localInput?.installTap(onBus: 0, bufferSize: 4096, format: localInputFormat) { (buffer, time) -> Void in
很确定你想取代这个:
let length = self.inputStream!.read(&buffer, maxLength: buffer.count) let data = NSData.init(bytes: buffer, length: buffer.count)
同
let length = self.inputStream!.read(&buffer, maxLength: buffer.count) let data = NSData.init(bytes: buffer, length: length)
另外,我并不是100%确定随机数据块总是可以用来制作audio缓冲区。 您可能需要首先将数据收集到更大的NSData块中。
现在,由于您始终传递8192块(即使您读取较less),缓冲区创build可能总是成功。 现在可能不会。