#author("2023-05-28T20:11:16+09:00","","")
#author("2023-05-29T12:15:20+09:00","","")
* GBサウンド2 [#wba2d938]
サウンド1は、サウンド2にSweepを加えたものです。他は全て同じなので理解しやすいと思います。

|主役|Frequency|周波数|
|引き立て役1|Sound length|音の長さ|
|引き立て役2|Wave Pattern Duty|デューティ比|
|引き立て役3|Envelope|初期音量、減衰増幅、変化量|
|引き立て役4(new!)|Sweep|一定の速度での周波数変化|

** 準備 [#gb3950c2]

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

** REG_SOUND1CNT_L [#re7e8c8a]
 4000060h - SOUND1CNT_L (NR10) - Channel 1 Sweep register (R/W)
   Bit        Expl.
   0-2   R/W  Number of sweep shift      (n=0-7)
   3     R/W  Sweep Frequency Direction  (0=Increase, 1=Decrease)
   4-6   R/W  Sweep Time; units of 7.8ms (0-7, min=7.8ms, max=54.7ms)
   7-15  -    Not used
 Sweep is disabled by setting Sweep Time to zero, if so, the direction bit should be set.
 The change of frequency (NR13,NR14) at each shift is calculated by the following formula where X(0) is initial freq & X(t-1) is last freq:
   X(t) = X(t-1) +/- X(t-1)/2^n

Bit0-2を0にすると無効になります。計算式に関しては音を聞いた方が早いので省略させてください。

** REG_SOUND1CNT_H [#wdccc5f0]
サウンド2と同じです。

 4000062h - SOUND1CNT_H (NR11, NR12) - Channel 1 Duty/Len/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.

** REG_SOUND1CNT_X [#k4b7a9a4]
サウンド2と同じです。

 4000064h - SOUND1CNT_X (NR13, NR14) - Channel 1 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

** テスト [#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<10; i++)
 	{
 		Mode3DrawPrintf(20,  4+i, "%04X", p[i].cur);
 	}
 
 	if(p[1].cur == 0) Mode3DrawStr(25, 4+1, "(Add)");
 	else              Mode3DrawStr(25, 4+1, "(Sub)");
 
 	switch(p[4].cur)
 	{
 	case 0: Mode3DrawStr(25, 4+4, "(12.5)"); break;
 	case 1: Mode3DrawStr(25, 4+4, "(25)  "); break;
 	case 2: Mode3DrawStr(25, 4+4, "(50)  "); break;
 	case 3: Mode3DrawStr(25, 4+4, "(75)  "); break;
 	}
 
 	if(p[6].cur == 0) Mode3DrawStr(25, 4+6, "(Dec)");
 	else              Mode3DrawStr(25, 4+6, "(Inc)");
 
 	switch(p[10].cur)
 	{
 	case 0: Mode3DrawStr(20, 14, "9-bits/32768 Hz "); break;
 	case 1: Mode3DrawStr(20, 14, "8-bits/65536 Hz "); break;
 	case 2: Mode3DrawStr(20, 14, "7-bits/131072 Hz"); break;
 	case 3: Mode3DrawStr(20, 14, "6-bits/262144 Hz"); break;
 	}
 
 	u16 L, H, X;
 
 	L = (p[2].cur<< 4) + (p[1].cur<< 3) + (p[0].cur);
 	H = (p[7].cur<<12) + (p[6].cur<<11) + (p[5].cur<< 8) + (p[4].cur<< 6) + (p[3].cur);
 	X = (p[9].cur<<14) + (p[8].cur);
 
 	Mode3DrawPrintf(33, 0, "%04X", L);
 	Mode3DrawPrintf(33, 1, "%04X", H);
 	Mode3DrawPrintf(33, 2, "%04X", X);
 }
 //---------------------------------------------------------------------------
 int main(void)
 {
 	REG_WSCNT = 0x4317;
 
 	Mode3Init();
 	IrqInit();
 	KeyInit();
 
 
 	ST_PARAM param[11];
 
 	bool isSnd = FALSE;
 	s16 sel = 0;
 
 	_Memset(&param, 0x00, sizeof(param));
 
 	param[ 0].cur = 0x2;
 	param[ 1].cur = 0x1;
 	param[ 2].cur = 0x7;
 	param[ 3].cur = 0x1;
 	param[ 4].cur = 0x2;
 	param[ 5].cur = 0x7;
 	param[ 6].cur = 0x0;
 	param[ 7].cur = 0xf;
 	param[ 8].cur = 0x60a;
 	param[ 9].cur = 0x0;
 	param[10].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[ 9].min = 0x0;
 	param[10].min = 0x0;
 
 	param[ 0].max = 0x7;
 	param[ 1].max = 0x1;
 	param[ 2].max = 0xf;
 	param[ 3].max = 0x3f;
 	param[ 4].max = 0x3;
 	param[ 5].max = 0x7;
 	param[ 6].max = 0x1;
 	param[ 7].max = 0xf;
 	param[ 8].max = 0x800;
 	param[ 9].max = 0x1;
 	param[10].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 = 0x10;
 	param[ 9].adj = 0x1;
 	param[10].adj = 0x1;
 
 	Mode3DrawStr(2,  0, "0x04000060 (REG_SOUND1CNT_L) = ");
 	Mode3DrawStr(2,  1, "0x04000062 (REG_SOUND1CNT_H) = ");
 	Mode3DrawStr(2,  2, "0x04000064 (REG_SOUND1CNT_X) = ");
 
 	Mode3DrawStr(2,  4, "Sweep Shifts    :");
 	Mode3DrawStr(2,  5, "Sweep Direction :");
 	Mode3DrawStr(2,  6, "Sweep Time      :");
 	Mode3DrawStr(2,  7, "Sound Length    :");
 	Mode3DrawStr(2,  8, "Wave Duty Cycle :");
 	Mode3DrawStr(2,  9, "Envlp Step Time :");
 	Mode3DrawStr(2, 10, "Envlp Step Dir  :");
 	Mode3DrawStr(2, 11, "Envlp Init Vol  :");
 	Mode3DrawStr(2, 12, "Frequency       :");
 	Mode3DrawStr(2, 13, "Length Flag     :");
 	Mode3DrawStr(2, 14, "Resampling Freq :");
 
 	Mode3DrawStr(0, 4+sel, ">");
 	DrawParam(param);
 
 	REG_SOUNDCNT_X = 0x80;		// turn on sound circuit
 	REG_SOUNDCNT_L = 0x1177;	// full volume, enable sound 1 to left and right
 	REG_SOUNDCNT_H = 2;			// Overall output ratio - Full
 	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, 4+sel, " ");
 			sel--;
 			Mode3DrawStr(0, 4+sel, ">");
 		}
 
 		if(rep & KEY_DOWN  && sel < 10)
 		{
 			Mode3DrawStr(0, 4+sel, " ");
 			sel++;
 			Mode3DrawStr(0, 4+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, X;
 
 			B = (param[10].cur<<14) + (REG_SOUNDBIAS & 0x3fff);
 			L = (param[2].cur<< 4) + (param[1].cur<< 3) + (param[0].cur);
 			H = (param[7].cur<<12) + (param[6].cur<<11) + (param[5].cur<< 8) + (param[4].cur<< 6) + (param[3].cur);
 			X = (param[9].cur<<14) + (param[8].cur);
 
 			REG_SOUNDBIAS   = B;
 			REG_SOUND1CNT_L = L;
 			REG_SOUND1CNT_H = H;
 			REG_SOUND1CNT_X = X + TRIFREQ_RESET;
 
 			isSnd = FALSE;
 		}
 	}
 }

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

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