forked from hissorii/px68k
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfmgen.h
266 lines (213 loc) · 6.24 KB
/
fmgen.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
// ---------------------------------------------------------------------------
// FM Sound Generator
// Copyright (C) cisc 1998, 2001.
// ---------------------------------------------------------------------------
#ifndef FM_GEN_H
#define FM_GEN_H
#include "common.h"
#include "fmgen_types.h"
// ---------------------------------------------------------------------------
// 出力サンプルの型
//
#define FM_SAMPLETYPE int16 // int16 or int32
// ---------------------------------------------------------------------------
// 定数その1
// 静的テーブルのサイズ
#define FM_LFOBITS 8 // 変更不可
#define FM_TLBITS 7
// ---------------------------------------------------------------------------
#define FM_TLENTS (1 << FM_TLBITS)
#define FM_LFOENTS (1 << FM_LFOBITS)
#define FM_TLPOS (FM_TLENTS/4)
// サイン波の精度は 2^(1/256)
#define FM_CLENTS (0x1000 * 2) // sin + TL + LFO
// ---------------------------------------------------------------------------
namespace FM
{
// Types ----------------------------------------------------------------
typedef FM_SAMPLETYPE Sample;
typedef int32 ISample;
enum OpType { typeN=0, typeM=1 };
void StoreSample(ISample& dest, int data);
class Chip;
// Operator -------------------------------------------------------------
class Operator
{
public:
Operator();
void SetChip(Chip* chip) { chip_ = chip; }
static void MakeTimeTable(uint ratio);
ISample Calc(ISample in);
ISample CalcL(ISample in);
ISample CalcFB(uint fb);
ISample CalcFBL(uint fb);
ISample CalcN(uint noise);
void Prepare();
void KeyOn();
void KeyOff();
void Reset();
void ResetFB();
int IsOn();
void SetDT(uint dt);
void SetDT2(uint dt2);
void SetMULTI(uint multi);
void SetTL(uint tl, bool csm);
void SetKS(uint ks);
void SetAR(uint ar);
void SetDR(uint dr);
void SetSR(uint sr);
void SetRR(uint rr);
void SetSL(uint sl);
void SetSSGEC(uint ssgec);
void SetFNum(uint fnum);
void SetDPBN(uint dp, uint bn);
void SetMode(bool modulator);
void SetAMON(bool on);
void SetMS(uint ms);
void Mute(bool);
// static void SetAML(uint l);
// static void SetPML(uint l);
int Out() { return out_; }
int dbgGetIn2() { return in2_; }
void dbgStopPG() { pg_diff_ = 0; pg_diff_lfo_ = 0; }
private:
typedef uint32 Counter;
Chip* chip_;
ISample out_, out2_;
ISample in2_;
// Phase Generator ------------------------------------------------------
uint32 PGCalc();
uint32 PGCalcL();
uint dp_; // ΔP
uint detune_; // Detune
uint detune2_; // DT2
uint multiple_; // Multiple
uint32 pg_count_; // Phase 現在値
uint32 pg_diff_; // Phase 差分値
int32 pg_diff_lfo_; // Phase 差分値 >> x
// Envelop Generator ---------------------------------------------------
enum EGPhase { next, attack, decay, sustain, release, off };
void EGCalc();
void EGStep();
void ShiftPhase(EGPhase nextphase);
void SSGShiftPhase(int mode);
void SetEGRate(uint);
void EGUpdate();
int FBCalc(int fb);
ISample LogToLin(uint a);
OpType type_; // OP の種類 (M, N...)
uint bn_; // Block/Note
int eg_level_; // EG の出力値
int eg_level_on_next_phase_; // 次の eg_phase_ に移る値
int eg_count_; // EG の次の変移までの時間
int eg_count_diff_; // eg_count_ の差分
int eg_out_; // EG+TL を合わせた出力値
int tl_out_; // TL 分の出力値
// int pm_depth_; // PM depth
// int am_depth_; // AM depth
int eg_rate_;
int eg_curve_count_;
int ssg_offset_;
int ssg_vector_;
int ssg_phase_;
uint key_scale_rate_; // key scale rate
EGPhase eg_phase_;
uint* ams_;
uint ms_;
uint tl_; // Total Level (0-127)
uint tl_latch_; // Total Level Latch (for CSM mode)
uint ar_; // Attack Rate (0-63)
uint dr_; // Decay Rate (0-63)
uint sr_; // Sustain Rate (0-63)
uint sl_; // Sustain Level (0-127)
uint rr_; // Release Rate (0-63)
uint ks_; // Keyscale (0-3)
uint ssg_type_; // SSG-Type Envelop Control
bool keyon_;
bool amon_; // enable Amplitude Modulation
bool param_changed_; // パラメータが更新された
bool mute_;
// Tables ---------------------------------------------------------------
static Counter rate_table[16];
static uint32 multable[4][16];
static const uint8 notetable[128];
static const int8 dttable[256];
static const int8 decaytable1[64][8];
static const int decaytable2[16];
static const int8 attacktable[64][8];
static const int ssgenvtable[8][2][3][2];
static uint sinetable[1024];
static int32 cltable[FM_CLENTS];
static bool tablehasmade;
static void MakeTable();
// friends --------------------------------------------------------------
friend class Channel4;
friend void __stdcall FM_NextPhase(Operator* op);
public:
int dbgopout_;
int dbgpgout_;
static const int32* dbgGetClTable() { return cltable; }
static const uint* dbgGetSineTable() { return sinetable; }
};
// 4-op Channel ---------------------------------------------------------
class Channel4
{
public:
Channel4();
void SetChip(Chip* chip);
void SetType(OpType type);
ISample Calc();
ISample CalcL();
ISample CalcN(uint noise);
ISample CalcLN(uint noise);
void SetFNum(uint fnum);
void SetFB(uint fb);
void SetKCKF(uint kc, uint kf);
void SetAlgorithm(uint algo);
int Prepare();
void KeyControl(uint key);
void Reset();
void SetMS(uint ms);
void Mute(bool);
void Refresh();
void dbgStopPG() { for (int i=0; i<4; i++) op[i].dbgStopPG(); }
private:
static const uint8 fbtable[8];
uint fb;
int buf[4];
int* in[3]; // 各 OP の入力ポインタ
int* out[3]; // 各 OP の出力ポインタ
int* pms;
int algo_;
Chip* chip_;
static void MakeTable();
static bool tablehasmade;
static int kftable[64];
public:
Operator op[4];
};
// Chip resource
class Chip
{
public:
Chip();
void SetRatio(uint ratio);
void SetAML(uint l);
void SetPML(uint l);
void SetPMV(int pmv) { pmv_ = pmv; }
uint32 GetMulValue(uint dt2, uint mul) { return multable_[dt2][mul]; }
uint GetAML() { return aml_; }
uint GetPML() { return pml_; }
int GetPMV() { return pmv_; }
uint GetRatio() { return ratio_; }
private:
void MakeTable();
uint ratio_;
uint aml_;
uint pml_;
int pmv_;
OpType optype_;
uint32 multable_[4][16];
};
}
#endif // FM_GEN_H