如何通过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可能总是成功。 现在可能不会。