iOS - 如何从流中读取音频并播放音频

8

感谢所有花时间阅读这个问题的人!

我使用MultipeerConnectivity创建了一个流。我能够将音频记录到CMSampleBuffer中,并将该缓冲区转换为UInt8数据。然后,使用以下方法将该数据发送给对等方:

outputStream!.write(u8ptr, maxLength: Int(buffer.mDataByteSize))

当数据出现在inputStream上时,将调用以下方法:
func stream(_ aStream: Stream, handle eventCode: Stream.Event) {

我已经有了打印语句,所以这部分应该运行良好。当数据真正出现时,我调用我的函数。
func readFromStream() {

我知道需要调用inputStream.read方法才能从流中读取数据,但我不确定如何实际读取数据并将其转换为NSData,以便使用AVAudioPlayer播放。

(除非您知道更好、更有效的方法)

这是目前我的代码,但我还没有测试过,我想肯定会出现问题。

func readFromStream() {
    var buffer = [UInt8](repeating: 0, count: 1024)

    while (inputStream!.hasBytesAvailable) {
        let length = inputStream!.read(&buffer, maxLength: buffer.count)

        if (length > 0) {

            if (audioEngine!.isRunning) {
                audioEngine!.stop()
                audioEngine!.reset()
            }

            print("\(#file) > \(#function) > \(length) bytes read")

            let audioBuffer = bytesToAudioBuffer(buffer)
            let mainMixer = audioEngine!.mainMixerNode

            audioEngine!.connect(audioPlayer!, to: mainMixer, format: audioBuffer.format)

            audioPlayer!.scheduleBuffer(audioBuffer, completionHandler: nil)

            do {
                try audioEngine!.start()
            }
            catch let error as NSError {
                print("\(#file) > \(#function) > error: \(error.localizedDescription)")
            }

            audioPlayer!.play()
        }
    }
}

根据我所了解的,没有音频正在播放。虽然我可以看到某个设备正在接收音频,但是却没有声音。

因此,我的问题基本上就是,我该如何将这个缓冲区转换为正确的数据类型,以便可以进行实时播放?

感谢您的帮助!如果您需要更多信息,请告诉我。

2个回答

7

我使用AVAudioPCMBuffers而不是CMSampleBuffers。这些可以通过从AVAudioEngine进行录制来创建。基本上,这是如何将AVAudioPCMBuffer转换为NSData并返回的。

func audioBufferToNSData(PCMBuffer: AVAudioPCMBuffer) -> NSData {
    let channelCount = 1  // given PCMBuffer channel count is 1
    let channels = UnsafeBufferPointer(start: PCMBuffer.floatChannelData, count: channelCount)
    let data = NSData(bytes: channels[0], length:Int(PCMBuffer.frameLength * PCMBuffer.format.streamDescription.pointee.mBytesPerFrame))

    return data
}

func dataToPCMBuffer(format: AVAudioFormat, data: NSData) -> AVAudioPCMBuffer {

    let audioBuffer = AVAudioPCMBuffer(pcmFormat: format,
                                       frameCapacity: UInt32(data.length) / format.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
}

4
将UInt8转换为NSData > 从UInt8获取NSData 完成后,只需使用AVAudioPlayer。
let player = AVAudioPlayer(data: data)
player.play()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接