SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

JavaScriptとFlashによるWebオルゴールの製作

JavaScript MIDIライブラリ「JavaScriptSakura」を使う

  • X ポスト
  • このエントリーをはてなブックマークに追加

JSSの内部(1/2)

JavaScriptについて

 JSSはJavaScriptで記述されていますが、基本的には機能ごとに変数を作り、その中でメソッドやプロパティをカンマで列挙した作りになっています。このような記述スタイルは、JSON(JavaScript Object Notation)と呼ばれ、可読性がすぐれ、名前空間が切れる表記法としてお勧めです。次は、JSSのソースの一部ですが、

var SakuraSMFFormatter = {
  big32: function(value){
    var d = [];
    d[3] = value % 256; value = parseInt(value / 256);
    d[2] = value % 256; value = parseInt(value / 256);
    d[1] = value % 256; value = parseInt(value / 256);
    d[0] = value % 256;
    return d;
  },

(…略…)
  setup: function(midis){
    this.midis = midis;
    this.track_chunks = [];
  }
};

 このとき、SakuraSMFFormatter.big32SakuraSMFFormatter.setupといった関数が使えるようになります。また、SakuraSMFFormatter内部ではthis.big32this.setupという書式で使うことができます。

内部処理ブロック

 JSSでは次の順序でMMLを処理しています。

  1. 字句解析(マクロ展開)
  2. 構文解析
  3. 意味解析
  4. SMF変換
処理内容
ブロック名意味
字句解析MMLをトークンとして切り出す
構文解析トークンを意味のある塊にまとめる
意味解析構文解析された情報を元にMIDIを生成する
SMF変換生成されたMIDIをSMFに変換する

 次項でそれぞれのブロックについて説明します。

字句解析

 JSSは字句解析を変数SakuraLexerの中で実装しています。この機能ブロックは、「マクロ登録/展開」および、「トークン切り出し」をしています。

マクロ登録/展開

 ここで言うマクロとは、意味や構文解析の前にトークン(MMLとして意味を持つ最小の文字列)を置換する機能です。マクロの目的はMMLでよく使う長い記述を短く書けるようにしたり、日本語で書けるようにすることです。JSSは、日本語マクロとリズムマクロの2種類のマクロ機能を持っています。

日本語マクロ

 日本語マクロは日本語をMMLに置き換える機能です。MML中で次のように定義します。

~{テンポ}={Tempo}

 これで「テンポ」→「Tempo」という変換が行われることになります。従って「テンポ」を定義した後は、

テンポ 60

 と書くと

Tempo 60

 と同じ意味になります。

 JSSでは~{XXX}={YYY}を見つけると、文字列変換ハッシュ(SakuraLexer.jmacro)に、「XXX→YYY」という対応を作ります。そして、トークン切り出し前には必ず文字列変換ハッシュに従って文字列変換を行うようにしています。

 日本語マクロに関してはデフォルトで定義用MMLを持ち、変数JapaneseDefaultMacroに定義しています。ユーザーから渡されるMMLの前に本MMLを評価し、日本語マクロを登録しています。そのため、日本語マクロ定義を意識することなくMMLを日本語で記述できます。

リズムマクロ

 リズムマクロは主としてリズムノートを簡易的に記述する目的で実装しています。一文字のアルファベットを任意の文字列に置き換えることができます。MML中で次のように定義します。

$b{n36,}
$s{n38,}

 リズムマクロを使う場合はRhythmと波括弧で囲まれた部分でのみ使用できます。

Rhythm{
bsbs
}

 上記はbにバスドラム、sにスネアドラムを割り当てて、リズムマクロで再生する例です。基本的には日本語マクロと処理方式は同じであり、$x{y}を見つけると文字列変換ハッシュ(SakuraLexer.rmacro)に「x→y」という対応表を作ります。

トークン切り出し

 トークンとは、MMLとして意味を持つ最小の文字列のことです。字句解析での主な処理は、与えられた文字列からトークンを切り出すことです。例えば、

rcdefagb→r c d e f g a b

 のように一つ一つ切り出していきます。あとの処理のため、このときにどんな種類のトークンなのかを記録しておきます。JSSでは大きく次のようにトークンを分類しています。

トークンの分類
項目説明
文字列リテラル{"~"}文字列リテラルです
アルファベットAbc変数定義用のアルファベット文字列です
10進数値10数値です
16進数値$a716進数値です
ノートa音符です。音符は特別なフォーマットを持っているので分類しています
無視|MIDI化に必要のないものはここに分類します。これは小節区切り文字になります
パラメータ
(単体)
>1トークンで意味が確定するものはここに分類します。これは「オクターブを上げる」というMMLになります
パラメータ
(引数つき)
@トークンの後に10進数値を複数必要とするものはここに分類します。これは「楽器を変更する」というMMLで、楽器番号を必要とします
パラメータ
(16進数引数つき)
SysExトークンの後に16進数値を複数必要とするものはここに分類します。これは「システムエクスクルーシブを発行する」というMMLで、システムエクスクルーシブバイト列を必要とします
再帰Sub構文解析中に再帰的に処理する必要のあるものはここに分類します。これは「時間を進めずにMMLを記述する」というMMLで、内部(引数)としてMMLを必要とします
その他 上記に当てはまらないもの

 例えば、次のようなMML文字列は、

Track(10) @33 l8c4<ba

 字句解析の結果としては次のようになります。

解析結果
Noトークン種類
1Trackパラメータ(引数つき)
2(その他
31010進数値
4)その他
5@パラメータ(引数つき)
63310進数値
7lパラメータ(引数つき)
8810進数値
9cノート
10410進数値
11<パラメータ(単体)
12bノート
13aノート

構文解析

 JSSは、構文解析を変数SakuraParserの中で実装しています。ここでは、バラバラになっているトークンを理解可能な最小の塊にまとめて次の処理ブロックへ渡すのが目的です。字句解析のときに種類の分類をしましたが、種類に従って構文解析を行います。

 ここではメインの機能であるノートとパラメータ(引数つき)について説明します。

ケース1:ノートの場合

 ノートは次のような書式になっています。

[音符名][臨時記号*][長さ][,ゲート][,ベロシティ][,タイミング]
ノート書式
項目意味
音符名a/b/c/d/e/f/g音符を表す一文字のアルファベット。a=ラです
臨時記号+/-/*臨時記号を表す一文字記号。+は#、-は♭、*はナチュラルを表します。省略可能
長さ4.n分音符のn。4.だと、付点4分音符を意味します。省略可能
ゲート95実際の発音時間をパーセントで示したもの。省略可能
ベロシティ75打鍵(キーボードを弾くこと)の強さを0~127で示したもの。0だとノートオフ。省略可能
タイミング-3発音タイミングのズレをステップ数(後述)で示したもの。省略可能

 音符名以外はすべて省略可能です。字句解析中でノートだと判定されたトークンを見つけるとノート書式の解析に入ります。例えば与えられたトークン列が次のようなものだとすると、

c 8 , , , 5 d . , 20 e - , , 90

 構文解析の結果は、次のようになります。

構文解析結果
No構文解析結果
1ノートc、8分音符、タイミング5
2ノートd、付点音符、ゲート20
3ノートe、臨時記号-、ベロシティ90

ケース2:パラメータの場合

 パラメータは次のような書式になっています。

[パラメータ名] [引数1][,引数2]..[,引数n]
    または、
[パラメータ名] = [引数1][,引数2]..[,引数n]
    または、
[パラメータ名] ( [引数1][,引数2]..[,引数n] )
パラメータ書式
項目意味
パラメータ名@パラメータを表す文字列。@は音色変更を意味する
引数151パラメータに必要な数値1。@の第1引数は楽器番号
引数216 パラメータに必要な数値2。@の第2引数はバンクセレクト(MSB)
引数n0パラメータに必要な数値n。@の第3引数はバンクセレクト(LSB)

 引数は無限に取ることができます。構文上、引数はすべて省略可能です。パラメータによっては省略不可能な場合や、一つしかパラメータを取らないものもありますが、構文解析上では同じ処理としています。上記表ではパラメータの引数の意味を書いていますが、ここでは意味については意識せず、とにかく構文どおりにトークンをまとめて行きます。

 字句解析で「パラメータ(引数つき)」としてトークンと認識されたものが、パラメータとして構文解析されます。次のトークンが該当します。

'TR','Track', 'CH', 'Channel', 'Port', 'REV', 'Reverb', 'CHO', 'Chorus',
'Volume', 'V', 'P','Panpot', 'EP', 'Expression', 'M', 'Modulation',
 'BR', 'BendRange',
'Tempo', 'TimeKey', 'TimeKeyFlag',
'onNote', 'Repeat', 'onTime', 'Random', 'TimeBase', 'Time', 'TrackSync',
'v_', 'q_', 'p%', 't_', 'v', 'o', 'q', 'p', 't',
'y','@'

 上記トークンを見つけるとパラメータ書式の解析に入ります。例えば与えられたトークン列が次のようなものだとすると、

Tempo = 40 CHO ( 50 ) @ 1 , , 1

 構文解析の結果は、次のようになります。

構文解析結果
No構文解析結果
1パラメータ Tempo、 引数1 40
2パラメータ CHO、 引数1 50
3パラメータ @、引数1=1、引数3=1

次のページ
JSSの内部(2/2)

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

クジラ飛行机(クジラヒコウヅクエ)

ソフト企画「くじらはんど」にて、多数のフリーソフトを公開しています。日本語プログラミング言語「なでしこ」、テキスト音楽「サクラ」、日本語Wiki記法が特徴の「KonaWiki」などを公開しています。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

adas(adas)

趣味プログラマー。10年以上前にゲーム作りでプログラミングに目覚めて以来、ソフトウェアで実現できるものは何でも興味の対象に。住処はhttp://www.0and1.org/

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/703 2006/11/24 00:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング