This article explains the structure of Dragon Quest 6 & Dragon Quest 3. The format is actually a variant of the Nintendo SPC, though there are many differences between this engine and the basic N-SPC format.

ドラゴンクエスト6とドラゴンクエスト3の音楽フォーマットのコマンドについて書き記しておきます。hbdqspcを作ってから半年経った今ようやく気がついたことには、これはSNES Nintendo Music Format Specに記した任天堂標準フォーマットの変種です。とはいえ、その構造やコマンドは結構大幅に異なっているので、同一のフォーマットとして取り扱うのはあまり賢明ではありません。

Structure

; song/sfx list (16 entries?)
f000: db $00,$00 ; lo-byte
f00c: db $80,$90 ; hi-byte
; seq header
8000: dw $000a ; instrument table offset
8002: dw $0016,$0200,$0300 ; start pos of voice stream for each track
8008: dw $0000 ; no more tracks
; instrument table (1 entry = 6 bytes)
800a: db $xx,$xx,$xx,$xx,$xx,$xx
8010: db $xx,$xx,$xx,$xx,$xx,$xx
; voice stream
8016: db ...

めんどくさがって疑似アセンブリの内容が幾分適当ですが……非常にシンプルで、かつまとまった構造をしています。ARAM上の絶対アドレスで位置を表現するフォーマットは多いですが、このエンジンでは、最初の楽曲位置はさておき、それ以降のシーケンスデータに関してはすべて「オフセット」で場所を示します。私が見た限り、曲へのポインタは上位バイトと下位バイトが少し離れた位置にありました。

細かいことは、拙作のhbdqspcを通して生のデータと向き合えば、それなりにわかるのではないかと思います。

Translated:

The trouble is that the contents of the pseudo-assembly are somewhat appropriate ... but it has a very simple and integrated structure. There are many formats that express position by absolute address on ARAM, but with this engine, the first music position is aside, and for all subsequent sequence data, the position is indicated by "offset". As far as I could see, the pointer to the song was a little bit apart from the high and low bytes.

The details can be understood as long as they correspond to the raw data through the hbdqspc of the masterpiece.

Voice Bytes

Mapping

VCMD Description Arguments
$00 End of Track
$01-7F Note Parameters [xy]
$80-CF Notes
$D0 Tie
$D1 Rest
$D2 Slur On
$D3 Slur Off
$D4 Set Instrument [xx]
$D5 Unknown.7
$D6 Pan [xx]
$D7 Pan Fade [xx yy]
$D8 Vibrato On [xx yy zz]
$D9 Vibrato Fade [xx]
$DA Vibrato Off
$DB Main Volume [xx]
$DC Main Volume Fade [xx yy]
$DD Tempo [xx]
$DE Unknown.1 [xx]
$DF Global Transpose [xx]
$E0 Per-Voice Transpose [xx]
$E1 Tremolo On [xx yy zz]
$E2 Tremolo Off
$E3 Volume [xx yy]
$E4 Volume Fade [xx yy]
$E5 Unknown.3 [xx yy zz]
$E6 Pitch Envelope To [xx yy zz]
$E7 Pitch Envelope From [xx yy zz]
$E8 Pitch Envelope Off
$E9 Tuning [xx]
$EA Echo Volume [xx yy]
$EB Echo Parameters [xx yy zz]
$EC Unknown.3 [xx yy zz]
$ED Echo Off
$EE Echo On
$EF Echo FIR [C0 C1 C2 C3 C4 C5 C6 C7]
$F0 Set ADSR [ADSR(1) ADSR(2)]
$F1 Duration / Velocity [xx]
$F2 Jump [xx yy]
$F3 Call Subroutine [xx yy]
$F4 Return From Subroutine
$F5 Noise On
$F6 Noise Off
$F7 Noise Clock [NCK]
$F8 Unknown.0
$F9 Execute Sub Command [nn ...]
$FA-FF Undefined (Out of Table)
SubCMD $00 Set Repeat Count [xx]
SubCMD $01 Conditional Loop [xx yy]
SubCMD $02 Unknown.1
SubCMD $03 Set Attack Rate [xx]
SubCMD $04 Set Decay Rate [xx]
SubCMD $05 Set Sustain Level [xx]
SubCMD $06 Set Release Rate [xx]
SubCMD $07 Set Sustain Rate [xx]
SubCMD $08 Undefined (Null)
SubCMD $09 Phase Reverse Surround On / Off [xx yy]
SubCMD $0A Undefined (Null)
SubCMD $0B-FF Undefined (Out of Table)

End of Track ($00)

チャンネルの演奏データの終端を意味します。

Translated:

Indicates the end of channel performance data.

Note Parameters ($01-7F)

VByte itself means the length of the following note (24 = quarter note, usually).
Takes 1 argument $xy:
  When $xy < $80:
    $x = Duration Rate (0-7)
    $y = Velocity Rate (0-15)

コマンドバイト自身で音の長さを表します。通常24が四分音符に相当します。

続くバイト($xyとする)が$80未満であればそれも処理します。xで音の長さ(クオンタイズ)、yで音の大きさを段階的に指定します。数値に対応してどのような比率が割り当てられているのかは、中のテーブルの値によります。

つまり、このコマンドの効果は(細かいパラメータの違いは除いて)任天堂エンジンと同じです。

Translated:

Itself represents the length of the sound-byte command. Equivalent to a quarter note is usually 24.

Last byte ($xy that) but it also handles of less than $80. x The length of the sound (quantization), y specify the size of the sound stages. What percentage of assigned numbers correspond to what is in the table depends on the value.

In other words, the effect of this command (except for small differences in parameters) engine is the same as Nintendo.

Duration Rate

0 1 2 3 4 5 6 7
35 70 105 140 175 210 245 255
$23 $46 $69 $8C $AF $D2 $F5 $FF

Velocity Rate

0 1 2 3 4 5 6 7 8 9 A B C D E F
25 40 55 70 85 100 115 130 145 160 176 190 205 220 235 255
$19 $28 $37 $46 $55 $64 $73 $82 $91 $A0 $B0 $BE $CD $DC $EB $FF

Notes ($80-CF)

VByte itself means tone of the note.

The tone map is an example, the default, it can be tuned differently.

Tone Map

C C+ D D+ E F F+ G G+ A A+ B
Octave 1 $80 $81 $82 $83 $84 $85 $86 $87 $88 $89 $8A $8B
Octave 2 $8C $8D $8E $8F $90 $91 $92 $93 $94 $95 $96 $97
Octave 3 $98 $99 $9A $9B $9C $9D $9E $9F $A0 $A1 $A2 $A3
Octave 4 $A4 $A5 $A6 $A7 $A8 $A9 $AA $AB $AC $AD $AE $AF
Octave 5 $B0 $B1 $B2 $B3 $B4 $B5 $B6 $B7 $B8 $B9 $BA $BB
Octave 6 $BC $BD $BE $BF $C0 $C1 $C2 $C3 $C4 $C5 $C6 $C7
Octave 7 $BC $BD $BE $BF $C0 $C1 $C2 $C3 $C4 $C5 $C6 $C7
Octave 8 $C8 $C9 $CA $CB $CC $CD $CE $CF

音程を伴って音符を意味します。長さや強さは$01-7fで設定します。

Translated:

Means the notes with a pitch. The length and intensity set at $ 01-7f.

Tie ($D0)

Tie keeps uttering sound.

Rest ($D1)

Rest stops uttering sound.

Slur On ($D2)

スラーの有効・無効を設定します。再発音することなく、音程のみ変更して音を鳴らす場合に使用します。

Translated:

Set the validity of the slur. Pronounced without re-used only when a sound change pitch.

Slur Off ($D3)

スラーの有効・無効を設定します。再発音することなく、音程のみ変更して音を鳴らす場合に使用します。

Translated:

Set the validity of the slur. Pronounced without re-used only when a sound change pitch.

Set Instrument ($D4)

xx = Voice Number
  SRCN and ADSR is stored in the instrument table, xx is index for it.

音色を設定します。実際に音源に設定されるSRCNやADSRの情報はテーブルに収められていて、このコマンドで指定するのはそのテーブルのインデックスです。

Translated:

Set the tone. Is set to the actual source of the information SRCN ADSR and they are contained in the table by this command to specify the index of the table.

Unknown.7 ($D5)

DQ6とDQ3でコードが違ったかもしれません。nopのようにも見えますが、なぜかサイズテーブルには長さが7だと書かれています。本家BGM中には出現しません。

Translated:

DQ3 and DQ6 code may be different. NOP may look like, the table size is why it says 7 in length. BGM does not appear in the upstream.

Pan ($D6)

Lower-5bit for pan value (0-20).

音の左右位置を設定します。値の範囲は0~20と狭いです(実際の設定比率は内部テーブル定義)。10を中心として、値が小さくなるにつれ左、大きくなるにつれ右に音が移動します。

任天堂エンジンでは上位ビットで左右の位相反転を決定しますが、このエンジンではsubcmd $09でそれを決定します。

Translated:

Set the location of the sound side. The range is from 0 to 20 and small (the ratio of the actual settings within the table definition.) 10 Focusing on the left becomes smaller the value, the right to move the sound grows.

Nintendo is the engine determines the phase reversal of left and right upper bits, the engine will be determined it sub command $09.

Pan Fade ($D7)

xx = Length
yy = Destination (yy <= 20?)

音の位置をxx時間かけて現在の値からyyへとフェード。

Translated:

Sound position from its current value over time xx yy to fade.

Vibrato On ($D8)

xx = Delay
yy = Rate
zz = Depth

ビブラート(音程の揺れ)を有効にします。発音からxx時間後に、yyの早さでzzの大きさのビブラートがかかるよう設定します。

Translated:

Vibrato (pitch swing) to be enabled. Hours later the sound xx, yy zz sets in as fast as it takes the size of vibrato.

Vibrato Fade ($D9)

xx = Length
  Fade vibrato depth from 0 to current value.

ビブラートの深さを一時的に0に設定したのち、xx時間かけて滑らかに元の値へと変化させて演奏するよう設定します。

Translated:

Temporarily set to 0 then the depth of vibrato, xx will configure it to play smoothly transformed into the original value over time.

Vibrato Off ($DA)

ビブラートを無効にします。具体的にはVibrato Depthを0にしています。

Translated:

Disable vibrato. Specifically, Vibrato Depth to 0.

Main Volume ($DB)

楽曲全体の音量をxxに設定します。初期値は最大値より幾分低い。

Translated:

The volume of the entire song set to xx. The initial value is somewhat lower than the maximum.

Main Volume Fade ($DC)

xx = Length
yy = Destination

楽曲全体の音量をxx時間かけて現在の値からyyへとフェード。

Translated:

The volume of the entire song from the current value over time xx yy to fade.

Tempo ($DD)

x = Speed 
  About 12240000/60000000 of beat per minutes?
  12240000 = (timer0) 2ms * 24 * 256

楽曲の演奏速度を指定します。bpmを12240000/60000000した値で指定します。

Translated:

Specifies the speed of music playing. 12240000/60000000 bpm to specify the value.

Unknown.1 ($DE)

Function is unknown; this function doesn't appear in any BGM.

Global Transpose ($DF)

xx = Semitones (Signed)

全チャンネルの演奏音程をxx上げます(負数も指定可)。

Translated:

xx raises the pitch of all channels playing (can also specify a negative number.)

Per-Voice Transpose ($E0)

xx = Semitones (Signed)

単一チャンネルの演奏音程をxx上げます(負数も指定可)。

Translated:

Increase the pitch plays a single-channel xx (can also specify a negative number.)

Tremolo On ($E1)

xx = Delay
yy = Rate
zz = Depth

トレモロ(音量の揺れ)を有効にします。発音からxx時間後に、yyの早さでzzの大きさのトレモロがかかるよう設定します。

Translated:

Tremolo (shaking volume) enabled. Hours later the sound xx, yy zz sets in as fast as it takes the size of the tremolo.

Tremolo Off ($E2)

Disable the tremolo.

Volume ($E3)

xx = Length
yy = Destination

Sets the volume (xx) of the channel (yy).

Volume Fade ($E4)

チャンネルの音量をxx時間かけて現在の値からyyへとフェード。

Translated:

The volume of the channel from its current value over time xx yy to fade.

Unknown.3 ($E5)

Function is unknown; this function doesn't appear in any BGM.

Pitch Envelope To ($E6)

xx = Delay
yy = Length
zz = Key (Signed)
Sort of "do pitch slide for all of the following notes" VCMD.
Utter a note normally, wait for xx ticks, then fade the key to zz semitones higher (lower, when it's a minus number) for yy ticks.

以降の音が「xx時間後にyy時間かけてzzだけ高くなる」ように指定します。zzは半音単位で、負数も指定できます。

Translated:

Since the sound of "xx yy hours after hours to increase by zz" as specified. zz is a semitone, you can also specify a negative number.

Pitch Envelope From ($E7)

xx = Delay
yy = Length
zz = Key (Signed)
Sort of "do pitch slide for all of the following notes" vcmd.
Utter a note from higher (lower, when it's a minus number) than zz semitones, wait for xx ticks, then fade the key to normal pitch for yy ticks.

Translated:

Since the sound of "high-pitched than usual pronunciation zz, xx yy h after return to normal pitch over time" as specified. zz is a semitone, you can also specify a negative number.

Pitch Envelope Off ($E8)

Disables the effect of the Pitch Envelope.

Tuning ($E9)

xx = Unsigned
  Make the pitch xx/256 semitones higher.

音程をわずかに変化させます。指定できる値は正の数のみなので、音程を下げることはできません。

Translated:

Slightly alters the pitch. Since only values are positive numbers, not to lower the pitch.

Echo Volume ($EA)

xx = Echo Left Volume (EVOL (L))
yy = Echo Right Volume (EVOL (R))

エコーを有効にするチャンネルと音量を指定します。レジスタに設定される値そのままです。

Translated:

Specifies the volume to enable the echo channel.Register value is set to remain the same.

Echo Parameters ($EB)

xx = Echo Delay (EDL)
yy = Echo Feedback (EFB)
zz = Echo Filter
  Index for Table (0 to 3)

エコーの詳細を設定します。xxとyyはレジスタの値そのまま、zzはFIRフィルタの種類で、0~3の範囲で指定します。

Translated:

Sets the details of the echo. The value of the register as it is xx and yy, zz are the FIR filter type can range from 0 to 3.

# FIR
0 FF 08 17 24 24 17 08 FF
1 58 BF DB F0 FE 07 0C 0C
2 0C 21 2B 2B 13 FE F3 F9
3 00 33 34 D9 E5 01 FC EB

Unknown.3c ($EC)

Function is unknown; this function doesn't appear in any BGM.

Echo Off ($ED)

Disable the echo channel.

Echo On ($EE)

Enable the echo channel.

Echo FIR ($EF)

Specify the echo channel FIR filter coefficients directly.

Set ADSR ($F0)

Specify the ADSR register directly.

Duration / Velocity ($F1)

xx ($00-7F) = Same as the second parameter of $01-7F

デュレーション・ベロシティの設定をします。$01-7fの2番目の引数の処理をコマンドとして独立させたものです。なので通常$80以上は指定しません。

Translated:

Set the duration velocity. $01-7F of the second argument is the command was processed as an independent. Hisashi Tooru more than $80 so is not specified.

Jump ($F2)

Jump to offset $yyxx from the head of sequence.

指定位置に無条件ジャンプします。位置はシーケンスのヘッダからの相対的なオフセットで指定します。ループに用いられます。

Translated:

Unconditionally jump to the specified location. Specify the offset position relative to the sequence header. Loop is used.

Call Subroutine ($F3)

Subroutine jump to offset $yyxx from the head of sequence (nesting is not allowed).

指定位置にサブルーチンジャンプします。$f2と違い、$f4で呼び出し位置に戻ります。特定フレーズを使い回すのに用いられます。サブルーチンのネストは許されません。

Translated:

Subroutine will jump to the specified location. Unlike $F2, $F4 call returns to the position. Is used to turn a phrase used. Subroutine nesting is not allowed.

Return From Subroutine ($F4)

Returns from a subroutine jump by $F3.

Noise On ($F5)

Enable SPC700 noise.

Noise Off ($F6)

Disable SPC700 noise.

Noise Clock ($F7)

ノイズのクロックを設定します。引数はNCKの値なので、$00-1fで指定します。

Translated:

Set the clock noise. Since the argument of NCK, $ 00-1f Specify.

Unknown.0 ($F8)

Function is unknown; this function doesn't appear in any BGM.

Undefined ($FA-FF)

Treatment is beyond the scope of the table. Please do not use.

Execute Sub Command ($F9)

nn = Sub Command (SubCMD) #

サブコマンドを実行します。nnの値に応じてさまざまなコマンドを実行します。

以下、サブコマンドに関して解説を続けます。nn以前の引数は省略しています。

Translated:

Sub-command. nn command depending on a variety of values.

Following command on the sub-commentary continues. nn old argument has been omitted.

Set Repeat Count (Sub Command $00)

Set Repeat Count for SubCMD $01

サブコマンド$01の条件ジャンプのループ回数を設定します。ループ部突入の直前に記せばよいでしょう。

Translated:

Subcommand sets the number of conditional jump loop $01. 記Se do I rush just before the loop part.

Conditional Loop (Sub Command $01)

1. If repeat count is non-zero, decrement it.
2. If it's still non-zero, jump to offset $yyxx.
3. Initial value of the repeat count is set by subcmd $00.

条件ジャンプです。カウンタが0になるまでは、デクリメントとともにジャンプを続けます。カウンタの初期値はサブコマンド$00で指定します。

Translated:

The conditional jump. 0 until the counter is decremented and continue to jump. Initial counter value is specified in the sub-command $00.

Unknown.1 (Sub Command $02)

Function is unknown; this function doesn't appear in any BGM. Appears to be NOP?

Set Attack Rate (Sub Command $03)

ADSRのARを指定します。値の範囲は$00-0fです。

Translated:

ADSR specify the AR. The range is a $00-0F.

Set Decay Rate (Sub Command $04)

ADSRのDRを指定します。値の範囲は$00-07です。

Translated:

ADSR specify the DR. The range is $00-07.

Set Sustain Level (Sub Command $05)

ADSRのSLを指定します。値の範囲は$00-07です。

Translated:

SL-ADSR specified. The range is $00-07.

Set Release Rate (Sub Command $06)

デュレーションで設定された長さの発音終了後に設定される、ADSRのSRを指定します。値の範囲は$00-1Fです。

Translated:

Be set after set in the pronunciation of long duration, ADSR specify the SR. The range is a $00-1F.

Set Sustain Rate (Sub Command $07)

デュレーションで設定された長さの発音時に設定される、ADSRのSRを指定します。値の範囲は$00-1Fです。

Translated:

Pronunciation is set at a length set by the duration, ADSR specify the SR. The range is a $00-1F.

Phase Reverse Surround On/Off (Sub Command $09)

xx is for Left
yy is for Right
  Zero     = Off
  Non-Zero = On

波形の位相反転の有無を、左右それぞれ設定します。

Translated:

Set the phase inversion of the waveform on the left and right respectively.

Translated and expanded upon from LoveEMU, previously http://d.hatena.ne.jp/loveemu/