【初投稿】Google Magenta でファイナルファンタジーの戦闘曲を学習させて新曲を作る試み

初めまして！
Qiita初投稿です。

自身の初学習成果を備忘録も兼ねて投稿します。
初学者向けの内容です！
開発環境は少し古いです😅
Magentaを導入して自動作曲アートとして何か面白いアイデアの参考になればと思います。
海外でもニルヴァーナの曲を学習させて新曲作ってみたというケースがありますが、この記事記載の手法（に近い）で作成されたものだと考察します。

# ■目的
既存のコンテンツ（ドラクエ、FFなど戦闘曲）を複数のシリーズ楽曲（SMF,.midファイル）を学習させて、次回作（となるような）シリーズ楽曲を生成するモデルを構築する。

## ■最終成果物だけ先に確認したい方はこちら
### アレンジデータを再生 (音量注意)
<iframe width="560" height="315" src="https://www.youtube.com/embed/MxpjGFbIi_8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

### AI生成のメロディデータを再生 (音量注意)
<iframe width="560" height="315" src="https://www.youtube.com/embed/UxswtpJBQfg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>




# ■この記事を読んでもらいたい方
・AIを使った作曲に興味がある方
・Magentaを使ってみたい方
・プログラマー、エンジニアだけど実はDTMやってる方
・作曲家だけど、実はプログラミングの勉強している方

# ■この記事で触れないこと
・Pythonの基礎
・ニューラルネットワークの基礎
・MIDIデータの中身、独自モデルの学習データの比率などの詳細
・DAWの使い方、MIDIデータの打ち込みテクニック
・Windows環境での説明
・Apple Silicon環境での説明

# ■参考文献
参考にした資料はこちらです。
【Magentaで開発 AI作曲】
https://www.ohmsha.co.jp/book/9784274227318/


# ■開発環境
MAC OS 10.15.7 Catalina
Magenta　2.1.3
TensorFlow　2.5.1
作業はターミナルのみで完結

【Magenta公式】
https://magenta.tensorflow.org/

【Magenta公式GitHub】
https://github.com/magenta/magenta

■Macローカル環境でのMIDI再生アプリ
MIDITrailを使いました。
https://apps.apple.com/jp/app/miditrail/id421739418?mt=12

このほかに、MACでしたら純正で【GarageBand】がインストールされていますのでMIDIファイルの確認だけであればインポートが可能です。
ただし【GarageBand】はMIDIのインポートは可能ですがエクスポートができませんので、MIDIデータの前処理が行っても書き出しが不可能です。
前処理したMIDIデータをエクスポートをしたい場合は上位製品の【Logic Pro】を購入する必要があります。

# ■アレンジ、編曲環境
MIDIデータの前処理にMIDI編集ができるDAWが必要です。
筆者は、MIDI編集ではNuendo及びCubaseを愛用しています。
（編曲はWINDOWSで行っているためユニバーサルアプリを使用。）
このほかWIN,MACの共通で使用できるDAWとして【PreSonus社】がリリースしている【Studio Oneシリーズ】のPrime（無償版）が多機能で優れています。						
DAWを使うのが始めてでしたらまずは無償で試すのもお勧めです。						
https://www.mi7.co.jp/products/presonus/studioone/prime/

# ■開発環境構築
はじめにPythonの仮想環境を作成します。
初学者向けの記事のため、かなり当たり前のことを記載しています。
仮にデスクトップにmagenta_ffという名前でフォルダを作りそこで仮想環境を構築します。

ディレクトリの移動
```
cd Desktop/magenta-ff
```
env作成
```
python3 -m venv magenta-env
```
作成した仮想環境の起動
```
source magenta-env/bin/activate
```

次にMagentaのレポジトリをGitHubからクローンします。
```
git clone https://github.com/tensorflow/magenta.git
```

カレントディレクトリをローカルにクローンしたmagentaへ移動
```
cd magenta
```

開発環境セット
```
pip install -e .
```

ライブラリの確認
```
pip list
```
ライブラリの依存関係が壊れているかはpip checkで確認。
```
pip check
```

すると筆者の環境では以下のエラーが出ました。
```
ERROR: tensorflow-metadata 1.2.0 has requirement absl-py<0.13,>=0.9, but you'll have absl-py 0.14.1 which is incompatible.
ERROR: bokeh 2.4.1 has requirement typing-extensions>=3.10.0, but you'll have typing-extensions 3.7.4.3 which is incompatible.
ERROR: kfac 0.2.3 has requirement tensorflow-probability==0.8, but you'll have tensorflow-probability 0.14.1 which is incompatible.
ERROR: tensor2tensor 1.15.7 has requirement tensorflow-probability==0.7.0, but you'll have tensorflow-probability 0.14.1 which is incompatible.
```
むむ、、どうやらライブラリの互換性が合わないバージョンがあるようです。
ライブラリの依存関係が崩れていてMagentaが正常に動作しない可能性があったため以下のライブラリを個別にダウングレードしました。
こっちを直すとあっちの依存関係が崩れて・・・なんだかモグラ叩きをやっている気分です😅
ひとつずつ慎重にダウングレードを行い、最終的には以下の順番でダウングレードを行いました。
```
pip install absl-py==0.12.0
pip install kfac==0.2.0
pip install tensorflow-probability==0.7.0
pip install cloudpickle==1.3
pip install bokeh==2.3.3
pip install numba==0.48.0
```
更新が終わったら都度必ずpip checkで確認。
```
pip check
```
### No broken requirements found.
最終的にこの一文がでればOK！！！
これでライブラリの依存関係が整いました。

# ■制作フロー
大枠のイメージですが図のようなフローでの実行をしています。
![スクリーンショット 2022-06-08 20.21.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1651386/9eb0c4b7-76ca-4ea8-638b-fdcc817a2ba6.png)


# ■MIDIデータの準備
MIDIファイルの入手ですが、大きくは3種類あります。
①国内の正規販売サイトで有料購入
→https://yamahamusicdata.jp/
著作者の監修を受けたデータを販売していますので、クオリティは大体整っています。

②自前で用意する
猛者は自作で作る！
またはサウンドクリエイターの知り合いがいれば耳コピで作ってもらう。
今回、使うデータはメロディとリフ（印象的な伴奏やフレーズ）だけですので全てをコピーする必要はないです。

③インターネットで公開されているMIDIデータを取得してくる
日本国内ではJASRACが目を光らせており、無料のMIDIサイトというのは現代ではほとんど存在していない状況です。
あったとしてもオルゴールアレンジなどの音数が少ないデータが多いです。

とりあえず、作業負荷と相談して以下のデータに決めました。
・FF1 通常戦闘曲
・FF2 通常戦闘曲
・FF3 通常戦闘曲
・FF4 通常戦闘曲
・FF5 通常戦闘曲
・FF5 ビッグブリッジの死闘
・FF7 通常戦闘曲
・FF7 ボス戦闘曲
・FF9 通常戦闘曲
・FF10 通常戦闘曲

どれも名曲ですね〜
選曲については・・・
御察しのとおり筆者はアラフォーなのでFF5~FF7ガチ世代なのでその分、配分多めにしています。
ポイントとして、作曲家を巨匠：植松伸夫 大先生（神）で統一しています。

①学習させるには曲数が圧倒的に足りないのでメロディ、リフ、ベースが埋めれる所はそのデータも1つのMIDIに格納して色々なバリエの前処理データを作成。10曲=>20曲分に【量マシ】
②学習に足りない分はMIDIファイル自体のコピーで【量マシマシ】行いました。
③さらにどの曲の特徴を多く持ってもらいたいかをコントロールするために特徴量が多めな曲をさらにコピーして【量チョモランマ】にしました。
果たしてこの方法が合っているのか謎ですが、まずは生成することを優先としました。

こうして元々は10曲のシングルトラックのMIDIデータでしたが最終的には600曲のMIDIデータとしてAIに学習させます。
曲数10〜50ファイルとかでも試してみましたが、後のtfrecord化の際に問題が出て正常にファイルの生成が出来ませんでしたのである程度楽曲数が必要だと思われます。

# ■MIDIをAIに学習
まずMIDIデータをそのままではAIに学習させることができないためtfrecord化が必要です。
個人的な都合でインプットディレクトリ、アウトプットディレクトリを開発用の仮想環境と違うディレクトリにしています。
コマンドは仮想環境上で実行してください。

```
///MIDIデータをtfrecord化///
///デスクトップのgame_mid_music作成しその中にFF_meloフォルダに先ほど用意した600曲のMIDIファイルを格納している///

convert_dir_to_note_sequences \
   --input_dir=/Users/自身のPCNAME/Desktop/game_mid_music/FF_melo \
   --output_file=/Users/自身のPCNAME/Desktop/game_mid_music/noteseq/notesequences.tfrecord \
   --recursive
```

これでnoteseqフォルダにnotesequences.tfrecordが生成されます。
続いて、TFRECORD化後、学習データと評価データの作成します。

```
///TFRECORD化後、学習データと評価データの作成///

melody_rnn_create_dataset \
--config=attention_rnn \
--input=/Users/自身のPCNAME/Desktop/game_mid_music/noteseq/notesequences.tfrecord \
--output_dir=/Users/自身のPCNAME/Desktop/game_mid_music/sequence_examples \
--eval_ratio=0.2
```

training_melodies.tfrecordとeval_melodies.tfrecordに分割されます。
次に任意モデルで学習します。

```
///任意モデル(attention_rnn)で1000回学習///

python /Users/自身のPCNAME/Desktop/magenta-ff/magenta/magenta/models/melody_rnn/melody_rnn_train.py  \
--config=attention_rnn \
--run_dir=/Users/自身のPCNAME/Desktop/game_mid_music/logdir/run1 \
--sequence_example_file=/Users/自身のPCNAME/Desktop/game_mid_music/sequence_examples/training_melodies.tfrecord \
--hparams="batch_size=64,rnn_layer_sizes=[64,64]” \
--num_training_steps=1000
```
ここは学習にかなり時間がかかります。
夜の内にコマンド実行して思い切って寝てしまいましょう。
自分の運を信じていれば大丈夫です！
朝確認して終わっていればOKです！
続いて評価をします。

```
python /Users/自身のPCNAME/Desktop/magenta-ff/magenta/magenta/models/melody_rnn/melody_rnn_train.py \
--config=attention_rnn \
--run_dir=/Users/自身のPCNAME/Desktop/game_mid_music/logdir/run1 \
--sequence_example_file=/Users/自身のPCNAME/Desktop/game_mid_music/sequence_examples/eval_melodies.tfrecord \
--hparams="batch_size=64,rnn_layer_sizes=[64,64]" \
--num_training_steps=1000 \
--eval 
```
eval（評価データ）の作成はすぐ終わると思います。

問題なく実行されればgame_mid_musicフォルダの中のsequence_examplesフォルダに【train_log】と【eval_log】が生成されますのでTensorBoardで確認します。
```
tensorboard --logdir=/Users/自身のPCNAME/Desktop/game_mid_music/logdir/
```
実行後
```
http://localhost:6006
```
でブラウザからTensorBoardを開きます。
筆者の実行結果は図のようになりました。
# TensorBoard
![スクリーンショット 2022-06-08 20.17.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1651386/d5da7783-01c9-91ae-9103-16b0393ced3d.png)

次にチェックポイントファイルを作成
仮テストなので10曲作成、尺は33小節分、テンポは170とします。
num_outputs=10
10曲作成

num_steps=528 
1曲の長さが33小節分

qpm=170.0
BPM170で出力
```
python /Users/自身のPCNAME/Desktop/magenta-ff/magenta/magenta/models/melody_rnn/melody_rnn_generate.py \
--config=attention_rnn \
--run_dir=/Users/自身のPCNAME/Desktop/game_mid_music/logdir//run1 \
--output_dir=/Users/自身のPCNAME/Desktop/game_mid_music/check_point_file \
--num_outputs=10 \
--num_steps=528 \
--qpm=170.0
--hparams="batch_size=64,rnn_layer_sizes=[64,64]" \
--primer_melody=“[57]”
```

問題なければBundlefileの作成をしましょう。

```
python /Users/自身のPCNAME/Desktop/magenta-ff/magenta/magenta/models/melody_rnn/melody_rnn_generate.py \
--config=attention_rnn \
--run_dir=/Users/自身のPCNAME/Desktop/game_mid_music/logdir//run1 \
--hparams="batch_size=64,rnn_layer_sizes=[64,64]" \
--bundle_file=/Users/自身のPCNAME/Desktop/game_mid_music/Bundle/FF_rnn.mag \
--save_generator_bundle
```
これでBundleフォルダ内にFF_rnn.magというバンドルファイルが作成されます。 
待望のファイナルファンタジーの名曲達を学んだ学習済みデータとなります。

# ■学習済みデータでMIDI生成を行う。
ここまで長かったですね・・・お疲れ様です。
いよいよ待望の学習済みデータでMIDIデータ生成を行います。
melody_rnn_generate.pyを使用します。
```
python /Users/自身のPCNAME/Desktop/magenta-ff/magenta/magenta/models/melody_rnn/melody_rnn_generate.py \
--config=attention_rnn \
--bundle_file=/Users/自身のPCNAME/Desktop/game_mid_music/Bundle/FF_rnn.mag \
--output_dir=/Users/自身のPCNAME/Desktop/game_mid_music/output_dir_my_model_midi \
--num_outputs=10 \
--num_steps=528 \
--qpm=170.0
--primer_melody=“[57]”
```

# ■自動作曲MIDIデータを確認
ここからは人間の出番です😎
30曲程生成して、出来が良いものを人間の手で選定。
納得できないデータが出た場合は、再度生成コマンドを実行してN数を増やすか再度学習データを作り直します（鬱）

その中で出来が良いデータがありました！
確認しやすいようにオーディオデータに変換しています。

### AI生成のメロディデータを再生 (音量注意)
<iframe width="560" height="315" src="https://www.youtube.com/embed/UxswtpJBQfg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>



いかがでしょうか？？？
おわかりいただけたであろうか・・・
よくわからんデータが・・・
できてしまったことを・・・
とはいえ・・・
なんか、イイ感じにリズミカルなフレーズで音楽的にもテーマを繰り返していて、
上手く Attention RNNの特徴が出ている。（ポジティブシンキング♪大事♪）
でも、1トラックのメロディだけなので成果物として物足りない
・・・なので

# ■自力でアレンジ
MIDIデータを読み込ませて自力でアレンジ💦
見にくいですが、図の上部の赤枠で囲まれたデータが先程の視聴ファイルです。
他のデータは編曲で作成したMIDIデータです。
作業時間3～4時間ほどで作りました（汗）
AI生成のメロディは変更しておらず、そのまま使用しています。
定番のイントロは追加しています。（このイントロはマジでチート）

### Nuendo（DAW）を使って人の手によるアレンジ結果の画
![スクリーンショット 2022-06-08 20.24.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1651386/3c122ce0-f04d-f41d-dad1-6d9ecf607aa0.png)

### アレンジデータを再生 (音量注意)
<iframe width="560" height="315" src="https://www.youtube.com/embed/MxpjGFbIi_8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

# ■結果
なんとかそれっぽくなった！！！
（脳筋的パワープレイ✊）

# ■振り返り
・仮想環境にインストールするライブラリの整合性問題が大変。
・MIDIファイルの前処理をDAW（音楽制作ソフト）で行った。
　一つ一つファイルを読み込んで美味しいポイントだけ抽出。　
・学習用MIDIデータの数が少ない。
　用意したMIDIファイルは10曲程度。
　まず、そのまま10曲程度で学習データを作成したが、Train0.8,Eval0.2の割合で検証ファイルが作成できないことに気付いた。
　この場合は検証するデータが足りない模様。
・メロディのみを抽出と考えたが、特徴的なFFっぽいフレーズとして、前奏、リフもあるのでメロディデータと合わせて学習させた。
　この方法が良いのかわからないがとりあえずデータが沢山欲しかった。
　コピー等を行い600曲くらいを学習させた。
・MIDIファイルの学習に時間がかかる。　
 MACのローカル環境で500曲を10000回学習で8時間程💦
・前処理のデータの問題だと思うが、今回はメロディよりもリフの生成データが多い印象を受けた。
・1000回学習、10000回学習のデータ両方作成してみたが、1000回学習のデータの方が音楽的には良い結果で出力されることが多かった。
　今回のケースでは10000回(accuracy.095)は過学習を起こしている。
　そもそも同じようなデータばかり学習させているので流石に過学習でした。
　過学習だと同じような曲（多様性のないつまらない曲）しか生成できない。
・回帰に関してはaccuracyが高いと偶発的な物は期待しにくい？


# ■最後に
MIDIデータを作成したり準備が大変ですが自動作曲に興味がある方は是非チャレンジしてみて下さい！！！
なかなか面白いデータができます。
今回のケースでは既存曲を利用しているので著作権周りの取り扱いは注意が必要です。
日本ではまだ法整備ができていませんので今後、こういった取組はNGとなる可能性もあります。

音生成AIに関して
→MuseGAN、Jukebox、MuseNet、Music Transformerなるものもあるようで、まだまだ奥が深い・・・

長い記事を読んでいただいてありがとうございました！