GBサウンド2

GBサウンドです。DMG(Dot Matrix Game)サウンドとも呼ばれる機能は、初代GameBoyから継承されている機能です。正直なところGBと互換性がある為、Pan Docなどのドキュメントを見た方が早いかもしれません。ここでは仕様的側面より、プログラム的視点で書かせていただこうと思います。なお中の人は1回も作曲経験がないのに書いていることをご了承ください。

ことはじめ

前回、DirectSoundでは音の中身を図(波形)で説明をしました。一方、GBサウンドはサウンド1~4まで存在していて、レジスタがひしめき合っています。パラメータの内容をいくら文章ベースで説明したとしても、耳で記憶する以上に近道はないと思っています。HUGETrackerで単音を鳴らしてパラメータを調整してやってみた方が有意義です。ここではTrackerでやっていることをプログラムでさせています。やさしい順にサウンド2→1→3→4と紹介していきます。それでは音を鳴らす方法のためのレジスタを見ていきましょう。

REG_SOUNDCNT_X

4000084h - SOUNDCNT_X (NR52) - Sound on/off (R/W)
Bits 0-3 are automatically set when starting sound output, and are automatically cleared when a sound ends.
(Ie. when the length expires, as far as length is enabled. The bits are NOT reset when an volume envelope ends.)
  Bit        Expl.
  0     R    Sound 1 ON flag (Read Only)
  1     R    Sound 2 ON flag (Read Only)
  2     R    Sound 3 ON flag (Read Only)
  3     R    Sound 4 ON flag (Read Only)
  4-6   -    Not used
  7     R/W  PSG/FIFO Master Enable (0=Disable, 1=Enable) (Read/Write)
  8-31  -    Not used
While Bit 7 is cleared, both PSG and FIFO sounds are disabled, and all PSG registers at 4000060h..4000081h are reset to zero
(and must be re-initialized after re-enabling sound).
However, registers 4000082h and 4000088h are kept read/write-able
(of which, 4000082h has no function when sound is off, whilst 4000088h does work even when sound is off).
REG_SOUNDCNT_X = 0x80;	// turn on sound circuit

まず、Bit7をPSG/FIFO Master Enableにします。しないと音が出ません。

REG_SOUNDCNT_L

4000080h - SOUNDCNT_L (NR50, NR51) - Channel L/R Volume/Enable (R/W)
  Bit        Expl.
  0-2   R/W  Sound 1-4 Master Volume RIGHT (0-7)
  3     -    Not used
  4-6   R/W  Sound 1-4 Master Volume LEFT (0-7)
  7     -    Not used
  8-11  R/W  Sound 1-4 Enable Flags RIGHT (each Bit 8-11, 0=Disable, 1=Enable)
  12-15 R/W  Sound 1-4 Enable Flags LEFT (each Bit 12-15, 0=Disable, 1=Enable)
REG_SOUNDCNT_L = 0x2277; // full volume, enable sound 2 to left and right

2進数は0010 0010 0111 0111bなので、Master Volume RIGHT,LEFTを0x7に、Sound 2 Enable Flags RIGHT,LEFTをEnableにします。

REG_SOUNDCNT_H

4000082h - SOUNDCNT_H (GBA only) - DMA Sound Control/Mixing (R/W)
  Bit        Expl.
  0-1   R/W  Sound # 1-4 Volume   (0=25%, 1=50%, 2=100%, 3=Prohibited)
  2     R/W  DMA Sound A Volume   (0=50%, 1=100%)
  3     R/W  DMA Sound B Volume   (0=50%, 1=100%)
  4-7   -    Not used
  8     R/W  DMA Sound A Enable RIGHT (0=Disable, 1=Enable)
  9     R/W  DMA Sound A Enable LEFT  (0=Disable, 1=Enable)
  10    R/W  DMA Sound A Timer Select (0=Timer 0, 1=Timer 1)
  11    W?   DMA Sound A Reset FIFO   (1=Reset)
  12    R/W  DMA Sound B Enable RIGHT (0=Disable, 1=Enable)
  13    R/W  DMA Sound B Enable LEFT  (0=Disable, 1=Enable)
  14    R/W  DMA Sound B Timer Select (0=Timer 0, 1=Timer 1)
  15    W?   DMA Sound B Reset FIFO   (1=Reset)
REG_SOUNDCNT_H = 2; // Overall output ratio - Full

ボリュームを100%にしています。

準備完了

操作をまとめたのが以下のコードです。サウンド2を使いたい場合はこの形が基本になります。

REG_SOUNDCNT_X = 0x80;		// turn on sound circuit
REG_SOUNDCNT_L = 0x2277;	// full volume, enable sound 2 to left and right
REG_SOUNDCNT_H = 2;		// Overall output ratio - Full

REG_SOUND2CNT_L、REG_SOUND2CNT_H

4000068h - SOUND2CNT_L (NR21, NR22) - Channel 2 Duty/Length/Envelope (R/W)
  Bit        Expl.
  0-5   W    Sound length; units of (64-n)/256s  (0-63)
  6-7   R/W  Wave Pattern Duty                   (0-3, see below)
  8-10  R/W  Envelope Step-Time; units of n/64s  (1-7, 0=No Envelope)
  11    R/W  Envelope Direction                  (0=Decrease, 1=Increase)
  12-15 R/W  Initial Volume of envelope          (1-15, 0=No Sound)
Wave Duty:
  0: 12.5% ( -_______-_______-_______ )
  1: 25%   ( --______--______--______ )
  2: 50%   ( ----____----____----____ ) (normal)
  3: 75%   ( ------__------__------__ )
The Length value is used only if Bit 6 in NR14 is set.
400006Ch - SOUND2CNT_H (NR23, NR24) - Channel 2 Frequency/Control (R/W)
  Bit        Expl.
  0-10  W    Frequency; 131072/(2048-n)Hz  (0-2047)
  11-13 -    Not used
  14    R/W  Length Flag  (1=Stop output when length in NR11 expires)
  15    W    Initial      (1=Restart Sound)
  16-31 -    Not used

音を作り出す重要な部分です。NR21, NR22などの記載はGameboyのレジスタ表記で互換性を持ちます。GBA本体にGBカードリッジを差しても遊べるようにできるてるのですから当然な話です。

Frequency

400006Ch - SOUND2CNT_H (NR23, NR24) - Channel 2 Frequency/Control (R/W)
0-10  W    Frequency; 131072/(2048-n)Hz  (0-2047)

主役はFrequency(周波数)で、他は引き立て役の意味を持ちます。0-2047という数字を式の通り入れてHzを算出するわけですけれど、世の中にはすでにドレミ音階のテーブルが存在しています。

u16 FreqTable[12*6] = {
//         C      C+       D      D+       E       F      F+       G      G+       A      A+       B
          44,    156,    262,    363,    457,    547,    631,    710,    786,    854,    923,    986,   // o3 
        1046,   1102,   1155,   1205,   1253,   1297,   1339,   1379,   1417,   1452,   1486,   1517,   // o4
        1546,   1575,   1602,   1627,   1650,   1673,   1694,   1714,   1732,   1750,   1767,   1783,   // o5
        1798,   1812,   1825,   1837,   1849,   1860,   1871,   1881,   1890,   1899,   1907,   1915,   // o6
        1923,   1930,   1936,   1943,   1949,   1954,   1959,   1964,   1969,   1974,   1978,   1982,   // o7
        1985,   1988,   1992,   1995,   1998,   2001,   2004,   2006,   2009,   2011,   2013,   2015,   // o8
};

オクターブ5のラ音、o5A=1750を計算してみると131072 / (2048-1750) = 131072 / 298 = 439.838...という数字が出てきました。四捨五入すれば440Hzです。TrackerやMMLライバはテーブルより音符を抽出しています。

Sound length

4000068h - SOUND2CNT_L (NR21, NR22) - Channel 2 Duty/Length/Envelope (R/W)
  0-5   W    Sound length; units of (64-n)/256s  (0-63)
400006Ch - SOUND2CNT_H (NR23, NR24) - Channel 2 Frequency/Control (R/W)
  14    R/W  Length Flag  (1=Stop output when length in NR11 expires)

フラグをセットすれば、長さをのパラメータが有効になります。数字が大きいほど音が長くなるかというと逆です。注意してください。

Wave Pattern Duty

4000068h - SOUND2CNT_L (NR21, NR22) - Channel 2 Duty/Length/Envelope (R/W)
  6-7   R/W  Wave Pattern Duty                   (0-3, see below)

Wave Duty:
  0: 12.5% ( -_______-_______-_______ )
  1: 25%   ( --______--______--______ )
  2: 50%   ( ----____----____----____ ) (normal)
  3: 75%   ( ------__------__------__ )

波形のON, OFFの割合を決めます。

Envelope

4000068h - SOUND2CNT_L (NR21, NR22) - Channel 2 Duty/Length/Envelope (R/W)
  8-10  R/W  Envelope Step-Time; units of n/64s  (1-7, 0=No Envelope)
  11    R/W  Envelope Direction                  (0=Decrease, 1=Increase)
  12-15 R/W  Initial Volume of envelope          (1-15, 0=No Sound)

各パラメータと波形の関係は以下のとおりです。図はhUGETrackerよりキャプチャしました。

Init0
Dir1
Step7
Init15
Dir0
Step7

テスト

実際にレジスタに直接値を入れて音を鳴らしてみます。以下にサンプルを用意しました。

REG_SOUNDBIAS

4000088h - SOUNDBIAS - Sound PWM Control (R/W, see below)
This register controls the final sound output. The default setting is 0200h, it is normally not required to change this value.
  Bit        Expl.
  0     -    Not used
  1-9   R/W  Bias Level (Default=100h, converting signed samples into unsigned)
  10-13 -    Not used
  14-15 R/W  Amplitude Resolution/Sampling Cycle (Default=0, see below)
  16-31 -    Not used
Amplitude Resolution/Sampling Cycle (0-3):
  0  9bit / 32.768kHz   (Default, best for DMA channels A,B)
  1  8bit / 65.536kHz
  2  7bit / 131.072kHz
  3  6bit / 262.144kHz  (Best for PSG channels 1-4)
For more information on this register, read the descriptions below.

Max Output Levels (with max volume settings) 2つのFIFOは、それぞれ出力範囲の最大値(±200h)に対応しています。 4つのPSGは、それぞれ出力範囲の4分の1(±80h)に対応します。6つのチャンネルの現在の出力レベルは、ハードウェアによって加算されます。

つまり、FIFOとPSGを合わせると、出力範囲の3分の1(±600h)に達します。

BIAS値はその符号付きの値に加えられます。デフォルトのBIAS(200h)では、可能な範囲は-400h~+800hとなりますが、符号なし10ビットの出力範囲0~3FFhを超える値は、MinMax(0,3FFh)にクリップされます。

Resampling to 32.768kHz / 9bit (default) PSGのチャンネル1〜4は内部的に262.144kHzで生成されており、DMAのサウンドA〜Bは理論的には16.78MHzまでのタイマーレートで生成可能です。

しかし、最終的に出力される音は、32.768kHzのレートで、9bitの深さ(上記の10bitの値を2で割った値)にリサンプリングされます。

必要に応じて、32.768kHzよりも高いレートをSOUNDBIASレジスタで選択することができますが、その場合は9bitよりも小さい深さになります。

PWM (Pulse Width Modulation) Output 16.78MHz / 1bit さて、いよいよ実際の出力です。GBAは2つの電圧(LowとHigh)しか出力できませんが、この「ビット」はシステムクロック速度(16.78MHz)で出力されます。

デフォルトの32.768kHzのサンプリングレートを使用した場合、1サンプルあたり512ビットが出力されます(512*32K=16M)。

各サンプル値(9ビット範囲、N=0~511)は、N個の下位ビットと512~N個の上位ビットで出力されます。

このようにして得られた「ノイズ」は、コンデンサやスピーカー、そして人間の聴覚によって平滑化され、32kHzのサンプリングレートで9ビットの電圧をD/A変換したクリーンな音になります。

BIASレベルの変更について 通常、きれいな音を出力するには200hを使用します。音が出ない期間(PWM回路がロービットのみを出力することで、消費電力を抑えたり、32KHzのノイズを防いだりしている)は、000hの値を使用すると良いでしょう。

またSoundBias機能(SWI19h)を使用すると,ハードスクラッチノイズを発生させずに,ゆっくりとBIASレベルを増減させることができます。


トップ   一覧 検索 最終更新   ヘルプ   最終更新のRSS