YMF825でMIDI音源

NUCLEO-F767ZIを使用してMIDI音源を作成しました。Sound ChipはYMF825です。

【追加】2020/7/5 Longan Nanoでも動かせるようにしました。 nyankov.hatenablog.com

ソースコード

github.com

イースのBGM「FOUNTAIN OF LOVE」を打ち込んで、作成した音源で鳴らしてみました。

www.youtube.com

〇2019/8/31 詳細を追加しました。

目次

目的

FM音源ICで好きなゲームのBGMを鳴らしたい!

ハードウェア

FM音源

YMF825を使用しました。

マイコン(評価ボード)

たまたまあったNUCLEO-F767ZIを使用しました。

工作

評価ボードにARDUINOインタフェースがあったので、ユニバーサル基板で YMF825シールドを作成して合体させようと思ったら、ビミョーにはまらない。。そういうものなのでしょうか。

仕方がないので無理やりさしました。

f:id:nyankov:20190825235533j:plain 曲がってますね。。

あと、YMF825Boardの2電源化には苦労しました。

ソフトウェア

開発環境

IDE

SEGGER Embedded Studioを使用しました。

https://www.segger.com/products/development-tools/embedded-studio/

デバッガ

Onboard DebuggerのST-LinkをJ-Linkに書き換えました。

〇方法はこちら

https://www.segger.com/products/debug-probes/j-link/models/other-j-links/st-link-on-board/

ソフトウェア設計

予備実験

はじめにYMF825Boardボードの動作確認を行いました。 下記のYAMAHA公式リポジトリにあるsample1 (ARDUINO用)のSPIドライバを STMicroのHALドライバに書き換えて動作確認を行いました。

yamaha-webmusic.github.io

2電源化対応で長い時間はんだ小手を押し付けてしまったため、ドレミ音が聞こえたときはホッとしました。

機能ブロック

こんな感じで設計しました。

f:id:nyankov:20190825131012p:plain

USBD

USBDはSTM32_USB_Device_Libraryを使用して実装しました。

ターミナルソフトでYMF825を直接制御したかったため、 USBMIDIにUSBCDCを追加した複合デバイスクラスを実装することにしました。 ソースコードはSTM32_USB_Device_Library内のAUDIOクラスとCDCクラスをベースにして作成しました。 また、AUDIOクラスに関するコンフィギュレーションディスクリプタは 規格書のAppendix B. Example: Simple MIDI Adapter (Informative)に記述されているものに書き換えました。 そのため、今回は未使用ですが、MIDIOUTもホスト側から認識できていました。

USBMIDIに関してはpcm1723さんのブログで学ばせて頂きました。

pcm1723.hateblo.jp

Shell

大層な名前をつけてしまいましたが、 受信した文字列に従って処理を実行するだけです。

入力はゲートウェイモードとコマンドモードに分けました。

ゲートウェイモード

16進数を1 Byte単位で文字列にして送信した場合は、USBCDC-SPIゲートウェイとして動作するようにしました。終端文字は<CR>で、<LF>は無視します。

例えば5byte文字列 "073A"+<CR>を送信すると、2byte数値0x073AをYMF825に送信します。

また、YMF825専用の処理となってしまいますが、I_ADRの7bitが1の場合、SPI Readを行い、受信したデータを16進文字列にしてホスト側に送信するようにしました。

コマンドモード

:始まりの文字列(+<CR>)を受信した場合、上記モードとは別モードとして動作するようにしました。 これは例えば

:info

:cfg

といったコマンドを作成してシステムの監視や設定を行おうと考えていたためです。

ただ、今のところコマンドは未実装です。

MIDI Message Parser

MIDI 1.0 規格書』と、悠人さんのサイトでMIDIについて勉強しながら、 MIDI Message Parserを作成しました。

www1.plala.or.jp

MIDI Message Parserはインスタンスとして生成するようにし、NoteOnやControlChangeといった各々のMIDIメッセージに対するコールバック関数をこのインスタンスに登録するようにしました。

これは今後、音源ICを追加したとき、コマンドによって動的に音源ICを切り替えられるようにしたかったためです。

SoundSourceDriver

MIDI Message Parserに登録するコールバック処理です。この部分にMIDIメッセージ受信時の処理を記述します。

f:id:nyankov:20190831125543p:plain

今回は、SoundSourceDriverの一つとして、single_ymf825というモジュールを作製しました。 MIDIチャンネルの番号を単純にそのままYMF825のtone numberにマッピングするようにしました。 そのため、各MIDIチャンネルの同時発音数は1となるので、動作としてはモード4(オムニオフ、モノモード)になるかと思います。 なので、同一チャンネルに和音があるようなMIDIファイルの場合、発音する音色は後勝ちとなります。 また、YMF825のToneParameterを更新するために、すべての音をOFFする必要があるようなので、 演奏中にProgramChangeを受信すると、音が途切れます。これ、何とかならないでしょうか。

あと、チャンネル10は常にノイズ音としました。

音色作成

FM音源はパラメータが多い上に感覚的に理解しづらい」

ということはなんとなく分かっていたつもりでしたが、いざ作ろうと思ったら、本当に何をしていいのかわからずに途方にくれてしまいました。

なので本買いました。

この本のおかげで、自分が出したい音色の設計方針を学ぶことができました。

作製した音色情報はToneTableに登録するようにしました。動作としてはProgramChangeでこのテーブルを参照し、YMF825に情報を流し込むといった感じです。

とりあえずGM音源としてNo.1からNo.128までの音色を作製しようと頑張ったのですが、 挫折しました(コーラスとかストリングスとかオケヒとか、いったいどうしろと。。)。

※音色(楽器)に関してはAkiyoshi Ogataさんのサイトで勉強させていただきました。

akiyoshiogata.com

MIDIファイルの作成

MIDIシーケンサー

くずさんの『世界樹5.7』を使用させていただきました。

https://openmidiproject.osdn.jp/Sekaiju.htmlopenmidiproject.osdn.jp

作成した音楽

イース ミネアの町のBGM 『FOUNTAIN OF LOVE』を素人なりに打ち込んでみました。 参考にしたのはPC-88版ですが、なかなか難しいですね。。