openMSX
AY8910.hh
Go to the documentation of this file.
1#ifndef AY8910_HH
2#define AY8910_HH
3
5#include "FloatSetting.hh"
6#include "SimpleDebuggable.hh"
7#include "TclCallback.hh"
8#include <array>
9#include <cstdint>
10
11namespace openmsx {
12
13class AY8910Periphery;
14class DeviceConfig;
15
20class AY8910 final : public ResampledSoundDevice
21{
22public:
23 AY8910(const std::string& name, AY8910Periphery& periphery,
24 const DeviceConfig& config, EmuTime::param time);
25 ~AY8910();
26
27 [[nodiscard]] uint8_t readRegister(unsigned reg, EmuTime::param time);
28 [[nodiscard]] uint8_t peekRegister(unsigned reg, EmuTime::param time) const;
29 void writeRegister(unsigned reg, uint8_t value, EmuTime::param time);
30 void reset(EmuTime::param time);
31
32 template<typename Archive>
33 void serialize(Archive& ar, unsigned version);
34
35private:
36 class Generator {
37 public:
38 inline void setPeriod(int value);
39 [[nodiscard]] inline unsigned getNextEventTime() const;
40 inline void advanceFast(unsigned duration);
41
42 template<typename Archive>
43 void serialize(Archive& ar, unsigned version);
44
45 protected:
46 Generator() = default;
47 inline void reset();
48
54 int period;
59 int count;
60 };
61
62 class ToneGenerator : public Generator {
63 public:
64 ToneGenerator();
65
66 inline void reset();
67
71 inline void advance(unsigned duration);
72
73 inline void doNextEvent(AY8910& ay8910);
74
77 [[nodiscard]] bool getOutput() const { return output; }
78
79 template<typename Archive>
80 void serialize(Archive& ar, unsigned version);
81
82 private:
83 [[nodiscard]] int getDetune(AY8910& ay8910);
84
85 private:
88 unsigned vibratoCount = 0;
89 unsigned detuneCount = 0;
90
93 bool output;
94 };
95
96 class NoiseGenerator : public Generator {
97 public:
98 NoiseGenerator();
99
100 inline void reset();
104 inline void advance(unsigned duration);
105
106 inline void doNextEvent();
107
110 [[nodiscard]] bool getOutput() const { return random & 1; }
111
112 template<typename Archive>
113 void serialize(Archive& ar, unsigned version);
114
115 private:
116 int random;
117 };
118
119 class Amplitude {
120 public:
121 explicit Amplitude(const DeviceConfig& config);
122 [[nodiscard]] auto getEnvVolTable() const { return envVolTable; }
123 [[nodiscard]] inline float getVolume(unsigned chan) const;
124 inline void setChannelVolume(unsigned chan, unsigned value);
125 [[nodiscard]] inline bool followsEnvelope(unsigned chan) const;
126
127 private:
128 const bool isAY8910; // must come before envVolTable
129 std::span<const float, 32> envVolTable;
130 std::array<float, 3> vol;
131 std::array<bool, 3> envChan;
132 };
133
134 class Envelope {
135 public:
136 explicit inline Envelope(std::span<const float, 32> envVolTable);
137 inline void reset();
138 inline void setPeriod(int value);
139 inline void setShape(unsigned shape);
140 [[nodiscard]] inline bool isChanging() const;
141 inline void advance(unsigned duration);
142 [[nodiscard]] inline float getVolume() const;
143
144 [[nodiscard]] inline unsigned getNextEventTime() const;
145 inline void advanceFast(unsigned duration);
146 inline void doNextEvent();
147
148 template<typename Archive>
149 void serialize(Archive& ar, unsigned version);
150
151 private:
152 inline void doSteps(int steps);
153
154 private:
155 std::span<const float, 32> envVolTable;
156 int period = 1;
157 int count = 0;
158 int step = 0;
159 int attack = 0;
160 bool hold = false, alternate = false, holding = false;
161 };
162
163 // SoundDevice
164 void generateChannels(std::span<float*> bufs, unsigned num) override;
165 [[nodiscard]] float getAmplificationFactorImpl() const override;
166
167 // Observer<Setting>
168 void update(const Setting& setting) noexcept override;
169
170 void wrtReg(unsigned reg, uint8_t value, EmuTime::param time);
171
172private:
173 AY8910Periphery& periphery;
174
175 struct Debuggable final : SimpleDebuggable {
176 Debuggable(MSXMotherBoard& motherBoard, const std::string& name);
177 [[nodiscard]] uint8_t read(unsigned address, EmuTime::param time) override;
178 void write(unsigned address, uint8_t value, EmuTime::param time) override;
179 } debuggable;
180
181 FloatSetting vibratoPercent;
182 FloatSetting vibratoFrequency;
183 FloatSetting detunePercent;
184 FloatSetting detuneFrequency;
185 TclCallback directionsCallback;
186 std::array<ToneGenerator, 3> tone;
187 NoiseGenerator noise;
188 Amplitude amplitude;
189 Envelope envelope;
190 std::array<uint8_t, 16> regs;
191 const bool isAY8910;
192 const bool ignorePortDirections;
193 bool doDetune;
194 bool detuneInitialized = false; // (lazily) initialize detune stuff
195};
196
197SERIALIZE_CLASS_VERSION(AY8910::Generator, 2);
198SERIALIZE_CLASS_VERSION(AY8910::ToneGenerator, 2);
199SERIALIZE_CLASS_VERSION(AY8910::NoiseGenerator, 2);
200
201} // namespace openmsx
202
203#endif // AY8910_HH
BaseSetting * setting
Models the general purpose I/O ports of the AY8910.
This class implements the AY-3-8910 sound chip.
Definition AY8910.hh:21
uint8_t readRegister(unsigned reg, EmuTime::param time)
Definition AY8910.cc:523
void reset(EmuTime::param time)
Definition AY8910.cc:510
void writeRegister(unsigned reg, uint8_t value, EmuTime::param time)
Definition AY8910.cc:567
uint8_t peekRegister(unsigned reg, EmuTime::param time) const
Definition AY8910.cc:548
void serialize(Archive &ar, unsigned version)
Definition AY8910.cc:1003
A Setting with a floating point value.
This file implemented 3 utility functions:
Definition Autofire.cc:9
void serialize(Archive &ar, T &t, unsigned version)
#define SERIALIZE_CLASS_VERSION(CLASS, VERSION)