📄 sound.c
字号:
#include "defs.h"#include "pcm.h"#include "sound.h"#include "cpu.h"#include "hw.h"#include "regs.h"#include "noise.h"const static byte dmgwave[16] ={ 0xac, 0xdd, 0xda, 0x48, 0x36, 0x02, 0xcf, 0x16, 0x2c, 0x04, 0xe5, 0x2c, 0xac, 0xdd, 0xda, 0x48};const static byte cgbwave[16] ={ 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,};const static byte sqwave[4][8] ={ { 0, 0,-1, 0, 0, 0, 0, 0 }, { 0,-1,-1, 0, 0, 0, 0, 0 }, { -1,-1,-1,-1, 0, 0, 0, 0 }, { -1, 0, 0,-1,-1,-1,-1,-1 }};
const static int freqtab[8] ={ (1<<14)*2, (1<<14), (1<<14)/2, (1<<14)/3, (1<<14)/4, (1<<14)/5, (1<<14)/6, (1<<14)/7};struct snd snd;#define RATE (snd.rate)#define WAVE (snd.wave) /* ram.hi+0x30 */#define S1 (snd.ch[0])#define S2 (snd.ch[1])#define S3 (snd.ch[2])#define S4 (snd.ch[3])static void s1_freq_d(int d){ if (RATE > (d<<4)) S1.freq = 0; else S1.freq = (RATE << 17)/d;}static void s1_freq(){
int d = 2048 - (((R_NR14&7)<<8) + R_NR13);
if (RATE > (d<<4)) S1.freq = 0;
else S1.freq = (RATE << 17)/d;}static void s2_freq(){ int d = 2048 - (((R_NR24&7)<<8) + R_NR23); if (RATE > (d<<4)) S2.freq = 0; else S2.freq = (RATE << 17)/d;}static void s3_freq(){ int d = 2048 - (((R_NR34&7)<<8) + R_NR33); if (RATE > (d<<3)) S3.freq = 0; else S3.freq = (RATE << 21)/d;}static void s4_freq(){ S4.freq = (freqtab[R_NR43&7] >> (R_NR43 >> 4)) * RATE; if (S4.freq >> 18) S4.freq = 1<<18;}void sound_dirty(){
S1.swlen = ((R_NR10>>4) & 7) << 14; S1.len = (64-(R_NR11&63)) << 13; S1.envol = R_NR12 >> 4; S1.endir = (R_NR12>>3) & 1; S1.endir |= S1.endir - 1; S1.enlen = (R_NR12 & 7) << 15;
S1.mixr = (R_NR51 & 1);
S1.mixl = (R_NR51 & 16) >> 4;
S1.type = R_NR11>>6;
S1.hold = R_NR14 & 64;
S1.swshift = (R_NR10 & 7);
S1.swdir = (R_NR10 & 8); s1_freq(); S2.len = (64-(R_NR21&63)) << 13; S2.envol = R_NR22 >> 4; S2.endir = (R_NR22>>3) & 1; S2.endir |= S2.endir - 1; S2.enlen = (R_NR22 & 7) << 15;
S2.mixr = (R_NR51 & 2) >> 1;
S2.mixl = (R_NR51 & 32) >> 5;
S2.type = R_NR21>>6;
S2.hold = (R_NR24 & 64); s2_freq(); S3.len = (256-R_NR31) << 20;
S3.mixr = (R_NR51 & 4) >> 2;
S3.mixl = (R_NR51 & 64) >> 6;
S3.hold = (R_NR34 & 64);
S3.endir = (R_NR32 & 96);
S3.envol = (3 - ((R_NR32>>5)&3)); s3_freq(); S4.len = (64-(R_NR41&63)) << 13; S4.envol = R_NR42 >> 4; S4.endir = (R_NR42>>3) & 1; S4.endir |= S4.endir - 1; S4.enlen = (R_NR42 & 7) << 15;
S4.mixr = (R_NR51 & 8) >> 3;
S4.mixl = (R_NR51 & 128) >> 7;
S4.hold = (R_NR44 & 64); s4_freq();
snd.master_voll = (R_NR50 & 0x07);
snd.master_volr = ((R_NR50 & 0x70)>>4);}void sound_off(){ memset(&S1, 0, sizeof S1); memset(&S2, 0, sizeof S2); memset(&S3, 0, sizeof S3); memset(&S4, 0, sizeof S4); R_NR10 = 0x80; R_NR11 = 0xBF; R_NR12 = 0xF3; R_NR14 = 0xBF; R_NR21 = 0x3F; R_NR22 = 0x00; R_NR24 = 0xBF; R_NR30 = 0x7F; R_NR31 = 0xFF; R_NR32 = 0x9F; R_NR33 = 0xBF; R_NR41 = 0xFF; R_NR42 = 0x00; R_NR43 = 0x00; R_NR44 = 0xBF; R_NR50 = 0x77; R_NR51 = 0xF3; R_NR52 = 0xF1; sound_dirty();}void sound_reset(){ memset(&snd, 0, sizeof snd); if (pcm.hz) snd.rate = (1<<21) / pcm.hz; else snd.rate = 0; memcpy(WAVE, hw.cgb ? cgbwave : dmgwave, 16); memcpy(ram.hi+0x30, WAVE, 16); sound_off();}void sound_mix(){ int s, l, r, f; if (!RATE || cpu.snd < RATE) return; for (; cpu.snd >= RATE; cpu.snd -= RATE) { l = r = 0; if (S1.on) { s = sqwave[S1.type][(S1.pos>>18)&7] & S1.envol; S1.pos += S1.freq; if (S1.hold && ((S1.cnt += RATE) >= S1.len)) S1.on = 0; if (S1.enlen && (S1.encnt += RATE) >= S1.enlen) { S1.encnt -= S1.enlen; S1.envol += S1.endir; if (S1.envol < 0) S1.envol = 0; if (S1.envol > 15) S1.envol = 15; } if (S1.swlen && (S1.swcnt += RATE) >= S1.swlen) { S1.swcnt -= S1.swlen;
if (S1.swshift)
{
f = S1.swfreq; if (S1.swdir) f -= (f >> S1.swshift); else f += (f >> S1.swshift);
if (f > 2047)
S1.on = 0;
else
{
S1.swfreq = f;
R_NR13 = f;
R_NR14 = (R_NR14 & 0xF8) | (f>>8);
s1_freq_d(2048 - f);
S1.hold = R_NR14 & 64;
}
} } s <<= 2; if (S1.mixr) r += s; if (S1.mixl) l += s; } if (S2.on) { s = sqwave[S2.type][(S2.pos>>18)&7] & S2.envol; S2.pos += S2.freq; if (S2.hold && ((S2.cnt += RATE) >= S2.len)) S2.on = 0; if (S2.enlen && (S2.encnt += RATE) >= S2.enlen) { S2.encnt -= S2.enlen; S2.envol += S2.endir; if (S2.envol < 0) S2.envol = 0; if (S2.envol > 15) S2.envol = 15; } s <<= 2; if (S2.mixr) r += s; if (S2.mixl) l += s; } if (S3.on) { s = WAVE[(S3.pos>>22) & 15]; if (S3.pos & (1<<21)) s &= 15; else s >>= 4; s -= 8; S3.pos += S3.freq; if (S3.hold && ((S3.cnt += RATE) >= S3.len)) S3.on = 0;
if (S3.endir)
s <<= S3.envol; else
s = 0; if (S3.mixr) r += s; if (S3.mixl) l += s; } if (S4.on) { if (R_NR43 & 8) s = 1 & (noise7[ (S4.pos>>20)&15] >> (7-((S4.pos>>17)&7))); else s = 1 & (noise15[ (S4.pos>>20)&4095] >> (7-((S4.pos>>17)&7))); s = (-s) & S4.envol; S4.pos += S4.freq; if (S4.hold && ((S4.cnt += RATE) >= S4.len)) S4.on = 0; if (S4.enlen && (S4.encnt += RATE) >= S4.enlen) { S4.encnt -= S4.enlen; S4.envol += S4.endir; if (S4.envol < 0) S4.envol = 0; if (S4.envol > 15) S4.envol = 15; } s += s << 1; if (S4.mixr) r += s; if (S4.mixl) l += s; }
l *= snd.master_voll;
r *= snd.master_volr;
l += (snd.master_voll - 3) << 4;
r += (snd.master_volr - 3) << 4;
if (pcm.buf) { if (pcm.pos >= pcm.len) pcm_submit(); if (pcm_get_16bits()) { short* sample = pcm.buf; l <<= 4; r <<= 4; if (pcm.stereo) { if (l > 32767) l = 32767; else if (l < -32768) l = -32768; if (r > 32767) r = 32767; else if (r < -32768) r = -32768; sample[pcm.pos++] = l; sample[pcm.pos++] = r; } else { l += r; l >>= 1; if (l > 32767) l = 32767; else if (l < -32768) l = -32768; sample[pcm.pos++] = l; } } else { l >>= 4; r >>= 4; if (pcm.stereo) { if (l > 127) l = 127; else if (l < -128) l = -128; if (r > 127) r = 127; else if (r < -128) r = -128; pcm.buf[pcm.pos++] = l + 128; pcm.buf[pcm.pos++] = r + 128; } else { l += r; l >>= 1; if (l > 127) l = 127; else if (l < -128) l = -128; pcm.buf[pcm.pos++] = l+128; } } } } R_NR52 = (R_NR52&0xf0) | S1.on | (S2.on<<1) | (S3.on<<2) | (S4.on<<3);}byte sound_read(byte r){ sound_mix(); return REG(r);}
void s1_init(){
S1.swcnt = 0; S1.swfreq = ((R_NR14&7)<<8) + R_NR13; S1.envol = R_NR12 >> 4; S1.endir = (R_NR12>>3) & 1; S1.endir |= S1.endir - 1; S1.enlen = (R_NR12 & 7) << 15; if (!S1.on) S1.pos = 0; S1.on = 1; S1.cnt = 0; S1.encnt = 0;}void s2_init(){ S2.envol = R_NR22 >> 4; S2.endir = (R_NR22>>3) & 1; S2.endir |= S2.endir - 1; S2.enlen = (R_NR22 & 7) << 15; if (!S2.on) S2.pos = 0; S2.on = 1; S2.cnt = 0; S2.encnt = 0;}void s3_init(){ if (!S3.on) S3.pos = 0; S3.cnt = 0;
S3.on = 1; //for (i = 0; i < 16; i++) // ram.hi[i+0x30] = 0x13 ^ ram.hi[i+0x31];}void s4_init(){ S4.envol = R_NR42 >> 4; S4.endir = (R_NR42>>3) & 1; S4.endir |= S4.endir - 1; S4.enlen = (R_NR42 & 7) << 15; S4.on = 1; S4.pos = 0; S4.cnt = 0; S4.encnt = 0;}void sound_write(byte r, byte b){
sound_mix(); switch (r) { case RI_NR10: R_NR10 = b; S1.swlen = ((R_NR10>>4) & 7) << 14; S1.swfreq = ((R_NR14&7)<<8) + R_NR13;
S1.swshift = (R_NR10 & 7);
S1.swdir = (R_NR10 & 8); break; case RI_NR11: R_NR11 = b; S1.len = (64-(R_NR11&63)) << 13;
S1.type = R_NR11>>6; break; case RI_NR12: R_NR12 = b; S1.envol = R_NR12 >> 4; S1.endir = (R_NR12>>3) & 1; S1.endir |= S1.endir - 1; S1.enlen = (R_NR12 & 7) << 15; break; case RI_NR13: R_NR13 = b; s1_freq(); break; case RI_NR14: R_NR14 = b;
S1.hold = R_NR14 & 64; s1_freq(); if (b & 128) s1_init(); break; case RI_NR21: R_NR21 = b; S2.len = (64-(R_NR21&63)) << 13;
S2.type = R_NR21>>6; break; case RI_NR22: R_NR22 = b; S2.envol = R_NR22 >> 4; S2.endir = (R_NR22>>3) & 1; S2.endir |= S2.endir - 1; S2.enlen = (R_NR22 & 7) << 15; break; case RI_NR23: R_NR23 = b; s2_freq(); break; case RI_NR24: R_NR24 = b;
S2.hold = (R_NR24 & 64); s2_freq(); if (b & 128) s2_init(); break; case RI_NR30: R_NR30 = b; if (!(b & 128)) S3.on = 0; break; case RI_NR31: R_NR31 = b; S3.len = (256-R_NR31) << 13; break; case RI_NR32: R_NR32 = b;
S3.endir = (R_NR32 & 96);
S3.envol = (3 - ((R_NR32>>5)&3)); break; case RI_NR33: R_NR33 = b; s3_freq(); break; case RI_NR34: R_NR34 = b;
S3.hold = (R_NR34 & 64); s3_freq(); if ((b & 128) && (R_NR30 & 0x80))
s3_init(); break; case RI_NR41: R_NR41 = b; S4.len = (64-(R_NR41&63)) << 13; break; case RI_NR42: R_NR42 = b; S4.envol = R_NR42 >> 4; S4.endir = (R_NR42>>3) & 1; S4.endir |= S4.endir - 1; S4.enlen = (R_NR42 & 7) << 15; break; case RI_NR43: R_NR43 = b; s4_freq(); break; case RI_NR44: R_NR44 = b;
S4.hold = (R_NR44 & 64); if (b & 128) s4_init(); break; case RI_NR50: R_NR50 = b;
snd.master_voll = (R_NR50 & 0x07);
snd.master_volr = ((R_NR50 & 0x70)>>4); break; case RI_NR51: R_NR51 = b;
S1.mixr = (R_NR51 & 1);
S1.mixl = (R_NR51 & 16) >> 4;
S2.mixr = (R_NR51 & 2) >> 1;
S2.mixl = (R_NR51 & 32) >> 5;
S3.mixr = (R_NR51 & 4) >> 2;
S3.mixl = (R_NR51 & 64) >> 6;
S4.mixr = (R_NR51 & 8) >> 3;
S4.mixl = (R_NR51 & 128) >> 7; break; case RI_NR52: R_NR52 = b; if (!(R_NR52 & 128)) sound_off(); break;
case 0x30:
case 0x31:
case 0x32:
case 0x33:
case 0x34:
case 0x35:
case 0x36:
case 0x37:
case 0x38:
case 0x39:
case 0x3A:
case 0x3B:
case 0x3C:
case 0x3D:
case 0x3E:
case 0x3F:
WAVE[r-0x30] = ram.hi[r] = b;
break;
default:
ram.hi[r] = b; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -