Mercurial > audlegacy-plugins
comparison src/console/Nes_Vrc6_Apu.cxx @ 12:3da1b8942b8b trunk
[svn] - remove src/Input src/Output src/Effect src/General src/Visualization src/Container
author | nenolod |
---|---|
date | Mon, 18 Sep 2006 03:14:20 -0700 |
parents | src/Input/console/Nes_Vrc6_Apu.cxx@13389e613d67 |
children | fb513e10174e |
comparison
equal
deleted
inserted
replaced
11:cff1d04026ae | 12:3da1b8942b8b |
---|---|
1 | |
2 // Nes_Snd_Emu 0.1.7. http://www.slack.net/~ant/ | |
3 | |
4 #include "Nes_Vrc6_Apu.h" | |
5 | |
6 /* Copyright (C) 2003-2006 Shay Green. This module is free software; you | |
7 can redistribute it and/or modify it under the terms of the GNU Lesser | |
8 General Public License as published by the Free Software Foundation; either | |
9 version 2.1 of the License, or (at your option) any later version. This | |
10 module is distributed in the hope that it will be useful, but WITHOUT ANY | |
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
12 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for | |
13 more details. You should have received a copy of the GNU Lesser General | |
14 Public License along with this module; if not, write to the Free Software | |
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ | |
16 | |
17 #include BLARGG_SOURCE_BEGIN | |
18 | |
19 Nes_Vrc6_Apu::Nes_Vrc6_Apu() | |
20 { | |
21 output( NULL ); | |
22 volume( 1.0 ); | |
23 reset(); | |
24 } | |
25 | |
26 Nes_Vrc6_Apu::~Nes_Vrc6_Apu() | |
27 { | |
28 } | |
29 | |
30 void Nes_Vrc6_Apu::reset() | |
31 { | |
32 last_time = 0; | |
33 for ( int i = 0; i < osc_count; i++ ) | |
34 { | |
35 Vrc6_Osc& osc = oscs [i]; | |
36 for ( int j = 0; j < reg_count; j++ ) | |
37 osc.regs [j] = 0; | |
38 osc.delay = 0; | |
39 osc.last_amp = 0; | |
40 osc.phase = 1; | |
41 osc.amp = 0; | |
42 } | |
43 } | |
44 | |
45 void Nes_Vrc6_Apu::output( Blip_Buffer* buf ) | |
46 { | |
47 for ( int i = 0; i < osc_count; i++ ) | |
48 osc_output( i, buf ); | |
49 } | |
50 | |
51 void Nes_Vrc6_Apu::run_until( nes_time_t time ) | |
52 { | |
53 require( time >= last_time ); | |
54 run_square( oscs [0], time ); | |
55 run_square( oscs [1], time ); | |
56 run_saw( time ); | |
57 last_time = time; | |
58 } | |
59 | |
60 void Nes_Vrc6_Apu::write_osc( nes_time_t time, int osc_index, int reg, int data ) | |
61 { | |
62 require( (unsigned) osc_index < osc_count ); | |
63 require( (unsigned) reg < reg_count ); | |
64 | |
65 run_until( time ); | |
66 oscs [osc_index].regs [reg] = data; | |
67 } | |
68 | |
69 void Nes_Vrc6_Apu::end_frame( nes_time_t time ) | |
70 { | |
71 if ( time > last_time ) | |
72 run_until( time ); | |
73 | |
74 assert( last_time >= time ); | |
75 last_time -= time; | |
76 } | |
77 | |
78 void Nes_Vrc6_Apu::save_snapshot( vrc6_snapshot_t* out ) const | |
79 { | |
80 out->saw_amp = oscs [2].amp; | |
81 for ( int i = 0; i < osc_count; i++ ) | |
82 { | |
83 Vrc6_Osc const& osc = oscs [i]; | |
84 for ( int r = 0; r < reg_count; r++ ) | |
85 out->regs [i] [r] = osc.regs [r]; | |
86 | |
87 out->delays [i] = osc.delay; | |
88 out->phases [i] = osc.phase; | |
89 } | |
90 } | |
91 | |
92 void Nes_Vrc6_Apu::load_snapshot( vrc6_snapshot_t const& in ) | |
93 { | |
94 reset(); | |
95 oscs [2].amp = in.saw_amp; | |
96 for ( int i = 0; i < osc_count; i++ ) | |
97 { | |
98 Vrc6_Osc& osc = oscs [i]; | |
99 for ( int r = 0; r < reg_count; r++ ) | |
100 osc.regs [r] = in.regs [i] [r]; | |
101 | |
102 osc.delay = in.delays [i]; | |
103 osc.phase = in.phases [i]; | |
104 } | |
105 if ( !oscs [2].phase ) | |
106 oscs [2].phase = 1; | |
107 } | |
108 | |
109 #include BLARGG_ENABLE_OPTIMIZER | |
110 | |
111 void Nes_Vrc6_Apu::run_square( Vrc6_Osc& osc, nes_time_t end_time ) | |
112 { | |
113 Blip_Buffer* output = osc.output; | |
114 if ( !output ) | |
115 return; | |
116 | |
117 int volume = osc.regs [0] & 15; | |
118 if ( !(osc.regs [2] & 0x80) ) | |
119 volume = 0; | |
120 | |
121 int gate = osc.regs [0] & 0x80; | |
122 int duty = ((osc.regs [0] >> 4) & 7) + 1; | |
123 int delta = ((gate || osc.phase < duty) ? volume : 0) - osc.last_amp; | |
124 nes_time_t time = last_time; | |
125 if ( delta ) | |
126 { | |
127 osc.last_amp += delta; | |
128 square_synth.offset( time, delta, output ); | |
129 } | |
130 | |
131 time += osc.delay; | |
132 osc.delay = 0; | |
133 int period = osc.period(); | |
134 if ( volume && !gate && period > 4 ) | |
135 { | |
136 if ( time < end_time ) | |
137 { | |
138 int phase = osc.phase; | |
139 | |
140 do | |
141 { | |
142 phase++; | |
143 if ( phase == 16 ) | |
144 { | |
145 phase = 0; | |
146 osc.last_amp = volume; | |
147 square_synth.offset( time, volume, output ); | |
148 } | |
149 if ( phase == duty ) | |
150 { | |
151 osc.last_amp = 0; | |
152 square_synth.offset( time, -volume, output ); | |
153 } | |
154 time += period; | |
155 } | |
156 while ( time < end_time ); | |
157 | |
158 osc.phase = phase; | |
159 } | |
160 osc.delay = time - end_time; | |
161 } | |
162 } | |
163 | |
164 void Nes_Vrc6_Apu::run_saw( nes_time_t end_time ) | |
165 { | |
166 Vrc6_Osc& osc = oscs [2]; | |
167 Blip_Buffer* output = osc.output; | |
168 if ( !output ) | |
169 return; | |
170 | |
171 int amp = osc.amp; | |
172 int amp_step = osc.regs [0] & 0x3F; | |
173 nes_time_t time = last_time; | |
174 int last_amp = osc.last_amp; | |
175 if ( !(osc.regs [2] & 0x80) || !(amp_step | amp) ) | |
176 { | |
177 osc.delay = 0; | |
178 int delta = (amp >> 3) - last_amp; | |
179 last_amp = amp >> 3; | |
180 saw_synth.offset( time, delta, output ); | |
181 } | |
182 else | |
183 { | |
184 time += osc.delay; | |
185 if ( time < end_time ) | |
186 { | |
187 int period = osc.period() * 2; | |
188 int phase = osc.phase; | |
189 | |
190 do | |
191 { | |
192 if ( --phase == 0 ) | |
193 { | |
194 phase = 7; | |
195 amp = 0; | |
196 } | |
197 | |
198 int delta = (amp >> 3) - last_amp; | |
199 if ( delta ) | |
200 { | |
201 last_amp = amp >> 3; | |
202 saw_synth.offset( time, delta, output ); | |
203 } | |
204 | |
205 time += period; | |
206 amp = (amp + amp_step) & 0xFF; | |
207 } | |
208 while ( time < end_time ); | |
209 | |
210 osc.phase = phase; | |
211 osc.amp = amp; | |
212 } | |
213 | |
214 osc.delay = time - end_time; | |
215 } | |
216 | |
217 osc.last_amp = last_amp; | |
218 } | |
219 |