# T'SoundSystem Spec

## Waht's New

・OSCの波形に新波形を追加（未検証）

・phコマンドの追加（未検証）

・mlコマンドの追加（未検証）

・nsコマンドの追加（未検証）

・コンパイラ側のチャンネル数制限を702まで増やした（未検証）

・スラー（&）の追加（未検証）

・内部32bit化（クリッピング対策済み）

・FMパイプの後半2本が正しく機能していなかったのを修正

## 基本機能

> 同時発音数 | 制限なし（コンパイラの仕様上の制限で702）。
> 音色表現力 | チェンネル毎に任意のモジュールを動的に選択可能。加えて、チャンネル間のFM変調機能搭載。ステレオ出力。
> 音程解像度 | 3種類から選択可能。
> 音量解像度 | 2種類から選択可能。
> タイマー | テンポ制御用とエンベロープ制御用の２本の擬似タイマー割り込みを内部に持つ。

### モジュール

> 0 | PSG | 矩形波音源。もっとも単純な音色しか出せないが、処理はもっとも軽い。
> 1 | FC | デューティ比を調節できる矩形波。ファミコンレベルの音色表現が可能。処理も軽い。
> 2 | NOISE | ノイズ音源。
> 3 | SIN | サイン波。FM変調をすることで、FM音源同様の表現が可能。若干重い。
> 4 | SCC | ウェーブテーブル音源。コナミ往年のSCC音源を再現可能。テーブルサイズは32。
> 5 | OSC | 固定波形テーブル音源。三角波や鋸波など、基本的な波形を再現。

### 音程解像度

> 0 | Hz | Hz単位での表現が可能。デフォルトのモード。
> 1 | MSX | MSXで使用されていたPSGと同等の解像度。高音域になると、音程が荒くなる。
> 2 | FM | FM音源等で使用されているような指数的な解像度。半音を64等分できる解像度を持つ。

### 音量解像度

> 0 | 線形 | 線形的な音量変化。
> 1 | 非線型 | FM音源などで採用されている音楽的な音量変化。
> 16 | 線形2 | 線形的な音量変化。ただし15段階指定の際に、全体を15分割せずに、上半分を15分割する。
> 17 | 非線型2 | FM音源などで採用されている音楽的な音量変化。ただし15段階指定の際に、全体を15分割せずに、上半分を15分割する。

# T'SoundSystem MML Manual

## 制御文

> #TITLE <[title]> | 曲名を登録する。'\'を使えば、'>'等も含めることができる。 GAMEBOYモードでは意味を持たない。 (例)#TITLE <RISING ZAN \<THE SAMURAI GUNMAN\>>
> #CHANNEL [n] | 曲のなかで使う最大音色数を指定する。 (例)#CHANNEL 3
> #PRAGMA [key] | 特定ハードウェア向けの曲データを作る際に使用。keyとしてGAMEBOY、FAMICOMが存在している。詳細は非公開。 (例)#PRAGMA GAMEBOY
> #WAV [n], <[table]> | SCC用の波形テーブル n にデータを設定する。signed char×32。パラメータの詳細は後述。 GAMEBOYモードの時は０〜15しかパラメータに含めることが出来ない。 (例)#WAV 0, <(0, 127),16, (-128, 127),16> 0〜255の256個登録できる。
> #TABLE [n], <[table]> | エンベロープ用の波形テーブル n にデータを設定する。signed char の任意長。パラメータの詳細は上に同じ。0〜255の256個登録できる。
> #OCTAVE [key] | keyはNORMALとREVERSEが指定可能。REVERSEを指定した場合は、相対オクターブ命令「>」「<」の機能が入れ替わる。 (例)#OCTAVE REVERSE
> #VOLUME [key] | keyはNORMALとREVERSEが指定可能。REVERSEを指定した場合は、相対音量命令「)」「(」の機能が入れ替わる。
> #FINENESS [n] | サスティンやLFOなどの処理に使うタイマーの精度を指定する。デフォルト値は368で0〜65535までの値をとり、小さいほど細かく処理される。あまり細かく指定すると極端に処理が重くなるので、せいぜい64程度までの値にすべきである。
> #A〜#Z, #AA〜#AZ, ..., #ZA〜#ZZ | 各チャンネルのMMLデータを記述する。
> #END | MMLの終了を示す。これ以降はコメントとして扱われる。

### テーブルパラメータ

要素の数だけ、「,」で区切ってパラメータを列挙する。

(l, m),n の書式で、lからmまでの値をn個のパラメータで線形補完する。例えば、(1,5),5 は、1,2,3,4,5 と同じ。

## MMLコマンド

### 制御関連

(*)対応モード : N = 通常モード、 G = ゲームボーイモード

> コマンド | 有効範囲 | 解説 | (*)
> t[n] | 1≦n(120)≦512 | テンポ指定。テンポ制御用のタイマーの値を操作するので全チャンネルに影響が及ぶ。 | N/G
> $ |  | 無限ループ開始位置指定。これが指定されると、チャンネルデータが最後まで演奏された時、この位置に戻る。 | N/G
> [[n] ... | ] | 2≦n(2)≦255 | ループ擬似命令。'['から']'の間をn回繰り返す。最終ループの時は、'|'まで来たらループを抜ける。'|'は省略可能。コンパイルの段階で展開される。そのため、バイナリサイズは大きくなってしまう。が、相対命令も有効。ネストは不可。 (例)[3c<] …(展開)→ c< c< c< | N/G
> /:[n] ... / ... :/ | 2≦n(2)≦255 | ループ命令。'/:'から':/'の間をn回繰り返す。最終ループの時は、'/'まで来たらループを抜ける。'/'は省略可能。ドライバレベルのループ機能なので、コンパイル時に展開される相対命令の類は繰り返されない。ネストは16重まで可能。 (例)/:2cde/fgab<:/c:/ …(展開)→ cdefgab cde <c | N
> { ... } |  | コメント。'{'から'}'で囲まれた部分をコメントとして扱う。ネストも可能。 | N/G

### 音色関連

> s[n] | 0≦n(0)≦255 | サスティン。キーオフ後にいきなり音を消さずに減衰させる。0の時はOFF。値が大きいほど減衰も急。 | N
> s[n],[m] | 0≦n(0)≦255, -128≦m(0)≦127 | 拡張サスティン。キーオフ後に、音量だけではなく、音程も同時に連続的に変化させる。mに対する音程の変化分は、音程モードにより、異なる。 | N
> % | 0≦n(0)≦255 | モジュール変更。モジュール指定に使う数値は後述。 | N
> @ | 0≦n(0)≦255 | 音色変更。変更の方法・有効範囲はモジュール毎に異なり、そのパラメータの有効性はコンパイル時にはチェックされないので注意。 | N/G
> ph[n] | 0≦n(0)≦255 | キーオン時の初期位相をn/128πに指定する。 | N

### 音程関連

> o[n] | 1≦n(4)≦8 | オクターブの指定。大きいほど高い。 | N/G
> > |  | オクターブ・相対ダウン。コンパイラ擬似命令。 | N/G
> < |  | オクターブ・相対アップ。コンパイラ擬似命令。 (例)cdrfgab<c | N/G
> a[n]〜g[n] | 1≦n(L)≦1024 | ラ〜ソにそれぞれ対応した音を出す。Lはl[n]で指定された値。 | N/G
> +(#)/- |  | a〜gの直後に記述することで、音程を半音単位で上げ/下げする。 | N/G
> r[n] | 1≦n(L)≦1024 | 休符指定。 | N/G
> k[n] | -128≦n(0)≦127 | ディチューン。 | N/G
> mp[a], [b], [c], [d], [e] | 0≦a≦65535, 0≦b≦255, 0≦c≦255, -128≦d≦127, 0≦e≦255 | ピッチモジュレーション。a : Delay, b : Depth, c : Width, d : Height, e : Delta。発声後、a 単位時間後にモジュレーション開始。width 単位時間おきに height 単位音程ずつ変化する。変化量の絶対値が depth に達したら、変化の方向を逆転する。以上の処理を、delta 回繰りかえしたら、depth は 1 増える。任意のパラメータを省略可能。これを使用すると s コマンドの第 2 パラメータは無効になる。 | N
> nt[n],[m] | 0≦n(0)≦255, 0≦m(0)≦255 | ノートエンベロープ。テーブルn番のデータでノートエンベロープ（キーオン・キーオフのない高速アルペジエータ）をかける。mは1回の変化が起こるまでの時間。mが大きいほど変化はゆっくりになる。いずれかの省略は不可。共に省略、またはmが0の時は機能をOFFにする。 | N
> ns[n] | -128≦n(0)≦127 | ノートシフト。チャンネル毎に指定可能。最終的なノート番号が0〜127に収まらない場合には最小値0や最大値127に丸められる。コンパイラ擬似命令。 | N/G
> ml[n] | 0≦n(1)≦255 | 再生周波数をn倍にする。 | N

### 音長関連

> q[n] | 0≦n(MG)≦MG | 実際に演奏する音調の割合。ある長さだけ音を伸ばそうとしたとき、実際にはその長さのn/MGが演奏され、残りの時間は休符になる。（現在はMG=16で固定） | N/G
> l[n] | 1≦n(4)≦1024 | 省略時の音調指定 | N/G
> . |  | 音長指定の直後に付加することで、長さを1.5倍にする。続けて複数付加できる。 | N/G
> ^ |  | タイ。音長のあとにさらに音長を追加する。 (例)c4^16 | N/G
> & |  | スラー。直前の音をq16相当で処理する。 | N/G

### 音量関連

> v[n] | 0≦n(10)≦15 | 音量を指定する。数値が大きいほど音も大きい。この方法で指定すると、パンポットで指定の位置に音がふられる。 | N/G
> v[n], [n] | 0≦n≦15 | 音量を指定する。始めの値が左、次の値が右のチャンネルの音量を示す。任意のパラメータを省略可能。 (例)v15,0 c v10, c v0,10 c v,15 c | N
> @v[n] | 0≦n(10)≦255 | 音量を細かく指定する。モノラル。 | N
> @v[n],[n] | 0≦n(10)≦255 | 音量を細かく指定する。ステレオ。 | N
> ) |  | 音量・相対ダウン。コンパイラ擬似命令。直前にvを使ったか、@vを使ったかで変化単位が変わる。 (例)v0 /:c)d)e:/ …(展開)→ v0c v1d v2e c v1d v2e | N/G
> ( |  | 音量・相対アップ。コンパイラ擬似命令。直前にvを使ったか、@vを使ったかで変化単位が変わる。 | N/G
> _[n] | 0≦n(1?)≦255 | 音量を相対的に、256段階指定単位でnだけダウンする。nの値は最初に省略された時は1、それ以外で省略された時は前回の値が使用される。ドライバプリミティブ命令。 (例)@v32 l16 c_8d_e_f_g …(展開)→ @v32 c16 @v24 d16 @v16 e16 @v8 f16 @v0 g16 | N
> ~[n] | 0≦n(1?)≦255 | 音量を相対的に、256段階指定単位でnだけアップする。nの値は最初に省略された時は1、それ以外で省略された時は前回の値が使用される。前回の値は「_」と「~」ではそれぞれ別々に管理される。 | N
> p[n] | 0≦n(0)≦3 | パンポットの指定。v[n]系のモノラル指定を使って音量指定した時だけ意味がある。0:mute, 1:left, 2:right, 3:center。 | N/G
> na[n],[m] | 0≦n(0)≦255, 0≦m(0)≦255 | 音量エンベロープ（高速アルペジエータ）。テーブルn番のデータでエンベロープをかける。mは1回の変化が起こるまでの時間。mが大きいほど変化はゆっくりになる。いずれかの省略は不可。共に省略、またはmが0の時は機能をOFFにする。 | N
> x[n],[m] | 0≦n(0)≦1, 0≦m(0)≦3 | 音量モード(n)、音程モード(m)の設定。 | N

### FM変調関連

> @i[n],[m] | 0≦n(0)≦8, 0≦m(0)≦3 | FM変調入力モードを設定する。nが0の時OFF。1〜8は変調の感度を表す。mは変調に使用するパイプ番号。 | N
> @o[n],[m] | 0≦n(0)≦2, 0≦m(0)≦3 | FM変調出力モードを設定する。nが0の時OFF。1の時は上書モード、2の時は加算モード。mは変調に使用するパイプ番号 | N

## モジュール

モジュール指定に使うIDは以下の通り。

> > ID | 音源 | 変調(IN/OUT)
> > --- | --- | ---
> > 0 | PSG | ×/×
> > 1 | FC | ×/×
> > 2 | NOISE | ×/×
> > 3 | SIN | ○/○
> > 4 | SCC | ○/○
> > 5 | OSC | ○/○

## OSC波形

OSCモジュール時の音色番号では以下の波形が指定できる。

> > ID | 波形
> > --- | ---
> > 0 | 正弦波
> > 1 | 鋸波（／）
> > 2 | 鋸波（＼）
> > 3 | 三角波（FC）
> > 4 | 三角波
> > 5 | 矩形波

## FM変調

### 変調出力モード

出力モードがONになると、そのチャンネルの波形データは、スピーカへは出力されず、パイプへ出力されます。パイプに出力されたデータはそれ以降のチャンネルに影響を与えることができます。

まず上書モードですが、このモードではすでにパイプにデータがあった場合でも、現在の出力でデータを上書きします。

加算モードでは、逆にパイプにあるデータと、現在の出力の合成波をパイプに出力します。

パイプのデータは自動に初期化されることはないので、パイプへ最初に出力するチャンネルは上書モードである必要があります。

### 変調入力モード

入力モードがONになると、パイプからの入力データを位相に反映させます。この時の反映の度合いは感度によります。

あるチャンネルからの出力を入力に利用する際、出力側のチャンネル番号を入力側のチャンネル番号よりも若いものにして、双方で同じ番号のパイプに出力/入力する必要があります。

### 例

>     Ａ→Ｂ→Ｃ♪

> >     #A @i0,0 @o1,0 { 最初のチャンネル。パイプ0に新規に出力 }
> >     #B @i1,0 @o1,0 { #Aの出力をパイプ0経由で位相に反映させたものを再度パイプ0に出力 }
> >     #C @i1,0 @o0,0 { #A->#Bをパイプ0経由で位相に反映させスピーカーへ出力 }

>     Ａ―＋→Ｃ♪
>     Ｂ―＋

> >     #A @i0,0 @o1,0 {パイプ0に新規出力 }
> >     #B @i0,0 @o2,0 {パイプ0に加算出力 }
> >     #C @i1,0 @o0,0 {#A+#Bをパイプ0経由で位相に反映させスピーカーへ出力 }

based on ver.0.93