サウンド4はホワイトノイズを作ります。各パラメータの関係は以下のとおりです。
| 主役1 | Frequency Ratio | |
| 主役2 | Frequency Shift | |
| 引き立て役1 | Sound length | 音の長さ |
| 引き立て役2 | Envelope | 初期音量、減衰増幅、変化量 |
| 引き立て役3 | Counter Step | 一定の速度での周波数変化 |
REG_SOUNDCNT_X = 0x80; // turn on sound circuit REG_SOUNDCNT_L = 0x8877; // full volume, enable sound 4 to left and right REG_SOUNDCNT_H = 2; // Overall output ratio - Full
4000078h - SOUND4CNT_L (NR41, NR42) - Channel 4 Length/Envelope (R/W) Bit Expl. 0-5 W Sound length; units of (64-n)/256s (0-63) 6-7 - Not used 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) 16-31 - Not used The Length value is used only if Bit 6 in NR44 is set.
400007Ch - SOUND4CNT_H (NR43, NR44) - Channel 4 Frequency/Control (R/W) The amplitude is randomly switched between high and low at the given frequency. A higher frequency will make the noise to appear 'softer'. When Bit 3 is set, the output will become more regular, and some frequencies will sound more like Tone than Noise. Bit Expl. 0-2 R/W Dividing Ratio of Frequencies (r) 3 R/W Counter Step/Width (0=15 bits, 1=7 bits) 4-7 R/W Shift Clock Frequency (s) 8-13 - Not used 14 R/W Length Flag (1=Stop output when length in NR41 expires) 15 W Initial (1=Restart Sound) 16-31 - Not used Frequency = 524288 Hz / r / 2^(s+1) ;For r=0 assume r=0.5 instead Noise Random Generator (aka Polynomial Counter) Noise randomly switches between HIGH and LOW levels, the output levels are calculated by a shift register (X), at the selected frequency, as such: 7bit: X=X SHR 1, IF carry THEN Out=HIGH, X=X XOR 60h ELSE Out=LOW 15bit: X=X SHR 1, IF carry THEN Out=HIGH, X=X XOR 6000h ELSE Out=LOW The initial value when (re-)starting the sound is X=40h (7bit) or X=4000h (15bit). The data stream repeats after 7Fh (7bit) or 7FFFh (15bit) steps.

#include "lib/gba.h"
#include "irq.arm.h"
#include "key.h"
#include "mode3.h"
//---------------------------------------------------------------------------
typedef struct {
s32 cur; // 現在値
s32 min;
s32 max;
s32 adj; // 増減値
} ST_PARAM;
//---------------------------------------------------------------------------
void DrawParam(ST_PARAM* p)
{
for(s32 i=0; i<8; i++)
{
Mode3DrawPrintf(20, 5+i, "%04X", p[i].cur);
}
if(p[2].cur == 0) Mode3DrawStr(25, 5+2, "(Dec)");
else Mode3DrawStr(25, 5+2, "(Inc)");
if(p[5].cur == 0) Mode3DrawStr(25, 5+5, "(15 steps)");
else Mode3DrawStr(25, 5+5, "( 7 steps)");
switch(p[8].cur)
{
case 0: Mode3DrawStr(20, 5+8, "9-bits/32768 Hz "); break;
case 1: Mode3DrawStr(20, 5+8, "8-bits/65536 Hz "); break;
case 2: Mode3DrawStr(20, 5+8, "7-bits/131072 Hz"); break;
case 3: Mode3DrawStr(20, 5+8, "6-bits/262144 Hz"); break;
}
u16 L, H;
L = (p[3].cur<<12) + (p[2].cur<<11) + (p[1].cur<< 8) + p[0].cur;
H = (p[7].cur<<14) + (p[6].cur<< 4) + (p[5].cur<< 3) + p[4].cur;
Mode3DrawPrintf(33, 0, "%04X", L);
Mode3DrawPrintf(33, 1, "%04X", H);
}
//---------------------------------------------------------------------------
int main(void)
{
REG_WSCNT = 0x4317;
Mode3Init();
IrqInit();
KeyInit();
ST_PARAM param[9];
bool isSnd = false;
s16 sel = 0;
_Memset(¶m, 0x00, sizeof(param));
param[ 0].cur = 0x0;
param[ 1].cur = 0x7;
param[ 2].cur = 0x0;
param[ 3].cur = 0xF;
param[ 4].cur = 0x6;
param[ 5].cur = 0x1;
param[ 6].cur = 0x3;
param[ 7].cur = 0x0;
param[ 8].cur = 0x3;
param[ 0].min = 0x0;
param[ 1].min = 0x0;
param[ 2].min = 0x0;
param[ 3].min = 0x0;
param[ 4].min = 0x0;
param[ 5].min = 0x0;
param[ 6].min = 0x0;
param[ 7].min = 0x0;
param[ 8].min = 0x0;
param[ 0].max = 0x3F;
param[ 1].max = 0x7;
param[ 2].max = 0x1;
param[ 3].max = 0xF;
param[ 4].max = 0x7;
param[ 5].max = 0x1;
param[ 6].max = 0xF;
param[ 7].max = 0x1;
param[ 8].max = 0x3;
param[ 0].adj = 0x1;
param[ 1].adj = 0x1;
param[ 2].adj = 0x1;
param[ 3].adj = 0x1;
param[ 4].adj = 0x1;
param[ 5].adj = 0x1;
param[ 6].adj = 0x1;
param[ 7].adj = 0x1;
param[ 8].adj = 0x1;
Mode3DrawStr(2, 0, "0x04000078 (REG_SOUND4CNT_L) = ");
Mode3DrawStr(2, 1, "0x0400007C (REG_SOUND4CNT_H) = ");
Mode3DrawStr(2, 5, "Sound Length :");
Mode3DrawStr(2, 6, "Envlp Step Time :");
Mode3DrawStr(2, 7, "Envlp Step Dir :");
Mode3DrawStr(2, 8, "Envlp Init Vol :");
Mode3DrawStr(2, 9, "Frequency Ratio :");
Mode3DrawStr(2, 10, "Counter Step :");
Mode3DrawStr(2, 11, "Shift Frequency :");
Mode3DrawStr(2, 12, "Length Flag :");
Mode3DrawStr(2, 13, "Resampling Freq :");
Mode3DrawStr(0, 5+sel, ">");
DrawParam(param);
REG_SOUNDCNT_X = 0x80; // turn on sound circuit
REG_SOUNDCNT_L = 0x8877; // full volume, enable sound 4 to left and right
REG_SOUNDCNT_H = 2; // Overall output ratio - Full
for(;;)
{
VBlankIntrWait();
KeyExec();
u16 rep = KeyGetRep();
u16 trg = KeyGetTrg();
if(rep & KEY_UP && sel > 0)
{
Mode3DrawStr(0, 5+sel, " ");
sel--;
Mode3DrawStr(0, 5+sel, ">");
}
if(rep & KEY_DOWN && sel < 8)
{
Mode3DrawStr(0, 5+sel, " ");
sel++;
Mode3DrawStr(0, 5+sel, ">");
}
if((rep & KEY_RIGHT) && (param[sel].cur < param[sel].max))
{
param[sel].cur += param[sel].adj;
DrawParam(param);
isSnd = true;
}
if((rep & KEY_LEFT) && (param[sel].cur > param[sel].min))
{
param[sel].cur -= param[sel].adj;
DrawParam(param);
isSnd = true;
}
if(isSnd == true || trg & KEY_A)
{
u16 B, L, H;
B = (param[8].cur<<14) + (REG_SOUNDBIAS & 0x3fff);
L = (param[3].cur<<12) + (param[2].cur<<11) + (param[1].cur<< 8) + param[0].cur;
H = (param[7].cur<<14) + (param[6].cur<< 4) + (param[5].cur<< 3) + param[4].cur;
REG_SOUNDBIAS = B;
REG_SOUND4CNT_L = L;
REG_SOUND4CNT_H = H + TRIFREQ_RESET;
isSnd = false;
}
}
}