-
Notifications
You must be signed in to change notification settings - Fork 1
/
midisynth.hpp
executable file
·378 lines (350 loc) · 14.7 KB
/
midisynth.hpp
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
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
// ソフトウェアMIDIシンセサイザ。
// Copyright(c)2003-2005 yuno
#ifndef midisynth_hpp
#define midisynth_hpp
#include <stdint.h>
#include <map>
#include <memory>
#include <vector>
namespace midisynth{
/*
typedef short int_least16_t;
typedef unsigned short uint_least16_t;
typedef long int_least32_t;
typedef unsigned long uint_least32_t;
typedef __int64 int_least64_t;
*/
class channel;
// システムモード列挙型。
enum system_mode_t{ system_mode_default, system_mode_gm, system_mode_gm2, system_mode_gs, system_mode_xg };
// コピー不可の基本クラス。
class uncopyable{
public:
uncopyable(){}
private:
uncopyable(const uncopyable&){}
void operator=(const uncopyable&){}
};
// ノート。発音中の音。
class note:uncopyable{
public:
note(int assign_, int panpot_):assign(assign_), panpot(panpot_){}
virtual ~note(){}
int get_assign()const{ return assign; }
int get_panpot()const{ return panpot; }
virtual bool synthesize(int_least32_t* buf, std::size_t samples, float rate, int_least32_t left, int_least32_t right) = 0;
virtual void note_off(int velocity) = 0;
virtual void sound_off() = 0;
virtual void set_frequency_multiplier(float value) = 0;
virtual void set_tremolo(int depth, float freq) = 0;
virtual void set_vibrato(float depth, float freq) = 0;
virtual void set_damper(int value) = 0;
virtual void set_sostenute(int value) = 0;
virtual void set_freeze(int value) = 0;
private:
int assign;
int panpot;
};
// ノートファクトリ。
// ノートオンメッセージに対して適切なノートを作り出す。
class note_factory:uncopyable{
public:
virtual note* note_on(int_least32_t program, int note, int velocity, float frequency_multiplier)=0;
protected:
~note_factory(){}
};
// MIDIチャンネル。
class channel:uncopyable{
enum{ NUM_NOTES = 128 };
public:
channel(note_factory* factory, int bank);
~channel();
int synthesize(int_least32_t* out, std::size_t samples, float rate, int_least32_t master_volume, int master_balance);
void reset_all_parameters();
void reset_all_controller();
void all_note_off();
void all_sound_off();
void all_sound_off_immediately();
void note_off(int note, int velocity);
void note_on(int note, int velocity);
void polyphonic_key_pressure(int note, int value);
void program_change(int value){ set_program(128 * bank + value); }
void channel_pressure(int value);
void pitch_bend_change(int value){ pitch_bend = value; update_frequency_multiplier(); }
void control_change(int control, int value);
void bank_select(int value);
void set_bank(int value){ bank = value; }
void set_program(int value){ program = value; }
void set_panpot(int value){ panpot = value; }
void set_volume(int value){ volume = value; }
void set_expression(int value){ expression = value; }
void set_pitch_bend_sensitivity(int value){ pitch_bend_sensitivity = value; update_frequency_multiplier(); }
void set_modulation_depth(int value){ modulation_depth = value; update_modulation(); }
void set_modulation_depth_range(int value){ modulation_depth_range = value; update_modulation(); }
void set_damper(int value);
void set_sostenute(int value);
void set_freeze(int value);
void set_fine_tuning(int value){ fine_tuning = value; update_frequency_multiplier(); }
void set_coarse_tuning(int value){ coarse_tuning = value; update_frequency_multiplier(); }
void set_RPN(int value){ RPN = value; NRPN = 0x3FFF; }
void set_NRPN(int value){ NRPN = value; RPN = 0x3FFF; }
void set_tremolo_frequency(float value){ tremolo_frequency = value; }
void set_vibrato_frequency(float value){ vibrato_frequency = value; }
void set_master_frequency_multiplier(float value){ master_frequency_multiplier = value; update_frequency_multiplier(); }
void set_mute(bool mute_){ mute = mute_; }
void set_system_mode(system_mode_t mode){ system_mode = mode; }
void mono_mode_on(){ all_note_off(); mono = true; }
void poly_mode_on(){ all_note_off(); mono = false; }
int get_program()const{ return program; }
int get_bank()const{ return bank; }
int get_panpot()const{ return panpot; }
int get_volume()const{ return volume; }
int get_expression()const{ return expression; }
int get_channel_pressure()const{ return pressure; }
int get_pitch_bend()const{ return pitch_bend; }
int get_pitch_bend_sensitivity()const{ return pitch_bend_sensitivity; }
int get_modulation_depth()const{ return modulation_depth; }
int get_modulation_depth_range()const{ return modulation_depth_range; }
int get_damper()const{ return damper; }
int get_sostenute()const{ return sostenute; }
int get_freeze()const{ return freeze; }
int get_fine_tuning()const{ return fine_tuning; }
int get_coarse_tuning()const{ return coarse_tuning; }
int get_RPN()const{ return RPN; }
int get_NRPN()const{ return NRPN; }
float get_tremolo_frequency()const{ return tremolo_frequency; }
float get_vibrato_frequency()const{ return vibrato_frequency; }
bool get_mute()const{ return mute; }
bool get_mono_mode()const{ return mono; }
private:
struct NOTE{
class note* note;
int key;
enum STATUS{
NOTEON, NOTEOFF, SOUNDOFF
}status;
NOTE(class note* p, int key_):note(p),key(key_),status(NOTEON){}
};
std::vector<NOTE> notes;
note_factory* factory;
int default_bank;
int program;
int bank;
int panpot;
int volume;
int expression;
int pressure;
int pitch_bend;
int pitch_bend_sensitivity;
int modulation_depth;
int modulation_depth_range;
int damper;
int sostenute;
int freeze;
int fine_tuning;
int coarse_tuning;
int RPN;
int NRPN;
bool mono;
bool mute;
float tremolo_frequency;
float vibrato_frequency;
float frequency_multiplier;
float master_frequency_multiplier;
system_mode_t system_mode;
int get_registered_parameter();
void set_registered_parameter(int value);
void update_frequency_multiplier();
void update_modulation();
};
// MIDIシンセサイザ。
class synthesizer:uncopyable{
enum{ NUM_CHANNELS = 16 };
public:
synthesizer(note_factory* factory);
channel* get_channel(int ch);
int synthesize(int_least16_t* output, std::size_t samples, float rate);
int synthesize_mixing(int_least32_t* output, std::size_t samples, float rate);
void reset();
void reset_all_parameters();
void reset_all_controller();
void all_note_off();
void all_sound_off();
void all_sound_off_immediately();
void note_on(int channel, int note, int velocity){ get_channel(channel)->note_on(note, velocity); }
void note_off(int channel, int note, int velocity){ get_channel(channel)->note_off(note, velocity); }
void polyphonic_key_pressure(int channel, int note, int value){ get_channel(channel)->polyphonic_key_pressure(note, value); }
void control_change(int channel, int control, int value){ get_channel(channel)->control_change(control, value); }
void program_change(int channel, int program){ get_channel(channel)->program_change(program); }
void channel_pressure(int channel, int value){ get_channel(channel)->channel_pressure(value); }
void pitch_bend_change(int channel, int value){ get_channel(channel)->pitch_bend_change(value); }
void sysex_message(const void* data, std::size_t size);
void midi_event(int command, int param1, int param2);
void midi_event(uint_least32_t message){ midi_event(message & 0xFF, (message >> 8) & 0x7F, (message >> 16) & 0x7F); }
void set_main_volume(int value){ main_volume = value; }
void set_master_volume(int value){ master_volume = value; }
void set_master_balance(int value){ master_balance = value; }
void set_master_fine_tuning(int value){ master_fine_tuning = value; update_master_frequency_multiplier(); }
void set_master_coarse_tuning(int value){ master_coarse_tuning = value; update_master_frequency_multiplier(); }
void set_system_mode(system_mode_t mode);
int get_main_volume()const{ return main_volume; }
int get_master_volume()const{ return master_volume; }
int get_master_balance()const{ return master_balance; }
int get_master_fine_tuning()const{ return master_fine_tuning; }
int get_master_coarse_tuning()const{ return master_coarse_tuning; }
system_mode_t get_system_mode()const{ return system_mode; }
private:
std::auto_ptr<channel> channels[NUM_CHANNELS];
float active_sensing;
int main_volume;
int master_volume;
int master_balance;
int master_fine_tuning;
int master_coarse_tuning;
float master_frequency_multiplier;
system_mode_t system_mode;
void update_master_frequency_multiplier();
};
// 正弦波生成器。
// 振幅 32768 (-32767~32767) の正弦波を生成する。
class sine_wave_generator{
public:
sine_wave_generator();
sine_wave_generator(float cycle);
void set_cycle(float cycle);
void add_modulation(int_least32_t x);
int get_next();
int get_next(int_least32_t modulation);
private:
uint_least32_t position;
uint_least32_t step;
};
// エンベロープ生成器。
// TL=0 のとき 0~32767 の値を生成する。
class envelope_generator{
public:
envelope_generator(int AR, int DR, int SR, int RR, int SL, int TL);
void set_rate(float rate);
void set_hold(float value);
void set_freeze(float value);
void key_off();
void sound_off();
bool is_finished()const{ return state == FINISHED; }
int get_next();
private:
enum{ ATTACK, ATTACK_RELEASE, DECAY, DECAY_RELEASE, SASTAIN, RELEASE, SOUNDOFF, FINISHED }state;
int AR, DR, SR, RR, TL;
uint_least32_t fAR, fDR, fSR, fRR, fSL, fTL, fOR, fSS, fDRR, fDSS;
uint_least32_t current;
float rate;
float hold;
float freeze;
void update_parameters();
};
// FMオペレータ (モジュレータおよびキャリア)。
class fm_operator{
public:
fm_operator(int AR, int DR, int SR, int RR, int SL, int TL, int KS, int ML, int DT, int AMS, int key);
void set_freq_rate(float freq, float rate);
void set_hold(float value){ eg.set_hold(value); }
void set_freeze(float value){ eg.set_freeze(value); }
void add_modulation(int_least32_t x){ swg.add_modulation(x); }
void key_off(){ eg.key_off(); }
void sound_off(){ eg.sound_off(); }
bool is_finished()const{ return eg.is_finished(); }
int get_next();
int get_next(int modulate);
int get_next(int lfo, int modulate);
inline int operator()(){ return get_next(); }
inline int operator()(int m){ return get_next(m); }
inline int operator()(int lfo, int m){ return get_next(lfo, m); }
private:
sine_wave_generator swg;
envelope_generator eg;
float ML;
float DT;
int_least32_t ams_factor;
int_least32_t ams_bias;
};
// FM音源パラメータ。
struct FMPARAMETER{
int ALG, FB, LFO;
struct{
int AR, DR, SR, RR, SL, TL, KS, ML, DT, AMS;
}op1, op2, op3, op4;
};
// ドラムパラメータ。
struct DRUMPARAMETER:FMPARAMETER{
int key, panpot, assign;
};
// FMサウンドジェネレータ。
class fm_sound_generator{
public:
fm_sound_generator(const FMPARAMETER& params, int note, float frequency_multiplier);
void set_rate(float rate);
void set_frequency_multiplier(float value);
void set_damper(int damper);
void set_sostenute(int sostenute);
void set_freeze(int freeze);
void set_tremolo(int depth, float frequency);
void set_vibrato(float depth, float frequency);
void key_off();
void sound_off();
bool is_finished()const;
int get_next();
private:
fm_operator op1;
fm_operator op2;
fm_operator op3;
fm_operator op4;
sine_wave_generator ams_lfo;
sine_wave_generator vibrato_lfo;
sine_wave_generator tremolo_lfo;
int ALG;
int FB;
float freq;
float freq_mul;
float ams_freq;
bool ams_enable;
int tremolo_depth;
float tremolo_freq;
int vibrato_depth;
float vibrato_freq;
float rate;
int feedback;
int damper;
int sostenute;
};
// FM音源ノート。
class fm_note:public note{
public:
fm_note(const FMPARAMETER& params, int note, int velocity, int panpot, int assign, float frequency_multiplier);
virtual void release(){ delete this; }
virtual bool synthesize(int_least32_t* buf, std::size_t samples, float rate, int_least32_t left, int_least32_t right);
virtual void note_off(int velocity);
virtual void sound_off();
virtual void set_frequency_multiplier(float value);
virtual void set_tremolo(int depth, float freq);
virtual void set_vibrato(float depth, float freq);
virtual void set_damper(int value);
virtual void set_sostenute(int value);
virtual void set_freeze(int value);
public:
fm_sound_generator fm;
int velocity;
};
// FM音源ノートファクトリ。
class fm_note_factory:public note_factory{
public:
fm_note_factory();
void clear();
void get_program(int number, FMPARAMETER& p);
bool set_program(int number, const FMPARAMETER& p);
bool set_drum_program(int number, const DRUMPARAMETER& p);
virtual note* note_on(int_least32_t program, int note, int velocity, float frequency_multiplier);
private:
std::map<int, FMPARAMETER> programs;
std::map<int, DRUMPARAMETER> drums;
};
}
#endif