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 
8 namespace openmsx {
9 namespace YM2413Okazaki {
10 
11 class YM2413;
12 
13 constexpr int EP_FP_BITS = 15;
15 
18 };
19 
20 class Patch {
21 public:
25  Patch();
26 
27  void initModulator(const uint8_t* data);
28  void initCarrier (const uint8_t* data);
29 
31  inline void setKR(uint8_t value);
33  inline void setML(uint8_t value);
35  inline void setKL(uint8_t value);
37  inline void setTL(uint8_t value);
39  inline void setWF(uint8_t value);
41  inline void setFB(uint8_t value);
43  inline void setSL(uint8_t value);
44 
45  const unsigned* WF; // 0-1 transformed to waveform[0-1]
46  const uint8_t* KL; // 0-3 transformed to tllTable[0-3]
47  unsigned SL; // 0-15 transformed to slTable[0-15]
48  uint8_t AMPM; // 0-3 2 packed booleans
49  bool EG; // 0-1
50  uint8_t KR; // 0-1 transformed to 10,8
51  uint8_t ML; // 0-15 transformed to mlTable[0-15]
52  uint8_t TL; // 0-63 transformed to TL2EG(0..63) == [0..252]
53  uint8_t FB; // 0,1-7 transformed to 0,7-1
54  uint8_t AR; // 0-15
55  uint8_t DR; // 0-15
56  uint8_t RR; // 0-15
57 };
58 
59 class Slot {
60 public:
61  void reset();
62 
64  [[nodiscard]] inline bool isActive() const;
65 
66  inline void slotOn();
67  inline void slotOn2();
68  inline void slotOff();
69  inline void setPatch(const Patch& patch);
70  inline void setVolume(unsigned value);
71 
72  [[nodiscard]] inline unsigned calc_phase(unsigned lfo_pm);
73  template<bool HAS_AM, bool FIXED_ENV>
74  [[nodiscard]] inline unsigned calc_envelope(int lfo_am, unsigned fixed_env);
75  template<bool HAS_AM> [[nodiscard]] unsigned calc_fixed_env() const;
76  void calc_envelope_outline(unsigned& out);
77  template<bool HAS_AM, bool FIXED_ENV>
78  [[nodiscard]] inline int calc_slot_car(unsigned lfo_pm, int lfo_am, int fm, unsigned fixed_env);
79  template<bool HAS_AM, bool HAS_FB, bool FIXED_ENV>
80  [[nodiscard]] inline int calc_slot_mod(unsigned lfo_pm, int lfo_am, unsigned fixed_env);
81 
82  [[nodiscard]] inline int calc_slot_tom();
83  [[nodiscard]] inline int calc_slot_snare(bool noise);
84  [[nodiscard]] inline int calc_slot_cym(unsigned phase7, unsigned phase8);
85  [[nodiscard]] inline int calc_slot_hat(unsigned phase7, unsigned phase8, bool noise);
86  inline void updatePG(unsigned freq);
87  inline void updateTLL(unsigned freq, bool actAsCarrier);
88  inline void updateRKS(unsigned freq);
89  inline void updateEG();
90  inline void updateAll(unsigned freq, bool actAsCarrier);
91 
92  template<typename Archive>
93  void serialize(Archive& ar, unsigned version);
94 
95  // OUTPUT
96  int feedback;
97  int output; // Output value of slot
98 
99  // for Phase Generator (PG)
100  unsigned cPhase; // Phase counter
101  unsigned dPhase[8]; // Phase increment
102 
103  // for Envelope Generator (EG)
104  unsigned volume; // Current volume
105  unsigned tll; // Total Level + Key scale level
106  const int* dPhaseDRTableRks; // (converted to EnvPhaseIndex)
107  EnvelopeState state; // Current state
109  EnvPhaseIndex eg_dPhase; // Phase increment amount
111  uint8_t slot_on_flag;
112  bool sustain; // Sustain
113 
115  Slot* sibling; // pointer to sibling slot (only valid for car -> mod)
116 };
117 
118 class Channel {
119 public:
120  Channel();
121  void reset(YM2413& ym2413);
122  inline void setPatch(unsigned num, YM2413& ym2413);
123  inline void setSustain(bool sustain, bool modActAsCarrier);
124  inline void keyOn();
125  inline void keyOff();
126 
128 
129  template<typename Archive>
130  void serialize(Archive& ar, unsigned version);
131 };
132 
133 class YM2413 final : public YM2413Core
134 {
135 public:
136  YM2413();
137 
138  // YM2413Core
139  void reset() override;
140  void writePort(bool port, uint8_t value, int offset) override;
141  void pokeReg(uint8_t reg, uint8_t data) override;
142  [[nodiscard]] uint8_t peekReg(uint8_t reg) const override;
143  void generateChannels(float* bufs[9 + 5], unsigned num) override;
144  [[nodiscard]] float getAmplificationFactor() const override;
145 
146  [[nodiscard]] Patch& getPatch(unsigned instrument, bool carrier);
147 
148  template<typename Archive>
149  void serialize(Archive& ar, unsigned version);
150 
151 private:
152  void writeReg(uint8_t r, uint8_t data);
153 
154  inline void keyOn_BD();
155  inline void keyOn_SD();
156  inline void keyOn_TOM();
157  inline void keyOn_HH();
158  inline void keyOn_CYM();
159  inline void keyOff_BD();
160  inline void keyOff_SD();
161  inline void keyOff_TOM();
162  inline void keyOff_HH();
163  inline void keyOff_CYM();
164  inline void setRhythmFlags(uint8_t old);
165  inline void update_key_status();
166  [[nodiscard]] inline bool isRhythm() const;
167  [[nodiscard]] inline unsigned getFreq(unsigned channel) const;
168 
169  template<unsigned FLAGS>
170  inline void calcChannel(Channel& ch, float* buf, unsigned num);
171 
172 private:
174  Channel channels[9];
175 
177  unsigned pm_phase;
178 
180  unsigned am_phase;
181 
183  unsigned noise_seed;
184 
186  Patch patches[19][2];
187 
189  uint8_t reg[0x40];
190  uint8_t registerLatch;
191 };
192 
193 } // namespace YM2413Okazaki
194 
198 
199 } // namespace openmsx
200 
201 #endif
Abstract interface for the YM2413 core.
Definition: YM2413Core.hh:27
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 initCarrier(const uint8_t *data)
void setTL(uint8_t value)
Set volume (total level) [0..63].
void initModulator(const uint8_t *data)
void setKL(uint8_t value)
Sets Key scale level [0..3].
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)
unsigned calc_envelope(int lfo_am, unsigned fixed_env)
unsigned calc_phase(unsigned lfo_pm)
unsigned calc_fixed_env() const
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)
void generateChannels(float *bufs[9+5], unsigned num) override
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 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)
constexpr int EP_FP_BITS
This file implemented 3 utility functions:
Definition: Autofire.cc:5
SERIALIZE_CLASS_VERSION(CassettePlayer, 2)