LoginSignup
11
11

More than 1 year has passed since last update.

Swift:ただ音を鳴らすだけ

Last updated at Posted at 2020-08-08

方法

AVAudioUnitSamplerを用いてMIDIと同種のノートを鳴らすことができる。複雑なことはしたくないけど、とにかく単音を任意の時間鳴らしたいという場合に有効。ただし、SoundFontを使わないと音の停止時に微妙にノイズが入る。

import AVFoundation

class Sampler {
    let audioEngine = AVAudioEngine()
    let unitSampler = AVAudioUnitSampler()

    init() {
        audioEngine.attach(unitSampler)
        audioEngine.connect(unitSampler, to: audioEngine.mainMixerNode, format: nil)
        try? audioEngine.start()
    }

    deinit {
        if audioEngine.isRunning {
            audioEngine.stop()
            audioEngine.disconnectNodeOutput(unitSampler)
            audioEngine.detach(unitSampler)
        }
    }

    func play() {
        // 一つ目の引数はMIDIのNote番号60は基本のド
        // withVelocityは音量に関係する値 0 ~ 127
        // onChannelはチャンネルを構成しないなら基本0
        unitSampler.startNote(60, withVelocity: 80, onChannel: 0)
    }

    func stop() {
        unitSampler.stopNote(60, onChannel: 0)
    }
}
let sampler = Sampler()

// 音を再生
sampler.play()

// 音を停止
sampler.stop()

SoundFontを使う場合

音質は使うSoundFontファイルに依存するが、基本的には終了時のノイズはなくなるので綺麗に音を鳴らすことができるようになる。例えば、よくあるピアノ音源のSoundFontファイルは100MB〜300MBくらいあるので、アプリの容量を抑えたい場合は軽量なSoundFontを探すか、自作するといいかもしれない。

init() {
    audioEngine.attach(unitSampler)
    audioEngine.connect(unitSampler, to: audioEngine.mainMixerNode, format: nil)
    if let _ = try? audioEngine.start() {
        loadSoundFont()
    }
}

func loadSoundFont() {
    guard let url = Bundle.main.url(forResource: "SoundFontファイル名", withExtension: "sf2") else { return }
    try? unitSampler.loadSoundBankInstrument(
        at: url, program: 0,
        bankMSB: UInt8(kAUSampler_DefaultMelodicBankMSB),
        bankLSB: UInt8(kAUSampler_DefaultBankLSB)
    )
}
11
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
11