SoundFontのBankが一つの場合は:
func loadMelodicSoundFont(url: URL, preset: Int, in bundle: Bundle = .main) throws {
try loadSoundFont(url: url, preset: preset, type: kAUSampler_DefaultMelodicBankMSB, in: bundle)
}
Bankがいくつかある場合はtype: IntにBank番号をアサインして使う。
func loadSoundFont(_ file: String, preset: Int, bank: Int, in bundle: Bundle = .main) throws {
guard let url = findFileURL(file, withExtension: ["sf2", "dls"], in: bundle) else {
Log("Soundfont file not found: \(file)")
throw NSError(domain: NSURLErrorDomain, code: NSFileReadUnknownError, userInfo: nil)
}
do {
var bMSB: Int
if bank <= 127 {
bMSB = kAUSampler_DefaultMelodicBankMSB
} else {
bMSB = kAUSampler_DefaultPercussionBankMSB
}
let bLSB: Int = bank % 128
try samplerUnit.loadSoundBankInstrument(
at: url,
program: MIDIByte(preset),
bankMSB: MIDIByte(bMSB),
bankLSB: MIDIByte(bLSB)
)
} catch let error as NSError {
Log("Error loading SoundFont \(file)")
throw error
}
}
// setup example
private func setup() {
// load sound font
loadSF2(name: soundFonts[1], bank: 17, preset: 27, sampler: guitarSampler)
// create a track if the mainSequencer doesn't have one
if mainSequencer.trackCount < 1 {
let _ = mainSequencer.newTrack("guitarTrack")
}
// add sampler to the mixer
mixer.addInput(guitarSampler)
// assign mixer as the engine's output
engine.output = mixer
do {
try engine.start()
} catch {
print("error starting the engine: \(error)")
}
}
public func loadSequence() {
// time will be tracking the position of the cursor
var time = 0.0
// I don't need to set the playhead to zero here...
// mainSequencer.setTime(0.0)
let guitarTrackManager = mainSequencer.tracks[0]
guitarTrackManager.clearRange(start: Duration(beats: time), duration: Duration(beats: 200))
// adding a note
guitarTrackManager.add(noteNumber: 50, velocity: 127, position: Duration(beats: time), duration: Duration(beats: 0.5))
// then, increment the time
time += 0.5
// add another note
guitarTrackManager.add(noteNumber: 52, velocity: 127, position: Duration(beats: time), duration: Duration(beats: 1))
// connect track to the sampler's midi in
guitarTrackManager.setMIDIOutput(guitarSampler.midiIn)
}
public func play() {
loadSequence()
mainSequencer.stop()
// rewind the playhead to the very start
mainSequencer.setTime(0.0)
mainSequencer.setTempo(60)
mainSequencer.play()
}
// in case you want to enable/disable looping
public func toggleLoop() {
if mainSequencer.loopEnabled {
mainSequencer.disableLooping()
} else {
mainSequencer.enableLooping()
}
}