2017-02-03 24 views
5

Cảm ơn mọi người dành thời gian để đọc câu hỏi!iOS - Cách đọc âm thanh từ một luồng và phát âm thanh

Vì vậy, tôi đã tạo luồng bằng MultipeerConnectivity. Tôi có thể ghi lại âm thanh vào CMSampleBuffer và chuyển đổi bộ đệm đó thành dữ liệu UInt8. Sau đó gửi dữ liệu đến một đẳng sử dụng phương pháp này:

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

Sau đó, khi dữ liệu hiển thị trên InputStream các phương pháp sau đây được gọi là:

func stream(_ aStream: Stream, handle eventCode: Stream.Event) { 

Tôi có báo cáo in, vì vậy phần này đang chạy khỏe. Khi dữ liệu thực sự xuất hiện, tôi gọi chức năng của tôi

func readFromStream() { 

Tôi biết rằng tôi cần phải gọi phương thức inputStream.read để thực sự đọc từ stream, nhưng tôi không chắc chắn làm thế nào để thực sự đọc các dữ liệu và sau đó chuyển nó sang NSData để nó có thể được chơi bằng AVAudioPlayer.

(Trừ khi bạn đang nhận thức được một cách hiệu quả hơn càng tốt)

Đây là những gì tôi có cho đến nay, nhưng tôi đã không kiểm tra nó và tôi giả sử có sẽ là vấn đề.

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() 
     } 
    } 
} 

Dựa trên những gì tôi có, không phát âm thanh. Đó là sự im lặng, nhưng tôi có thể thấy rằng âm thanh đang được nhận bởi một trong các thiết bị.

Vì vậy, về cơ bản, câu hỏi của tôi là, làm cách nào để chuyển đổi bộ đệm này thành loại dữ liệu chính xác để có thể phát trực tuyến?

Cảm ơn sự giúp đỡ của bạn! Nếu bạn cần thêm thông tin, xin vui lòng cho tôi biết.

Trả lời

4

Thay vì sử dụng CMSampleBuffers tôi đã sử dụng AVAudioPCMBuffers. Chúng có thể được tạo bằng cách ghi từ AVAudioEngine. Về cơ bản đây là cách tôi chuyển đổi AVAudioPCMBuffer thành NSData và ngược lại.

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

Để chuyển đổi uint8 vào NSData>NSData from UInt8

Một khi bạn đã làm điều đó, chỉ cần sử dụng AVAudioPlayer

let player = AVAudioPlayer(data: data) 
player.play()