1 #include "mdaPianoVoice.h"
3 mdaPianoVoice::mdaPianoVoice(double rate
, Sample
* master_samples
, KGRP
* master_kgrp
) {
8 samples
= master_samples
;
11 // TODO: load default values from ttl file
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
;
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
;
45 float mdaPianoVoice::p_helper(unsigned short id
, Param d
) {
47 return default_preset
[p_offset(id
)];
53 void mdaPianoVoice::on(unsigned char key
, unsigned char velocity
) {
54 // store key that turned this voice on (used in 'get_key')
63 k
= (key
- 60) * (key
- 60);
64 l
= fine
+ random
* ((float)(k
% 13) - 6.5f
); //random & fine tune
66 if(key
> 60) l
+= stretch
* (float)k
; //stretch
71 if(velocity
> 40) s
+= (long)(sizevel
* (float)(velocity
- 40));
75 while(key
> (kgrp
[k
].high
+ s
)) k
+= SAMPLES_PER_NOTE
; // find keygroup
76 sample_index
= k
; // store sample index
78 l
+= (float)(key
- kgrp
[k
].root
); // pitch
80 l
= 22050.0f
* iFs
* (float)exp(0.05776226505 * l
);
82 l
= 32000.0f
* iFs
* (float)exp(0.05776226505 * l
);
84 delta
= (long)(65536.0f
* l
);
89 if(velocity
> 48) sample_index
++; // mid velocity sample
90 if(velocity
> 80) sample_index
++; // high velocity sample
94 end
= samples
[sample_index
].size
;
96 end
= samples
[sample_index
].size
- 1;
98 loop
= kgrp
[sample_index
].loop
;
102 env
= (0.5f
+ velsens
) * (float)pow(0.0078f
* velocity
, velsens
); //velocity
104 l
= 50.0f
+ *p(p_muffling_filter
) * *p(p_muffling_filter
) * muff
+ muffvel
* (float)(velocity
- 64); //muffle
105 if(l
< (55.0f
+ 0.25f
* (float)key
)) l
= 55.0f
+ 0.25f
* (float)key
;
106 if(l
> 210.0f
) l
= 210.0f
;
110 env
= (3.0f
+ 2.0f
* velsens
) * (float)pow(0.0078f
* velocity
, velsens
); // velocity
111 // high notes quieter
113 env
*= (float)exp(0.01f
* (float)(60 - key
));
118 if(key
< 12) key
= 12;
119 if(key
> 108) key
= 108;
123 outr
= l
+ l
* width
* (float)(key
- 60);
126 if(key
< 44) key
= 44; //limit max decay length
127 l
= 2.0f
* *p(p_envelope_decay
);
128 if(l
< 1.0f
) l
+= 0.25f
- 0.5f
* *p(p_envelope_decay
);
129 dec
= (float)exp(-iFs
* exp(-0.6 + 0.033 * (double)key
- l
));
131 outr
= volume
+ volume
* width
* (float)(key
- 60);
132 outl
= volume
+ volume
- outr
;
134 if(key
< 44) key
= 44; // limit max decay length
135 dec
= (float)exp(-iFs
* exp(-1.0 + 0.03 * (double)key
- 2.0f
* *p(p_envelope_decay
)));
138 // some keyboards send note off events as 'note on' with velocity 0
144 void mdaPianoVoice::reset() {
152 memset(comb
, 0, sizeof(float) * 256);
154 tl
= tr
= lfo0
= dlfo
= 0.0f
;
157 m_key
= lvtk::INVALID_KEY
;
161 void mdaPianoVoice::release(unsigned char velocity
) {
164 //no release on highest notes
165 if(m_key
< 94 || m_key
== SUSTAIN
) {
166 dec
= (float)exp(-iFs
* exp(2.0 + 0.017 * (double)m_key
- 2.0 * *p(p_envelope_release
)));
169 dec
= (float)exp(-iFs
* exp(6.0 + 0.01 * (double)m_key
- 5.0 * *p(p_envelope_release
)));
175 //Mark the voice to be turned off later. It may not be set to
176 //INVALID_KEY yet, because the release sound still needs to be
177 //rendered. m_key is finally set to INVALID_KEY by 'render' when
183 void mdaPianoVoice::render(uint32_t from
, uint32_t to
) {
184 // abort if no key is pressed
185 // initially m_key is INVALID_KEY, so no sound will be rendered
186 if (m_key
== lvtk::INVALID_KEY
)
193 for (uint32_t frame
= from
; frame
< to
; ++frame
) {
194 // initialize left and right output
197 frac
+= delta
; // integer-based linear interpolation
199 frac
&= 0xFFFF; // why AND it with all ones?
200 if(pos
> end
) pos
-= loop
; // jump back to loop sample
203 i
= samples
[sample_index
].buffer
[pos
];
204 i
= (i
<< 7) + (frac
>> 9) * (samples
[sample_index
].buffer
[pos
+ 1] - i
) + 0x40400000;
205 x
= env
* (*(float *)&i
- 3.0f
); //fast int->float
207 env
= env
* dec
; //envelope
208 f0
+= ff
* (x
+ f1
- f0
); //muffle filter
216 x
= cdep
* comb
[cpos
]; //stereo simulator
219 p(p_left
)[frame
] += l
+ x
;
220 p(p_right
)[frame
] += r
- x
;
222 // alternative method (probably faster), said to not work on intel mac
223 //i = samples[sample_index].buffer[pos];
224 //i = (i << 7) + (frac >> 9) * (samples[sample_index].buffer[pos + 1] - i) + 0x40400000;
226 i
= samples
[sample_index
].buffer
[pos
] + ((frac
* (samples
[sample_index
].buffer
[pos
+ 1] - samples
[sample_index
].buffer
[pos
])) >> 16);
227 x
= env
* (float)i
/ 32768.0f
;
228 env
= env
* dec
; // envelope
232 x
-= overdrive
* x
* x
;
241 tl
+= tfrq
* (l
- tl
);
242 tr
+= tfrq
* (r
- tr
);
243 r
+= treb
* (r
- tr
);
244 l
+= treb
* (l
- tl
);
246 lfo0
+= dlfo
* lfo1
; // LFO for tremolo and autopan
248 l
+= l
* lmod
* lfo1
;
249 r
+= r
* rmod
* lfo1
; // TODO: worth making all these local variables?
252 p(p_left
)[frame
] += l
;
253 p(p_right
)[frame
] += r
;
257 // turn off further processing when the envelope has rendered the voice silent
259 m_key
= lvtk::INVALID_KEY
;
263 if(fabs(tl
)<1.0e-10) tl
= 0.0f
; // anti-denormal
264 if(fabs(tr
)<1.0e-10) tr
= 0.0f
;
269 void mdaPianoVoice::update(Param par
) {
271 size
= (long)(12.0f
* p_helper(p_hardness_offset
, par
) - 6.0f
);
272 sizevel
= 0.12f
* p_helper(p_velocity_to_hardness
, par
);
273 muffvel
= p_helper(p_velocity_to_muffling
, par
) * p_helper(p_velocity_to_muffling
, par
) * 5.0f
;
275 velsens
= 1.0f
+ p_helper(p_velocity_sensitivity
, par
) + p_helper(p_velocity_sensitivity
, par
);
276 if(p_helper(p_velocity_sensitivity
, par
) < 0.25f
) {
277 velsens
-= 0.75f
- 3.0f
* p_helper(p_velocity_sensitivity
, par
);
280 fine
= p_helper(p_fine_tuning
, par
) - 0.5f
;
281 random
= 0.077f
* p_helper(p_random_detuning
, par
) * p_helper(p_random_detuning
, par
);
282 stretch
= 0.000434f
* (p_helper(p_stretch_tuning
, par
) - 0.5f
);
284 cdep
= p_helper(p_stereo_width
, par
) * p_helper(p_stereo_width
, par
);
285 trim
= 1.50f
- 0.79f
* cdep
;
286 width
= 0.04f
* p_helper(p_stereo_width
, par
); if(width
> 0.03f
) width
= 0.03f
;
288 size
= (long)(12.0f
* p_helper(p_hardness
, par
) - 6.0f
);
289 treb
= 4.0f
* p_helper(p_treble_boost
, par
) * p_helper(p_treble_boost
, par
) - 1.0f
; // treble gain
292 if(p_helper(p_treble_boost
, par
) > 0.5f
) {
297 tfrq
= 1.0f
- (float)exp(-iFs
* tfrq
);
299 rmod
= lmod
= p_helper(p_modulation
, par
) + p_helper(p_modulation
, par
) - 1.0f
; // lfo depth
300 if(p_helper(p_modulation
, par
) < 0.5f
) rmod
= -rmod
;
301 dlfo
= 6.283f
* iFs
* (float)exp(6.22f
* p_helper(p_lfo_rate
, par
) - 2.61f
); // lfo rate
303 velsens
= 1.0f
+ p_helper(p_velocity_sensitivity
, par
) + p_helper(p_velocity_sensitivity
, par
);
304 if(p_helper(p_velocity_sensitivity
, par
) < 0.25f
) {
305 velsens
-= 0.75f
- 3.0f
* p_helper(p_velocity_sensitivity
, par
);
308 width
= 0.03f
* p_helper(p_stereo_width
, par
);
309 fine
= p_helper(p_fine_tuning
, par
) - 0.5f
;
310 random
= 0.077f
* p_helper(p_random_tuning
, par
) * p_helper(p_random_tuning
, par
);
311 overdrive
= 1.8f
* p_helper(p_overdrive
, par
);