VisionProでMIDIファイルを再生する

# はじめに
VisionProでMIDIファイルを再生しようと思って実装をしました。

今回実装したレポジトリはこちらです
https://github.com/kanakanho/PlayMIDI

# プロジェクトの設定
<img width="3024" alt="image.png (746.3 kB)" src="https://img.esa.io/uploads/production/attachments/13979/2024/07/31/148413/c39023cc-d74b-47fc-b3b9-413ddb32b2b6.png">

# 音楽を流すコード
```swift:Play.swift
import AVFoundation

class Play {
    private let midiFile: String
    private let soundFontFile: String
    private var midiPlayer: AVMIDIPlayer?
    
    init(midiFile: String,soundFontFile: String) {
        self.midiFile = midiFile
        self.soundFontFile = soundFontFile
        
        // Ensure MIDI file URL is valid
        guard let midiFileURL = Bundle.main.url(forResource: midiFile, withExtension: "mid") else {
            print("MIDIファイルが見つかりません")
            fatalError("MIDIファイルが見つかりません")
        }
        
        // Ensure SoundFont file URL is valid
        guard let soundFontFileURL = Bundle.main.url(forResource: soundFontFile, withExtension: "sf2") else {
            print("SoundFontファイルが見つかりません")
            fatalError("SoundFontファイルが見つかりません")
        }
        
        do {
            midiPlayer = try AVMIDIPlayer(contentsOf: midiFileURL, soundBankURL: soundFontFileURL)
        } catch {
            print("AVMIDIPlayerの初期化エラー: \(error.localizedDescription)")
            return
        }
    }
    
    func play() {
        midiPlayer?.prepareToPlay()
        
        if let midiPlayer = midiPlayer, !midiPlayer.isPlaying {
            midiPlayer.play()
        }
    }
}

```

```swift:ContentView.swift
struct ContentView: View {
    @State private var player: Play = Play(midiFile: "audio",soundFontFile: "soundfont")
...
    var body: some View {
        VStack {
            Image(systemName: "waveform.circle")
                .resizable()
                .scaledToFit()
                .frame(width: 100)
                .onTapGesture {
                    player.play()
                }
...
```

# 音源の追加
プロジェクトの`PlayMIDI`以下に MIDI ファイルをドラッグアンドドロップ

すると下のようにポップアップが出てくる

<img width="1512" alt="image.png (1.2 MB)" src="https://img.esa.io/uploads/production/attachments/13979/2024/07/31/148413/84da7a2b-b39d-43ae-b998-9bcd135c94bb.png">

`Finish`を選択

<img width="270" alt="image.png (63.8 kB)" src="https://img.esa.io/uploads/production/attachments/13979/2024/07/31/148413/9fe875a3-c74b-4a02-8199-955731851cfa.png">


プロジェクトの`Assets`を開く
<img width="1378" alt="image.png (653.2 kB)" src="https://img.esa.io/uploads/production/attachments/13979/2024/07/31/148413/f859534c-a34f-47ed-bd28-b92a2481dc16.png">

`Assets`を開き、プロジェクトに追加したファイルをドラッグして追加する

<img width="1512" alt="image.png (906.9 kB)" src="https://img.esa.io/uploads/production/attachments/13979/2024/07/31/148413/2306aa29-740b-4bf7-8f44-326d787e5d1d.png">

追加後
<img width="1512" alt="image.png (1.0 MB)" src="https://img.esa.io/uploads/production/attachments/13979/2024/07/31/148413/5155e6fd-5d91-41d7-8047-4891e15d975e.png">

同様にsoundfontも追加する

# 動作確認
左上の実行マークからエミュを起動する

アプリが起動するとこのような画面になる
<img width="1478" alt="image.png (4.2 MB)" src="https://img.esa.io/uploads/production/attachments/13979/2024/07/31/148413/b3956eec-f496-4e72-9ced-2eb663338c7a.png">

ウィンドウ上のアイコンをクリックすると音が流れます！

:::note warn
なおエミュレータではビープ音しか聴こません。
サウンドフォントを適応させるには実機での検証が必要になります。
:::


# 終わりに
今回はVisionPro（Swift）でのMIDIファイルの再生を試してみました。サウンドフォントが使えるので鳴らしたい楽器で音が流せますね！

# 参考にした記事

https://develop.hateblo.jp/entry/swift-midi-player

https://qiita.com/Kyome/items/0b514d8b799b956dc73d

お借りしたsf2ファイル  

https://sites.google.com/site/soundfonts4u/