カテゴリー
AudioKit iOS Swift

AudioKitにSoundFontを読み込みシーケンスの最小構築

gitHub repo

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()
  }
}