-
-
Save alessandrostone/387708e39ed044a8c7845f89252a7baa to your computer and use it in GitHub Desktop.
Swift Playground shows how to play multiple wav files on top of background audio file, using AVAudioPlayerNode, AVAudioMixerNode, AVAudioEngine
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import AVFoundation | |
import UIKit | |
import PlaygroundSupport | |
PlaygroundPage.current.needsIndefiniteExecution = true | |
class AudioPlayer { | |
var backgroundAudioFile:AVAudioFile | |
var topAudioFiles: [AVAudioFile] = [] | |
var engine:AVAudioEngine | |
var backgroundAudioNode: AVAudioPlayerNode | |
var topAudioAudioNodes = [AVAudioPlayerNode]() | |
var mixer: AVAudioMixerNode | |
var timer: Timer! | |
var urls: [URL] = [] | |
init (_ url: URL, urls: [URL] = []) { | |
backgroundAudioFile = try! AVAudioFile(forReading: url) | |
topAudioFiles = urls.map { try! AVAudioFile(forReading: $0) } | |
engine = AVAudioEngine() | |
mixer = AVAudioMixerNode() | |
engine.attach(mixer) | |
engine.connect(mixer, to: engine.outputNode, format: nil) | |
self.urls = urls | |
backgroundAudioNode = AVAudioPlayerNode() | |
for _ in topAudioFiles { | |
topAudioAudioNodes += [AVAudioPlayerNode()] | |
} | |
} | |
func start() { | |
engine.attach(backgroundAudioNode) | |
engine.connect(backgroundAudioNode, to: mixer, format: nil) | |
backgroundAudioNode.scheduleFile(backgroundAudioFile, at: nil, completionHandler: nil) | |
try! engine.start() | |
backgroundAudioNode.play() | |
for node in topAudioAudioNodes { | |
engine.attach(node) | |
engine.connect(node, to: mixer, format: nil) | |
} | |
try! engine.start() | |
// simulate rescheduling files played on top of background audio | |
DispatchQueue.global().async { [unowned self] in | |
for i in 0..<1000 { | |
sleep(2) | |
let index = i % self.topAudioAudioNodes.count | |
let node = self.topAudioAudioNodes[index] | |
node.scheduleFile(self.topAudioFiles[index], at: nil, completionHandler: nil) | |
node.play() | |
} | |
} | |
} | |
} | |
let bundle = Bundle.main | |
let beepLow = bundle.url(forResource: "beeplow", withExtension: "wav")! | |
let beepMid = bundle.url(forResource: "beepmid", withExtension: "wav")! | |
let backgroundAudio = bundle.url(forResource: "backgroundAudio", withExtension: "wav")! | |
let audioPlayer = AudioPlayer(backgroundAudio, urls: [beepLow, beepMid]) | |
audioPlayer.start() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment