Search code examples
iosswiftavaudioengineavaudioplayernode

Swift: Play gapless audio with AVAudioEngine (AVAudioPlayerNode)?


Basically, I am trying to play AAC(with ADTS header) streams with AudioEngine through websockets (I am using StarScream). I play these audio in real time and there are glitches between the audio packets while playing. These are the steps I tried:

  1. Received data from WebSocket
extension ViewController: WebSocketDelegate {
    func didReceive(event: WebSocketEvent, client: WebSocket) {
        switch event {
        case .binary(let data):
            // Here is the AAC Stream. I store them in a buffer (NSMutableData)

        default:
            break
        }
    }
}
  1. Parse the AAC (AAC to PCM)

Saved the data to audio.aac using FileHandle and decoded it using AVAudioFile

func decodeAACTOPCM(aac: Data) -> AVAudioPCMBuffer? {
        self.fileHelper.createFile(name: "audio.aac")
        self.fileHelper.writeFile(data: aac)
        let url = URL(fileURLWithPath: fileHelper.path)
        do {
            let audioFile = try AVAudioFile(forReading: url)
            guard let buffer = AVAudioPCMBuffer(pcmFormat: audioFile.processingFormat, frameCapacity: .init(audioFile.length * 3)) else {
                return nil
            }
            try audioFile.read(into: buffer)
            buffer.frameLength = buffer.frameCapacity
            print("Buffer size \(buffer.frameLength)")
            return buffer
        } catch {
            print(error)
            return nil
        }
    }
  1. Play the PCM Data
func playPCM(_ pcm: AVAudioPCMBuffer) {
     audioFilePlayer.scheduleBuffer(pcm, at: nil, options: .interrupts, completionHandler: nil)
}
  1. The final result audio has some glitch between each audio packets. The issue was similar to this.. https://storage.googleapis.com/webfundamentals-assets/videos/gap.webm

Any suggestions on what I did wrong is appreciated.

Thank you!


Solution

  • Finally! I have solved this issue with AudioQueue. If anyone struggling the same issue as mine in Swift, this AudioQueue sample code saved me.

    https://gist.github.com/zonble/635ea00cb125bc50b3f5880e16ba71b7