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], &reg [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 = &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