★この記事は「IchigoJam Advent Calendar 2024」に参加しています。
クリスマスにお馴染みの曲「ジングルベル」を、IchigoJamのPLAY命令で奏でてみます。
まずはそのまま演奏
とりあえず普通にプログラムを書くと、
10 PLAY "CAGFC2R2 CAGFD2R2 DA+GFE2R2 <CC>A+GA2R2 CAGFC2R2 CAGFD2R2 DA+GF<CCCC DC>A+GFR<CR >AAARAAAR A<C>F4.G8A2R2 A+A+A+A+A+AAA AGGAGR<CR >AAARAAAR A<C>F4.G8A2R2 A+A+A+A+A+AAA <CC>A+GF2R2"
190文字なので1行に何とか入りますが、何しろ長いので打ちづらいです。
もっと長い曲だったら1行(250文字)に入らないでしょう。
ですので、フレーズ(4小節)で区切ってPLAYしてみます。
10 PLAY "CAGFC2R2 CAGFD2R2":WAIT 470 20 PLAY "DA+GFE2R2 <CC>A+GA2R2":WAIT 470 30 PLAY "CAGFC2R2 CAGFD2R2":WAIT 470 40 PLAY "DA+GF<CCCC DC>A+GFR<CR":WAIT 470 50 PLAY "AAARAAAR A<C>F4.G8A2R2":WAIT 470 60 PLAY "A+A+A+A+A+AAA AGGAGR<CR":WAIT 470 70 PLAY "AAARAAAR A<C>F4.G8A2R2":WAIT 470 80 PLAY "A+A+A+A+A+AAA <CC>A+GF2R2"
PLAY命令は実行するとすぐ次へ行ってしまうので、WAITを入れないと演奏する前に次の行へ行ってしまって、曲になりません。
標準だとテンポ120(T120、1秒間に2拍)なので、4小節(16拍)だと8秒(WAIT 480)待てばよいです。
が、そのまま「WAIT 480」だとIchigoJam環境によっては間延びするので、「WAIT 470」にしています。
正確に前のフレーズ演奏が終わってから次へ行くには、
10 PLAY "CAGFC2R2 CAGFD2R2" 15 IF SOUND() CONT 20 PLAY "DA+GFE2R2 <CC>A+GA2R2" 25 IF SOUND() CONT 30 PLAY "CAGFC2R2 CAGFD2R2" 35 IF SOUND() CONT 40 PLAY "DA+GF<CCCC DC>A+GFR<CR" 45 IF SOUND() CONT 50 PLAY "AAARAAAR A<C>F4.G8A2R2" 55 IF SOUND() CONT 60 PLAY "A+A+A+A+A+AAA AGGAGR<CR" 65 IF SOUND() CONT 70 PLAY "AAARAAAR A<C>F4.G8A2R2" 75 IF SOUND() CONT 80 PLAY "A+A+A+A+A+AAA <CC>A+GF2R2"
と、SOUND関数を使って、演奏終了まで待って次へ行くとよいです。
が、WAITで待つ方が手軽で、プログラムが短くて済みます。
フレーズを使って短縮、文字列指定
フレーズ毎に区切ってみると、10行と30行、50行と70行のフレーズは全く同じなのがわかります。
音楽の曲はこういう構成がよくあります。
この「ジングルベル」なら、フレーズが「A→B→A→C→D→E→D→F」の構成になっていて、実際のフレーズは6種類しかありません。
せっかくなので短縮・簡略化したい所です。
ここで、文字変数をうまく使ってみます。
IchigoJam BASICでは、文字列を変数に代入できます。
A="ABC"
この時、変数Aには何が入るかと言うと、文字列「ABC」が入っているメモリのアドレスが入ります。
(このようにメモリアドレスが入った変数を「ポインタ」と言います)
そして、PLAY命令も文字列だけでなく、文字変数(ポインタ)で音階を指定できます。例えば、
10 A="CDE" 20 PLAY A
で、「PLAY "CDE"」と同じく「ドレミ」が鳴ります。
この文字変数を使って、ジングルベルを演奏してみます。
10 A="CAGFC2R2 CAGFD2R2" 20 B="DA+GFE2R2 <CC>A+GA2R2" 30 C="DA+GF<CCCC DC>A+GFR<CR" 40 D="AAARAAAR A<C>F4.G8A2R2" 50 E="A+A+A+A+A+AAA AGGAGR<CR" 60 F="A+A+A+A+A+AAA <CC>A+GF2R2" 70 PLAY A:WAIT 470 80 PLAY B:WAIT 470 90 PLAY A:WAIT 470 100 PLAY C:WAIT 470 110 PLAY D:WAIT 470 120 PLAY E:WAIT 470 130 PLAY D:WAIT 470 140 PLAY F
MML(音符)を打つのが6フレーズ分で済みますし、演奏部分も順番がわかりやすいです。
が、同じような「PLAY」や「WAIT」を何度も打つのが面倒です。
配列変数を使う
実は文字変数(ポインタ)は配列変数でも使えます。
通常変数を配列変数に置き換えると、
10 [0]="CAGFC2R2 CAGFD2R2" 20 [1]="DA+GFE2R2 <CC>A+GA2R2" 30 [2]="DA+GF<CCCC DC>A+GFR<CR" 40 [3]="AAARAAAR A<C>F4.G8A2R2" 50 [4]="A+A+A+A+A+AAA AGGAGR<CR" 60 [5]="A+A+A+A+A+AAA <CC>A+GF2R2" 70 PLAY [0]:WAIT 470 80 PLAY [1]:WAIT 470 90 PLAY [0]:WAIT 470 100 PLAY [2]:WAIT 470 110 PLAY [3]:WAIT 470 120 PLAY [4]:WAIT 470 130 PLAY [3]:WAIT 470 140 PLAY [5]
MMLを配列変数8個に設定すれば、演奏部分を簡略化できます。
10 [0]="CAGFC2R2 CAGFD2R2" 20 [1]="DA+GFE2R2 <CC>A+GA2R2" 30 [2]=[0] 40 [3]="DA+GF<CCCC DC>A+GFR<CR" 50 [4]="AAARAAAR A<C>F4.G8A2R2" 60 [5]="A+A+A+A+A+AAA AGGAGR<CR" 70 [6]=[4] 80 [7]="A+A+A+A+A+AAA <CC>A+GF2R2" 90 FOR N=0 TO 7 100 PLAY [N]:WAIT 470 110 NEXT
これですっきりした演奏プログラムになりました。
WAITの代わりにSOUND関数を使えば、
10 [0]="CAGFC2R2 CAGFD2R2" 20 [1]="DA+GFE2R2 <CC>A+GA2R2" 30 [2]=[0] 40 [3]="DA+GF<CCCC DC>A+GFR<CR" 50 [4]="AAARAAAR A<C>F4.G8A2R2" 60 [5]="A+A+A+A+A+AAA AGGAGR<CR" 70 [6]=[4] 80 [7]="A+A+A+A+A+AAA <CC>A+GF2R2" 90 FOR N=0 TO 7 100 PLAY [N] 110 IF SOUND() CONT 120 NEXT
こうすると、各フレーズの長さが違う場合や、演奏テンポを変えた場合にも対応できます。
10 [0]="T140CAGFC2R2 CAGFD2R2" 20 [1]="T140DA+GFE2R2 <CC>A+GA2R2" 30 [2]=[0] 40 [3]="T140DA+GF<CCCC DC>A+GFR<CR" 50 [4]="T140AAARAAAR A<C>F4.G8A2R2" 60 [5]="T140A+A+A+A+A+AAA AGGAGR<CR" 70 [6]=[4] 80 [7]="T140A+A+A+A+A+AAA <CC>A+GF2R2" 90 FOR N=0 TO 7 100 PLAY [N] 110 IF SOUND() CONT 120 NEXT
テンポ140(T140)にして速くしてみました。
この方がジングルベルらしいです(^_^)