プログラムはこんな感じです。
・BGM01.BAS(MSX2,MSX2+,MSX turboR)
10 DEFINT A-Z:DIM BG$(8)
20 FOR I=0 TO 8: READ BG$(I):NEXT
30 ON INTERVAL=80 GOSUB 90:BG=0
40 INTERVAL ON
50 '
60 PRINT BG;
70 IF INKEY$="" THEN 60 ELSE END
80 '
90 PLAY BG$(BG)
100 BG=BGMOD8+1:RETURN
110 '
120 DATA T180L4o5s9m8500
130 DATA d2o4a2o5,eo4ar2
140 DATA o5e2o4a2o5,fdr4d8d8
150 DATA c+dr4d8d8,efd.d8
160 DATA gfed,dc+r2
20 FOR I=0 TO 8: READ BG$(I):NEXT
30 ON INTERVAL=80 GOSUB 90:BG=0
40 INTERVAL ON
50 '
60 PRINT BG;
70 IF INKEY$="" THEN 60 ELSE END
80 '
90 PLAY BG$(BG)
100 BG=BGMOD8+1:RETURN
110 '
120 DATA T180L4o5s9m8500
130 DATA d2o4a2o5,eo4ar2
140 DATA o5e2o4a2o5,fdr4d8d8
150 DATA c+dr4d8d8,efd.d8
160 DATA gfed,dc+r2
・実行画面(SCREEN0で実行)
・解説
10 文字列の定義
20 BGMデータの読み取り
30 一定の時間ごとに割り込み処理する行番号の指定
40 割り込み処理の開始
60~70 メインルーチン
90~100 割り込み処理(BGMの演奏)
120~160 BGMデータ
・BGMデータのつくり方
T<テンポ>は1分間に演奏する4分音符の数です。T180の場合、4分音符一つは60秒/180つまり20/60秒となります。このプログラムでは、T180の4分音符4個分のデータで区切っていますので、PLAY命令が1回で演奏する時間は80/60秒となります。
・割り込み処理について
ON INTERVAL GOSUB命令は、一定の時間ごとに実行する行番号を指定します。時間は1/60秒単位で指定できます。このプログラムでは、PLAY命令の1回の演奏時間が80/60秒なので、
ON INTERVAL=80 GOSUB 90
としています。
INTERVAL ON命令で、割り込み処理を開始しています。
・割り込み処理(BGMの演奏)
行番号90で、PLAY命令を実行し演奏しています。
行番号100では、次に演奏するデータを計算しています。
BG$(0)にはMMLの初期設定が入っていますので、BG=8を演奏した後はBG=1にします。
このプログラムでは、
IF BG=8 THEN BG=1 ELSE BG=BG+1
という処理をMOD(割り算の余り)を使って、
BG=BG MOD 8 +1
で計算しています。この方が処理が速く、メモリの節約にもなります。
F-BASICにも、ON INTERVAL GOSUB命令はあるのですが、1秒単位での指定だったため、BGMデータを作る際、音楽のテンポなどを考慮しなければなりませんでした。
MSX-BASICは1/60秒単位なので、かなり使いやすいと思います。
また、一定の間隔で演奏するため、BGMデータの最後がR<休止>の時は省略できます。
"eo4ar2" → "eo4a"
実際に、BASICでゲームなどにBGMを組み込むと、PLAY命令のバッファが溜まってきて、他のプログラムが動かなくなる場合が多々あります。休止の部分を削除してPLAY命令のバッファが溜まらないように工夫したり、INTERVALの間隔を少し増やして調整してみましょう。
・動画
https://youtu.be/eZv3y_suIdk
0 件のコメント:
コメントを投稿