+ Organ: add pitch bend inertia
[calf.git] / src / calf / organ.h
blob5c71c16d231dac1ba0158f40ce9bf98cb814fce4
1 /* Calf DSP Library
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
25 #include "synth.h"
26 #include "envelope.h"
27 #include "metadata.h"
29 #define ORGAN_KEYTRACK_POINTS 4
31 namespace dsp
34 struct organ_parameters {
35 enum { FilterCount = 2, EnvCount = 3 };
36 struct organ_filter_parameters
38 float cutoff;
39 float resonance;
40 float envmod[organ_parameters::EnvCount];
41 float keyf;
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!)
52 float drawbars[9];
53 float harmonics[9];
54 float waveforms[9];
55 float detune[9];
56 float phase[9];
57 float pan[9];
58 float routing[9];
59 float foldover;
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;
72 float filter_chain;
73 float master;
75 organ_filter_parameters filters[organ_parameters::FilterCount];
76 organ_env_parameters envs[organ_parameters::EnvCount];
77 float lfo_rate;
78 float lfo_amt;
79 float lfo_wet;
80 float lfo_phase;
81 float lfo_mode;
83 float global_transpose;
84 float global_detune;
86 float polyphony;
88 float quad_env;
90 float pitch_bend_range;
92 float dummy_mapcurve;
94 //////////////////////////////////////////////////////////////////////////
95 // these parameters are calculated
97 double perc_decay_const, perc_fm_decay_const;
98 float multiplier[9];
99 int phaseshift[9];
100 float cutoff;
101 unsigned int foldvalue;
102 float pitch_bend;
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
121 public:
122 typedef waveform_family<ORGAN_WAVE_BITS> small_wave_family;
123 typedef waveform_family<ORGAN_BIG_WAVE_BITS> big_wave_family;
124 public:
125 organ_parameters *parameters;
126 protected:
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;
131 int note;
132 dsp::decay amp;
133 /// percussion FM carrier amplitude envelope
134 dsp::decay pamp;
135 /// percussion FM modulator amplitude envelope
136 dsp::decay fm_amp;
137 dsp::fixed_point<int64_t, 20> pphase, dpphase;
138 dsp::fixed_point<int64_t, 20> modphase, moddphase;
139 float fm_keytrack;
140 int &sample_rate_ref;
141 bool &released_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)
143 float rel_age_const;
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);
154 public:
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);
162 void update_pitch()
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);
172 void perc_reset()
174 pphase = 0;
175 modphase = 0;
176 dpphase = 0;
177 moddphase = 0;
178 note = -1;
182 class organ_vibrato
184 protected:
185 enum { VibratoSize = 6 };
186 float vibrato_x1[VibratoSize][2], vibrato_y1[VibratoSize][2];
187 float lfo_phase;
188 dsp::onepole<float> vibrato[2];
189 public:
190 void reset();
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 {
195 protected:
196 enum { Channels = 2, BlockSize = 64, EnvCount = organ_parameters::EnvCount, FilterCount = organ_parameters::FilterCount };
197 union {
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];
203 adsr envs[EnvCount];
204 dsp::inertia<dsp::linear_ramp> expression;
205 organ_vibrato vibrato;
206 float velocity;
207 bool perc_released;
208 /// The envelopes have ended and the voice is in final fadeout stage
209 bool finishing;
210 dsp::inertia<dsp::exponential_ramp> inertia_pitchbend;
212 public:
213 organ_voice()
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);
221 void reset() {
222 inertia_pitchbend.ramp.set_length(sample_rate / (BlockSize * 30)); // 1/30s
223 vibrato.reset();
224 phase = 0;
225 for (int i = 0; i < FilterCount; i++)
227 filterL[i].reset();
228 filterR[i].reset();
232 void note_on(int note, int vel) {
233 stolen = false;
234 finishing = false;
235 perc_released = false;
236 released = false;
237 reset();
238 this->note = note;
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);
244 envs[i].note_on();
246 update_pitch();
247 velocity = vel * 1.0 / 127.0;
248 amp.set(1.0f);
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())
257 pamp.reinit();
259 rel_age_const = pamp.get() * ((1.0/44100.0)/0.03);
260 for (int i = 0; i < EnvCount; i++)
261 envs[i].note_off();
264 virtual float get_priority() { return stolen ? 20000 : (perc_released ? 1 : (sostenuto ? 200 : 100)); }
266 virtual void steal() {
267 perc_released = true;
268 finishing = true;
269 stolen = true;
272 void render_block();
274 virtual int get_current_note() {
275 return 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()));
281 void update_pitch();
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 {
290 public:
291 int sample_rate;
292 bool released;
294 percussion_voice(organ_parameters *_parameters)
295 : organ_voice_base(_parameters, sample_rate, released)
296 , released(false)
300 bool get_active() {
301 return (note != -1) && pamp.get_active();
303 bool get_noticable() {
304 return (note != -1) && (pamp.get() > 0.2 * parameters->percussion_level);
306 void setup(int sr) {
307 sample_rate = sr;
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)
322 float buf[4096][2];
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;
341 return v;
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;
351 params_changed();
352 global_vibrato.reset();
354 void update_params();
355 void control_change(int controller, int value)
357 #if 0
358 if (controller == 11)
360 parameters->cutoff = value / 64.0 - 1;
362 #endif
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:
372 default:
373 return true;
374 case organ_voice_base::perctrig_eachplus:
375 return !percussion.get_noticable();
376 case organ_voice_base::perctrig_polyphonic:
377 return false;
384 #endif