#author("2023-05-29T12:26:05+09:00","","")
#author("2025-06-02T22:24:15+09:00","","")
* サウンド4 [#l4f16171]

サウンド4はホワイトノイズを作ります。各パラメータの関係は以下のとおりです。

|主役1|Frequency Ratio||
|主役2|Frequency Shift||
|引き立て役1|Sound length|音の長さ|
|引き立て役2|Envelope|初期音量、減衰増幅、変化量|
|引き立て役3|Counter Step|一定の速度での周波数変化|

** 準備 [#fcf204ac]

 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

** REG_SOUND4CNT_L [#fdfc4c5e]
 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.

** REG_SOUND4CNT_H [#u59a9912]
 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.

** テスト [#z44c4a03]

#ref(1.png,nolink)

 #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;
 	bool isSnd = false;
 	s16 sel = 0;
 
 	_Memset(&param, 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;
 				isSnd = true;
 		}
 
 		if((rep & KEY_LEFT) && (param[sel].cur > param[sel].min))
 		{
 				param[sel].cur -= param[sel].adj;
 				DrawParam(param);
 
 				isSnd = TRUE;
 				isSnd = true;
 		}
 
 		if(isSnd == TRUE || trg & KEY_A)
 		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;
 			isSnd = false;
 		}
 	}
 }

** 履歴 [#k390a23f]
- 2023/05/29

トップ   差分 履歴 リロード   一覧 検索 最終更新   ヘルプ   最終更新のRSS