NUCLEO-F767ZIを使用してMIDI音源 を作成しました。Sound ChipはYMF825です。
【追加】2020/7/5 Longan Nanoでも動かせるようにしました。
nyankov.hatenablog.com
ソースコード
github.com
イース のBGM「FOUNTAIN OF LOVE」を打ち込んで、作成した音源で鳴らしてみました。
VIDEO www.youtube.com
〇2019/8/31 詳細を追加しました。
目次
目的
FM音源 ICで好きなゲームのBGMを鳴らしたい!
ハードウェア
YMF825を使用しました。
たまたまあったNUCLEO-F767ZIを使用しました。
工作
評価ボードにARDUINO インタフェースがあったので、ユニバーサル基板で
YMF825シールドを作成して合体させようと思ったら、ビミョーにはまらない。。そういうものなのでしょうか。
仕方がないので無理やりさしました。
曲がってますね。。
あと、YMF825Boardの2電源化には苦労しました。
ソフトウェア
開発環境
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電源化対応で長い時間はんだ小手を押し付けてしまったため、ドレミ音が聞こえたときはホッとしました。
機能ブロック
こんな感じで設計しました。
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 メッセージ受信時の処理を記述します。
今回は、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
くずさんの『世界樹 5.7』を使用させていただきました。
https://openmidiproject.osdn.jp/Sekaiju.html openmidiproject.osdn.jp
作成した音楽
イース ミネアの町のBGM 『FOUNTAIN OF LOVE』を素人なりに打ち込んでみました。
参考にしたのはPC-88版ですが、なかなか難しいですね。。