openMSX
YM2413Burczynski.hh
Go to the documentation of this file.
1#ifndef YM2413BURCZYNSKI_HH
2#define YM2413BURCZYNSKI_HH
3
4#include "YM2413Core.hh"
5
6#include "FixedPoint.hh"
7#include "serialize_meta.hh"
8
9#include <array>
10#include <span>
11
12namespace openmsx {
13namespace YM2413Burczynski {
14
15// sin wave entries
16static constexpr int SIN_BITS = 10;
17static constexpr size_t SIN_LEN = 1 << SIN_BITS;
18static constexpr size_t SIN_MASK = SIN_LEN - 1;
19
20class Channel;
21
25
26class Slot
27{
28public:
29 Slot();
30
31 void resetOperators();
32
36 void updateGenerators(const Channel& channel);
37
38 [[nodiscard]] int calcOutput(const Channel& channel, unsigned eg_cnt, bool carrier,
39 unsigned lfo_am, int phase);
40 [[nodiscard]] int calc_slot_mod(const Channel& channel, unsigned eg_cnt, bool carrier,
41 unsigned lfo_pm, unsigned lfo_am);
42 [[nodiscard]] int calc_envelope(const Channel& channel, unsigned eg_cnt, bool carrier);
43 [[nodiscard]] int calc_phase(const Channel& channel, unsigned lfo_pm);
44
45 enum KeyPart : uint8_t { KEY_MAIN = 1, KEY_RHYTHM = 2 };
46 void setKeyOn(KeyPart part);
47 void setKeyOff(KeyPart part);
48 void setKeyOnOff(KeyPart part, bool enabled);
49
52 [[nodiscard]] bool isActive() const;
53
56 void setFrequencyMultiplier(uint8_t value);
57
60 void setKeyScaleRate(bool value);
61
65 void setEnvelopeSustained(bool value);
66
69 void setVibrato(bool value);
70
73 void setAmplitudeModulation(bool value);
74
77 void setTotalLevel(const Channel& channel, uint8_t value);
78
81 void setKeyScaleLevel(const Channel& channel, uint8_t value);
82
85 void setWaveform(uint8_t value);
86
89 void setFeedbackShift(uint8_t value);
90
93 void setAttackRate(const Channel& channel, uint8_t value);
94
97 void setDecayRate(const Channel& channel, uint8_t value);
98
101 void setReleaseRate(const Channel& channel, uint8_t value);
102
105 void setSustainLevel(uint8_t value);
106
109 void updateFrequency(const Channel& channel);
110
111 template<typename Archive>
112 void serialize(Archive& ar, unsigned version);
113
114public: // public for serialization, otherwise could be private
121
122private:
125 void setEnvelopeState(EnvelopeState state);
126
127 void updateTotalLevel(const Channel& channel);
128 void updateAttackRate(int kcodeScaled);
129 void updateDecayRate(int kcodeScaled);
130 void updateReleaseRate(int kcodeScaled);
131
132 std::span<const unsigned, SIN_LEN> waveTable; // waveform select
133
134 // Phase Generator
135 FreqIndex phase{0}; // frequency counter
136 FreqIndex freq{0}; // frequency counter step
137
138 // Envelope Generator
139 int TL{0}; // total level: TL << 2
140 int TLL{0}; // adjusted now TL
141 int egOut{0}; // envelope counter
142 int sl{0}; // sustain level: sl_tab[SL]
143 EnvelopeState state;
144
145 std::array<int, 2> op1_out = {0, 0}; // MOD output for feedback
146 bool eg_sustain{false}; // percussive/non-percussive mode
147 uint8_t fb_shift{0}; // feedback shift value
148
149 uint8_t key{0}; // 0 = KEY OFF, >0 = KEY ON
150
151 std::span<const uint8_t, 8> eg_sel_dp;
152 std::span<const uint8_t, 8> eg_sel_ar;
153 std::span<const uint8_t, 8> eg_sel_dr;
154 std::span<const uint8_t, 8> eg_sel_rr;
155 std::span<const uint8_t, 8> eg_sel_rs;
156 unsigned eg_mask_dp{0}; // == (1 << eg_sh_dp) - 1
157 unsigned eg_mask_ar{0}; // == (1 << eg_sh_ar) - 1
158 unsigned eg_mask_dr{0}; // == (1 << eg_sh_dr) - 1
159 unsigned eg_mask_rr{0}; // == (1 << eg_sh_rr) - 1
160 unsigned eg_mask_rs{0}; // == (1 << eg_sh_rs) - 1
161 uint8_t eg_sh_dp{0}; // (dump state)
162 uint8_t eg_sh_ar{0}; // (attack state)
163 uint8_t eg_sh_dr{0}; // (decay state)
164 uint8_t eg_sh_rr{0}; // (release state for non-perc.)
165 uint8_t eg_sh_rs{0}; // (release state for perc.mode)
166
167 uint8_t ar{0}; // attack rate: AR<<2
168 uint8_t dr{0}; // decay rate: DR<<2
169 uint8_t rr{0}; // release rate:RR<<2
170 uint8_t KSR{0}; // key scale rate
171 uint8_t ksl{0}; // key scale level
172 uint8_t mul{0}; // multiple: mul_tab[ML]
173
174 // LFO
175 uint8_t AMmask{0}; // LFO Amplitude Modulation enable mask
176 uint8_t vib{0}; // LFO Phase Modulation enable flag (active high)
177};
178
180{
181public:
184 [[nodiscard]] int calcOutput(unsigned eg_cnt, unsigned lfo_pm, unsigned lfo_am, int fm);
185
188 void setFrequency(int block_fnum);
189
192 void setFrequencyLow(uint8_t value);
193
196 void setFrequencyHigh(uint8_t value);
197
202 void updateInstrumentPart(int part, uint8_t value);
203
207 void updateInstrument(std::span<const uint8_t, 8> inst);
208
209 [[nodiscard]] int getBlockFNum() const;
210 [[nodiscard]] FreqIndex getFrequencyIncrement() const;
211 [[nodiscard]] int getKeyScaleLevelBase() const;
212 [[nodiscard]] uint8_t getKeyCode() const;
213 [[nodiscard]] bool isSustained() const;
214 void setSustain(bool sustained);
215
216 template<typename Archive>
217 void serialize(Archive& ar, unsigned version);
218
221
222private:
223 // phase generator state
224 int block_fnum{0}; // block+fnum
225 FreqIndex fc{0}; // Freq. increment base
226 int ksl_base{0}; // KeyScaleLevel Base step
227 bool sus{false}; // sus on/off (release speed in percussive mode)
228};
229
230class YM2413 final : public YM2413Core
231{
232public:
233 YM2413();
234
235 // YM2413Core
236 void reset() override;
237 void writePort(bool port, uint8_t value, int offset) override;
238 void pokeReg(uint8_t reg, uint8_t value) override;
239 [[nodiscard]] uint8_t peekReg(uint8_t reg) const override;
240 void generateChannels(std::span<float*, 9 + 5> bufs, unsigned num) override;
241 [[nodiscard]] float getAmplificationFactor() const override;
242
243 template<typename Archive>
244 void serialize(Archive& ar, unsigned version);
245
246private:
247 void writeReg(uint8_t reg, uint8_t value);
248
251 void resetOperators();
252
253 [[nodiscard]] bool isRhythm() const;
254
255 [[nodiscard]] Channel& getChannelForReg(uint8_t reg);
256
261 void updateCustomInstrument(int part, uint8_t value);
262
263 void setRhythmFlags(uint8_t old);
264
265private:
267 std::array<Channel, 9> channels;
268
270 unsigned eg_cnt;
271
273 int noise_rng;
274
276 unsigned idleSamples;
277
280 LFOAMIndex lfo_am_cnt;
281 LFOPMIndex lfo_pm_cnt;
282
289 std::array<std::array<uint8_t, 8>, 19> inst_tab;
290
292 std::array<uint8_t, 0x40> reg;
293 uint8_t registerLatch;
294};
295
296} // namespace YM2413Burczynski
297
301
302} // namespace openmsx
303
304#endif
void updateInstrument(std::span< const uint8_t, 8 > inst)
Sets all synthesis parameters as specified by the instrument.
void updateInstrumentPart(int part, uint8_t value)
Sets some synthesis parameters as specified by the instrument.
void setFrequencyLow(uint8_t value)
Changes the lower 8 bits of the frequency for this channel.
void serialize(Archive &ar, unsigned version)
void setFrequency(int block_fnum)
Sets the frequency for this channel.
void setFrequencyHigh(uint8_t value)
Changes the higher 4 bits of the frequency for this channel.
int calcOutput(unsigned eg_cnt, unsigned lfo_pm, unsigned lfo_am, int fm)
Calculate the value of the current sample produced by this channel.
void setSustainLevel(uint8_t value)
Sets the sustain level [0..15].
EnvelopeState
Envelope Generator phases Note: These are ordered: phase constants are compared in the code.
int calc_phase(const Channel &channel, unsigned lfo_pm)
int calc_slot_mod(const Channel &channel, unsigned eg_cnt, bool carrier, unsigned lfo_pm, unsigned lfo_am)
int calc_envelope(const Channel &channel, unsigned eg_cnt, bool carrier)
void setEnvelopeSustained(bool value)
Sets the envelope type of the current instrument.
void setKeyOnOff(KeyPart part, bool enabled)
void setAttackRate(const Channel &channel, uint8_t value)
Sets the attack rate [0..15].
void setFrequencyMultiplier(uint8_t value)
Sets the frequency multiplier [0..15].
void setReleaseRate(const Channel &channel, uint8_t value)
Sets the release rate [0..15].
void setWaveform(uint8_t value)
Sets the waveform: 0 = sinus, 1 = half sinus, half silence.
void updateFrequency(const Channel &channel)
Called by Channel when block_fnum changes.
int calcOutput(const Channel &channel, unsigned eg_cnt, bool carrier, unsigned lfo_am, int phase)
void serialize(Archive &ar, unsigned version)
void setVibrato(bool value)
Enables (true) or disables (false) vibrato.
void setAmplitudeModulation(bool value)
Enables (true) or disables (false) amplitude modulation.
void setDecayRate(const Channel &channel, uint8_t value)
Sets the decay rate [0..15].
void setFeedbackShift(uint8_t value)
Sets the amount of feedback [0..7].
void setKeyScaleLevel(const Channel &channel, uint8_t value)
Sets the key scale level: 0->0 / 1->1.5 / 2->3.0 / 3->6.0 dB/OCT.
void updateGenerators(const Channel &channel)
Update phase increment counter of operator.
void setTotalLevel(const Channel &channel, uint8_t value)
Sets the total level: [0..63].
bool isActive() const
Does this slot currently produce an output signal?
void setKeyScaleRate(bool value)
Sets the key scale rate: true->0, false->2.
void generateChannels(std::span< float *, 9+5 > bufs, unsigned num) override
Generate the sound output.
void writePort(bool port, uint8_t value, int offset) override
Write to the YM2413 register/data port.
void serialize(Archive &ar, unsigned version)
void reset() override
Reset this YM2413 core.
void pokeReg(uint8_t reg, uint8_t value) override
Write to a YM2413 register (for debug).
float getAmplificationFactor() const override
Returns normalization factor.
uint8_t peekReg(uint8_t reg) const override
Read from a YM2413 register (for debug).
Abstract interface for the YM2413 core.
Definition YM2413Core.hh:28
FixedPoint< 16 > FreqIndex
16.16 fixed point type for frequency calculations.
This file implemented 3 utility functions:
Definition Autofire.cc:11
#define SERIALIZE_CLASS_VERSION(CLASS, VERSION)