2017-02-03 25 views
5

Dziękuję wszystkim, którzy poświęcają czas na przeczytanie tego pytania!iOS - Jak odczytać dźwięk ze strumienia i odtwarzać dźwięk

Więc zrobiłem strumień przy użyciu MultipeerConnectivity. Mogę nagrać audio do CMSampleBuffer i przekonwertować ten bufor na dane UInt8. Następnie wysłać te dane do równorzędnego stosując metodę:

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

wtedy, gdy dane pokazuje się na InputStream następująca metoda nazywa się:

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

mam instrukcje print, więc ta część jest uruchomiony w porządku. Gdy dane rzeczywiście pojawia się wzywam moja funkcja

func readFromStream() { 

wiem, że muszę wywołać metodę inputStream.read faktycznie czytać ze strumienia, ale nie jestem pewien, jak właściwie odczytać dane, a następnie przekonwertuj go na NSData, aby można go było odtwarzać za pomocą AVAudioPlayer.

(Chyba, że ​​jesteś świadomy lepszego, bardziej efektywny sposób)

To, co mam tak daleko, ale nie testowałem go i zakładamy, że nie będzie problemów.

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

Na podstawie posiadanych danych nie ma dźwięku. To jest cisza, ale widzę, że dźwięk jest odbierany przez jedno z urządzeń.

Moje pytanie brzmi: jak przekonwertować ten bufor na właściwy typ danych, aby można było go odtwarzać na żywo?

Dziękuję za pomoc! Jeśli potrzebujesz więcej informacji, daj mi znać.

Odpowiedz

4

Zamiast używać CMSampleBuffers użyłem AVAudioPCMBuffers. Można je utworzyć, nagrywając z AVAudioEngine. Zasadniczo tutaj jest jak konwertowałem AVAudioPCMBuffer na NSData iz powrotem.

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

Aby przekonwertować Uint8 do NSData>NSData from UInt8

Gdy już to zrobisz, wystarczy użyć AVAudioPlayer

let player = AVAudioPlayer(data: data) 
player.play() 
Powiązane problemy