3
votes

I'm trying develop app what play streaming PCM data from server.

I have used AudioQueue, but it does not work well.

PCM data format (from server) :

Sample rate = 48000, num of channel = 2, Bit per sample = 16

And, server is not streaming fixed bytes to client.

(Streaming variable bytes. Ex : 30848, 128, 2764, ... bytes )

My source code :

Here, ASBD structure what I have setted & create Audio Queue object (language : Swift)

// Create ASBD structure & set properties.
var streamFormat = AudioStreamBasicDescription()

streamFormat.mSampleRate = 48000
streamFormat.mFormatID = kAudioFormatLinearPCM
streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked
streamFormat.mFramesPerPacket = 1
streamFormat.mChannelsPerFrame = 2
streamFormat.mBitsPerChannel = 16

streamFormat.mBytesPerFrame = (streamFormat.mBitsPerChannel / 8) * streamFormat.mChannelsPerFrame
streamFormat.mBytesPerPacket = streamFormat.mBytesPerFrame
streamFormat.mReserved = 0

// Create AudioQueue for playing PCM streaming data.
var err = AudioQueueNewOutput(&streamFormat, self.queueCallbackProc, nil, nil, nil, 0, &aq)

...

I have setted ASBD structure & created AudioQueue object like the above.

AudioQueue play streamed PCM data very well for a few seconds,

but soon playing sound is on and off. What can I do?

(still streaming, and queueing AudioQueue)

Please give me any idea.

1
do lower bandwidth formats work? - Rhythmic Fistman
Pardon? I dont't know what you say well. - user6081283
Does it work when you try and stream a more compact format like mp3? - Rhythmic Fistman
I use it only playing PCM data. To play mp3, AAC, etc formats, use AudioQueue with AudioFileStream APIs. - user6081283
That's 48000/s*4bytes*8bits/byte = 1.5Mbit. Can your network sustain that throughput? - Rhythmic Fistman

1 Answers

5
votes

You need to do (at least) two things:

You need to buffer data to handle latency jitter and different packet sizes between the data from the server, and the data that the audio queue callback requests. A typical solution involves using a circular fifo/buffer, pre-filled with a certain amount of data, enough to handle the worse case network jitter (you will need to statistically analyze this number). The audio queue callback can just copy the requested amount of data out of the circular fifo. The network code tries to keep it filled.

You may also need some way to conceal errors when the two rates are not sufficiently identical: e.g. some way to duplicate or synthesize extra sound when the network rate is too slow, and some way to leave out samples when the network rate is too high, both ways trying to be as inaudible as possible and without producing loud clicks at any rate discontinuities or network drop-outs.