Pyxel 2.4版のMMLで音楽を再生する


<2026-03-22 追記>
 本記事は2.4版時の紹介です。MMLについては公式サイトのユーザーガイドを参照してください.。

Pyxel User Guide ー リンク集 ドキュメント - Pyxel MML コマンド


 

Pyxel BGMをMMLで設定する

 2025-07-04リリースの Pyxel 2.4 でサウンドエンジンとMMLの文法が新しくなりました。
 2.3版でのMMLからパラメータの値の範囲などが変わっていますので,2.4版でMMLを使用する場合の参考にしてください。

 2.4への移行方法については公式サイトのFAQを確認してください。
 pyxel/docs/faq-ja.md at main · kitao/pyxel · GitHub
  (新バージョンへの移行方法 - バージョン2.4への移行方法)

<2025-07-10追記>
Web版Pyxelで使用するバージョンを固定する方法が,公式サイトで紹介されています。
https://github.com/kitao/pyxel/blob/main/docs/pyxel-web-ja.md#pyxel-%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%92%E5%9B%BA%E5%AE%9A%E3%81%99%E3%82%8B
「Web 版 Pyxel の使い方-Pyxel のバージョンを固定する」を参照してください。

Web 版 Pyxel はサーバー上の最新版を参照しているため、今後のバージョンアップの内容次第で既存のコードが動作しなくなる可能性があります。
この状況を防ぐには、HTML ファイル内で Pyxel のバージョンを指定し、参照するバージョンを固定してください。
具体的には、Pyxel を読み込むコードで、

<script src="https://cdn.jsdelivr.net/gh/kitao/pyxel@2.4/wasm/pyxel.js"></script>

<script src="https://cdn.jsdelivr.net/gh/kitao/pyxel@2.4.6/wasm/pyxel.js"></script>

のように、固定したいバージョン番号を指定します。

 

MML(Music Macro Language)

 テキスト形式で音楽データを記述できる言語です。
 Music Macro Language - Wikipedia

PyxelのMML仕様

 API仕様(2.4版時の紹介)


・mml(code)
MML (Music Macro Language)の文字列を渡すと MML モードに移行し、その内容に沿ってサウンドが再生されます。MML モードではnotesやspeedなどの通常のパラメータは無視され、mml()で解除できます。
例:pyxel.sounds[0].mml("T120 Q90 @1 V100 O5 L8 C4&CC.C.D16 @VIB1{10,20,20} E2C2")

 MMLの詳細
 pyxel/docs/faq-ja.md at main · kitao/pyxel · GitHub

 Pyxel よくある質問 - API 仕様と使い方 - PyxelのMMLの使い方を教えてください


Sound クラスのmml関数に MML (Music Macro Language) 文字列を渡すと、MML モードに移行し、その内容に沿ってサウンドが再生されるようになります。
MML モードでは、notesやspeedなどの通常のパラメータは無視され、指定した文字列の内容に沿ってサウンドが再生されます。mml()を呼ぶと MML モードをリセットできます。
play関数にサウンド番号の代わりに直接 MML 文字列を渡して再生することもできます。
例:pyxel.play(0, "CDEFG")

 
<2026-02-01 追記 公式サイトコマンド一覧を参照してください>




 

コマンドの例

コマンド
(範囲)
記述例 内容
T (1-) T150 テンポ (BPM) を指定する。デフォルトは 120。(1分間に何回拍があるかの数値なので高いほうが速い)
Q (0-100) Q100 cdef Q30 ggg2 発音する長さをパーセントで指定する。100 で音の切れ目がなくなり,0 だと発音されない。デフォルトは 80。(ゲート,ゲートタイム)
@ (0-) @0 音色 (初期状態では 0:Triangle / 1:Square / 2:Pulse / 3:Noise) を指定する。デフォルトは 0。(レトロゲームサウンドでは,メロディー:Pulse/Square,ベース:Triangle,ドラム:Noise で用いることが多いそうです)
V (0-127) V100 音量を指定する。デフォルトは 100。
K (整数) cde2 K1 cde2 トランスポーズ量(音程オフセット)を半音単位で指定する。12 で音程が 1 オクターブ上がる。デフォルトは 0。(移調)
Y (整数) cde2 Y60 cde2 デチューン(音程ずれ)を cent 単位で指定する。100 で半音上がり,-100 で半音下がる。デフォルトは 0。
O (-1 - 9) O4 cde2 O5 cde2 オクターブを指定する。O4の A の音が 440 Hz になる。デフォルトは 4。
> cdefgab>cdefgab オクターブを 1 上げる。最大 9。
< b<b>fg オクターブを 1 下げる。最小 -1。
L (1-192) cde2 L8 cde2 音符と休符のデフォルトの長さを指定する。L4 が 4 分音符。デフォルトは 4。
C/D/E/F/G/A/B cdefedc2 指定した音階の音を再生する。(c ド,d レ,e ミ,f ファ,g ソ,a ラ,b シ)
F16の様に後ろに 1/2/4/8/16/32 の数値を指定すると,その音だけ長さを切り替える。
R crcr 休符を再生する。
R8の様に休符の後ろに 1/2/4/8/16/32 の数値を指定すると、その休符だけ長さを切り替える。
#または+ a#
d+
音の後ろに記述すると、その音を半音上げる。
- >c<a8b-8>cdc2<ar 音の後ろに記述すると、その音を半音下げる。
. cccd.e8deefg2. 付点。音の後ろに記述すると、その音の長さを 1/2 延ばす。
& c4c8r8 c4&c8r8 タイ。同じ音程の次の音を一つの音として繋げる。異なる高さの音に指定するとエラーになる(Pyxel 2.3版と異なるので注意)。
 2026-02-01追記
 2.5.13版からスラーとしても使えるようになりました。
 ・異なる音程を繋ぐとスラー(レガート、音の切れ目なし)になります。
 ・C4&16のように長さのみを指定することも可能。

[ ] (1-) [cde2]4 [ 繰り返す内容 ] 回数 で間のフレーズを指定した回数だけ再生する。回数を省略した場合は無限に繰り返す。入れ子にすることも可能。

エンベロープ,ビブラート,グライド

 Pyxel MMLではより細かい表現ができるコマンドが用意されています。

コマンド(範囲) 内容
@ENV (0-) エンベロープ(音量変化のカーブ)のスロットを切り替える。0 を指定するとオフになる。
@ENV { init_vol, dur_ticks1, vol1, dur_ticks2, vol2, ... } 指定したスロットのエンベロープを設定して切り替える。スロット 0 は指定できない。
{ }内は、「初期音量 (最初の 1 回のみ)」の後,「区間の長さ (tick)、音量 (vol)」を繰り返し指定する。1 tick は 4 分音符を 48 等分した長さ。
例:@ENV 1 { 30, 20, 100, 50, 0 }(音量を 30 から 20 tick かけて 100 にした後, 50 tick かけて 0 に変化させる)
@VIB (0-) ビブラート(音程を揺らすエフェクト)のスロットを切り替える。0 を指定するとオフになる。
@VIB { delay_ticks, period_ticks, depth_cents } 指定したスロットのビブラートを設定して切り替える。スロット 0 は指定できない。
{ }内は「ディレイ時間 (tick)、周期 (tick)、深さ (cent)」をこの順で指定する。1 tick は 4 分音符を 48 等分した長さ。
例:@VIB 1 {24, 12, 100}(24 tick 経過後、12 tick 周期でプラス半音からマイナス半音の範囲で音程を揺らす)
@GLI (0-) グライド(音程変化のエフェクト)のスロットを切り替える。0 を指定するとオフになる。
@GLI { offset_cents, dur_ticks } { }内は「最初の音程変化量 (cent)、0 に戻るまでの時間 (tick)」を指定する。1 tick は 4 分音符を 48 等分した長さ。
各パラメータに*を指定すると、音程変化量は前回の音程からの差分、変化時間は各音の再生時間が自動的に適用される。
例:@GLI 1 { -100, 24 }(半音下から始まり、24 tick かけて本来の音程に戻る)

記述例

import pyxel
pyxel.init(128, 128)
        
# mmlメソッドでMMLを登録
# エンベロープ(音量変化のカーブ)
pyxel.sounds[0].mml( "@ENV1{120,36,0} cde2 @ENV0 cde2" )
# ビブラート(音程を揺らすエフェクト)
pyxel.sounds[1].mml( "@VIB1{24,12,100} cde2 @VIB0 cde2" )
# グライド(音程変化のエフェクト)
pyxel.sounds[2].mml( "@GLI1{-100,24} cde2 @GLI0 cde2" )

# ミュージック0の ch0にサウンド0,1,2を登録(連続再生)
pyxel.musics[0].set([0,1,2])

# ミュージックを再生 playm(msc, [sec], [loop])
pyxel.playm(0,loop=False)

pyxel.show() # Escキーで終了
公式サンプル

 公式サンプルではシューティングゲームのコード内にMMLの再生について記述されています。(Appクラス内 init_sound() 参照)
 pyxel/python/pyxel/examples/09_shooter.py at main · kitao/pyxel · GitHub

 

MMLを再生するプログラム例

Pyxelではサウンドとミュージックの2つの項目があります。(Pyxel BGMの再生 - 勉強ボックス管理者ブログ)を参照してください。

項目 内容
サウンド(0~63) 音を格納するオブジェクト。MMLメソッドでここに音楽を設定する。0番目から63番目までの64個設定可能。pyxel.play()メソッドでサウンドを指定して再生することができます。
ミュージック(0~7) ミュージックには複数のサウンドを組み合わせて登録することができます。pyxel.playm()メソッドでミュージックを指定して再生することができます。

 

サウンドを再生する例

 0番目のサウンドにMMLで記述した音楽を設定し,Pキーが押されたときに再生するプログラムの例です。(初期処理でサウンドを作成しておき,ゲーム中にplay()メソッドで再生)

import pyxel
pyxel.init(128, 128)

# mmlメソッドでMMLを登録
pyxel.sounds[0].mml( "T100 Q80 @0 O4 V120 L4 cdefgab>cdefgab>c" )

def update():
    if pyxel.btn(pyxel.KEY_P):
        # サウンドを再生 play(ch, snd, [sec], [loop], [resume])
        pyxel.play(0,0,loop=False)
    return

def draw():
    pyxel.cls(0)
    pyxel.text(10,10,"Press P to play.",7)
    return

pyxel.run(update, draw)

・play(ch, snd, [sec], [loop], [resume])
 チャンネルch (0-3) でサウンドsnd (0-63) を再生します。sndがリストの場合順に再生されます。secで再生開始位置を秒単位で指定できます(Pyxel 2.4変更点)。

 MMLの記述は空白を入れたり複数行に分けて記述することもできます(※文字列は連結してメソッドに渡す)。

import pyxel
pyxel.init(128, 128)

# mmlメソッドでMMLを登録
pyxel.sounds[0].mml( "T100 Q80 @0 O4 V120 L4" +
                     "cdefedcr efgagfer" +
                     "crcrcrcr c8c8d8d8 e8e8f8f8 edcr" )

# サウンドを再生 play(ch, snd, [sec], [loop], [resume])
pyxel.play(0,0,loop=False)

pyxel.show() # Escキーで終了

 

ミュージックを再生する例

 複数のサウンドを同時に再生する例です。(ミュージッククラスのset()メソッドでサウンドを登録して,playm()メソッドで再生)

import pyxel
pyxel.init(128, 128)

# mmlメソッドでMMLを登録
# サウンド0 メロディー
pyxel.sounds[0].mml( "T100 Q80 @1 O4 V120 L4" +
                     "cdefedcr efgagfer" +
                     "crcrcrcr c8c8d8d8 e8e8f8f8 edcr" )

# サウンド1とサウンド2で伴奏
pyxel.sounds[1].mml( "T100 Q80 @0 O3 V80 L2" +
                     "gggg gggg" +
                     "gggg gggg")

pyxel.sounds[2].mml( "T100 Q80 @0 O3 V80 L2" +
                     "cccc cccc" +
                     "cccc cccc")

# ミュージック0の ch0にサウンド0 ch1とch2に伴奏を登録
pyxel.musics[0].set([0],[1],[2])

# ミュージックを再生 playm(msc, [sec], [loop])
pyxel.playm(0,loop=False)

pyxel.show() # Escキーで終了

・ミュージッククラス set(snds0, snds1, snds2, ...)
 チャンネルのサウンド (0-63) のリストを設定します。空リストを指定するとそのチャンネルは再生に使用しません。
 snds0 ch0 のサウンドをリストで指定
 snds1 ch1 のサウンドをリストで指定
 snds2 ch2 のサウンドをリストで指定
 snds3 ch3 のサウンドをリストで指定
 使用例 pyxel.music[0].set([0, 1], [2, 3], [4])
・playm(msc, [sec], [loop])
 ミュージックmsc (0-7) を再生します。secで再生開始位置を秒単位で指定できます(Pyxel 2.4変更点)。loopにTrueを指定するとループ再生します。

 

音楽ファイルの出力

 save()メソッドを使うと,Pyxelで設定したサウンドやミュージックをWAVファイルに保存することができます。(FFmpegを利用できる環境ではMP4ファイル出力も可能です。実行ユーザーの環境変数 Path にffmpeg\bin の場所が設定されている必要があります)

音楽ファイルを出力するプログラム例

import pyxel
pyxel.init(128, 128)
pyxel.sounds[0].mml( "T100 Q80 @1 O4 V120 L4 cdefedcr efgagfer crcrcrcr c8c8d8d8 e8e8f8f8 edcr" )
pyxel.sounds[1].mml( "T100 Q80 @0 O3 V80 L2 gggg gggg gggg gggg")
pyxel.sounds[2].mml( "T100 Q80 @0 O3 V80 L2 cccc cccc cccc cccc")
pyxel.musics[0].set([0],[1],[2])

sec = pyxel.sounds[0].total_sec() # サウンドの再生時間を取得

# サウンドのファイル出力
# save(filename, sec, [ffmpeg])
pyxel.sounds[0].save("snd0", sec) # snd0.wav
#pyxel.sounds[0].save("snd0", sec, ffmpeg=True) # snd0.wav , snd0.mp4

# ミュージックのファイル出力
# save(filename, sec, [ffmpeg])
pyxel.musics[0].save("msc0", sec) # msc0.wav
#pyxel.musics[0].save("msc0", sec, ffmpeg=True) # msc0.wav , msc0.mp4

pyxel.quit()

・サウンドクラス total_sec()
 サウンドの再生時間を秒で返します。MMLで無限ループが使用されている場合は None を返します。
・サウンドクラス save(filename, sec, [ffmpeg])
・ミュージッククラス save(filename, sec, [ffmpeg])
 filename ファイル名を文字列で指定します。(拡張子は自動で付加)
 sec 再生秒数を指定します。(float値)
 ffmpeg 省略するとWAVファイルが作成されます。Trueを指定すると,FFmpegを実行するウィンドウが起動してMP4ファイルも作成されます。

 save()メソッドの引数は2.3版での回数指定から,再生秒数指定に変更になっていますので注意してください。

 

参考ポスト

 MMLを設定する例として,@frenchbread1222 さんの下記ポストなどを参考にしてみてください。


 ・基本編(1/3: 波形と音量変化と音長)
 ・基本編(2/3: 硬い音色と柔らかい音色,ビブラート)
 ・基本編(3/3: ベースとドラム)
 ・応用編(1/3: 三角波を使ったタム回し)※ロックマン2より
 ・応用編(2/3: 擬似ディレイ) ← アルペジオ+ディレイ
 ・応用編(3/3:ディレイ+デチューン)

 

MMLの作り方参考サイト

 作曲できるアプリを使用して曲を作り,MML形式で出力させる等が一般的のようです。(「MML 作成」や「MML 作曲」で検索してみてください)

 MML作成講座 https://mabitarumml.web.fc2.com/MML1.html
 MMLで作曲のススメ https://www.youtube.com/watch?v=0l9MUcJXeBE

 
 テキスト音楽「サクラ」 
 直接MMLを書いて再生してみたい場合は,ブラウザで実行できる「ピコサクラ」,Windows用アプリ「テキスト音楽 サクラ」が上記サイトから利用できます。

 
 Short VGM generator by ABA Games
 ABA Gamesさんの短いゲーム音楽を生成するツール
「Select music」で曲を選んで,「Generate」ボタンを押すとランダムで曲が生成されます。※PyxelのMMLと異なるコマンドは適宜置き換える必要があります。
 (補足)生成されたMMLのテキストボックスが画面に表示しきれない場合は,Webブラウザ上で「Tabキー」と「Shiftキー+Tabキー」による要素のフォーカス移動を利用すると,テキストボックスやボタンを移動することができます。


 * 関連記事
kinutani.hateblo.jp