1 // AY-3-8910 sound chip emulator
2
3 // $package
4 #ifndef AY_APU_H
5 #define AY_APU_H
6
7 #include "blargg_common.h"
8 #include "Blip_Buffer.h"
9
10 class Ay_Apu {
11 public:
12 // Basics
13 enum Ay_Apu_Type
14 {
15 Ay8910 = 0,
16 Ay8912,
17 Ay8913,
18 Ay8914,
19 Ym2149 = 0x10,
20 Ym3439,
21 Ymz284,
22 Ymz294,
23 Ym2203 = 0x20,
24 Ym2608,
25 Ym2610,
26 Ym2610b
27 };
28
set_type(Ay_Apu_Type type)29 void set_type( Ay_Apu_Type type ) { type_ = type; }
30
31 // Sets buffer to generate sound into, or 0 to mute.
32 void set_output( Blip_Buffer* );
33
34 // Writes to address register
write_addr(int data)35 void write_addr( int data ) { addr_ = data & 0x0F; }
36
37 // Emulates to time t, then writes to current data register
write_data(blip_time_t t,int data)38 void write_data( blip_time_t t, int data ) { run_until( t ); write_data_( addr_, data ); }
39
40 // Emulates to time t, then subtracts t from the current time.
41 // OK if previous write call had time slightly after t.
42 void end_frame( blip_time_t t );
43
44 // More features
45
46 // Reads from current data register
47 int read();
48
49 // Resets sound chip
50 void reset();
51
52 // Number of registers
53 enum { reg_count = 16 };
54
55 // Same as set_output(), but for a particular channel
56 enum { osc_count = 3 };
57 void set_output( int chan, Blip_Buffer* );
58
59 // Sets overall volume, where 1.0 is normal
volume(double v)60 void volume( double v ) { synth_.volume( 0.7/osc_count/amp_range * v ); }
61
62 // Sets treble equalization
treble_eq(blip_eq_t const & eq)63 void treble_eq( blip_eq_t const& eq ) { synth_.treble_eq( eq ); }
64
65 private:
66 // noncopyable
67 Ay_Apu( const Ay_Apu& );
68 Ay_Apu& operator = ( const Ay_Apu& );
69
70 // Implementation
71 public:
72 Ay_Apu();
73 BLARGG_DISABLE_NOTHROW
74 typedef BOOST::uint8_t byte;
75
76 private:
77 struct osc_t
78 {
79 blip_time_t period;
80 blip_time_t delay;
81 short last_amp;
82 short phase;
83 Blip_Buffer* output;
84 } oscs [osc_count];
85
86 Ay_Apu_Type type_;
87
88 blip_time_t last_time;
89 byte addr_;
90 byte regs [reg_count];
91
92 blip_time_t noise_delay;
93 unsigned noise_lfsr;
94
95 blip_time_t env_delay;
96 byte const* env_wave;
97 int env_pos;
98 byte env_modes [8] [48]; // values already passed through volume table
99
100 void write_data_( int addr, int data );
101 void run_until( blip_time_t );
102
103 public:
104 enum { amp_range = 255 };
105 Blip_Synth_Norm synth_; // used by Ay_Core for beeper sound
106 };
107
set_output(int i,Blip_Buffer * out)108 inline void Ay_Apu::set_output( int i, Blip_Buffer* out )
109 {
110 assert( (unsigned) i < osc_count );
111 oscs [i].output = out;
112 }
113
end_frame(blip_time_t time)114 inline void Ay_Apu::end_frame( blip_time_t time )
115 {
116 if ( time > last_time )
117 run_until( time );
118
119 last_time -= time;
120 assert( last_time >= 0 );
121 }
122
123 #endif
124