サウンド4

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

主役1Frequency Ratio
主役2Frequency Shift
引き立て役1Sound length音の長さ
引き立て役2Envelope初期音量、減衰増幅、変化量
引き立て役3Counter 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

REG_SOUND4CNT_L

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

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.

テスト

1.png
#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;
		}
	}
}

履歴


添付ファイル: file1.png 19件 [詳細]

トップ   差分 履歴 リロード   一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2023-05-29 (月) 12:26:05