comparison Plugins/Input/console/Nes_Fme7_Apu.cxx @ 1691:e24213152357 trunk

[svn] .cpp -> .cxx This has the nice side effect that we don't need to add .cpp to .SUFFIXES for OpenBSD.
author js
date Thu, 14 Sep 2006 13:33:10 -0700
parents Plugins/Input/console/Nes_Fme7_Apu.cpp@705d4c089fce
children
comparison
equal deleted inserted replaced
1690:bb1323938306 1691:e24213152357
1
2 // Game_Music_Emu 0.3.0. http://www.slack.net/~ant/
3
4 #include "Nes_Fme7_Apu.h"
5
6 #include <string.h>
7
8 /* Copyright (C) 2003-2006 Shay Green. This module is free software; you
9 can redistribute it and/or modify it under the terms of the GNU Lesser
10 General Public License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version. This
12 module is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 more details. You should have received a copy of the GNU Lesser General
16 Public License along with this module; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
18
19 #include BLARGG_SOURCE_BEGIN
20
21 void Nes_Fme7_Apu::reset()
22 {
23 last_time = 0;
24
25 for ( int i = 0; i < osc_count; i++ )
26 oscs [i].last_amp = 0;
27
28 fme7_snapshot_t* state = this;
29 memset( state, 0, sizeof *state );
30 }
31
32 #include BLARGG_ENABLE_OPTIMIZER
33
34 unsigned char Nes_Fme7_Apu::amp_table [16] =
35 {
36 #define ENTRY( n ) (unsigned char) (n * amp_range + 0.5)
37 ENTRY(0.0000), ENTRY(0.0078), ENTRY(0.0110), ENTRY(0.0156),
38 ENTRY(0.0221), ENTRY(0.0312), ENTRY(0.0441), ENTRY(0.0624),
39 ENTRY(0.0883), ENTRY(0.1249), ENTRY(0.1766), ENTRY(0.2498),
40 ENTRY(0.3534), ENTRY(0.4998), ENTRY(0.7070), ENTRY(1.0000)
41 #undef ENTRY
42 };
43
44 void Nes_Fme7_Apu::run_until( blip_time_t end_time )
45 {
46 require( end_time >= last_time );
47
48 for ( int index = 0; index < osc_count; index++ )
49 {
50 int mode = regs [7] >> index;
51 int vol_mode = regs [010 + index];
52 int volume = amp_table [vol_mode & 0x0f];
53
54 if ( !oscs [index].output )
55 continue;
56
57 // check for unsupported mode
58 #ifndef NDEBUG
59 if ( (mode & 011) <= 001 && vol_mode & 0x1f )
60 dprintf( "FME7 used unimplemented sound mode: %02X, vol_mode: %02X\n",
61 mode, vol_mode & 0x1f );
62 #endif
63
64 if ( (mode & 001) | (vol_mode & 0x10) )
65 volume = 0; // noise and envelope aren't supported
66
67 // period
68 int const period_factor = 16;
69 unsigned period = (regs [index * 2 + 1] & 0x0f) * 0x100 * period_factor +
70 regs [index * 2] * period_factor;
71 if ( period < 50 ) // around 22 kHz
72 {
73 volume = 0;
74 if ( !period ) // on my AY-3-8910A, period doesn't have extra one added
75 period = period_factor;
76 }
77
78 // current amplitude
79 int amp = volume;
80 if ( !phases [index] )
81 amp = 0;
82 int delta = amp - oscs [index].last_amp;
83 if ( delta )
84 {
85 oscs [index].last_amp = amp;
86 synth.offset( last_time, delta, oscs [index].output );
87 }
88
89 blip_time_t time = last_time + delays [index];
90 if ( time < end_time )
91 {
92 Blip_Buffer* const osc_output = oscs [index].output;
93 int delta = amp * 2 - volume;
94
95 if ( volume )
96 {
97 do
98 {
99 delta = -delta;
100 synth.offset_inline( time, delta, osc_output );
101 time += period;
102 }
103 while ( time < end_time );
104
105 oscs [index].last_amp = (delta + volume) >> 1;
106 phases [index] = (delta > 0);
107 }
108 else
109 {
110 // maintain phase when silent
111 int count = (end_time - time + period - 1) / period;
112 phases [index] ^= count & 1;
113 time += (long) count * period;
114 }
115 }
116
117 delays [index] = time - end_time;
118 }
119
120 last_time = end_time;
121 }
122