sagafrontier @ うぃき

サウンドデータ (AKAO Format)

最終更新:

匿名ユーザー

- view
だれでも歓迎! 編集

SQUARE Playstation's soft 初期/後期AKAO Format


この資料は、旧SQUARE社(現SQUARE ENIX社)のPlaystation向けソフトのサウンドのフォーマット"AKAO"について記述した。
(他旧SQUARE社の音源ドライバには、SMDS(ゼノギアス等), HOSA(DEWPRISM)等がある)

バージョン

初期AKAO
初期は細かな仕様の変動が激しく、実際のところ一枚岩ではない。時系列順に示す。
  • FINAL FANTASY 7 (1997)

SaGa Frontier は FF7 と概ね似ているが、FC コマンドの内容などが異なる。
FF7 では音色・サンプルの情報はヘッダーレスのファイルに記録されていたが、SaGa Frontier では "AKAO" シグネチャつきのフォーマットに変更されている。
  • Saga Frontier (1997)

ここから FC xx 形式のメタイベントが導入される (本資料では詳細を記していないが後期AKAOの FE xx とほぼ同じ):
  • FRONT MISSION 2 (1997)
  • チョコボの不思議なダンジョン (1997) (シーケンスデータが圧縮されている)

ここからヘッダーサイズが 16 バイトから 32 バイトになる (本資料では詳細を記していない):
  • パラサイト・イヴ (1998)

後期AKAO
  • アナザー・マインド (1998)
  • チョコボの不思議なダンジョン2 (1998)
  • FINAL FANTASY 8 (1999)
  • チョコボレーシング ~幻界へのロード~ (1999)
  • SaGa Frontier 2 (1999)
  • レーシングラグーン (1999)
  • 聖剣伝説 LEGEND OF MANA (1999)
  • FRONT MISSION 3 (1999)
  • クロノ・クロス (1999)
  • VAGRANT STORY (2000)
  • FINAL FANTASY 9 (2000)
  • FINAL FANTASY 2 (Playstation版) (2002)


BYTE
1Byte(8bit)である事を示す。
WORD
2Byte(16bit)である事を示す。
DWORD
4Byte(32bit)である事を示す。
AKAOは、リトルエンディアンで記述される。




(1) ヘッダー


初期AKAO

Address Type
0x0000 BYTE(4) "AKAO" のASCII文字列
0x0004 WORD File Serial ID:曲毎に番号が異なる。
0x0006 WORD File Size(先頭の16Byteを除く)
0x0008 WORD Reverb Type (0~9)
0x000A BYTE Timestamp (年) (BCD形式)
0x000B BYTE Timestamp (月) (BCD形式)
0x000C BYTE Timestamp (日) (BCD形式)
0x000D BYTE Timestamp (時) (BCD形式)
0x000E BYTE Timestamp (分) (BCD形式)
0x000F BYTE Timestamp (秒) (BCD形式)

Address Type
0x0010 DWORD 使用されるチャンネル。各bitがそれぞれのチャンネルに対応。基本的に下位のbitから順に使用するが例外あり(例:FF7「不安な心」)。上位8bitは効果なし。
0x0014 WORD 曲データのある相対アドレス ch1 … (5)項参照 ※該当チャンネル使用時に限り記録される
0x0016 WORD 曲データのある相対アドレス ch2 ※該当チャンネル使用時に限り記録される
0x0018 WORD 曲データのある相対アドレス ch3 ※該当チャンネル使用時に限り記録される
・・・ ・・・ ・・・
0x0040 WORD 曲データのある相対アドレス ch23 ※該当チャンネル使用時に限り記録される
0x0042 WORD 曲データのある相対アドレス ch24 ※該当チャンネル使用時に限り記録される

尚、初期AKAOで記述される相対アドレスは、2Byte先のアドレスを基点とする。

チャンネルは、静的にハードウェアの各チャンネルに割り当てられる。
殆どの曲は、Playstationの最大発音数24音を、
曲で16チャンネル、効果音で8チャンネルで使用し、効果音と共存させている模様。
一部の曲は、16チャンネル以上使用している場合がある。
例)
  • FINAL FANTASY 7 星の危機 (24チャンネル)
  • FINAL FANTASY 7 スタッフロール (20チャンネル)

Reverb Type については以下のとおり。

説明
0 Reverb Off
1 Room
2 Studio (Small)
3 Studio (Medium)
4 Studio (Large)
5 Hall
6 Space Echo
7 Echo
8 Delay
9 Pipe Echo


後期AKAO

0x0000 BYTE(4) "AKAO"のASCII文字列
0x0004 WORD File Serial ID:曲毎に番号が異なる。
0x0006 WORD File Size
0x0008 WORD Reverb Type (0~9)
・・・ ・・・ ・・・
0x001E WORD 不明
0x0020 DWORD 使用されるチャンネル。各bitがそれぞれのチャンネルに対応。基本的に下位のbitから順に使用する。
0x0024 DWORD 不明
0x0028 DWORD 不明
0x002C DWORD 不明
0x0030 DWORD 拡張音色データ情報への相対アドレス (0: 未使用) … (2)項参照
0x0034 DWORD パーカッション情報への相対アドレス (0: 未使用) … (4)項参照
0x0038 DWORD 不明
0x003C DWORD 不明
0x0040 WORD 曲データのある相対アドレス ch1 … (5)項参照 ※該当チャンネル使用時に限り記録される
0x0042 WORD 曲データのある相対アドレス ch2 ※該当チャンネル使用時に限り記録される
0x0044 WORD 曲データのある相対アドレス ch3 ※該当チャンネル使用時に限り記録される
・・・ ・・・ ・・・
0x007C WORD 曲データのある相対アドレス ch31 ※該当チャンネル使用時に限り記録される
0x007E WORD 曲データのある相対アドレス ch32 ※該当チャンネル使用時に限り記録される
後期AKAOの相対アドレスは、書かれているアドレスを基点とする。
相対アドレスとは、その位置からのオフセット量を示す。
たとえば、0x0040に書かれているch1の相対アドレスが0x0010であった場合、
0x0040+0x0010=0x0050番地から、ch1のデータが書かれている事を示す。

後期AKAOには最大32個のチャンネルがあるが、Playstationの最大発音数は24音であり、
効果音も含めて、音源ドライバーがハードウェアへ動的に音を割り当てるようになっている。






(2) 音色データ情報ヘッダー (Key-Split Instruments)

2Byte×16個の構造体(合計32Byte)
16個の拡張音色データのオフセットが記載されている。…(3)
オフセットの基点は(2)の0x20バイト先、すなわち(3)の先頭アドレスである。

曲データ中の"0xFE 0x14"で指定される音色番号に対応しており、
先頭から順に、それぞれ音色番号0,1,2,・・・,15番の拡張音色データへのアドレスを示す。

数値が0xFFFFの場合は、当該番号の音色は未使用である事を示す。
(最適化されたPSFファイルでは0で消去されていたりするが)

例:
80101EF0: 00 00 10 00 30 00 58 00 80 00 B0 00 C0 00 E0 00
80101F00: 08 01 20 01 FF FF FF FF FF FF FF FF FF FF FF FF
音色番号0の(3)音色データ情報は 0x80101F10 に存在、音色番号1は 0x80101F20 に、音色番号2は 0x80101F40 に、以下同様。


(3) 音色データ情報 (Key-Split Instrument Regions)

拡張音色データの定義が記載される。拡張音色データではキー範囲ごとに異なるサンプルを使用できる。
本データの所在は ①初期AKAOの0xFCの引数、あるいは ②後期AKAOの(2)項 によって示される。

8Byte×(n)の構造体となる。構造は以下の通り
0 音色番号 (A1 コマンドの引数に指定する値と同じ)
1 適用音程範囲 開始ノート番号
2 適用音程範囲 終了ノート番号
3 ADSR Attack Rate (0-127)
4 ADSR Sustain Rate (0-127)
5 ADSR Sustain Mode (1, 3, 5, 7)
6 ADSR Release Rate (0-31)
7 ボリューム (n/128, 0のときは増減なし)

ADSR Sustain Mode は以下のいずれかを指定する。
1 Linear increase
3 Linear decrease
5 Exponential increase
7 Exponential decrease

サウンドドライバが正しくゾーンを選択できるよう、以下の条件に合わせてデータを記載すること。
  • 音色ごとに、終了ノート番号が小さい順にデータを並べなければならない
  • 音色ごとに、最後尾のゾーン定義の後ろには、ゾーンの終端を表すエントリを記録しなければならない
    • 後期AKAOでは、8バイトすべてが0の終端データを記録しなければならない(厳密には ADSR Sustain Mode が 0 のデータが終端として判定される)
    • それ以前、パラサイト・イヴでは、80 80 80 80 00 00 00 00 が記録される。音色番号が 0x80 以上のデータが終端とみなされる模様



(4) パーカッション音色データ

8Byteの構造体の配列。先頭の8Byteから C, Cis, D, Dis, E … の音色データを示す。

オクターブの扱いが初期AKAOと後期AKAOで異なる。
初期AKAOではオクターブは無視される。したがって、配列の要素数は最大で12であると考えられる。
後期AKAOではオクターブが反映されるため、配列の要素数は最大で128であると考えられる。
実際にシーケンスに表れる要素数は固定ではないが、要素数が明示的に記述されているわけでもない。この配列はシーケンスデータの末尾に配置されるため、ファイルサイズを確認し、ファイルサイズ外の領域にはアクセスしないようにプログラムを作成すると良いだろう。

初期AKAO
0 パーカッション音色番号 (A1 コマンドの引数に指定する値と同じ)
1 発音する音程(ノート番号)
2 ボリューム 小数部 (※)
3 ボリューム 整数部 (※)
4 パンポット (AA コマンドの引数に指定する値と同じ、64 が中央)

ボリュームは A8 コマンドの音量値を上書きする形で実現される。ここで指定する値は (A8コマンドで指定する値 * 128) と等価である。したがって、A8 コマンドで指定可能な最大値 0x3F80 (127 * 128) 以下の値を指定するのが妥当な使用法であると考えるが、それを超えるケースが実在するかどうかは不明。

初期AKAO パラサイト・イヴ
データが1バイト増えている。
5 リバーブ on/off (1 or 0)

後期AKAO
データが8バイトに再編成されている。
0 パーカッション音色番号 (A1 コマンドの引数に指定する値と同じ)
1 発音する音程(ノート番号)
2 ADSR Attack Rate (0-127)
3 ADSR Sustain Rate (0-127)
4 ADSR Sustain Mode (1, 3, 5, 7)
5 ADSR Release Rate (0-31)
6 ボリューム (n/128, 0のときは増減なし)
7 パンポット (bit 0-6) および リバーブ on/off (bit 7)


尚、8Byteの構造体が全て0x00のときは、未使用である事を示す。

構造上、0x00がたくさん並ぶ事があるが、『決して、AKAOデータの終わりではない』ので、抜き出し時は注意。
一部資料には、『0x00が連続したらAKAOデータ終わり』とか書いてあったけど、そんな事は無い。
ヘッダーのファイルサイズ通りに切り出せば、問題ない。




(5) シーケンスデータ


0x00~0x99
音符・休符を示す。
音程の変換式は以下のようになります。

バイトコード / 11 = 音の高さ
0=ド
1=ド#
2=レ
3=レ#
4=ミ
5=ファ
6=ファ#
7=ソ
8=ソ#
9=ラ
10=ラ#
11=シ
12=タイ(直前の音を切らずに伸ばす)
13=休符

バイトコード / 11 の余り = 音の長さ
0=全音符 (192 ticks)
1=2分音符 (96 ticks)
2=4分音符 (48 ticks)
3=8分音符 (24 ticks)
4=16分音符 (12 ticks)
5=32分音符 ( 6 ticks)
6=64分音符 ( 3 ticks)
7=6分音符 (32 ticks)
8=12分音符 (16 ticks)
9=24分音符 ( 8 ticks)
10=48分音符 ( 4 ticks)

パラサイト・イヴ以前の初期AKAOにおいては、スラーやレガートが有効ではない通常の状況では、音符の実際の発音の長さ(デュレーション)は上記から -2 ticks した長さになる。アナザー・マインド以降の後期AKAOではこの限りではない。

0x9A~0x9F
未定義命令。

0xA0
シーケンス終了。
無限ループしない場合の終端となる。

0xA1, voice:BYTE
音色番号を(voice)に指定する。
又、ハードウェアエンベロープを音色の規定値に設定する。

0xA2, length:BYTE
次の音符・休符(0x00~0x99コマンド)の音長を、強制的に(length)[ticks]にする。
効果は持続しない。それ以降の音符・休符は通常どおりに解釈される。

0xA3, volume:BYTE
音量を、(volume)にする。

0xA4, length:BYTE, depth:BYTE
(length)[ticks]で(signed char)(depth)×100[cent]だけ、音程を推移する。
(length)が0の場合は 256 ticks と解釈される。

0xA5, octave:BYTE
オクターブを(ocrave)に設定する。
基本的に4が中央Cとなるが、音色によってサンプリングされた周波数が異なる為、この限りで無い。

0xA6
オクターブを1つ上げる。

0xA7
オクターブを1つ下げる。

0xA8, expression:BYTE
2系統目の音量。音符の表現付けの為に使われる。
音源ドライバ内部で、0xA1コマンドの引数と掛け算が行われ、それが実際の音量になる。

0xA9, length:BYTE, expression:BYTE
(length)[ticks]で、(expression)に音量を推移する。
(length)が0の場合は 256 ticks と解釈される。

0xAA, panpot:BYTE
パンポットを指定する。64が中央。

0xAB, length:BYTE, panpot:BYTE
(length)[ticks]で、(panpot)にパンポットを推移する。
(length)が0の場合は 256 ticks と解釈される。

0xAC, clock:BYTE
ノイズ周波数を(clock)の下位6bit(0~0x3F)の値に設定する。
ただし、上位2bitが0でない場合は相対指定となり、下位6bitを符号付きで解釈して現在のノイズ周波数を相対的に変化させる。

0xAD, ar:BYTE
ハードウェア・エンベロープ (ADSR) の Attack Rate を設定する。

0xAE, dr:BYTE
ハードウェア・エンベロープ (ADSR) の Decay Rate を設定する。

0xAF, sl:BYTE
ハードウェア・エンベロープ (ADSR) の Sustain Level を設定する。

0xB0, dr:BYTE, sl:BYTE
ハードウェア・エンベロープ (ADSR) の Decay Rate と Sustain Level を設定する。

0xB1, sr:BYTE
ハードウェア・エンベロープ (ADSR) の Sustain Rate を設定する。

0xB2, rr:BYTE
ハードウェア・エンベロープ (ADSR) の Release Rate を設定する。

0xB3
ハードウェア・エンベロープ (ADSR) を、音色のデフォルトに戻す。

0xB4, delay:BYTE, rate:BYTE, type:BYTE
音程LFOを指定する。
delay[ticks]が、LFO開始までの時間。
rate[ticks]が、LFOの1ステップの長さ。値が小さいほど変化が高速になる。(rate)が0の場合は 256 ticks と解釈される。
type(0~15)はLFOの波形の種類を指定する。
波形ごとに1周期あたりのサンプル数は異なるため、LFOの周期は一概には言えない。

0xB5, depth:BYTE
音程LFOの振幅量を指定する。

depthの最上位bitで振幅量の範囲を指定する。
0の場合は最大で約 ± 50 cents の範囲 (1の場合と比べて振幅が 15/256)
1の場合は最大で約 ± 700 cents の範囲
のはず。

0xB6
音程LFOを停止する。

0xB7, armode:BYTE
ハードウェア・エンベロープ (ADSR) の Attack Mode を設定する。

ハードウェアの仕様説明は省略するが(PSX Spex などを参照)、値の説明は以下のとおり。

説明
0 Direct Mode
1 Linear Increase Mode (Normal Phase)
2 Linear Increase Mode (Inverted Phase)
3 Linear Decrease Mode (Normal Phase)
4 Linear Decrease Mode (Inverted Phase)
5 Exponential Increase Mode (Normal Phase)
6 Exponential Increase Mode (Inverted Phase)
7 Exponential Decrease Mode

0xB8, delay:BYTE, rate:BYTE, type:BYTE
音量LFOを指定する。
delay[ticks]が、LFO開始までの時間。
rate[ticks]が、LFOの1ステップの長さ。値が小さいほど変化が高速になる。(rate)が0の場合は 256 ticks と解釈される。
type(0~15)はLFOの波形の種類を指定する。
波形ごとに1周期あたりのサンプル数は異なるため、LFOの周期は一概には言えない。

0xB9, depth:BYTE
音量LFOの振幅量を指定する。

0xBA
音量LFOを停止する。

0xBB, srmode:BYTE
ハードウェア・エンベロープ (ADSR) の Sustain Mode を設定する。

0xBC, rate:BYTE, type:BYTE
パンポットLFOを指定する。
rate[ticks]が、LFOの1ステップの長さ。値が小さいほど変化が高速になる。(rate)が0の場合は 256 ticks と解釈される。
type(0~15)はLFOの波形の種類を指定する。
波形ごとに1周期あたりのサンプル数は異なるため、LFOの周期は一概には言えない。

0xBD, depth:BYTE
パンポットLFOの振幅量を指定する。

0xBE
パンポットLFOを停止する。

0xBF, rrmode:BYTE
ハードウェア・エンベロープ (ADSR) の Release Mode を設定する。

0xC0, semitones:BYTE
(signed char)(semitones)だけ移調する。絶対値指定。

0xC1, semitones:BYTE
(signed char)(semitones)だけ移調する。相対値指定。

0xC2
リバーブを有効にする。

0xC3
リバーブを無効にする。

0xC4
ノイズを有効にする。

0xC5
ノイズを無効にする。

0xC6
FM変調を有効にする。

0xC7
FM変調を無効にする。

0xC8
リピート開始点
リピートはおそらく4重までネスト可能

0xC9, count:BYTE
リピート終了点
(count)の回数に達するまで、リピート開始点に戻って演奏を繰り返す。
(count)が0の場合は256と解釈される。

0xCA
無条件リピート
リピート回数を+1してから、リピート開始点に戻って演奏を繰り返す。

0xCB
ノイズ、FM変調、リバーブ、0xF4 (オーバーレイ)、0xF8 (代理発音) などの効果をリセットする。

0xCC
スラー開始。
実際には、KeyOn/KeyOffの操作を停止し、音程のレジスタのみを変更する処理となる。
間に休符が挟まれた場合は、スラーを終了する。

0xCD
スラー終了

0xCE, delay:BYTE
ノイズを有効にして、一定時間後に無効にする。
delay[ticks]が無効化までの時間。delayが0の場合は 256 ticks と解釈される。

0xCF, delay:BYTE
ノイズの有効・無効を一定時間後に反転する。
delay[ticks]が無効化までの時間。delayが0の場合は 256 ticks と解釈される。

0xD0
レガート開始。音符が終了する直前のKeyOffの操作をしないようにする。

0xD1
レガート終了

0xD2, delay:BYTE
FM変調を有効にして、一定時間後に無効にする。
delay[ticks]が無効化までの時間。delayが0の場合は 256 ticks と解釈される。

0xD3, delay:BYTE
FM変調の有効・無効を一定時間後に反転する。
delay[ticks]が無効化までの時間。delayが0の場合は 256 ticks と解釈される。

0xD4
ノートの音程を無視し、1つ前のチャンネルの再生周波数をコピーして使用するようになる特殊なコマンド。

0xD5
0xD4の効果を解除する。

0xD6
1つ前のチャンネルの再生周波数を音量に乗算するようになる特殊なコマンド。
つまり、1つ前のチャンネルが低い音を出すほど音量は小さくなり、高い音を出すほど音量は大きくなる。

0xD7
0xD6の効果を解除する。

0xD8, pitch:BYTE
(signed char)(pitch)だけ音程をずらす。絶対値指定。

音程が変化する範囲は±1オクターブ。
(pitch)は再生周波数に対する倍率を示す。cents のような対数スケールではない。
たとえば、127で127/128倍(約+1オクターブ)、-128で128/256倍(-1オクターブ)に再生周波数を変化させる。

0xD9, pitch:BYTE
(signed char)(pitch)だけ音程をずらす。相対値指定。

0xDA, speed:BYTE
ポルタメント有効化。音符間の音程がなめらかに推移するようになる。
speed[ticks]がポルタメントの速さ(長さ)。speedが0の場合は 256 ticks と解釈される。

0xDB
ポルタメント無効化

0xDC, dlength:BYTE
これ以降に出現する音符の長さを固定する奇妙なコマンド。おそらく効果音向け。

(signed char)dlength[ticks] で長さを相対的に指定する。(初期値は0=無効)
dlength を加算後の長さが 1~255 の範囲内でなければクリップする(0 にはできないはずで、有効化すると無効化できないかも)。

0xDD, length:BYTE, depth:BYTE
(length)[ticks]で、(depth)に音程LFOのdepthを推移する。
(length)が0の場合は 256 ticks と解釈される。

0xDE, length:BYTE, depth:BYTE
(length)[ticks]で、(depth)に音量LFOのdepthを推移する。
(length)が0の場合は 256 ticks と解釈される。

0xDF, length:BYTE, depth:BYTE
(length)[ticks]で、(depth)にパンポットLFOのdepthを推移する。
(length)が0の場合は 256 ticks と解釈される。


0xE0以降のコマンドは、初期AKAOと後期AKAOで異なるので注意。

初期AKAO

0xE0~0xE7
未実装命令。効果は 0xA0 と同じ。

0xE8, tempo:WORD
テンポを設定する。BPM (拍/分) に変換する式は以下のとおり。
bpm = tempo / 218.453333333
正確には以下の式から上記の結論となる。
PPQN = 48
TIMER_FREQ = 0x44E8
bpm = 60.0 / (PPQN * (65536.0 / tempo) * (TIMER_FREQ / (33868800.0 / 8)))

FINAL FANTASY 7 では、タイマーの係数が異なる。
bpm = tempo / 214.998204082
正確には以下の式から上記の結論となる。
PPQN = 48
TIMER_FREQ = 0x43D1
bpm = 60.0 / (PPQN * (65536.0 / tempo) * (TIMER_FREQ / (33868800.0 / 8)))

0xE9, length:BYTE, tempo:WORD
テンポを、(length)[ticks]で、(tempo)に推移する。
(length)が0の場合は 256 ticks と解釈される。

0xEA, reverb:WORD
リバーブの深さを、(reverb)に設定する。

0xEB, length:BYTE, reverb:WORD
リバーブの深さを、(length)[ticks]で、(reverb)に推移する。
(length)が0の場合は 256 ticks と解釈される。

0xEC, address:WORD
パーカッションに切り替える。
(address)に、パーカッション情報の構造体がある相対アドレスが記述される。…(4)

0xED
パーカッションを終了する。

0xEE, address:WORD
(address)(相対アドレス)に無条件ジャンプする。
主に無限ループに使われるが、一部、条件ジャンプ命令などと組み合わせ、
スパゲティーな構造になっている曲もあり、この限りで無い。

0xEF, condition:BYTE, address:BYTE
(condition)条件下において、(address)(相対アドレス)に条件ジャンプする。
ゲームの進行状況において曲を進行させる場合等に使われる。

0xF0, count:BYTE, address:WORD
リピート(0xC8~0xC9, 0xCA)内条件分岐。
(count)目のリピートであった場合、(address)(相対アドレス)にジャンプする。
(count)が0の場合は256と解釈される。

0xF1, count:BYTE, address:WORD
リピート(0xC8~0xC9, 0xCA)内条件分岐。0xF0と類似。
(count)目のリピートであった場合、(address)(相対アドレス)にジャンプしてリピートを終了する。
(count)が0の場合は256と解釈される。

0xF2, voice:BYTE
音色番号を(voice)に指定する。0xA1コマンドと異なり、ループポイント以前のサンプルを再生しない。

技術的には、ループ開始アドレスを規定どおりに設定するが、サンプル開始アドレスを2ブロック分の短い無音の ADPCM サンプルに向けることでこのような動作を実現する。

0xF3 (SaGa Frontier)
不明

0xF3 (FINAL FANTASY 7)
不明。トラックだけでなくシーケンス全体に影響を及ぼす。

0xF4, voice:BYTE, voice2:BYTE (FINAL FANTASY 7)
未使用チャンネルを使用して2つの音色で同じ旋律を演奏する。オーバーレイ。FF7「不安な心」で使用されている。
主チャンネルの音色番号を(voice)に設定し、未使用チャンネルに割り当てられる副チャンネルの音色番号を(voice2)に設定する。

2つのチャンネルは ADPCM の再生周波数を共有しており、音色ごとに音程が計算されるわけではないことに注意が必要。併用できるインストゥルメントは限られるかもしれない。

0xF5~0xF8 (SaGa Frontier)
未実装命令。効果は 0xA0 と同じ。

0xF5 (FINAL FANTASY 7)
0xF4 の効果を解除する。

0xF6, balance:BYTE (FINAL FANTASY 7)
0xF4 のオーバーレイの主チャンネルと副チャンネルの音量バランスを 0~127 で指定する。
balanceが0だと主チャンネルが100%で副チャンネルが0%、127だとその逆となる。

0xF7, length:BYTE, balance:BYTE (FINAL FANTASY 7)
0xF6 のオーバーレイの音量バランスを、(length)[ticks]で、(balance)に推移する。
(length)が0の場合は 256 ticks と解釈される。

0xF8, rr:BYTE
未使用チャンネルを使用して、音符を2つのチャンネルの間で交互にキーオンする。FF7のオープニングや鷲の砦のティンパニ、ティファのテーマのメロディパートなどで使用されている。
その際、ハードウェア・エンベロープ (ADSR) の Release Rate を (rr) に設定する。

0xF9
0xF8 の効果を解除する。

0xFA~0xFB
未実装命令。効果は 0xA0 と同じ。

0xFC, address:WORD (SaGa Frontier)
拡張音色を設定する。
音色情報の構造体は、(address)(相対アドレス)に記述される。
構造体は、(3)項参照。

FINAL FANTASY 7 では:
0xE0~0xE7 と同じ未定義命令。

0xFD, timebase:BYTE, time:BYTE
拍子情報。(timebase)は一拍あたりのtick数を表し、(time)は一小節あたりの拍数を表す。
言い換えると、拍子を(time)[分子]/(192÷(timebase))[分母]に設定するといえる。

ただし、初期化のために2つのパラメータに0を指定するケースがあるようなので、プログラムを作成する際は0除算の可能性に注意が必要。

ゲーム内ではこの情報に基づいて現在の小節番号と拍数がカウントされる。

0xFE, measure:BYTE
小節番号を指定された値に設定する。

0xFF
未実装命令。効果は 0xA0 と同じ。



後期AKAO


0xE0
不明

0xE1, unknown:BYTE
不明

0xE2
不明

0xE3
不明

0xE4, length:BYTE, rate:BYTE
(length)[ticks]で、(depth)に音程LFOのrateを推移する。
(length)が0の場合は 256 ticks と解釈される。

0xE5, length:BYTE, rate:BYTE
(length)[ticks]で、(depth)に音量LFOのrateを推移する。
(length)が0の場合は 256 ticks と解釈される。

0xE6, length:BYTE, rate:BYTE
(length)[ticks]で、(depth)にパンLFOのrateを推移する。
(length)が0の場合は 256 ticks と解釈される。

0xE6, unknown:BYTE, unknown:BYTE
不明

0xE7~0xEF
不明

0xF0~0xFD, length:BYTE
音符・休符・タイ
音長は、length[ticks]となる。(ただし 0xA2 や 0xDC によって上書きされる可能性がある。このあたりの扱いは通常の音符と同じ)
0xF0 C
0xF1 Cis
0xF2 D
0xF3 Dis
0xF4 E
0xF5 F
0xF6 Fis
0xF7 G
0xF8 Gis
0xF9 A
0xFA B
0xFB H
0xFC タイ
0xFD 休符

0xFE, 0x00, tempo:WORD
テンポを設定する。BPM (拍/分) に変換する式は以下のとおり。
bpm = tempo / 218.453333333
正確には以下の式から上記の結論となる。
PPQN = 48
TIMER_FREQ = 0x44E8
bpm = 60.0 / (PPQN * (65536.0 / tempo) * (TIMER_FREQ / (33868800.0 / 8)))

0xFE, 0x01, length:BYTE, tempo:WORD
テンポを、(length)[ticks]で、(tempo)に推移する。
(length)が0の場合は 256 ticks と解釈される。

0xFE, 0x02, reverb:WORD
リバーブの深さを、(reverb)に設定する。

0xFE, 0x03, length:BYTE, reverb:WORD
リバーブの深さを、(length)[ticks]で、(reverb)に推移する。
(length)が0の場合は 256 ticks と解釈される。

0xFE, 0x04
パーカッションに切り替える。(4)項参照

0xFE, 0x05
パーカッションを終了する。

0xFE, 0x06, address:WORD
(address)(相対アドレス)に無条件ジャンプする。
主に無限ループに使われるが、一部、条件ジャンプ命令などと組み合わせ、
スパゲティーな構造になっている曲もあり、この限りで無い。

0xFE, 0x07, condition:BYTE, address:WORD
(condition)条件下において、(address)(相対アドレス)に条件ジャンプする。
ゲームの進行状況において曲を進行させる場合等に使われる。
例)
  • FINAL FANTASY 9 ラスボス
  • VAGRANT STORYの一部の曲

0xFE, 0x08, count:BYTE, address:WORD
リピート(0xC8~0xC9, 0xCA)内条件分岐。
(count)目のリピートであった場合、(address)(相対アドレス)にジャンプする。
(count)が0の場合は256と解釈される。

0xFE, 0x09, count:BYTE, address:WORD
リピート(0xC8~0xC9, 0xCA)内条件分岐。
(count)目のリピートであった場合、(address)(相対アドレス)にジャンプしてリピートを終了する。
(count)が0の場合は256と解釈される。

0xFE, 0x0A, voice:BYTE
音色番号を(voice)に指定する。0xA1コマンドと異なり、ループポイント以前のサンプルを再生しない。

技術的には、ループ開始アドレスを規定どおりに設定するが、サンプル開始アドレスを短い無音の ADPCM サンプルに向けることでこのような動作を実現する。

0xFE, 0x0B, address:WORD, address2:WORD
不明

0xFE, 0x0E, address:WORD
(address)(相対アドレス)にジャンプする。0xFE 0x0F で元の位置に復帰する。
ネスト不可。ネストした場合、以前のリターンアドレスは上書きされる。

0xFE, 0x0F
0xFE 0x0E から復帰する。

0xFE, 0x10, count:BYTE
(count) で指定された数のハードウェアチャンネルを予約する。
各トラックで予約チャンネルを使用するには別途 0xFE 0x1D の使用が必要。

0xFE, 0x11
予約チャンネルを解放する(予約チャンネルの数を0に設定する)

0xFE 0x12, length:BYTE, volume:BYTE
(length)[ticks]で、(volume)に音量を推移する。
(length)が0の場合は 256 ticks と解釈される。

0xFE, 0x14, voice:BYTE
拡張音色を設定する。(2)項参照

0xFE, 0x15, timebase:BYTE, time:BYTE
拍子を、(time)[分子]/(192÷(timebase))[分母]に設定する。

0xFE, 0x16, measure:BYTE
小節番号。

0xFE 0x19, length:BYTE, expression:BYTE
0xA9 の音量フェードをノートオンごとに適用する。
(length)が0の場合は 256 ticks と解釈される。

0xFE, 0x1A
不明

0xFE, 0x1B
不明。0xFE 0x1A の効果を解除する

0xFE, 0x1C, unknown:BYTE
不明

0xFE, 0x1D
0xFE 0x10 で割り当てられた予約チャンネルを現在のトラックの発音に使用する。
発音時は予約チャンネルを優先的に使用する。予約チャンネルがすべて使用済みの場合は、残りのチャンネルの使用を通常どおり試みる。

0xFE, 0x1E
0xFE 0x1D の効果を無効にし、現在のトラックで予約チャンネルを使用しないようにする。

0xFE, 0x1F
不明

0xFF
不明

後期AKAOインプリメンテーションマップ


後期AKAOにも、ゲームタイトルごとの実装の違いはわずかながら存在する。問題になるオペコードはあまり楽曲に登場することがなく一通りの解釈をしていても実際は問題にならないものがほとんどのように思うが、参考情報としてタイトル別の実装のばらつきを次の表に示す。

次の表は、ゲームタイトルごとにオペコードにどのようなデータ形式・効果が割り当てられているかを示している。(void) は引数を取らないオペコードであることを示す。n/a は処理が割り当てられていないことを示す(E0 と同じ効果になる)。NOP と書かれているオペコードは、引数を読み飛ばしているだけで処理が見られないことを表す。ばらつきのないオペコードについてはとくに情報を記していない。

Game Title (Year) E0 E1 E2 E3 E4 E5 E6 FE 0B FE 0C FE 0D FE 0E FE 0F FE 10 FE 11 ... FE 13 ... FE 17 FE 18 ... FE 1A FE 1B FE 1C FE 1D FE 1E FE 1F
Another Mind (1998) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
Chocobo Dungeon 2 (1998) (void) n/a n/a n/a n/a n/a n/a (int16, int16) NOP (byte, byte) NOP (void) (byte) (length: byte, target: byte) (byte) (void) n/a (byte) (length: byte, target: byte) (void) (void) n/a n/a n/a n/a
Final Fantasy 8 (1999) (void) n/a n/a n/a n/a n/a n/a (int16, int16) NOP (byte, byte) NOP (void) (byte) (length: byte, target: byte) NOP (byte) NOP (void) n/a (byte) (length: byte, target: byte) (void) (void) (byte) (void) (void) n/a
Chocobo Racing (1999) (void) n/a n/a n/a n/a n/a n/a (int16, int16) NOP (byte, byte) NOP (void) (byte) (length: byte, target: byte) AllocReservedVoices (byte) FreeReservedVoices (void) n/a (byte) (length: byte, target: byte) (void) (void) (byte) UseReservedVoices (void) UseNoReservedVoices (void) n/a
SaGa Frontier 2 (1999) (void) n/a n/a n/a n/a n/a n/a (int16, int16) NOP (byte, byte) NOP (void) (byte) (length: byte, target: byte) AllocReservedVoices (byte) FreeReservedVoices (void) n/a (byte) (length: byte, target: byte) (void) (void) NOP (byte) UseReservedVoices (void) UseNoReservedVoices (void) n/a
Racing Lagoon (1999) (void) n/a n/a n/a n/a n/a n/a (int16, int16) NOP (byte, byte) NOP (void) (byte) (length: byte, target: byte) AllocReservedVoices (byte) FreeReservedVoices (void) n/a (byte) (length: byte, target: byte) (void) (void) NOP (byte) UseReservedVoices (void) UseNoReservedVoices (void) n/a
Legend of Mana (1999) (void) (byte) (void) n/a n/a n/a n/a (int16, int16) n/a n/a Pattern (int16) PatternEnd (void) AllocReservedVoices (byte) FreeReservedVoices (void) n/a (byte) (length: byte, target: byte) (void) (void) NOP (byte) UseReservedVoices (void) UseNoReservedVoices (void) n/a
Front Mission 3 (1999) (void) (byte) (void) n/a n/a n/a n/a (int16, int16) n/a n/a Pattern (int16) PatternEnd (void) AllocReservedVoices (byte) FreeReservedVoices (void) n/a (byte) (length: byte, target: byte) (void) (void) NOP (byte) UseReservedVoices (void) UseNoReservedVoices (void) n/a
Chrono Cross (1999) (void) (byte) (void) n/a VibratoRateSlide (byte, byte) TremoloRateSlide (byte, byte) PanLfoRateSlide (byte, byte) Unknown (?) n/a n/a Pattern (int16) PatternEnd (void) AllocReservedVoices (byte) FreeReservedVoices (void) (void) n/a n/a (void) (void) NOP (byte) UseReservedVoices (void) UseNoReservedVoices (void) n/a
Vagrant Story (2000) (void) (byte) (void) n/a n/a n/a n/a (int16, int16) (byte) n/a Pattern (int16) PatternEnd (void) AllocReservedVoices (byte) FreeReservedVoices (void) n/a n/a n/a (void) (void) (byte) UseReservedVoices (void) UseNoReservedVoices (void) (void)
Final Fantasy 9 (2000) (void) (byte) (void) n/a VibratoRateSlide (byte, byte) TremoloRateSlide (byte, byte) PanLfoRateSlide (byte, byte) (int16, int16) n/a n/a Pattern (int16) PatternEnd (void) AllocReservedVoices (byte) FreeReservedVoices (void) n/a n/a n/a (void) (void) NOP (byte) UseReservedVoices (void) UseNoReservedVoices (void) n/a
Final Fantasy Origins - Final Fantasy 2 (2002) (void) (byte) (void) n/a VibratoRateSlide (byte, byte) TremoloRateSlide (byte, byte) PanLfoRateSlide (byte, byte) (int16, int16) n/a n/a Pattern (int16) PatternEnd (void) AllocReservedVoices (byte) FreeReservedVoices (void) n/a n/a n/a (void) (void) NOP (byte) UseReservedVoices (void) UseNoReservedVoices (void) n/a


AKAO サンプルデータファイル

本ページでは AKAO のシーケンスデータについて説明してきたが、音楽を再生するにはあわせてサンプルデータの理解が必要となる。
サンプルデータはシーケンスデータと同じく AKAO シグネチャつきのファイルに格納されているため、その構造を以下に示す。

初期AKAO - FINAL FANTASY 7

FF7 では以下のファイルにサンプルが格納されている。
  • SOUND/INSTR.DAT - メインサウンドのアーティキュレーション情報およびピッチ情報 (93 instruments)
  • SOUND/INSTR2.DAT - 「片翼の天使」のクワイアのデータ。ファイル構成は同上 (4 instruments)
  • SOUND/INSTR.ALL - メインサウンドの SPU 転送先アドレスとサンプル本体
  • SOUND/INSTR2.ALL- 「片翼の天使」のクワイアのデータ。ファイル構成は同上

INSTR.DAT (アーティキュレーション情報およびピッチ情報)

64バイトの構造体が繰り返される。ファイルサイズは記録されていないことから、読み込みサイズはプログラム内にハードコードされている。
Address Type
0x0000 DWORD サンプルの開始位置 (SPU アドレス)
0x0004 DWORD サンプルのループ開始位置 (SPU アドレス)
0x0008 BYTE ADSR: attack rate (0x00-0x7f)
0x0009 BYTE ADSR: decay rate (0x00-0x0f)
0x000A BYTE ADSR: sustain level (0x00-0x0f)
0x000B BYTE ADSR: sustain rate (0x00-0x7f)
0x000C BYTE ADSR: release rate (0x00-0x1f)
0x000D BYTE ADSR: attack mode (1, 5)
0x000E BYTE ADSR: sustain mode (1, 3, 5, 7)
0x000F BYTE ADSR: release mode (3, 7)
0x0010 DWORD[12] 音階ごとの基準ピッチ (C, Cis, D...)

基準ピッチはオクターブ6の音階における再生レートを表す。

INSTR.ALL (SPU 転送先アドレスと PSX-ADPCM 本体)

0x0000 DWORD サンプルデータの転送先 SPU アドレス
0x0004 DWORD サンプルデータのサイズ
0x0008 DWORD 0 (未使用?)
0x000C DWORD 0 (未使用?)
0x0010 BYTE[] サンプルデータ (PSX-ADPCM)

初期AKAO - SaGa Frontier

ファイルが一体化され、AKAO シグネチャが付与された。
Address Type
0x0000 BYTE(4) "AKAO" のASCII文字列
0x0004 WORD 未使用?
0x0006 WORD 未使用?
0x0008 WORD 未使用?
0x000A BYTE Timestamp (年) (BCD形式)
0x000B BYTE Timestamp (月) (BCD形式)
0x000C BYTE Timestamp (日) (BCD形式)
0x000D BYTE Timestamp (時) (BCD形式)
0x000E BYTE Timestamp (分) (BCD形式)
0x000F BYTE Timestamp (秒) (BCD形式)
0x0010 DWORD サンプルデータの転送先 SPU アドレス
0x0014 DWORD サンプルデータのサイズ
0x0018 DWORD 開始ID
0x001C DWORD 未使用?
0x0020 DWORD 未使用?
0x0024 DWORD 未使用?
0x0028 DWORD 未使用?
0x002C DWORD 未使用?
0x0030 DWORD 未使用?
0x0034 DWORD 未使用?
0x0038 DWORD 未使用?
0x003C DWORD 未使用?

インストゥルメントの個数は (128 - 開始ID) で算出される。

次に64バイトの構造体の繰り返しによるアーティキュレーション情報・ピッチ情報が続く。構造体の内容は FF7 の INSTR.DAT と同一のため説明は割愛する。

さらにその後ろには、サンプルデータが配置される。

初期AKAO

どのID帯にインストゥルメントをロードするかを指定可能となった。
また、終了ID が追加され、インストゥルメントの格納数が可変となった。
それ以外の点は SaGa Frontier と同じ。
Address Type
0x001C DWORD 終了ID (0 の場合は 0x100 とみなされる)

後期AKAO - Another Mind

Another Mind は過渡期のバージョンであり、他の後期AKAOとは若干異なるファイルレイアウトが採用されている。

ファイルの冒頭に出現する64バイトのヘッダーは後述のバージョンとおそらく同様。終了IDがインストゥルメントの個数になった模様。

Address Type
0x001C DWORD インストゥルメントの個数

ヘッダーの後には、64バイトの構造体の繰り返しによるアーティキュレーション情報・ピッチ情報が続く。構造体の内容は前バージョンと似ているが項目の順序が異なっているほか、サンプルの位置情報が SPU アドレスからオフセットに変更された。

また、基準ピッチが Q8 固定小数点数に変更されており、旧バージョンよりも値が256倍大きい点にも注意。

Address Type
0x0000 DWORD サンプルの開始位置 (サンプルデータ内の相対オフセット)
0x0004 DWORD サンプルのループ開始位置 (サンプルデータ内の相対オフセット)
0x0008 DWORD[12] 音階ごとの基準ピッチ (C, Cis, D...) (Q8 固定小数点数)
0x0038 BYTE ADSR: attack rate (0x00-0x7f)
0x0039 BYTE ADSR: decay rate (0x00-0x0f)
0x003A BYTE ADSR: sustain level (0x00-0x0f)
0x003B BYTE ADSR: sustain rate (0x00-0x7f)
0x003C BYTE ADSR: release rate (0x00-0x1f)
0x003D BYTE ADSR: attack mode (1, 5)
0x003E BYTE ADSR: sustain mode (1, 3, 5, 7)
0x003F BYTE ADSR: release mode (3, 7)

後期AKAO

Another Mind と比較すると、アーティキュレーション情報が64バイトから16バイトに再構成された。

ファイルの先頭には、以下の64バイトのヘッダーが記録される。

Address Type
0x0000 BYTE(4) "AKAO" のASCII文字列
0x0004 WORD File Serial ID
0x0006 WORD 不明
0x0008 DWORD 不明
0x000C DWORD 不明
0x0010 DWORD サンプルデータの転送先 SPU アドレス
0x0014 DWORD サンプルデータのサイズ
0x0018 DWORD 開始ID
0x001C DWORD インストゥルメントの個数
0x0020 DWORD 不明
0x0024 DWORD 不明
0x0028 DWORD 不明
0x002C DWORD 不明
0x0030 DWORD 不明
0x0034 DWORD 不明
0x0038 DWORD 不明
0x003C DWORD 不明

次に16バイトの構造体の繰り返しによるアーティキュレーション情報が続く。

Address Type
0x0000 DWORD サンプルの開始位置 (サンプルデータ内の相対オフセット)
0x0004 DWORD サンプルのループ開始位置 (サンプルデータ内の相対オフセット)
0x0008 WORD (signed) Fine Tune (※)
0x000A WORD Unity Key
0x000C WORD ADSR1
0x000E WORD ADSR2

※Fine Tune: 再生周波数に対する倍率を示す。cents のような対数スケールではない。たとえば、0x7FFF で 0x7FFF/0x8000 倍(約+1オクターブ)、-0x8000で0x8000/0x10000倍(-1オクターブ)に再生周波数を変化させる。

この後ろにサンプルデータが配置される。