openMSX
YM2413Okazaki.hh
Go to the documentation of this file.
1#ifndef YM2413OKAZAKI_HH
2#define YM2413OKAZAKI_HH
3
4#include "YM2413Core.hh"
5#include "FixedPoint.hh"
6#include "serialize_meta.hh"
7#include <array>
8#include <span>
9
10namespace openmsx {
11namespace YM2413Okazaki {
12
13class YM2413;
14
15inline constexpr int EP_FP_BITS = 15;
17
18// Size of sin table
19inline constexpr int PG_BITS = 9;
20inline constexpr int PG_WIDTH = 1 << PG_BITS;
21inline constexpr int PG_MASK = PG_WIDTH - 1;
22
26
27class Patch {
28public:
32 Patch();
33
34 void initModulator(std::span<const uint8_t, 8> data);
35 void initCarrier (std::span<const uint8_t, 8> data);
36
38 void setKR(uint8_t value);
40 void setML(uint8_t value);
42 void setKL(uint8_t value);
44 void setTL(uint8_t value);
46 void setWF(uint8_t value);
48 void setFB(uint8_t value);
50 void setSL(uint8_t value);
51
52 std::span<const unsigned, PG_WIDTH> WF; // 0-1 transformed to waveform[0-1]
53 std::span<const uint8_t, 16 * 8> KL; // 0-3 transformed to tllTab[0-3]
54 unsigned SL; // 0-15 transformed to slTable[0-15]
55 uint8_t AMPM = 0; // 0-3 2 packed booleans
56 bool EG = false; // 0-1
57 uint8_t KR; // 0-1 transformed to 10,8
58 uint8_t ML; // 0-15 transformed to mlTable[0-15]
59 uint8_t TL; // 0-63 transformed to TL2EG(0..63) == [0..252]
60 uint8_t FB; // 0,1-7 transformed to 0,7-1
61 uint8_t AR = 0; // 0-15
62 uint8_t DR = 0; // 0-15
63 uint8_t RR = 0; // 0-15
64};
65
66class Slot {
67public:
68 Slot();
69 void reset();
70
72 [[nodiscard]] bool isActive() const;
73
74 void slotOn();
75 void slotOn2();
76 void slotOff();
77 void setPatch(const Patch& patch);
78 void setVolume(unsigned value);
79
80 [[nodiscard]] unsigned calc_phase(unsigned lfo_pm);
81 template<bool HAS_AM, bool FIXED_ENV>
82 [[nodiscard]] unsigned calc_envelope(int lfo_am, unsigned fixed_env);
83 template<bool HAS_AM> [[nodiscard]] unsigned calc_fixed_env() const;
84 void calc_envelope_outline(unsigned& out);
85 template<bool HAS_AM, bool FIXED_ENV>
86 [[nodiscard]] int calc_slot_car(unsigned lfo_pm, int lfo_am, int fm, unsigned fixed_env);
87 template<bool HAS_AM, bool HAS_FB, bool FIXED_ENV>
88 [[nodiscard]] int calc_slot_mod(unsigned lfo_pm, int lfo_am, unsigned fixed_env);
89
90 [[nodiscard]] int calc_slot_tom();
91 [[nodiscard]] int calc_slot_snare(bool noise);
92 [[nodiscard]] int calc_slot_cym(unsigned phase7, unsigned phase8);
93 [[nodiscard]] int calc_slot_hat(unsigned phase7, unsigned phase8, bool noise);
94 void updatePG(unsigned freq);
95 void updateTLL(unsigned freq, bool actAsCarrier);
96 void updateRKS(unsigned freq);
97 void updateEG();
98 void updateAll(unsigned freq, bool actAsCarrier);
99
100 template<typename Archive>
101 void serialize(Archive& ar, unsigned version);
102
103 // OUTPUT
105 int output; // Output value of slot
106
107 // for Phase Generator (PG)
108 unsigned cPhase; // Phase counter
109 std::array<unsigned, 8> dPhase; // Phase increment
110
111 // for Envelope Generator (EG)
112 unsigned volume; // Current volume
113 unsigned tll; // Total Level + Key scale level
114 std::span<const int, 16> dPhaseDRTableRks; // (converted to EnvPhaseIndex)
115 EnvelopeState state; // Current state
117 EnvPhaseIndex eg_dPhase; // Phase increment amount
120 bool sustain; // Sustain
121
123 Slot* sibling; // pointer to sibling slot (only valid for car -> mod)
124};
125
126class Channel {
127public:
128 Channel();
129 void reset(YM2413& ym2413);
130 void setPatch(unsigned num, YM2413& ym2413);
131 void setSustain(bool sustain, bool modActAsCarrier);
132 void keyOn();
133 void keyOff();
134
136
137 template<typename Archive>
138 void serialize(Archive& ar, unsigned version);
139};
140
141class YM2413 final : public YM2413Core
142{
143public:
144 YM2413();
145
146 // YM2413Core
147 void reset() override;
148 void writePort(bool port, uint8_t value, int offset) override;
149 void pokeReg(uint8_t reg, uint8_t data) override;
150 [[nodiscard]] uint8_t peekReg(uint8_t reg) const override;
151 void generateChannels(std::span<float*, 9 + 5> bufs, unsigned num) override;
152 [[nodiscard]] float getAmplificationFactor() const override;
153
154 [[nodiscard]] Patch& getPatch(unsigned instrument, bool carrier);
155
156 template<typename Archive>
157 void serialize(Archive& ar, unsigned version);
158
159private:
160 void writeReg(uint8_t r, uint8_t data);
161
162 void keyOn_BD();
163 void keyOn_SD();
164 void keyOn_TOM();
165 void keyOn_HH();
166 void keyOn_CYM();
167 void keyOff_BD();
168 void keyOff_SD();
169 void keyOff_TOM();
170 void keyOff_HH();
171 void keyOff_CYM();
172 void setRhythmFlags(uint8_t old);
173 void update_key_status();
174 [[nodiscard]] bool isRhythm() const;
175 [[nodiscard]] unsigned getFreq(unsigned channel) const;
176
177 template<unsigned FLAGS>
178 void calcChannel(Channel& ch, std::span<float> buf);
179
180private:
182 std::array<Channel, 9> channels;
183
185 unsigned pm_phase;
186
188 unsigned am_phase;
189
191 unsigned noise_seed;
192
194 std::array<std::array<Patch, 2>, 19> patches;
195
197 std::array<uint8_t, 0x40> reg;
198 uint8_t registerLatch;
199};
200
201} // namespace YM2413Okazaki
202
206
207} // namespace openmsx
208
209#endif
Abstract interface for the YM2413 core.
Definition YM2413Core.hh:28
void serialize(Archive &ar, unsigned version)
void setSustain(bool sustain, bool modActAsCarrier)
void setPatch(unsigned num, YM2413 &ym2413)
void setSL(uint8_t value)
Sets sustain level [0..15].
void setFB(uint8_t value)
Sets the amount of feedback [0..7].
Patch()
Creates an uninitialized Patch object; call initXXX() before use.
void initModulator(std::span< const uint8_t, 8 > data)
std::span< const unsigned, PG_WIDTH > WF
void setTL(uint8_t value)
Set volume (total level) [0..63].
std::span< const uint8_t, 16 *8 > KL
void setKL(uint8_t value)
Sets Key scale level [0..3].
void initCarrier(std::span< const uint8_t, 8 > data)
void setML(uint8_t value)
Sets the frequency multiplier factor [0..15].
void setWF(uint8_t value)
Set waveform [0..1].
void setKR(uint8_t value)
Sets the Key Scale of Rate (0 or 1).
void serialize(Archive &ar, unsigned version)
void setVolume(unsigned value)
int calc_slot_mod(unsigned lfo_pm, int lfo_am, unsigned fixed_env)
void setPatch(const Patch &patch)
void updateTLL(unsigned freq, bool actAsCarrier)
void calc_envelope_outline(unsigned &out)
void updatePG(unsigned freq)
void updateRKS(unsigned freq)
void setEnvelopeState(EnvelopeState state)
std::array< unsigned, 8 > dPhase
unsigned calc_envelope(int lfo_am, unsigned fixed_env)
unsigned calc_phase(unsigned lfo_pm)
std::span< const int, 16 > dPhaseDRTableRks
int calc_slot_hat(unsigned phase7, unsigned phase8, bool noise)
int calc_slot_cym(unsigned phase7, unsigned phase8)
int calc_slot_car(unsigned lfo_pm, int lfo_am, int fm, unsigned fixed_env)
void updateAll(unsigned freq, bool actAsCarrier)
uint8_t peekReg(uint8_t reg) const override
Read from a YM2413 register (for debug).
void serialize(Archive &ar, unsigned version)
void writePort(bool port, uint8_t value, int offset) override
Write to the YM2413 register/data port.
void generateChannels(std::span< float *, 9+5 > bufs, unsigned num) override
Generate the sound output.
void pokeReg(uint8_t reg, uint8_t data) override
Write to a YM2413 register (for debug).
float getAmplificationFactor() const override
Returns normalization factor.
void reset() override
Reset this YM2413 core.
Patch & getPatch(unsigned instrument, bool carrier)
This file implemented 3 utility functions:
Definition Autofire.cc:9
#define SERIALIZE_CLASS_VERSION(CLASS, VERSION)