]> git.elephly.net Git - software/lv2-mdametapiano.git/blob - src/mdaPianoVoice.cpp
crudely merge mdaEPiano and mdaPiano
[software/lv2-mdametapiano.git] / src / mdaPianoVoice.cpp
1 #include "mdaPianoVoice.h"
2
3 mdaPianoVoice::mdaPianoVoice(double rate, Sample * master_samples, KGRP * master_kgrp) {
4 //set tuning
5 Fs = rate;
6 iFs = 1.0f/Fs;
7
8 samples = master_samples;
9 kgrp = master_kgrp;
10
11 // TODO: load default values from ttl file
12 #ifdef PIANO
13 default_preset[p_offset(p_envelope_decay)] = 0.500f;
14 default_preset[p_offset(p_envelope_release)] = 0.500f;
15 default_preset[p_offset(p_hardness_offset)] = 0.500f;
16 default_preset[p_offset(p_velocity_to_hardness)] = 0.500f;
17 default_preset[p_offset(p_muffling_filter)] = 0.803f;
18 default_preset[p_offset(p_velocity_to_muffling)] = 0.251f;
19 default_preset[p_offset(p_velocity_sensitivity)] = 0.376f;
20 default_preset[p_offset(p_stereo_width)] = 0.500f;
21 default_preset[p_offset(p_polyphony)] = 0.330f; // unused
22 default_preset[p_offset(p_fine_tuning)] = 0.500f;
23 default_preset[p_offset(p_random_detuning)] = 0.246f;
24 default_preset[p_offset(p_stretch_tuning)] = 0.500f;
25 #elif defined EPIANO
26 default_preset[p_offset(p_envelope_decay)] = 0.500f;
27 default_preset[p_offset(p_envelope_release)] = 0.500f;
28 default_preset[p_offset(p_hardness)] = 0.500f;
29 default_preset[p_offset(p_treble_boost)] = 0.500f;
30 default_preset[p_offset(p_modulation)] = 0.500f;
31 default_preset[p_offset(p_lfo_rate)] = 0.650f;
32 default_preset[p_offset(p_velocity_sensitivity)] = 0.250f;
33 default_preset[p_offset(p_stereo_width)] = 0.500f;
34 default_preset[p_offset(p_polyphony)] = 0.500f; // unused
35 default_preset[p_offset(p_fine_tuning)] = 0.500f;
36 default_preset[p_offset(p_random_tuning)] = 0.146f;
37 default_preset[p_offset(p_overdrive)] = 0.000f;
38 #endif
39
40 reset();
41 update(Default);
42 }
43
44
45 float mdaPianoVoice::p_helper(unsigned short id, Param d) {
46 if (d == Default)
47 return default_preset[p_offset(id)];
48 else
49 return *p(id);
50 }
51
52
53 void mdaPianoVoice::on(unsigned char key, unsigned char velocity) {
54 // store key that turned this voice on (used in 'get_key')
55 m_key = key;
56 update(Current);
57
58 float l=99.0f;
59 #ifdef PIANO
60 uint32_t k, s;
61 #elif defined EPIANO
62 long k, s;
63 #endif
64
65 if(velocity > 0)
66 {
67 k = (key - 60) * (key - 60);
68 l = fine + random * ((float)(k % 13) - 6.5f); //random & fine tune
69 #ifdef PIANO
70 if(key > 60) l += stretch * (float)k; //stretch
71 #endif
72
73 s = size;
74 #ifdef PIANO
75 if(velocity > 40) s += (uint32_t)(sizevel * (float)(velocity - 40));
76 #endif
77
78 k = 0;
79 while(key > (kgrp[k].high + s)) k += SAMPLES_PER_NOTE; // find keygroup
80 #ifdef EPIANO
81 if(velocity > 48) k++; // mid velocity sample
82 if(velocity > 80) k++; // high velocity sample
83 #endif
84 sample_index = k; // store sample index
85
86 l += (float)(key - kgrp[k].root); // pitch
87 #ifdef PIANO
88 l = 22050.0f * iFs * (float)exp(0.05776226505 * l);
89 delta = (uint32_t)(65536.0f * l);
90 #elif defined EPIANO
91 l = 32000.0f * iFs * (float)exp(0.05776226505 * l);
92 delta = (long)(65536.0f * l);
93 #endif
94 frac = 0;
95 pos = 0;
96
97 #ifdef PIANO
98 end = samples[sample_index].size;
99 #elif defined EPIANO
100 end = samples[sample_index].size - 1;
101 #endif
102 loop = kgrp[sample_index].loop;
103
104
105 #ifdef PIANO
106 env = (0.5f + velsens) * (float)pow(0.0078f * velocity, velsens); //velocity
107
108 l = 50.0f + *p(p_muffling_filter) * *p(p_muffling_filter) * muff + muffvel * (float)(velocity - 64); //muffle
109 if(l < (55.0f + 0.25f * (float)key)) l = 55.0f + 0.25f * (float)key;
110 if(l > 210.0f) l = 210.0f;
111 ff = l * l * iFs;
112 f0 = f1 = 0.0f;
113 #elif defined EPIANO
114 env = (3.0f + 2.0f * velsens) * (float)pow(0.0078f * velocity, velsens); // velocity
115 // high notes quieter
116 if(key > 60) {
117 env *= (float)exp(0.01f * (float)(60 - key));
118 }
119 #endif
120
121 // note->pan
122 if(key < 12) key = 12;
123 if(key > 108) key = 108;
124
125 #ifdef PIANO
126 l = volume * trim;
127 outr = l + l * width * (float)(key - 60);
128 outl = l + l - outr;
129
130 if(key < 44) key = 44; //limit max decay length
131 l = 2.0f * *p(p_envelope_decay);
132 if(l < 1.0f) l += 0.25f - 0.5f * *p(p_envelope_decay);
133 dec = (float)exp(-iFs * exp(-0.6 + 0.033 * (double)key - l));
134 #elif defined EPIANO
135 outr = volume + volume * width * (float)(key - 60);
136 outl = volume + volume - outr;
137
138 if(key < 44) key = 44; // limit max decay length
139 dec = (float)exp(-iFs * exp(-1.0 + 0.03 * (double)key - 2.0f * *p(p_envelope_decay)));
140 #endif
141 } else {
142 // some keyboards send note off events as 'note on' with velocity 0
143 release(0);
144 }
145 }
146
147
148 void mdaPianoVoice::reset() {
149 env = 0.0f;
150 dec = 0.99f;
151 sustain = 0;
152 volume = 0.2f;
153 #ifdef PIANO
154 muff = 160.0f;
155 cpos = 0;
156 #elif defined EPIANO
157 tl = tr = lfo0 = dlfo = 0.0f;
158 lfo1 = 1.0f;
159 #endif
160 m_key = lvtk::INVALID_KEY;
161 }
162
163
164 void mdaPianoVoice::release(unsigned char velocity) {
165 if(sustain==0) {
166 #ifdef PIANO
167 //no release on highest notes
168 if(m_key < 94 || m_key == SUSTAIN) {
169 dec = (float)exp(-iFs * exp(2.0 + 0.017 * (double)m_key - 2.0 * *p(p_envelope_release)));
170 }
171 #elif defined EPIANO
172 dec = (float)exp(-iFs * exp(6.0 + 0.01 * (double)m_key - 5.0 * *p(p_envelope_release)));
173 #endif
174 } else {
175 m_key = SUSTAIN;
176 }
177
178 //Mark the voice to be turned off later. It may not be set to
179 //INVALID_KEY yet, because the release sound still needs to be
180 //rendered. m_key is finally set to INVALID_KEY by 'render' when
181 //env < SILENCE
182 m_key = SUSTAIN;
183 }
184
185
186 void mdaPianoVoice::render(uint32_t from, uint32_t to) {
187 // abort if no key is pressed
188 // initially m_key is INVALID_KEY, so no sound will be rendered
189 if (m_key == lvtk::INVALID_KEY)
190 return;
191
192 float x, l, r;
193 #ifdef PIANO
194 uint32_t i;
195 #elif defined EPIANO
196 long i;
197 #endif
198
199 update(Current);
200 for (uint32_t frame = from; frame < to; ++frame) {
201 // initialize left and right output
202 l = r = 0.0f;
203
204 frac += delta; // integer-based linear interpolation
205 pos += frac >> 16;
206 frac &= 0xFFFF; // why AND it with all ones?
207 if(pos > end) pos -= loop; // jump back to loop sample
208
209 #ifdef PIANO
210 i = samples[sample_index].buffer[pos];
211 i = (i << 7) + (frac >> 9) * (samples[sample_index].buffer[pos + 1] - i) + 0x40400000;
212 x = env * (*(float *)&i - 3.0f); //fast int->float
213
214 env = env * dec; //envelope
215 f0 += ff * (x + f1 - f0); //muffle filter
216 f1 = x;
217
218 l += outl * f0;
219 r += outr * f0;
220
221 comb[cpos] = l + r;
222 ++cpos &= 0x7F;
223 x = cdep * comb[cpos]; //stereo simulator
224
225 // write to output
226 p(p_left)[frame] += l + x;
227 p(p_right)[frame] += r - x;
228 #elif defined EPIANO
229 // alternative method (probably faster), said to not work on intel mac
230 //i = samples[sample_index].buffer[pos];
231 //i = (i << 7) + (frac >> 9) * (samples[sample_index].buffer[pos + 1] - i) + 0x40400000;
232
233 i = samples[sample_index].buffer[pos] + ((frac * (samples[sample_index].buffer[pos + 1] - samples[sample_index].buffer[pos])) >> 16);
234 x = env * (float)i / 32768.0f;
235 env = env * dec; // envelope
236
237 // overdrive
238 if(x>0.0f) {
239 x -= overdrive * x * x;
240 if(x < -env)
241 x = -env;
242 }
243
244 l += outl * x;
245 r += outr * x;
246
247 // treble boost
248 tl += tfrq * (l - tl);
249 tr += tfrq * (r - tr);
250 r += treb * (r - tr);
251 l += treb * (l - tl);
252
253 lfo0 += dlfo * lfo1; // LFO for tremolo and autopan
254 lfo1 -= dlfo * lfo0;
255 l += l * lmod * lfo1;
256 r += r * rmod * lfo1; // TODO: worth making all these local variables?
257
258 // write to output
259 p(p_left)[frame] += l;
260 p(p_right)[frame] += r;
261 #endif
262 }
263
264 // turn off further processing when the envelope has rendered the voice silent
265 if (env < SILENCE) {
266 m_key = lvtk::INVALID_KEY;
267 }
268
269 #ifdef EPIANO
270 if(fabs(tl)<1.0e-10) tl = 0.0f; // anti-denormal
271 if(fabs(tr)<1.0e-10) tr = 0.0f;
272 #endif
273 }
274
275
276 void mdaPianoVoice::update(Param par) {
277 #ifdef PIANO
278 size = (uint32_t)(12.0f * p_helper(p_hardness_offset, par) - 6.0f);
279 sizevel = 0.12f * p_helper(p_velocity_to_hardness, par);
280 muffvel = p_helper(p_velocity_to_muffling, par) * p_helper(p_velocity_to_muffling, par) * 5.0f;
281
282 velsens = 1.0f + p_helper(p_velocity_sensitivity, par) + p_helper(p_velocity_sensitivity, par);
283 if(p_helper(p_velocity_sensitivity, par) < 0.25f) {
284 velsens -= 0.75f - 3.0f * p_helper(p_velocity_sensitivity, par);
285 }
286
287 fine = p_helper(p_fine_tuning, par) - 0.5f;
288 random = 0.077f * p_helper(p_random_detuning, par) * p_helper(p_random_detuning, par);
289 stretch = 0.000434f * (p_helper(p_stretch_tuning, par) - 0.5f);
290
291 cdep = p_helper(p_stereo_width, par) * p_helper(p_stereo_width, par);
292 trim = 1.50f - 0.79f * cdep;
293 width = 0.04f * p_helper(p_stereo_width, par); if(width > 0.03f) width = 0.03f;
294 #elif defined EPIANO
295 size = (long)(12.0f * p_helper(p_hardness, par) - 6.0f);
296 treb = 4.0f * p_helper(p_treble_boost, par) * p_helper(p_treble_boost, par) - 1.0f; // treble gain
297
298 // treble frequency
299 if(p_helper(p_treble_boost, par) > 0.5f) {
300 tfrq = 14000.0f;
301 } else {
302 tfrq = 5000.0f;
303 }
304 tfrq = 1.0f - (float)exp(-iFs * tfrq);
305
306 rmod = lmod = p_helper(p_modulation, par) + p_helper(p_modulation, par) - 1.0f; // lfo depth
307 if(p_helper(p_modulation, par) < 0.5f) rmod = -rmod;
308 dlfo = 6.283f * iFs * (float)exp(6.22f * p_helper(p_lfo_rate, par) - 2.61f); // lfo rate
309
310 velsens = 1.0f + p_helper(p_velocity_sensitivity, par) + p_helper(p_velocity_sensitivity, par);
311 if(p_helper(p_velocity_sensitivity, par) < 0.25f) {
312 velsens -= 0.75f - 3.0f * p_helper(p_velocity_sensitivity, par);
313 }
314
315 width = 0.03f * p_helper(p_stereo_width, par);
316 fine = p_helper(p_fine_tuning, par) - 0.5f;
317 random = 0.077f * p_helper(p_random_tuning, par) * p_helper(p_random_tuning, par);
318 overdrive = 1.8f * p_helper(p_overdrive, par);
319 #endif
320 }