サウンド1は、サウンド2にSweepを加えたものです。他は全て同じなので理解しやすいと思います。
主役 | Frequency | 周波数 |
引き立て役1 | Sound length | 音の長さ |
引き立て役2 | Wave Pattern Duty | デューティ比 |
引き立て役3 | Envelope | 初期音量、減衰増幅、変化量 |
引き立て役4(new!) | Sweep | 一定の速度での周波数変化 |
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
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にすると無効になります。計算式に関しては音を聞いた方が早いので省略させてください。
サウンド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.
サウンド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
#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(¶m, 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 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; } } }