「MML」とは「Music Macro Language」の略。マイコン少年ならPLAY文やMUSIC文で憶えている人も多いかもしれないね。カンタンに言えば、コンピューターで音楽の譜面を表わす記法というところ。
残念ながらプチコンには付属していないこの機能だけど、プチコンのBEEP命令を使ってMMLを再現したツワモノがいるぞ。
プログラムをRUNしてみると、自動的に音楽が再生されるだろう。この音楽が実はプログラム内で「MML形式で」書かれているのだ(26~34行目)。もちろんこの部分を書き換えればオリジナルの楽曲も鳴らせるぞ。
- ’┌───────────────────┐
- ’│MML v1.0 │
- ’├───────────────────┤
- ’│C,D,E,F,G,A,B,C#―A#│
- ’│L1,L2,L4,L8,L16,L32│
- ’│O0―4,<,>,@0―127 │
- ’│P0―127,V0―V127 │
- ’├───────────────────┤
- ’│ミシ゛ッソウ │
- ’│Tempo,Loop,[],Key │
- ’└───────────────────┘
- VISIBLE 1,1,0,0,0,0
- CLS
- CLEAR
- PRINT”┌───────────────┐”
- PRINT”│MML PLAYER v1.0│”
- PRINT”└───────────────┘”
- ’---8マテ゛(オオキイトテンホ゜オチル)
- MMLTR=8
- PRINT”1)MMLシステムショキカ”
- GOSUB @MMLRESET
- ’---エンソウテ゛-タ
- @BGM1
- DATA”@16CDEFGAB<C>”
- DATA”@18V50P127CRCRGRGR”
- DATA”@30P32GFDBGFCA”
- DATA”@19L16C<C>C<C>C<C>C<C>”
- ’---
- DATA”@31L16CRRRRRRRCRRRRRRR”
- DATA”@53L16RRRRCRRRRRRRCRRC”
- DATA”V30@54L16RCCCRCCCRCCCRCCR”
- DATA”@48L16RRRRRRRRRRRRRRCC”
- ’---
- PRINT”2)BGMテ゛-タセッテイ”
- RESTORE @BGM1
- GOSUB @MMLSET
- FOR T=0 TO MMLTR-1
- PRINT ” ”;T;”:”;MML$(T)
- NEXT
- ’┌───────┐
- ’│メインル-フ゜│
- ’└───────┘
- PRINT”3)BGMエンソウチュウ”
- STY=CSRY
- ’MLOOP=FALSE
- ’---
- @LOOP
- ’ GOSUB @PUTSTAT
- GOSUB @MMLPLAY
- VSYNC 1
- GOTO @LOOP
- END
- ’---トラックスウカ゛オオイトキハツカワナイコト
- @PUTSTAT
- LOCATE 0,STY
- FOR T=0 TO MMLTR-1
- PRINT ” ”;T;”=”;
- PRINT CH(T,_MI);” ”
- NEXT
- RETURN
- ’┌───────┐
- ’│MMLエンソウ│
- ’└───────┘
- @MMLPLAY
- FOR T=0 TO MMLTR-1
- GOSUB @MMLSUB
- NEXT
- RETURN
- ’---1トラックコ゛トエンソウ
- @MMLSUB
- IF CH(T,_MS)==0 THEN RETURN
- ’---ナカ゛サカクニン
- L=CH(T,_MLC)-1
- CH(T,_MLC)=L
- IF L>0 THEN RETURN
- ’---ノ-トマテ゛クリカエス
- @CMDLOOP
- GOSUB @MMLGET
- IF C$==”” THEN RETURN
- ’---コマント゛コ゛トノショリヘ
- IF C$==”L” THEN @MCLEN
- IF C$==”O” THEN @MCOCT
- IF C$==”V” THEN @MCVOL
- IF C$==”P” THEN @MCPAN
- IF C$==”@” THEN @MCVCE
- IF C$==”R” THEN @MCRR
- IF C$==”<” THEN @MCOUP
- IF C$==”>” THEN @MCODW
- ’---オンテイセッテイ
- NT=ASC(C$)-ASC(”A”)
- IF NT<0 OR NT>7 THEN @MCERR
- NT=MNOTE(NT)
- ’---ツキ゛ハ#カ?
- GOSUB @MMLCHK
- IF C$!=”#” THEN @MNOTE
- NT=NT+1
- GOSUB @MMLNEXT
- ’---
- @MNOTE
- CH(T,_MN)=NT
- ’---オクタ-フ゛コウリョ
- OC=CH(T,_MO)-2
- NT=NT+(OC*12)
- ’---オトヲナラス
- VC=CH(T,_MX)
- VL=CH(T,_MV)
- PN=CH(T,_MP)
- NT=NT*MPLEN
- BEEP VC,NT,VL,PN
- ’---ナカ゛サヲイレテヌケル
- @MCRR
- CH(T,_MLC)=CH(T,_ML)
- RETURN
- ’---エラ-
- @MCERR
- PRINT”オカシナMMLテ゛ス(”;C$;”)”
- END
- ’---ナカ゛サヘンカ
- @MCLEN
- GOSUB @MNGET
- I=_L32:IF N==32 THEN @MCLSET
- I=_L16:IF N==16 THEN @MCLSET
- I=_L8:IF N==8 THEN @MCLSET
- I=_L4:IF N==4 THEN @MCLSET
- I=_L2:IF N==2 THEN @MCLSET
- I=_L1:IF N==1 THEN @MCLSET
- GOTO @MCERR
- ’---
- @MCLSET
- CH(T,_ML)=MLEN(I)
- GOTO @CMDLOOP
- ’---オクタ-フ゛ヘンカ
- @MCOCT
- GOSUB @MNGET
- CH(T,_MO)=N
- GOTO @CMDLOOP
- @MCOUP
- CH(T,_MO)=CH(T,_MO)+1
- GOTO @CMDLOOP
- @MCODW
- CH(T,_MO)=CH(T,_MO)-1
- GOTO @CMDLOOP
- ’---オンリョウヘンカ
- @MCVOL
- GOSUB @MNGET
- CH(T,_MV)=N
- GOTO @CMDLOOP
- ’---ハ゜ンホ゜ットヘンカ
- @MCPAN
- GOSUB @MNGET
- CH(T,_MP)=N
- GOTO @CMDLOOP
- ’---オンショクヘンカ
- @MCVCE
- GOSUB @MNGET
- CH(T,_MX)=N
- GOTO @CMDLOOP
- ’---ツキ゛ノコマント゛サキヨミ
- @MMLCHK
- I=CH(T,_MI)
- C$=MID$(MML$(T),I,1)
- RETURN
- ’---ヨミコミイチヘンコウ
- @MMLNEXT
- I=I+1
- IF I>=CH(T,_MS) THEN I=0
- CH(T,_MI)=I
- RETURN
- ’---コマント゛シュトク
- @MMLGET
- I=CH(T,_MI)
- IF I==CH(T,_MS) THEN @MCHKLOOP
- ’---コマント゛
- CH(T,_MI)=I+1
- C$=MID$(MML$(T),I,1)
- RETURN
- ’---キョクセ゛ンタイル-フ゜?
- @MCHKLOOP
- IF MLOOP==FALSE THEN @MMLTEND
- CH(T,_MI)=0
- GOTO @MMLGET
- ’---トラックオワリ
- @MMLTEND
- C$=””:CH(T,_MS)=0
- RETURN
- ’---スウシ゛シュトク
- @MNGET
- N=0:NC=0
- ’---
- @MNLOOP
- GOSUB @MNCHK
- IF R==FALSE THEN @MNEXIT
- N=N*10+(C-ASC(”0”))
- ’---ツキ゛ヘススメル
- I=I+1
- IF I!=CH(T,_MS) THEN @MNSKIP
- IF MLOOP==FALSE THEN RETURN
- I=0
- @MNSKIP
- CH(T,_MI)=I
- NC=NC+1
- GOTO @MNLOOP
- ’---
- @MNEXIT
- IF NC THEN RETURN
- C$=”NUM”
- GOTO @MCERR
- ’---ツキ゛ハスウシ゛カ?
- @MNCHK
- I=CH(T,_MI)
- C=ASC(MID$(MML$(T),I,1))
- R=C>=ASC(”0”) AND C<=ASC(”9”)
- RETURN
- ’┌───────┐
- ’│MMLショキカ│
- ’└───────┘
- @MMLRESET
- RESTORE @MMLRESET
- IF TRMAX>8 THEN TRMAX=8
- ’---ナカ゛サ(32,16,8,4,2,1)
- DIM MLEN(6)
- L=3
- FOR I=0 TO 5
- MLEN(I)=L
- L=L*2
- NEXT
- _L32=0
- _L16=1
- _L8=2
- _L4=3
- _L2=4
- _L1=5
- ’---ハンオンノナカ゛サ
- MPLEN=FLOOR(4096/12)
- ’---セ゛ンタイノヨウソ
- MLOOP=TRUE
- MTEMPO=120
- MTMPCNT=0
- ’---ノ-トヨウ(ABCDEFG)
- DIM MNOTE(7)
- DATA 9,11,0,2,4,5,7
- FOR I=0 TO 6
- READ MNOTE(I)
- NEXT
- ’---エンソウヨウノワ-クテイキ゛
- _ML=0:’ナカ゛サ
- _MO=1:’オクタ-フ゛
- _MN=2:’オンテイ
- _MK=3:’キ-
- _MV=4:’ホ゛リュ-ム
- _MP=5:’ハ゜ンホ゜ット
- _MS=6:’サイス゛
- _MX=7:’オンショク
- _MLC=8:’ナカ゛サカウンタ
- _MI=9:’オフセット
- _MMAX=10
- DIM MML$(MMLTR)
- DIM CH(MMLTR,_MMAX)
- ’---ワ-クリセット
- FOR T=0 TO TR-1
- CH(T,_MS)=0
- NEXT
- RETURN
- ’┌───────┐
- ’│MMLセッテイ│
- ’└───────┘
- @MMLSET
- FOR T=0 TO MMLTR-1
- READ MML$(T)
- CH(T,_MS)=LEN(MML$(T))
- CH(T,_ML)=MLEN(_L4)
- CH(T,_MLC)=0
- CH(T,_MO)=2
- CH(T,_MN)=0
- CH(T,_MK)=0
- CH(T,_MV)=100
- CH(T,_MP)=64
- CH(T,_MX)=16+T
- NEXT
- RETURN