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 byte* data);
28  void initCarrier (const byte* data);
29 
31  inline void setKR(byte value);
33  inline void setML(byte value);
35  inline void setKL(byte value);
37  inline void setTL(byte value);
39  inline void setWF(byte value);
41  inline void setFB(byte value);
43  inline void setSL(byte value);
44 
45  const unsigned* WF; // 0-1 transformed to waveform[0-1]
46  const byte* KL; // 0-3 transformed to tllTable[0-3]
47  unsigned SL; // 0-15 transformed to slTable[0-15]
48  byte AMPM; // 0-3 2 packed booleans
49  bool EG; // 0-1
50  byte KR; // 0-1 transformed to 10,8
51  byte ML; // 0-15 transformed to mlTable[0-15]
52  byte TL; // 0-63 transformed to TL2EG(0..63) == [0..252]
53  byte FB; // 0,1-7 transformed to 0,7-1
54  byte AR; // 0-15
55  byte DR; // 0-15
56  byte RR; // 0-15
57 };
58 
59 class Slot {
60 public:
61  void reset();
62 
63  inline void setEnvelopeState(EnvelopeState state);
64  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  inline unsigned calc_phase(unsigned lfo_pm);
73  template <bool HAS_AM, bool FIXED_ENV>
74  inline unsigned calc_envelope(int lfo_am, unsigned fixed_env);
75  template <bool HAS_AM> unsigned calc_fixed_env() const;
76  void calc_envelope_outline(unsigned& out);
77  template<bool HAS_AM, bool FIXED_ENV>
78  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  inline int calc_slot_mod(unsigned lfo_pm, int lfo_am, unsigned fixed_env);
81 
82  inline int calc_slot_tom();
83  inline int calc_slot_snare(bool noise);
84  inline int calc_slot_cym(unsigned phase7, unsigned phase8);
85  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
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 
127  Slot mod, car;
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  inline void keyOn_BD();
139  inline void keyOn_SD();
140  inline void keyOn_TOM();
141  inline void keyOn_HH();
142  inline void keyOn_CYM();
143  inline void keyOff_BD();
144  inline void keyOff_SD();
145  inline void keyOff_TOM();
146  inline void keyOff_HH();
147  inline void keyOff_CYM();
148  inline void setRhythmFlags(byte old);
149  inline void update_key_status();
150  inline bool isRhythm() const;
151  inline unsigned getFreq(unsigned channel) const;
152  Patch& getPatch(unsigned instrument, bool carrier);
153 
154  template <unsigned FLAGS>
155  inline void calcChannel(Channel& ch, float* buf, unsigned num);
156 
157  template<typename Archive>
158  void serialize(Archive& ar, unsigned version);
159 
160 private:
161  // YM2413Core
162  void reset() override;
163  void writeReg(byte reg, byte data) override;
164  byte peekReg(byte reg) const override;
165  void generateChannels(float* bufs[9 + 5], unsigned num) override;
166  float getAmplificationFactor() const override;
167 
169  Channel channels[9];
170 
172  unsigned pm_phase;
173 
175  unsigned am_phase;
176 
178  unsigned noise_seed;
179 
181  Patch patches[19][2];
182 
184  byte reg[0x40];
185 };
186 
187 } // namespace YM2413Okazaki
188 
192 
193 } // namespace openmsx
194 
195 #endif
void setWF(byte value)
Set waveform [0..1].
void setKR(byte value)
Sets the Key Scale of Rate (0 or 1).
void setSL(byte value)
Sets sustain level [0..15].
void setTL(byte value)
Set volume (total level) [0..63].
uint8_t byte
8 bit unsigned integer
Definition: openmsx.hh:26
Abstract interface for the YM2413 core.
Definition: YM2413Core.hh:26
void initModulator(const byte *data)
void setML(byte value)
Sets the frequency multiplier factor [0..15].
SERIALIZE_CLASS_VERSION(CassettePlayer, 2)
void initCarrier(const byte *data)
void setKL(byte value)
Sets Key scale level [0..3].
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
Patch()
Creates an uninitialized Patch object; call initXXX() before use.
YM2413
Definition: YM2413.cc:88
void setFB(byte value)
Sets the amount of feedback [0..7].
constexpr int EP_FP_BITS
void serialize(Archive &ar, T &t, unsigned version)