公開日:2025/09/20
title.png

36th Season


#36-3 サウンドジェネレータの設計.3

 本HPではMML(Music Macro Language)を使って音楽を演奏するソフトウェアを作ってきました。
 Arduinoマイコンボードではハードウェアがギブンなので、マイコンの汎用PWMタイマや割り込み機能などを駆使して、ソフトウェアで工夫しながら実装してきた、のが実態です。
 Cmod A7ボード(FPGA)を使えば、音楽演奏に特化したハードウェアの設計が可能なので、MMLを使った音楽演奏を容易に実現可能なハードウェアの設計が可能です。これこそFPGAの醍醐味ですよ。

 前回までにサウンドジェネレータSNDG1PBユニットの設計実装が完了していますので、今回はソフトウェア開発環境を整備した後、FPGAに焼き付けて実動作の確認まで終わらせたいと思います。

開発環境の整備

 Moscoviumの開発環境と言えば、Blockly for Moscoviumなのです。SNDG1PBユニットを制御して、音楽演奏を可能とするカスタムブロック群を追加しました(下図、およびリンク)。

a316_blky_sndg.png

 詳細な使い方については、上図リンクからマニュアルでご確認ください。


 簡単な使い方としてはsndg play MMLブロックを使うのがお勧めです(下コード)。

a362_blkypmml.png

 上のコードだけで、SNDG1PBユニットの初期設定も含めて「ドレミファソラシド」の音階が演奏できます。

 MMLを1個づつFIFOに書き込むことで、より細かく制御したい場合などに向けて、sndg play pointerブロックを用意しています。インターフェイスや制御方法が異なるだけで、どちらのブロックでも同様に音楽演奏が可能です。

 具体的なコード例については、後ほどリンクする完成プログラムでご確認いただけます。

 こちらのマニュアルを参照して、Blockly for MoscoviumおよびBlockly.XML→Moscovium.ASM変換スクリプトのアップデートを済ませてから先にお進みください。

使い方のヒント

 SNDG1PBユニットにはFIFOバッファが32段搭載されています。FIFO残少割り込みSGERは、FIFO内の演奏コード数が8個以下になった時に発生します。裏返すと、SGER割り込みが発生した時点で、32−8=24個程の演奏コードを書き込む余地があるという事です。
 24個からマージンを確保して16個程度と考え、演奏したい楽譜を16音毎に分割してMML文字列を作っておきましょう。SGER割り込みが発生する度に、sndg play MMLブロックを使用して、その16音を一気にFIFOバッファへ書き込みます。
 これを繰り返すと、途切れなく、楽譜を演奏し続けることができます。

 もう少し細かく制御したい場合には、sndg play pointerブロックを使うと、1音づつFIFOに書き込む事ができます。制御の難易度は上がりますが、きめ細かい制御が可能となります。特にその様な要求が無い場合は、sndg play MMLブロックがお手軽に使えてお勧めです。

文字列型定数

 Blockly for Moscoviumでは、文字列型変数を使うことができます。
 MMLも文字列ですが、あまり、プログラム中で文字列操作して使う事は無く、基本的には文字列型定数として使われます。ところが、Blockly for Moscoviumで文字列型変数に文字列型定数を代入すると、ROM上の文字列型定数が、わざわざRAM上の文字列型変数領域にコピーされてしまいます(下コード例)。

a362_blkystrc.png

  変換後のアセンブラソースリスト抜粋:
  // r1="C44,D44,E44,F44,G44,A44,B44,C54"
  ldwi r1,lab__auto_0001_text
  // r0=&var_str[ ]
  ldwi r0,var_str
  add r0,r6
  ld$(z) r0,[r0]
  push$(z) r0
  // end of var_str="C44,D44,E44,F44,G44,A44,B44,C54"
  pop$(z) r0
  jal$(z)r7 _strcpy_r0_r1
  :
  : (中略)
  :
  // string constants
  _auto_0001_text:
  dats "C44,D44,E44,F44,G44,A44,B44,C54\0"


 文字列がMMLである場合、ただ文字列型定数として参照するだけなので、ROMから直接参照すれば充分で、わざわざRAMにコピー(_strcpy_r0_r1サブルーチン)するのは無駄です。

 その回避策として、文字列型定数ラベルの宣言と参照ができるよう拡張しておきました(下コード例)。

a362_blkytlab.png

 text labelブロックで文字列型定数へのアドレスラベルを宣言して、pointer toブロックで、アドレスラベルを文字列として参照したコード例です。変換後のアセンブラソースリストは各自確認して見てください。

プログラム

 SNDG1PBユニットを制御して、Moscoviumで音楽演奏🎷を実行するプログラムを以下にリンクしておきます。

  完成プログラム:play_mml.bxml

※ブラウザによっては、XMLファイルをレンダリングして表示してしまうため、拡張子を.bxmlとしてあります。

 Blockly for MoscoviumのXMLタブに貼り付けて、ご利用ください。コンパイル手順は、こちらを参照してください。コンパイルしてMoscoviumマイコンへ書き込むと、シリアルモニタから以下のコマンドを受け付ける様になっています。

  シリアルモニタコマンド仕様:

 なお、SNDG1PBユニットに対応した、最新版のBlockly for Moscoviumが必要です。Blockly for Moscovium開発環境の構築および更新に関しては、こちらの記事をご覧ください。

実験の演奏会

 SNDG1PBユニットを搭載したMBOC115GS3208マイコンおよび、こちらのプログラムを書き込んだCmod A7ボードと、パッシブブザー回路を以下表に従って接続してください。

Cmod A7ボード 接続 パッシブブザー回路
VU(5V) Vcc
GND GND
sndg0_pwm PWM0
sndg1_pwm PWM1

※Vccには、VCC3V3(3.3V電源)を接続してもOKです。5V電源と比べると、電流量が減少して音量が下がるので、回路定数で調整してください。

 以下図に実験中の様子を示します。

a362_expr.jpg


 では、サンプルに従って実験して見ましょう。

  実験サンプル:【 】内はシリアルモニタからの送信データ
  【,C44,D44,E44,F44,G44,A44,B44,C54】
  OK: short-cut,C44,D44,E44,F44,G44,A44,B44,C54

 「ドレミファソラシド」の音階を演奏してみました。ちゃんと音階が聞こえましたか?


 次に、いくつか簡単な効果音を試しておきます。

  【,A516,F516,A516,F58.】 …… 「ピポ・ピポン」(正解!)
  OK: short-cut,A516,F516,A516,F58.

  【,C#416,C#48.】 …… 「ブ・ブー」(不正解)
  OK: short-cut,C#416,C#48.


 さて、停車した救急車のサイレン音は「B44,G44」らしいです。こちらに向かって走って来る救急車のサイレン音は、ドップラー効果によって、異なる周波数(音)に聞こえます。

 MMLで演奏して確かめてみましょう。

  【,C54,G#44,C54,G#44,B44,G44,Bb44,Gb44,Bb44,Gb44】
  OK: short-cut,C54,G#44,C54,G#44,B44,G44,Bb44,Gb44,Bb44,Gb44

 それらしく聴こえたでしょうか?


 続いて、簡単な曲を演奏してみましょう。Tera Term等、テキストファイルを送信可能な通信ソフトウェアを使って、MMLファイルを送信します。
 昔作ったMMLファイルと、今回新たに起こしたMMLファイルを、以下表にまとめておきますのでお試しください。

#5-8 MMLで音楽を奏でる 備考
1) きらきら星  
2) カエルの合唱  
3) めだかの学校  
#13-3 MMLで三和音を演奏する(仕上げ) 備考
4) Ardious 二和音(2チャンネル使用)版
5) エリーゼのために 二和音(2チャンネル使用)版
今回作成 備考
6) Happy Birth Day 二和音(2チャンネル使用)版
7) カエルの合唱(二輪唱) 二輪唱(2チャンネル使用)版
8) 威風堂々 二和音(2チャンネル使用)版


  【play】
  OK+ receiving mml... ('end' to exit receive)
  :
  : (中略)
  :
  【end】
  OK+ start play
  :
  : (中略)
  :
  OK: exit play 315[byte]

 昔、Arduino UNOとTFTシールドで作った自作ゲーム(Ardious)の開幕テーマ曲と効果音を演奏してみました(上表の4)。二和音版なので、2個のパッシブブザーから協調して異なる音が演奏されたはずです。


 以下動画で、実際にSNDG1PBユニットを使って演奏した音楽をお聞きいただけます。



 MMLファイル(二和音版エリーゼのために)が、上動画のBGMとして流れています。音楽演奏可能なWindowsソフトウェアなどで演奏させたのではなく、実際にCmod A7ボードとパッシブブザー×2個、SNDG1PBユニットで演奏した曲を録音した音源です。
 楽譜などから起こしたMML(音楽)を演奏できる事もGoodなのですが、アラーム音や効果音など、ユーザインターフェイスとしての使い道も開けました。


 通常のマイコンボードでは、汎用タイマや割り込みなどのソフトウェア技術を総動員して音楽演奏していたのですが、今回は音楽演奏専用ハードウェアを設計して使ったので、ソフトウェア側の負荷は軽くなっています。昨今ではFPGAボード(中華製は【非推奨】)が安価に入手できるので、ハードウェア(RTL)設計を嗜んでおくと、出来る事の幅が広がるんです\(1^−^)/。


btn_arduino.png

btn_prev.png btn_next.png

home