Skip to content

Instantly share code, notes, and snippets.

@bibscy
Last active April 16, 2019 20:22
Show Gist options
  • Save bibscy/1c30aa6ebb21f9734d1466c978a127a6 to your computer and use it in GitHub Desktop.
Save bibscy/1c30aa6ebb21f9734d1466c978a127a6 to your computer and use it in GitHub Desktop.
import AVFoundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
class AudioPlayer {
var topAudioFiles: [AVAudioFile] = []
var engine:AVAudioEngine
var backgroundAudioNode: AVAudioPlayerNode
var backgroundAudioFile: AVAudioFile
var topAudioAudioNodes = [AVAudioPlayerNode]()
var mixer: AVAudioMixerNode
var timer: Timer!
var urls: [URL] = []
var player: AVPlayer!
var times = [NSValue]()
var delays = [UInt64]()
init (_ url: URL, urls: [URL] = []) {
self.urls = urls
topAudioFiles = urls.map { try! AVAudioFile(forReading: $0) }
backgroundAudioFile = try! AVAudioFile(forReading: url)
player = AVPlayer(url: url)
engine = AVAudioEngine()
mixer = AVAudioMixerNode()
engine.attach(mixer)
engine.connect(mixer, to: engine.outputNode, format: nil)
backgroundAudioNode = AVAudioPlayerNode()
initTopAudioNodes()
try! engine.start()
}
func initTopAudioNodes() {
for _ in topAudioFiles {
topAudioAudioNodes += [AVAudioPlayerNode()]
}
for node in topAudioAudioNodes {
engine.attach(node)
engine.connect(node, to: mixer, format: nil)
}
}
func playWithAudioPlayerAndNodes() {
player.play()
var i = 1
player.addBoundaryTimeObserver(forTimes: times, queue: nil) {
let index = i % self.topAudioAudioNodes.count
let node = self.topAudioAudioNodes[index]
node.scheduleFile(self.topAudioFiles[index], at: nil, completionHandler: nil)
node.play()
i += 1
}
}
}//end class
let bundle = Bundle.main
let beepLow = bundle.url(forResource: "1", withExtension: "wav")!
let beepMid = bundle.url(forResource: "2", withExtension: "wav")!
let backgroundAudio = URL(string: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3")!
//even if I try to use a local file, it will still output error. For example let backgroundAudio = bundle.url(forResource: "2", withExtension: "wav")!
let audioPlayer = AudioPlayer(backgroundAudio, urls: [beepLow, beepMid])
// second approach using AVPlayer and boundary time observer:
audioPlayer.playWithAudioPlayerAndNodes()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment