move voice parameters to mdaPianoVoice
[software/lv2-mdametapiano.git] / src / mdaPianoVoice.cpp
1 #include "mdaPianoVoice.h"
2
3 mdaPianoVoice::mdaPianoVoice(double rate, short * samples, KGRP * master_kgrp) {
4 //set tuning
5 Fs = rate;
6 iFs = 1.0f/Fs;
7
8 waves = samples;
9 kgrp = master_kgrp;
10
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;
23
24 comb = new float[256];
25 reset();
26 }
27
28
29 void mdaPianoVoice::reset() {
30 env = 0.0f;
31 dec = 0.99f;
32 muff = 160.0f;
33 volume = 0.2f;
34 sustain = 0;
35 cpos = 0;
36 m_key = LV2::INVALID_KEY;
37 }
38
39
40 float mdaPianoVoice::p_helper(unsigned short id, Param d) {
41 if (d == Default)
42 return default_preset[p_offset(id)];
43 else
44 return *p(id);
45 }
46
47
48 void mdaPianoVoice::on(unsigned char note, unsigned char velocity)
49 {
50 // store key that turned this voice on (used in 'get_key')
51 m_key = key;
52
53 // TODO: replace with this voice's local copy
54 float * param = programs[curProgram].param;
55 float l=99.0f;
56 uint32_t v, vl=0, k, s;
57
58 if(velocity>0)
59 {
60 // TODO: move this to mdaPiano.cpp
61 /*
62 if(activevoices < poly) //add a note
63 {
64 vl = activevoices;
65 activevoices++;
66 }
67 else //steal a note
68 {
69 for(v=0; v<poly; v++) //find quietest voice
70 {
71 if(voice[v].env < l) { l = voice[v].env; vl = v; }
72 }
73 }
74 */
75
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
79
80 s = size;
81 if(velocity > 40) s += (uint32_t)(sizevel * (float)(velocity - 40));
82
83 k = 0;
84 while(note > (kgrp[k].high + s)) k++; //find keygroup
85
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);
89 voice[vl].frac = 0;
90 voice[vl].pos = kgrp[k].pos;
91 voice[vl].end = kgrp[k].end;
92 voice[vl].loop = kgrp[k].loop;
93
94 voice[vl].env = (0.5f + velsens) * (float)pow(0.0078f * velocity, velsens); //velocity
95
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;
101
102 voice[vl].note = note; //note->pan
103 if(note < 12) note = 12;
104 if(note > 108) note = 108;
105 l = volume * trim;
106 voice[vl].outr = l + l * width * (float)(note - 60);
107 voice[vl].outl = l + l - voice[vl].outr;
108
109 if(note < 44) note = 44; //limit max decay length
110 l = 2.0f * param[0];
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));
113 }
114 else //note off
115 {
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?
118 {
119 if(sustain==0)
120 {
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]));
123 }
124 else voice[v].note = SUSTAIN;
125 }
126 }
127 }
128
129
130 void mdaPianoVoice::process(float **inputs, float **outputs, uint32_t sampleFrames)
131 {
132 float* out0 = outputs[0];
133 float* out1 = outputs[1];
134 uint32_t event=0, frame=0, frames, v;
135 float x, l, r;
136 uint32_t i;
137
138 while(frame<sampleFrames)
139 {
140 frames = notes[event++];
141 if(frames>sampleFrames) frames = sampleFrames;
142 frames -= frame;
143 frame += frames;
144
145 while(--frames>=0)
146 {
147 VOICE *V = voice;
148 l = r = 0.0f;
149
150 for(v=0; v<activevoices; v++)
151 {
152 V->frac += V->delta; //integer-based linear interpolation
153 V->pos += V->frac >> 16;
154 V->frac &= 0xFFFF;
155 if(V->pos > V->end) V->pos -= V->loop;
156
157 i = waves[V->pos];
158 i = (i << 7) + (V->frac >> 9) * (waves[V->pos + 1] - i) + 0x40400000;
159 x = V->env * (*(float *)&i - 3.0f); //fast int->float
160
161 /////////////////////
162 //TODO: This was used in processReplacing instead of the above
163 /*
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
168 */
169 /////////////////////
170
171 V->env = V->env * V->dec; //envelope
172 V->f0 += V->ff * (x + V->f1 - V->f0); //muffle filter
173 V->f1 = x;
174
175 l += V->outl * V->f0;
176 r += V->outr * V->f0;
177
178 //TODO: this was used in processReplacing
179 /////////////////////
180 /*
181 if(!(l > -2.0f) || !(l < 2.0f))
182 {
183 printf("what is this shit? %d, %f, %f\n", i, x, V->f0);
184 l = 0.0f;
185 }
186 if(!(r > -2.0f) || !(r < 2.0f))
187 {
188 r = 0.0f;
189 }
190 */
191 /////////////////////
192
193 V++;
194 }
195 comb[cpos] = l + r;
196 ++cpos &= cmax;
197 x = cdep * comb[cpos]; //stereo simulator
198
199 // TODO: processReplacing simply assigned instead of adding
200 *out0++ += l + x;
201 *out1++ += r - x;
202 }
203
204 if(frame<sampleFrames)
205 {
206 uint32_t note = notes[event++];
207 uint32_t vel = notes[event++];
208 noteOn(note, vel);
209 }
210 }
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
213 }
214
215
216 void mdaPianoVoice::update(Param par)
217 {
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;
223
224 velsens = 1.0f + param[6] + param[6];
225 if(param[6] < 0.25f) velsens -= 0.75f - 3.0f * param[6];
226
227 fine = param[9] - 0.5f;
228 random = 0.077f * param[10] * param[10];
229 stretch = 0.000434f * (param[11] - 0.5f);
230
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;
234
235 poly = 8 + (uint32_t)(24.9f * param[8]);
236 }