Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/snes/dsp/voice.cpp
2 views
1
#ifdef DSP_CPP
2
3
inline void DSP::voice_output(voice_t &v, bool channel) {
4
//apply left/right volume
5
int amp = (state.t_output * (int8)VREG(voll + channel)) >> 7;
6
7
//add to output total
8
state.t_main_out[channel] += amp;
9
state.t_main_out[channel] = sclamp<16>(state.t_main_out[channel]);
10
11
//optionally add to echo total
12
if(state.t_eon & v.vbit) {
13
state.t_echo_out[channel] += amp;
14
state.t_echo_out[channel] = sclamp<16>(state.t_echo_out[channel]);
15
}
16
}
17
18
void DSP::voice_1(voice_t &v) {
19
state.t_dir_addr = (state.t_dir << 8) + (state.t_srcn << 2);
20
state.t_srcn = VREG(srcn);
21
}
22
23
void DSP::voice_2(voice_t &v) {
24
//read sample pointer (ignored if not needed)
25
uint16 addr = state.t_dir_addr;
26
if(!v.kon_delay) addr += 2;
27
uint8 lo = smp.apuram[(uint16)(addr + 0)];
28
uint8 hi = smp.apuram[(uint16)(addr + 1)];
29
state.t_brr_next_addr = ((hi << 8) + lo);
30
31
state.t_adsr0 = VREG(adsr0);
32
33
//read pitch, spread over two clocks
34
state.t_pitch = VREG(pitchl);
35
}
36
37
void DSP::voice_3(voice_t &v) {
38
voice_3a(v);
39
voice_3b(v);
40
voice_3c(v);
41
}
42
43
void DSP::voice_3a(voice_t &v) {
44
state.t_pitch += (VREG(pitchh) & 0x3f) << 8;
45
}
46
47
void DSP::voice_3b(voice_t &v) {
48
state.t_brr_byte = smp.apuram[(uint16)(v.brr_addr + v.brr_offset)];
49
state.t_brr_header = smp.apuram[(uint16)(v.brr_addr)];
50
}
51
52
void DSP::voice_3c(voice_t &v) {
53
//pitch modulation using previous voice's output
54
55
if(state.t_pmon & v.vbit) {
56
state.t_pitch += ((state.t_output >> 5) * state.t_pitch) >> 10;
57
}
58
59
if(v.kon_delay) {
60
//get ready to start BRR decoding on next sample
61
if(v.kon_delay == 5) {
62
v.brr_addr = state.t_brr_next_addr;
63
v.brr_offset = 1;
64
v.buf_pos = 0;
65
state.t_brr_header = 0; //header is ignored on this sample
66
}
67
68
//envelope is never run during KON
69
v.env = 0;
70
v.hidden_env = 0;
71
72
//disable BRR decoding until last three samples
73
v.interp_pos = 0;
74
v.kon_delay--;
75
if(v.kon_delay & 3) v.interp_pos = 0x4000;
76
77
//pitch is never added during KON
78
state.t_pitch = 0;
79
}
80
81
//gaussian interpolation
82
int output = gaussian_interpolate(v);
83
84
//noise
85
if(state.t_non & v.vbit) {
86
output = (int16)(state.noise << 1);
87
}
88
89
//apply envelope
90
state.t_output = ((output * v.env) >> 11) & ~1;
91
v.t_envx_out = v.env >> 4;
92
93
//immediate silence due to end of sample or soft reset
94
if(REG(flg) & 0x80 || (state.t_brr_header & 3) == 1) {
95
v.env_mode = env_release;
96
v.env = 0;
97
}
98
99
if(state.every_other_sample) {
100
//KOFF
101
if(state.t_koff & v.vbit) {
102
v.env_mode = env_release;
103
}
104
105
//KON
106
if(state.kon & v.vbit) {
107
v.kon_delay = 5;
108
v.env_mode = env_attack;
109
}
110
}
111
112
//run envelope for next sample
113
if(!v.kon_delay) envelope_run(v);
114
}
115
116
void DSP::voice_4(voice_t &v) {
117
//decode BRR
118
state.t_looped = 0;
119
if(v.interp_pos >= 0x4000) {
120
brr_decode(v);
121
v.brr_offset += 2;
122
if(v.brr_offset >= 9) {
123
//start decoding next BRR block
124
v.brr_addr = (uint16)(v.brr_addr + 9);
125
if(state.t_brr_header & 1) {
126
v.brr_addr = state.t_brr_next_addr;
127
state.t_looped = v.vbit;
128
}
129
v.brr_offset = 1;
130
}
131
}
132
133
//apply pitch
134
v.interp_pos = (v.interp_pos & 0x3fff) + state.t_pitch;
135
136
//keep from getting too far ahead (when using pitch modulation)
137
if(v.interp_pos > 0x7fff) v.interp_pos = 0x7fff;
138
139
//output left
140
voice_output(v, 0);
141
}
142
143
void DSP::voice_5(voice_t &v) {
144
//output right
145
voice_output(v, 1);
146
147
//ENDX, OUTX and ENVX won't update if you wrote to them 1-2 clocks earlier
148
state.endx_buf = REG(endx) | state.t_looped;
149
150
//clear bit in ENDX if KON just began
151
if(v.kon_delay == 5) state.endx_buf &= ~v.vbit;
152
}
153
154
void DSP::voice_6(voice_t &v) {
155
state.outx_buf = state.t_output >> 8;
156
}
157
158
void DSP::voice_7(voice_t &v) {
159
//update ENDX
160
REG(endx) = (uint8)state.endx_buf;
161
state.envx_buf = v.t_envx_out;
162
}
163
164
void DSP::voice_8(voice_t &v) {
165
//update OUTX
166
VREG(outx) = (uint8)state.outx_buf;
167
}
168
169
void DSP::voice_9(voice_t &v) {
170
//update ENVX
171
VREG(envx) = (uint8)state.envx_buf;
172
}
173
174
#endif
175
176