Sources/AudioKit/AudioKit.docc/Samplers.md
The term "sampler" is a bit misleading. Originally, it referred to a hardware device capable of recording ("sampling") sound and then re-playing it from a keyboard. In practice, the playback aspect proved to be far more popular then the recording aspect, and today the two functions are nearly always completely separated. What we call a "sampler" today is simply a system for replaying previously-prepared sounds ("samples").
NOTE: In earlier versions of AudioKit, AppleSampler was called Sampler.
Apple's AUSampler Audio Unit, despite a few unfortunate flaws, is exceptionally powerful, and has served as the basis for countless sample-based iOS music apps. It has five huge advantages over the other two sampler modules:
Unfortunately, AUSampler has some fatal flaws, and indeed appears to be an unfinished project. Using it as a plug-in on the Mac, to develop sample-based instruments (sample sets + metadata) tends to be an exercise in frustration. It can crash the DAW. Using AUSamplers plug-in in a DAW gives a GUI which is supposed to be able to read SoundFont, DLS and EXS24 metadata files, but in practice rarely does so perfectly. Its native .aupreset metadata format, which is a Property List, is undocumented and confusing. The .aupreset can be edited within Xcode Property List editor. After converting a EXS24 or before deploying to iOS usually the paths need to be manually fixed. See Apple Technical Note TN2283. The .aupreset can also be programmatically edited using PresetManager and PresetBuilder. External example in StackOverflow.
The AudioKit class AppleSampler basically just wraps an instance of AUsampler and makes its Objective-C based API accessible from Swift. Most music apps use the higher-level MIDISampler class, whose enableMIDI() function connects it directly to the stream of incoming MIDI data.
When the audio session route changes (the iOS device is plugged into an external sound interface, headphones are connected, you start capturing a video on a mac using Quicktime...) Samplers start producing distorted audio.
Registering for audio route changes is simple and doesn't require anything from the basic app flow like the delegate or view controllers. Just do:
NotificationCenter.default.addObserver(self, selector: #selector(routeChanged), name: .AVAudioSessionRouteChange, object: AVAudioSession.sharedInstance())
Define the event handler:
@objc func routeChanged(_ notification: Notification) {
Log("Audio route changed")
AudioKit.stop() // Note 1
do {
try sampler.loadEXS24(yourSounds) // Note 2
} catch {
Log("could not load samples")
}
AudioKit.start()
}
Note 1: Sometimes stopping and starting AudioKit is not necessary. I suspect that this has something to do with sampling rates and bit rates, but I didn't investigate further, because I needed to support the stricter case anyway
Note 2: Samplers need to reload. AudioKit could implement route tracking in the main singleton, register all samplers and do this automatically to work properly out of the box.