Skip to content

Instantly share code, notes, and snippets.

@standinga
Created May 2, 2019 19:08
Show Gist options
  • Save standinga/3e5a68bb0680c8c7ee8dafd1af0c3b53 to your computer and use it in GitHub Desktop.
Save standinga/3e5a68bb0680c8c7ee8dafd1af0c3b53 to your computer and use it in GitHub Desktop.
AudioPlayer.swift for medium article (1st version)
import AVFoundation
class AudioPlayer: NSObject {
private let engine = AVAudioEngine()
private let playerNode = AVAudioPlayerNode()
private var file: AVAudioFile!
private var isPlaying = false
private let audioPlayerQueue = DispatchQueue(label: "AudioPlayerQueue")
init(_ url: URL) {
guard let file = try? AVAudioFile(forReading: url) else {
fatalError("can't load file")
}
self.file = file
super.init()
engine.attach(playerNode)
}
func play() {
audioPlayerQueue.sync {
guard !self.isPlaying else { return }
self.startPlaying()
}
}
private func startPlaying() {
engine.connect(playerNode, to: engine.mainMixerNode, format: file.processingFormat)
scheduleLoop(file)
let hardwareFormat = engine.outputNode.outputFormat(forBus: 0)
engine.connect(engine.mainMixerNode, to: engine.outputNode, format: hardwareFormat)
do {
try engine.start()
} catch {
fatalError("can't start engine \(error)")
}
playerNode.play()
isPlaying = true
}
private func scheduleLoop(_ file: AVAudioFile) {
playerNode.scheduleFile(file, at: nil) {
self.audioPlayerQueue.async {
if self.isPlaying {
self.scheduleLoop(file)
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment