About dividing Data type data into small pieces to fit in datagram size

I am trying to send and receive an audio data(saved by .caf extension device) using Network.framework.

This is my plan.

  1. convert file into Data type using below code:
guard let data = try? Data(contentsOf: recordedDocumentURL) else {
            print("recorded file to data conversion failed in touchUpCallButton Method")
            return
        }
  1. send Data type data using NWConnection.send, UDP.
  2. receive Data type data using NWConnection.receiveMessage
  3. convert received Data type data into AVAudioFile type data and play it using AVAudioEngine

Right now my problem is that size of data converted from audio file is too big to fit in maximumDatagramSize to send.

So in my understanding, I need to split Data type into many small bytes of data and send it one by one.

But in this case, I need to collect received data to make complete audio file again, so received device can play complete audio file.

And.. I'm stuck at this step.

I can't find right solution to divide Data type into small pieces to send by datagram using UDP.

What I have in my mind is to use 'subdata(in: Range<Data.Index>) -> Data' function and 'append(Data)' function to divide and sum up data.

Is this right approach to solve my problem?

Little advice would be very appreciated!

Accepted Reply

What I am trying to do is to build a Walkie-Talkie app.

Real-time audio is one reason to use UDP. However, you can’t just break a file up into chunks, send the chunks over UDP, and reassemble them at the other end. Well, you can, but by doing so you lose any benefit you get from using UDP in the first place.

You have a choice here:

  • If you want the audio to go across in real time, use UDP and split up your data so that each chunk is playable. The receiver can then play the data as it arrives. If a packet is lost, the user will hear a glitch but such is the nature of real time audio.

  • If you want to eliminate such glitches, send the data over a TCP connection. The downside here is that you lose real time playback. If a packet is lost, TCP will retransmit under the covers and you won’t be able to play any audio until the retransmit is complete.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

  • Thank you very much! I have tried to solve my problem via UDP. I have implemented an extension in Data type to convert AVAudioPCMBuffer into Data and vice versa. AVAudioPCMBuffer type data is 4096 sized buffer from device mic input. Flow of data is like this. buffer data : AVAudioPCMBuffer -> Data -> send via UDP -> Data -> AVAudioPCMBuffer -> AVAudioPlayer.scheduleBuffer(buffer) -> AVAudioPlayer.play(). Still, I need to reduce size of converted buffer data because that converted data is a bit larger than maximumDatagramSize, but I think this should be another type of question, so maybe I will write another post for it. Thanks for your help again!

Add a Comment

Replies

Why are you using UDP for this?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

  • What I am trying to do is to build a Walkie-Talkie app.

    At first, I watched WWDC video introducing Network.framework and decided to use Network.framework to implement networking in my Walkie-Talkie app.

    The reason I choose Network.framework is that it I was trying to implement my app's networking by socket programming, and Network.framework is introduced as modern alternative to socket programming.

    After that, I decided to use Peer-to-Peer network because I wanted my app to work without any main server, and I thought P2P network fits concept of walkie-talkie(nearby communication).

    To accomplish implementing P2P network using Network.framework, I found an Tic-Tac-Toe example using Peer to Peer option in Network.framework, and used it as guidance of my app.

    While implementing my walkie-talkie app, I first tried to implement a real-time voice streaming using sockets, but it was too difficult to accomplish.

    -> I think this is where I thought I should use UDP in my project. Because what I was trying to implement was VoIP, and UDP is ideal solution for it.

    After few research, I figured out that most of Push-To-Talk apps record user's voice and sends it, not real-time streams it.

    So I decided to record and send user's voice to implement Push-To-Talk, and I still thought UDP is ideal solution for it, because it is voice data I am trying to send, and I thought little loss would be okay while fast response is very important in walkie-talkie.

Add a Comment

What I am trying to do is to build a Walkie-Talkie app.

Real-time audio is one reason to use UDP. However, you can’t just break a file up into chunks, send the chunks over UDP, and reassemble them at the other end. Well, you can, but by doing so you lose any benefit you get from using UDP in the first place.

You have a choice here:

  • If you want the audio to go across in real time, use UDP and split up your data so that each chunk is playable. The receiver can then play the data as it arrives. If a packet is lost, the user will hear a glitch but such is the nature of real time audio.

  • If you want to eliminate such glitches, send the data over a TCP connection. The downside here is that you lose real time playback. If a packet is lost, TCP will retransmit under the covers and you won’t be able to play any audio until the retransmit is complete.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

  • Thank you very much! I have tried to solve my problem via UDP. I have implemented an extension in Data type to convert AVAudioPCMBuffer into Data and vice versa. AVAudioPCMBuffer type data is 4096 sized buffer from device mic input. Flow of data is like this. buffer data : AVAudioPCMBuffer -> Data -> send via UDP -> Data -> AVAudioPCMBuffer -> AVAudioPlayer.scheduleBuffer(buffer) -> AVAudioPlayer.play(). Still, I need to reduce size of converted buffer data because that converted data is a bit larger than maximumDatagramSize, but I think this should be another type of question, so maybe I will write another post for it. Thanks for your help again!

Add a Comment