#author("2023-05-29T12:17:03+09:00","","")
#author("2023-05-29T12:26:05+09:00","","")
* サウンド4 [#l4f16171]

 This channel is used to output white noise. This is done by randomly switching the amplitude between high and low at a given frequency. Depending on the frequency the noise will appear 'harder' or 's ofter'.
 
 It is also possible to influence the function of the random generator, so the that the output becomes more regular, resulting in a limited ability to output Tone instead of Noise.
サウンド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;
 	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;
 		}
 
 		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;
 		}
 	}
 }

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

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