2 * Drawbar organ emulator.
4 * Copyright (C) 2007 Krzysztof Foltman
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
19 * Boston, MA 02111-1307, USA.
22 #ifndef __CALF_ORGAN_H
23 #define __CALF_ORGAN_H
29 #define ORGAN_KEYTRACK_POINTS 4
34 struct organ_parameters
{
35 enum { FilterCount
= 2, EnvCount
= 3 };
36 struct organ_filter_parameters
40 float envmod
[organ_parameters::EnvCount
];
44 struct organ_env_parameters
46 float attack
, decay
, sustain
, release
, velscale
, ampctl
;
49 //////////////////////////////////////////////////////////////////////////
50 // these parameters are binary-copied from control ports (order is important!)
60 float percussion_time
;
61 float percussion_level
;
62 float percussion_wave
;
63 float percussion_harmonic
;
64 float percussion_vel2amp
;
65 float percussion_fm_time
;
66 float percussion_fm_depth
;
67 float percussion_fm_wave
;
68 float percussion_fm_harmonic
;
69 float percussion_vel2fm
;
70 float percussion_trigger
;
71 float percussion_stereo
;
75 organ_filter_parameters filters
[organ_parameters::FilterCount
];
76 organ_env_parameters envs
[organ_parameters::EnvCount
];
83 float global_transpose
;
90 float pitch_bend_range
;
94 //////////////////////////////////////////////////////////////////////////
95 // these parameters are calculated
97 double perc_decay_const
, perc_fm_decay_const
;
101 unsigned int foldvalue
;
104 float percussion_keytrack
[ORGAN_KEYTRACK_POINTS
][2];
106 organ_parameters() : pitch_bend(1.0f
) {}
108 inline int get_percussion_wave() { return dsp::fastf2i_drm(percussion_wave
); }
109 inline int get_percussion_fm_wave() { return dsp::fastf2i_drm(percussion_fm_wave
); }
112 #define ORGAN_WAVE_BITS 12
113 #define ORGAN_WAVE_SIZE 4096
114 #define ORGAN_BIG_WAVE_BITS 17
115 #define ORGAN_BIG_WAVE_SIZE 131072
116 /// 2^ORGAN_BIG_WAVE_SHIFT = how many (quasi)periods per sample
117 #define ORGAN_BIG_WAVE_SHIFT 5
119 class organ_voice_base
: public calf_plugins::organ_enums
122 typedef waveform_family
<ORGAN_WAVE_BITS
> small_wave_family
;
123 typedef waveform_family
<ORGAN_BIG_WAVE_BITS
> big_wave_family
;
125 organ_parameters
*parameters
;
127 static small_wave_family (*waves
)[wave_count_small
];
128 static big_wave_family (*big_waves
)[wave_count_big
];
130 // dsp::sine_table<float, ORGAN_WAVE_SIZE, 1> sine_wave;
133 /// percussion FM carrier amplitude envelope
135 /// percussion FM modulator amplitude envelope
137 dsp::fixed_point
<int64_t, 20> pphase
, dpphase
;
138 dsp::fixed_point
<int64_t, 20> modphase
, moddphase
;
140 int &sample_rate_ref
;
142 /// pamp per-sample (linear) step during release stage (calculated on release so that it will take 30ms for it to go from "current value at release point" to 0)
145 organ_voice_base(organ_parameters
*_parameters
, int &_sample_rate_ref
, bool &_released_ref
);
147 inline float wave(float *data
, dsp::fixed_point
<int, 20> ph
) {
148 return ph
.lerp_table_lookup_float(data
);
150 inline float big_wave(float *data
, dsp::fixed_point
<int64_t, 20> &ph
) {
151 // wrap to fit within the wave
152 return ph
.lerp_table_lookup_float_mask(data
, ORGAN_BIG_WAVE_SIZE
- 1);
155 static inline small_wave_family
&get_wave(int wave
) {
156 return (*waves
)[wave
];
158 static inline big_wave_family
&get_big_wave(int wave
) {
159 return (*big_waves
)[wave
];
161 static void precalculate_waves(calf_plugins::progress_report_iface
*reporter
);
164 float phase
= dsp::midi_note_to_phase(note
, 100 * parameters
->global_transpose
+ parameters
->global_detune
, sample_rate_ref
);
165 dpphase
.set((long int) (phase
* parameters
->percussion_harmonic
* parameters
->pitch_bend
));
166 moddphase
.set((long int) (phase
* parameters
->percussion_fm_harmonic
* parameters
->pitch_bend
));
168 // this doesn't really have a voice interface
169 void render_percussion_to(float (*buf
)[2], int nsamples
);
170 void perc_note_on(int note
, int vel
);
171 void perc_note_off(int note
, int vel
);
185 enum { VibratoSize
= 6 };
186 float vibrato_x1
[VibratoSize
][2], vibrato_y1
[VibratoSize
][2];
188 dsp::onepole
<float> vibrato
[2];
191 void process(organ_parameters
*parameters
, float (*data
)[2], unsigned int len
, float sample_rate
);
194 class organ_voice
: public dsp::voice
, public organ_voice_base
{
196 enum { Channels
= 2, BlockSize
= 64, EnvCount
= organ_parameters::EnvCount
, FilterCount
= organ_parameters::FilterCount
};
198 float output_buffer
[BlockSize
][Channels
];
199 float aux_buffers
[3][BlockSize
][Channels
];
201 dsp::fixed_point
<int64_t, 52> phase
, dphase
;
202 dsp::biquad_d1
<float> filterL
[2], filterR
[2];
204 dsp::inertia
<dsp::linear_ramp
> expression
;
205 organ_vibrato vibrato
;
208 /// The envelopes have ended and the voice is in final fadeout stage
210 dsp::inertia
<dsp::exponential_ramp
> inertia_pitchbend
;
214 : organ_voice_base(NULL
, sample_rate
, perc_released
)
215 , expression(dsp::linear_ramp(16))
216 , inertia_pitchbend(dsp::exponential_ramp(1))
218 inertia_pitchbend
.set_now(1);
222 inertia_pitchbend
.ramp
.set_length(sample_rate
/ (BlockSize
* 30)); // 1/30s
225 for (int i
= 0; i
< FilterCount
; i
++)
232 void note_on(int note
, int vel
) {
235 perc_released
= false;
239 const float sf
= 0.001f
;
240 for (int i
= 0; i
< EnvCount
; i
++)
242 organ_parameters::organ_env_parameters
&p
= parameters
->envs
[i
];
243 envs
[i
].set(sf
* p
.attack
, sf
* p
.decay
, p
.sustain
, sf
* p
.release
, sample_rate
/ BlockSize
);
247 velocity
= vel
* 1.0 / 127.0;
249 perc_note_on(note
, vel
);
252 void note_off(int /* vel */) {
253 // reset age to 0 (because decay will turn from exponential to linear, necessary because of error cumulation prevention)
254 perc_released
= true;
255 if (pamp
.get_active())
259 rel_age_const
= pamp
.get() * ((1.0/44100.0)/0.03);
260 for (int i
= 0; i
< EnvCount
; i
++)
264 virtual float get_priority() { return stolen
? 20000 : (perc_released
? 1 : (sostenuto
? 200 : 100)); }
266 virtual void steal() {
267 perc_released
= true;
274 virtual int get_current_note() {
277 virtual bool get_active() {
278 // printf("note %d getactive %d use_percussion %d pamp active %d\n", note, amp.get_active(), use_percussion(), pamp.get_active());
279 return (note
!= -1) && (amp
.get_active() || (use_percussion() && pamp
.get_active()));
282 inline bool use_percussion()
284 return dsp::fastf2i_drm(parameters
->percussion_trigger
) == perctrig_polyphonic
&& parameters
->percussion_level
> 0;
288 /// Not a true voice, just something with similar-ish interface.
289 class percussion_voice
: public organ_voice_base
{
294 percussion_voice(organ_parameters
*_parameters
)
295 : organ_voice_base(_parameters
, sample_rate
, released
)
301 return (note
!= -1) && pamp
.get_active();
303 bool get_noticable() {
304 return (note
!= -1) && (pamp
.get() > 0.2 * parameters
->percussion_level
);
311 struct drawbar_organ
: public dsp::basic_synth
, public calf_plugins::organ_enums
{
312 organ_parameters
*parameters
;
313 percussion_voice percussion
;
314 organ_vibrato global_vibrato
;
316 drawbar_organ(organ_parameters
*_parameters
)
317 : parameters(_parameters
)
318 , percussion(_parameters
) {
320 void render_separate(float *output
[], int nsamples
)
323 dsp::zero(&buf
[0][0], 2 * nsamples
);
324 basic_synth::render_to(buf
, nsamples
);
325 if (dsp::fastf2i_drm(parameters
->lfo_mode
) == organ_voice_base::lfomode_global
)
327 for (int i
= 0; i
< nsamples
; i
+= 64)
328 global_vibrato
.process(parameters
, buf
+ i
, std::min(64, nsamples
- i
), sample_rate
);
330 if (percussion
.get_active())
331 percussion
.render_percussion_to(buf
, nsamples
);
332 float gain
= parameters
->master
* (1.0 / 8);
333 for (int i
=0; i
<nsamples
; i
++) {
334 output
[0][i
] = gain
*buf
[i
][0];
335 output
[1][i
] = gain
*buf
[i
][1];
338 dsp::voice
*alloc_voice() {
339 block_voice
<organ_voice
> *v
= new block_voice
<organ_voice
>();
340 v
->parameters
= parameters
;
343 virtual void percussion_note_on(int note
, int vel
) {
344 percussion
.perc_note_on(note
, vel
);
346 virtual void params_changed() = 0;
347 virtual void setup(int sr
) {
348 basic_synth::setup(sr
);
349 percussion
.setup(sr
);
350 parameters
->cutoff
= 0;
352 global_vibrato
.reset();
354 void update_params();
355 void control_change(int controller
, int value
)
358 if (controller
== 11)
360 parameters
->cutoff
= value
/ 64.0 - 1;
363 dsp::basic_synth::control_change(controller
, value
);
365 void pitch_bend(int amt
);
366 virtual bool check_percussion() {
367 switch(dsp::fastf2i_drm(parameters
->percussion_trigger
))
369 case organ_voice_base::perctrig_first
:
370 return active_voices
.empty();
371 case organ_voice_base::perctrig_each
:
374 case organ_voice_base::perctrig_eachplus
:
375 return !percussion
.get_noticable();
376 case organ_voice_base::perctrig_polyphonic
: