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