iOS - 如何从流中读取音频并播放音频
iOS - How to read audio from a stream and play the audio
感谢所有花时间阅读问题的人!
所以我使用 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()
}
}
}
据我所知,没有播放音频。一片寂静,但我可以看到其中一台设备正在接收音频。
基本上,我的问题是,如何将此缓冲区转换为正确的数据类型以便可以现场播放?
感谢您的帮助!如果您需要更多信息,请告诉我。
将 UInt8 转换为 NSData >
完成后,只需使用 AVAudioPlayer
let player = AVAudioPlayer(data: data)
player.play()
我没有使用 CMSampleBuffers,而是使用了 AVAudioPCMBuffers。这些可以通过从 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
}
感谢所有花时间阅读问题的人!
所以我使用 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()
}
}
}
据我所知,没有播放音频。一片寂静,但我可以看到其中一台设备正在接收音频。
基本上,我的问题是,如何将此缓冲区转换为正确的数据类型以便可以现场播放?
感谢您的帮助!如果您需要更多信息,请告诉我。
将 UInt8 转换为 NSData >
完成后,只需使用 AVAudioPlayer
let player = AVAudioPlayer(data: data)
player.play()
我没有使用 CMSampleBuffers,而是使用了 AVAudioPCMBuffers。这些可以通过从 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
}