NEWS

IchigoJamで電子楽器を操作#9(MML解読プログラムを作るに脱線)

2022.6.3

前回のプログラムでほぼ完成したMMLプログラムですが、ちょっと問題ありなんですよね。
プログラムを見ると

20 Z="CDEC4D4E4"

になってて、ここにMMLで音符を入力していきます。この1行だけに楽譜を入れるって、ちょっと短すぎますよね。そのため、今回はもっと長く楽譜を入力できるようにすることと、もうちょっと見やすいプログラムに変更してみました。途中経過はまったくありません、一気に大規模改修ですm(__)m
以下のプログラムがすべてになりますが、反転している文字は「デバッグ用」です。ちゃんとMMLが解読できているか調べるために入れています。MIDIで使うときは消してください。あと、VIDEO 0を使った方がテンポが安定します。

10 'MML-MIDI
20 BPS 312500:UART 3
30 CLV:T=100:O=60
40 LET [65],9,11,0,2,4,5,7
50 [0]="CDEFGAB>C<"
60 [1]="C4C4.C8C8.C16C16."
70 [2]="C4.C8.C16.C32."
80 [3]="C+D+C+8D+16"
90 [4]="C+4.D+8.E+16."
100 IF 4<I END ELSE A=[I]:? I
110 @LOOP:M=PEEK(A):L=0
120 IF M==0 I=I+1:GOTO 100
130 IF (64<M AND M<72) OR R==114 GOTO @MML_START
140 O=O+((M==62)-(M=60))*12
150 A=A+1:GOTO @LOOP
160 @MML_START
170 N=[M]
180 A=A+1:M=PEEK(A)
190 IF M==43 OR M==45 N=N+(M==43)-(M==45):GOTO 180
200 IF 47<M AND M<58 GOTO @LEN
210 @VOICE
220 IF L==0 W=T/4
230 '? CHR$(#90,N+O,127):WAIT W
240 '? CHR$(#90,N+O,0)
250 ? "NOTE:";N+O,"LEN:";W
260 GOTO @LOOP
270 @LEN
280 L=(L*10)+(M-48)
290 A=A+1:M=PEEK(A)
300 IF 47<M AND M<58 GOTO 280
310 W=T/L
320 IF M==46 W=W+W/2
330 GOTO @VOICE

突然の大改修で目が回っているかもしれませんが、まずはこのプログラムを入力してみましょう。ラベル機能を使ったので簡単な説明を入れておきます。

110 @LOOP:M=PEEK(A):L=0

160 @MML_START

210 @VOICE

270 @LEN

以下のようにで始まる文字をラベルと言って、GOTO行番号ではなくラベルを指定できるようになります。

260 GOTO @LOOP

330 GOTO @VOICE

こんな感じです。行番号の場合RENUMで変わったり、削除したりすることがあるので、GOTOも書き換えが必要になるときがあります。でもラベルなら、自分で名前を変えない限り、ずっとそのままで大丈夫です。それに、名前に意味を付けておけば分かりやすくなります
今回のプログラムでは

  • @LOOP:MMLを繰り返して読み込む
  • @MML_START:アルファベットが見つかったのでMMLの解読を始める
  • @VOICE:音を出す
  • @LEN:音の長さを解読する

このようなラベル名と意味を付けました。そして、肝心なMML部分は配列を使って長い音楽にも対応しました。

50 [0]="CDEFGAB>C<"
60 [1]="C4C4.C8C8.C16C16."
70 [2]="C4.C8.C16.C32."
80 [3]="C+D+C+8D+16"
90 [4]="C+4.D+8.E+16."
100 IF 4<I END ELSE A=[I]:? I

50行から90行が音符(楽譜)になります。配列[0]~[4]に入れていますが、もっと大きな配列にしても大丈夫です。だたし、最後の配列番号を教えてあげないといけません。それが100行に書いてあります。このプログラムでは配列番号の最後は4です。なので配列[5]を読み込もうと思ったら終了するようにIF 4<Iと条件を入れています。ちなみに配列番号[65]以降はノート番号が入っているので、最大の配列は[64]までとなります。
あとワンポイントとして、30行に初期値を入れています。

30 CLV:T=100:O=60

Tはテンポですが、音楽のように4分音符を基準としたものではなく「全音符の時にWAITでどれだけ待つか」を決めています。もしT=60なら全音符は1秒音が出ます。次のOはオクターブ。前にも説明しましたが、ピアノの真ん中あたりにあるドが60です。これを初期値として始まります。
もう一つ、220行に初期値のようなものとして音の長さを省略したときに、どの程度の長さにするか決めています。

220 IF L==0 W=T/4

このプログラムでは音長省略時は4分音符としているので「T/4」としています。8分音符が多い楽譜の場合は、ここの「4」を8にすれば8分音符になってMML作成が楽になります。

さて、これでMML解析プログラムは終了。
こうやってプログラムを作ると言うのは、どうやって作るかを教えてもらうのではなく、たくさんある命令をどんな順番で書けばいいか考えて、何度も失敗して作っていくものです。だからたくさん失敗しましょう。「コピーはダメ」と言う人いるけど、公開されてるなら、他人が作ったプログラムをたくさん見てマネしてください。失敗だけでなく成功の経験値も必要です。早い話が、

たくさんキーを叩いて、たくさんプログラムを作ればいい。

それだけ。

以下のリンクをクリックするとIchigoJamWebでこのプログラムが実行できます。278バイトの空きメモリがあるので、そこそこ入力できると思います。

IchigoJamWebへ