2

I am trying to set up an audio queue to play streamed audio data. So far this is what I have:

    var audioStream = AudioStreamBasicDescription()
    audioStream.mSampleRate = 44100
    audioStream.mFormatID = kAudioFormatAppleLossless
    audioStream.mFramesPerPacket = 352
    audioStream.mChannelsPerFrame = 2

    AudioQueueNewOutputWithDispatchQueue(
        &self.playerState.queue, // nil `AudioQueueRef?`
        &audioStream,
        0,
        self.callback) { aq, buffer in
            self.output(self.playerState, aq: aq, buffer: buffer)
    }

and this is where I am not really sure

func output (_ playerState: PlayerState, aq: AudioQueueRef, buffer: AudioQueueBufferRef)

Basically, playerState has several audio packets that I (think I) need to copy to the buffer (AudioQueueBufferRef). Other than that, I am not really sure.

Not sure if its helpful but, here is a sample audio packet:

[32, 0, 0, 4, 6, 19, 8, 8, 129, 249, 214, 3, 147, 251, 90, 19, 8, 9, 187, 248, 253, 255, 186, 0, 57, 255, 6, 130, 134, 131, 3, 6, 4, 129, 0, 192, 129, 193, 194, 6, 8, 12, 16, 81, 100, 201, 157, 185, 135, 163, 49, 109, 117, 97, 89, 101, 93, 49, 41, 33, 37, 29, 13, 17, 12, 237, 138, 180, 101, 70, 131, 12, 3, 6, 1, 196, 24, 129, 16, 197, 24, 67, 58, 210, 113, 153, 209, 207, 93, 244, 219, 28, 98, 18, 74, 48, 200, 76, 204, 70, 80, 33, 175, 16, 210, 124, 243, 215, 90, 80, 141, 145, 32, 33, 138, 75, 20, 149, 141, 80, 200, 204, 142, 115, 110, 125, 248, 226, 245, 2, 212, 181, 40, 226, 47, 150, 156, 105, 148, 49, 145, 153, 26, 51, 76, 153, 8, 140, 37, 46, 249, 203, 143, 55, 236, 228, 130, 239, 149, 172, 217, 140, 205, 70, 204, 35, 177, 230, 252, 242, 210, 85, 35, 13, 214, 54, 165, 243, 157, 229, 125, 4, 205, 20, 17, 223, 34, 173, 52, 67, 52, 118, 106, 119, 170, 206, 112, 65, 85, 200, 214, 187, 136, 69, 74, 57, 133, 107, 139, 73, 96, 243, 49, 56, 181, 34, 55, 231, 213, 179, 165, 140, 208, 131, 172, 215, 247, 41, 176]

My question is how do I

A) copy the data to the buffer and

B) play the audio from the audio queue / buffer?

Edit: this is on MacOS not iOS

zoecarver
  • 5,523
  • 2
  • 26
  • 56
  • Do you really need to use an AudioQueue directly or do you really need to jam a buffer of audio data into the audio path? If you just want to play a sound from a file or url, you can use `AVPlayer(init(url:))` or you can make an AVPlayerItem if you need more control and give that to AVPlayer. Every layer you go down with this framework will give you more control but requires a lot more work. – Will Aug 17 '18 at 22:28
  • I am getting packets from a server, so I cannot just give it a URL (for complicated reasons that aren't really important). I don't need that much control but, I am not sure of a better way to do this. Also, I should mention that this is on MacOS not iOS. – zoecarver Aug 17 '18 at 22:30
  • Check out `AVAssetResourceLoader` and this answer https://stackoverflow.com/questions/39854439/avplayer-loading-avasset-from-file-that-is-appended-simultaneously-by-external-s Pipe your data into a stream and play that stream using AVPlayer – Will Aug 17 '18 at 22:53
  • I will look into that, thanks. – zoecarver Aug 17 '18 at 22:57
  • 1
    This is old, but it's a complete example of using AudioQueue for playing streaming audio. https://github.com/mattgallagher/AudioStreamer – John Fricker Aug 21 '18 at 15:18
  • @JohnFricker Thanks, that is super helpful. – zoecarver Aug 21 '18 at 16:31

1 Answers1

0

A) To copy the data to the buffer

let maxIndex = playerState.packets.count - 1
let index = Int(packet.sequenceNumber) & maxIndex
guard writePacket(packet, to: index) else { return }

And then, you'll have to update the write index, and playback status.

B) To start playing set the state of the player, you'll have to load the buffers, enqueue them and then set the playerState :

self.playerState.isPlaying = true

And start playing the audio:

AudioQueueStart(playerState.queue, nil)

For a fully fledged implementation with error handling have a look here.

ielyamani
  • 17,807
  • 10
  • 55
  • 90