Mercurial > audlegacy-plugins
comparison src/console/Nes_Namco_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_Namco_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_Namco_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_Namco_Apu::Nes_Namco_Apu() | |
20 { | |
21 output( NULL ); | |
22 volume( 1.0 ); | |
23 reset(); | |
24 } | |
25 | |
26 Nes_Namco_Apu::~Nes_Namco_Apu() | |
27 { | |
28 } | |
29 | |
30 void Nes_Namco_Apu::reset() | |
31 { | |
32 last_time = 0; | |
33 addr_reg = 0; | |
34 | |
35 int i; | |
36 for ( i = 0; i < reg_count; i++ ) | |
37 reg [i] = 0; | |
38 | |
39 for ( i = 0; i < osc_count; i++ ) | |
40 { | |
41 Namco_Osc& osc = oscs [i]; | |
42 osc.delay = 0; | |
43 osc.last_amp = 0; | |
44 osc.wave_pos = 0; | |
45 } | |
46 } | |
47 | |
48 void Nes_Namco_Apu::output( Blip_Buffer* buf ) | |
49 { | |
50 for ( int i = 0; i < osc_count; i++ ) | |
51 osc_output( i, buf ); | |
52 } | |
53 | |
54 /* | |
55 void Nes_Namco_Apu::reflect_state( Tagged_Data& data ) | |
56 { | |
57 reflect_int16( data, 'ADDR', &addr_reg ); | |
58 | |
59 static const char hex [17] = "0123456789ABCDEF"; | |
60 int i; | |
61 for ( i = 0; i < reg_count; i++ ) | |
62 reflect_int16( data, 'RG\0\0' + hex [i >> 4] * 0x100 + hex [i & 15], ® [i] ); | |
63 | |
64 for ( i = 0; i < osc_count; i++ ) | |
65 { | |
66 reflect_int32( data, 'DLY0' + i, &oscs [i].delay ); | |
67 reflect_int16( data, 'POS0' + i, &oscs [i].wave_pos ); | |
68 } | |
69 } | |
70 */ | |
71 | |
72 void Nes_Namco_Apu::end_frame( nes_time_t time ) | |
73 { | |
74 if ( time > last_time ) | |
75 run_until( time ); | |
76 | |
77 assert( last_time >= time ); | |
78 last_time -= time; | |
79 } | |
80 | |
81 #include BLARGG_ENABLE_OPTIMIZER | |
82 | |
83 void Nes_Namco_Apu::run_until( nes_time_t nes_end_time ) | |
84 { | |
85 int active_oscs = (reg [0x7F] >> 4 & 7) + 1; | |
86 for ( int i = osc_count - active_oscs; i < osc_count; i++ ) | |
87 { | |
88 Namco_Osc& osc = oscs [i]; | |
89 Blip_Buffer* output = osc.output; | |
90 if ( !output ) | |
91 continue; | |
92 | |
93 blip_resampled_time_t time = | |
94 output->resampled_time( last_time ) + osc.delay; | |
95 blip_resampled_time_t end_time = output->resampled_time( nes_end_time ); | |
96 osc.delay = 0; | |
97 if ( time < end_time ) | |
98 { | |
99 const BOOST::uint8_t* osc_reg = ® [i * 8 + 0x40]; | |
100 if ( !(osc_reg [4] & 0xE0) ) | |
101 continue; | |
102 | |
103 int volume = osc_reg [7] & 15; | |
104 if ( !volume ) | |
105 continue; | |
106 | |
107 long freq = (osc_reg [4] & 3) * 0x10000 + osc_reg [2] * 0x100L + osc_reg [0]; | |
108 if ( freq < 64 * active_oscs ) | |
109 continue; // prevent low frequencies from excessively delaying freq changes | |
110 blip_resampled_time_t period = | |
111 output->resampled_duration( 983040 ) / freq * active_oscs; | |
112 | |
113 int wave_size = 32 - (osc_reg [4] >> 2 & 7) * 4; | |
114 if ( !wave_size ) | |
115 continue; | |
116 | |
117 int last_amp = osc.last_amp; | |
118 int wave_pos = osc.wave_pos; | |
119 | |
120 do | |
121 { | |
122 // read wave sample | |
123 int addr = wave_pos + osc_reg [6]; | |
124 int sample = reg [addr >> 1] >> (addr << 2 & 4); | |
125 wave_pos++; | |
126 sample = (sample & 15) * volume; | |
127 | |
128 // output impulse if amplitude changed | |
129 int delta = sample - last_amp; | |
130 if ( delta ) | |
131 { | |
132 last_amp = sample; | |
133 synth.offset_resampled( time, delta, output ); | |
134 } | |
135 | |
136 // next sample | |
137 time += period; | |
138 if ( wave_pos >= wave_size ) | |
139 wave_pos = 0; | |
140 } | |
141 while ( time < end_time ); | |
142 | |
143 osc.wave_pos = wave_pos; | |
144 osc.last_amp = last_amp; | |
145 } | |
146 osc.delay = time - end_time; | |
147 } | |
148 | |
149 last_time = nes_end_time; | |
150 } | |
151 |