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
;
92 //////////////////////////////////////////////////////////////////////////
93 // these parameters are calculated
95 double perc_decay_const
, perc_fm_decay_const
;
99 unsigned int foldvalue
;
102 float percussion_keytrack
[ORGAN_KEYTRACK_POINTS
][2];
104 organ_parameters() : pitch_bend(1.0f
) {}
106 inline int get_percussion_wave() { return dsp::fastf2i_drm(percussion_wave
); }
107 inline int get_percussion_fm_wave() { return dsp::fastf2i_drm(percussion_fm_wave
); }
110 #define ORGAN_WAVE_BITS 12
111 #define ORGAN_WAVE_SIZE 4096
112 #define ORGAN_BIG_WAVE_BITS 17
113 #define ORGAN_BIG_WAVE_SIZE 131072
114 /// 2^ORGAN_BIG_WAVE_SHIFT = how many (quasi)periods per sample
115 #define ORGAN_BIG_WAVE_SHIFT 5
117 class organ_voice_base
: public calf_plugins::organ_enums
120 typedef waveform_family
<ORGAN_WAVE_BITS
> small_wave_family
;
121 typedef waveform_family
<ORGAN_BIG_WAVE_BITS
> big_wave_family
;
123 organ_parameters
*parameters
;
125 static small_wave_family (*waves
)[wave_count_small
];
126 static big_wave_family (*big_waves
)[wave_count_big
];
128 // dsp::sine_table<float, ORGAN_WAVE_SIZE, 1> sine_wave;
131 /// percussion FM carrier amplitude envelope
133 /// percussion FM modulator amplitude envelope
135 dsp::fixed_point
<int64_t, 20> pphase
, dpphase
;
136 dsp::fixed_point
<int64_t, 20> modphase
, moddphase
;
138 int &sample_rate_ref
;
140 /// 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)
143 organ_voice_base(organ_parameters
*_parameters
, int &_sample_rate_ref
, bool &_released_ref
);
145 inline float wave(float *data
, dsp::fixed_point
<int, 20> ph
) {
146 return ph
.lerp_table_lookup_float(data
);
148 inline float big_wave(float *data
, dsp::fixed_point
<int64_t, 20> &ph
) {
149 // wrap to fit within the wave
150 return ph
.lerp_table_lookup_float_mask(data
, ORGAN_BIG_WAVE_SIZE
- 1);
153 static inline small_wave_family
&get_wave(int wave
) {
154 return (*waves
)[wave
];
156 static inline big_wave_family
&get_big_wave(int wave
) {
157 return (*big_waves
)[wave
];
159 static void precalculate_waves(calf_plugins::progress_report_iface
*reporter
);
162 float phase
= dsp::midi_note_to_phase(note
, 100 * parameters
->global_transpose
+ parameters
->global_detune
, sample_rate_ref
);
163 dpphase
.set((long int) (phase
* parameters
->percussion_harmonic
* parameters
->pitch_bend
));
164 moddphase
.set((long int) (phase
* parameters
->percussion_fm_harmonic
* parameters
->pitch_bend
));
166 // this doesn't really have a voice interface
167 void render_percussion_to(float (*buf
)[2], int nsamples
);
168 void perc_note_on(int note
, int vel
);
169 void perc_note_off(int note
, int vel
);
183 enum { VibratoSize
= 6 };
184 float vibrato_x1
[VibratoSize
][2], vibrato_y1
[VibratoSize
][2];
186 dsp::onepole
<float> vibrato
[2];
189 void process(organ_parameters
*parameters
, float (*data
)[2], unsigned int len
, float sample_rate
);
192 class organ_voice
: public dsp::voice
, public organ_voice_base
{
194 enum { Channels
= 2, BlockSize
= 64, EnvCount
= organ_parameters::EnvCount
, FilterCount
= organ_parameters::FilterCount
};
196 float output_buffer
[BlockSize
][Channels
];
197 float aux_buffers
[3][BlockSize
][Channels
];
199 dsp::fixed_point
<int64_t, 52> phase
, dphase
;
200 dsp::biquad_d1
<float> filterL
[2], filterR
[2];
202 dsp::inertia
<dsp::linear_ramp
> expression
;
203 organ_vibrato vibrato
;
206 /// The envelopes have ended and the voice is in final fadeout stage
211 : organ_voice_base(NULL
, sample_rate
, perc_released
),
212 expression(dsp::linear_ramp(16)) {
218 for (int i
= 0; i
< FilterCount
; i
++)
225 void note_on(int note
, int vel
) {
228 perc_released
= false;
232 const float sf
= 0.001f
;
233 for (int i
= 0; i
< EnvCount
; i
++)
235 organ_parameters::organ_env_parameters
&p
= parameters
->envs
[i
];
236 envs
[i
].set(sf
* p
.attack
, sf
* p
.decay
, p
.sustain
, sf
* p
.release
, sample_rate
/ BlockSize
);
240 velocity
= vel
* 1.0 / 127.0;
242 perc_note_on(note
, vel
);
245 void note_off(int /* vel */) {
246 // reset age to 0 (because decay will turn from exponential to linear, necessary because of error cumulation prevention)
247 perc_released
= true;
248 if (pamp
.get_active())
252 rel_age_const
= pamp
.get() * ((1.0/44100.0)/0.03);
253 for (int i
= 0; i
< EnvCount
; i
++)
257 virtual float get_priority() { return stolen
? 20000 : (perc_released
? 1 : (sostenuto
? 200 : 100)); }
259 virtual void steal() {
260 perc_released
= true;
267 virtual int get_current_note() {
270 virtual bool get_active() {
271 // printf("note %d getactive %d use_percussion %d pamp active %d\n", note, amp.get_active(), use_percussion(), pamp.get_active());
272 return (note
!= -1) && (amp
.get_active() || (use_percussion() && pamp
.get_active()));
275 inline bool use_percussion()
277 return dsp::fastf2i_drm(parameters
->percussion_trigger
) == perctrig_polyphonic
&& parameters
->percussion_level
> 0;
281 /// Not a true voice, just something with similar-ish interface.
282 class percussion_voice
: public organ_voice_base
{
287 percussion_voice(organ_parameters
*_parameters
)
288 : organ_voice_base(_parameters
, sample_rate
, released
)
294 return (note
!= -1) && pamp
.get_active();
296 bool get_noticable() {
297 return (note
!= -1) && (pamp
.get() > 0.2 * parameters
->percussion_level
);
304 struct drawbar_organ
: public dsp::basic_synth
, public calf_plugins::organ_enums
{
305 organ_parameters
*parameters
;
306 percussion_voice percussion
;
307 organ_vibrato global_vibrato
;
309 drawbar_organ(organ_parameters
*_parameters
)
310 : parameters(_parameters
)
311 , percussion(_parameters
) {
313 void render_separate(float *output
[], int nsamples
)
316 dsp::zero(&buf
[0][0], 2 * nsamples
);
317 basic_synth::render_to(buf
, nsamples
);
318 if (dsp::fastf2i_drm(parameters
->lfo_mode
) == organ_voice_base::lfomode_global
)
320 for (int i
= 0; i
< nsamples
; i
+= 64)
321 global_vibrato
.process(parameters
, buf
+ i
, std::min(64, nsamples
- i
), sample_rate
);
323 if (percussion
.get_active())
324 percussion
.render_percussion_to(buf
, nsamples
);
325 float gain
= parameters
->master
* (1.0 / 8);
326 for (int i
=0; i
<nsamples
; i
++) {
327 output
[0][i
] = gain
*buf
[i
][0];
328 output
[1][i
] = gain
*buf
[i
][1];
331 dsp::voice
*alloc_voice() {
332 block_voice
<organ_voice
> *v
= new block_voice
<organ_voice
>();
333 v
->parameters
= parameters
;
336 virtual void percussion_note_on(int note
, int vel
) {
337 percussion
.perc_note_on(note
, vel
);
339 virtual void params_changed() = 0;
340 virtual void setup(int sr
) {
341 basic_synth::setup(sr
);
342 percussion
.setup(sr
);
343 parameters
->cutoff
= 0;
345 global_vibrato
.reset();
347 void update_params();
348 void control_change(int controller
, int value
)
351 if (controller
== 11)
353 parameters
->cutoff
= value
/ 64.0 - 1;
356 dsp::basic_synth::control_change(controller
, value
);
358 void pitch_bend(int amt
);
359 virtual bool check_percussion() {
360 switch(dsp::fastf2i_drm(parameters
->percussion_trigger
))
362 case organ_voice_base::perctrig_first
:
363 return active_voices
.empty();
364 case organ_voice_base::perctrig_each
:
367 case organ_voice_base::perctrig_eachplus
:
368 return !percussion
.get_noticable();
369 case organ_voice_base::perctrig_polyphonic
: