1 #include "mdaPianoVoice.h"
3 mdaPianoVoice::mdaPianoVoice(double rate
, short * samples
, KGRP
* master_kgrp
) {
11 default_preset
[p_offset(p_envelope_decay
)] = 0.500f
;
12 default_preset
[p_offset(p_envelope_release
)] = 0.500f
;
13 default_preset
[p_offset(p_hardness_offset
)] = 0.500f
;
14 default_preset
[p_offset(p_velocity_to_hardness
)] = 0.500f
;
15 default_preset
[p_offset(p_muffling_filter
)] = 0.803f
;
16 default_preset
[p_offset(p_velocity_to_muffling
)] = 0.251f
;
17 default_preset
[p_offset(p_velocity_sensitivity
)] = 0.376f
;
18 default_preset
[p_offset(p_stereo_width
)] = 0.500f
;
19 default_preset
[p_offset(p_polyphony
)] = 0.330f
;
20 default_preset
[p_offset(p_fine_tuning
)] = 0.500f
;
21 default_preset
[p_offset(p_random_detuning
)] = 0.246f
;
22 default_preset
[p_offset(p_stretch_tuning
)] = 0.500f
;
24 comb
= new float[256];
29 void mdaPianoVoice::reset() {
36 m_key
= LV2::INVALID_KEY
;
40 float mdaPianoVoice::p_helper(unsigned short id
, Param d
) {
42 return default_preset
[p_offset(id
)];
48 void mdaPianoVoice::on(unsigned char note
, unsigned char velocity
)
50 // store key that turned this voice on (used in 'get_key')
53 // TODO: replace with this voice's local copy
54 float * param
= programs
[curProgram
].param
;
56 uint32_t v
, vl
=0, k
, s
;
60 // TODO: move this to mdaPiano.cpp
62 if(activevoices < poly) //add a note
69 for(v=0; v<poly; v++) //find quietest voice
71 if(voice[v].env < l) { l = voice[v].env; vl = v; }
76 k
= (note
- 60) * (note
- 60);
77 l
= fine
+ random
* ((float)(k
% 13) - 6.5f
); //random & fine tune
78 if(note
> 60) l
+= stretch
* (float)k
; //stretch
81 if(velocity
> 40) s
+= (uint32_t)(sizevel
* (float)(velocity
- 40));
84 while(note
> (kgrp
[k
].high
+ s
)) k
++; //find keygroup
86 l
+= (float)(note
- kgrp
[k
].root
); //pitch
87 l
= 22050.0f
* iFs
* (float)exp(0.05776226505 * l
);
88 voice
[vl
].delta
= (uint32_t)(65536.0f
* l
);
90 voice
[vl
].pos
= kgrp
[k
].pos
;
91 voice
[vl
].end
= kgrp
[k
].end
;
92 voice
[vl
].loop
= kgrp
[k
].loop
;
94 voice
[vl
].env
= (0.5f
+ velsens
) * (float)pow(0.0078f
* velocity
, velsens
); //velocity
96 l
= 50.0f
+ param
[4] * param
[4] * muff
+ muffvel
* (float)(velocity
- 64); //muffle
97 if(l
< (55.0f
+ 0.25f
* (float)note
)) l
= 55.0f
+ 0.25f
* (float)note
;
98 if(l
> 210.0f
) l
= 210.0f
;
99 voice
[vl
].ff
= l
* l
* iFs
;
100 voice
[vl
].f0
= voice
[vl
].f1
= 0.0f
;
102 voice
[vl
].note
= note
; //note->pan
103 if(note
< 12) note
= 12;
104 if(note
> 108) note
= 108;
106 voice
[vl
].outr
= l
+ l
* width
* (float)(note
- 60);
107 voice
[vl
].outl
= l
+ l
- voice
[vl
].outr
;
109 if(note
< 44) note
= 44; //limit max decay length
111 if(l
< 1.0f
) l
+= 0.25f
- 0.5f
* param
[0];
112 voice
[vl
].dec
= (float)exp(-iFs
* exp(-0.6 + 0.033 * (double)note
- l
));
116 // TODO: move the loop to mdaPiano.cpp
117 for(v
=0; v
<NVOICES
; v
++) if(voice
[v
].note
==note
) //any voices playing that note?
121 if(note
< 94 || note
== SUSTAIN
) //no release on highest notes
122 voice
[v
].dec
= (float)exp(-iFs
* exp(2.0 + 0.017 * (double)note
- 2.0 * param
[1]));
124 else voice
[v
].note
= SUSTAIN
;
130 void mdaPianoVoice::process(float **inputs
, float **outputs
, uint32_t sampleFrames
)
132 float* out0
= outputs
[0];
133 float* out1
= outputs
[1];
134 uint32_t event
=0, frame
=0, frames
, v
;
138 while(frame
<sampleFrames
)
140 frames
= notes
[event
++];
141 if(frames
>sampleFrames
) frames
= sampleFrames
;
150 for(v
=0; v
<activevoices
; v
++)
152 V
->frac
+= V
->delta
; //integer-based linear interpolation
153 V
->pos
+= V
->frac
>> 16;
155 if(V
->pos
> V
->end
) V
->pos
-= V
->loop
;
158 i
= (i
<< 7) + (V
->frac
>> 9) * (waves
[V
->pos
+ 1] - i
) + 0x40400000;
159 x
= V
->env
* (*(float *)&i
- 3.0f
); //fast int->float
161 /////////////////////
162 //TODO: This was used in processReplacing instead of the above
164 //i = (i << 7) + (V->frac >> 9) * (waves[V->pos + 1] - i) + 0x40400000; //not working on intel mac !?!
165 i = waves[V->pos] + ((V->frac * (waves[V->pos + 1] - waves[V->pos])) >> 16);
166 x = V->env * (float)i / 32768.0f;
167 //x = V->env * (*(float *)&i - 3.0f); //fast int->float
169 /////////////////////
171 V
->env
= V
->env
* V
->dec
; //envelope
172 V
->f0
+= V
->ff
* (x
+ V
->f1
- V
->f0
); //muffle filter
175 l
+= V
->outl
* V
->f0
;
176 r
+= V
->outr
* V
->f0
;
178 //TODO: this was used in processReplacing
179 /////////////////////
181 if(!(l > -2.0f) || !(l < 2.0f))
183 printf("what is this shit? %d, %f, %f\n", i, x, V->f0);
186 if(!(r > -2.0f) || !(r < 2.0f))
191 /////////////////////
197 x
= cdep
* comb
[cpos
]; //stereo simulator
199 // TODO: processReplacing simply assigned instead of adding
204 if(frame
<sampleFrames
)
206 uint32_t note
= notes
[event
++];
207 uint32_t vel
= notes
[event
++];
211 for(v
=0; v
<activevoices
; v
++) if(voice
[v
].env
< SILENCE
) voice
[v
] = voice
[--activevoices
];
212 notes
[0] = EVENTS_DONE
; //mark events buffer as done
216 void mdaPianoVoice::update(Param par
)
218 //TODO: use local copy
219 float * param
= programs
[curProgram
].param
;
220 size
= (uint32_t)(12.0f
* param
[2] - 6.0f
);
221 sizevel
= 0.12f
* param
[3];
222 muffvel
= param
[5] * param
[5] * 5.0f
;
224 velsens
= 1.0f
+ param
[6] + param
[6];
225 if(param
[6] < 0.25f
) velsens
-= 0.75f
- 3.0f
* param
[6];
227 fine
= param
[9] - 0.5f
;
228 random
= 0.077f
* param
[10] * param
[10];
229 stretch
= 0.000434f
* (param
[11] - 0.5f
);
231 cdep
= param
[7] * param
[7];
232 trim
= 1.50f
- 0.79f
* cdep
;
233 width
= 0.04f
* param
[7]; if(width
> 0.03f
) width
= 0.03f
;
235 poly
= 8 + (uint32_t)(24.9f
* param
[8]);