0657baff2ac4952e5de6795d4c3f1438d6850cba
[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 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 reset();
25 update(Default);
26 }
27
28
29 float mdaPianoVoice::p_helper(unsigned short id, Param d) {
30 if (d == Default)
31 return default_preset[p_offset(id)];
32 else
33 return *p(id);
34 }
35
36
37 void mdaPianoVoice::on(unsigned char key, unsigned char velocity) {
38 // store key that turned this voice on (used in 'get_key')
39 m_key = key;
40 update(Current);
41
42 float l=99.0f;
43 uint32_t k, s;
44
45 if(velocity > 0)
46 {
47 k = (key - 60) * (key - 60);
48 l = fine + random * ((float)(k % 13) - 6.5f); //random & fine tune
49 if(key > 60) l += stretch * (float)k; //stretch
50
51 s = size;
52 if(velocity > 40) s += (uint32_t)(sizevel * (float)(velocity - 40));
53
54 k = 0;
55 while(key > (kgrp[k].high + s)) k++; // find keygroup
56 sample_index = k; // store sample index
57
58 l += (float)(key - kgrp[k].root); // pitch
59 l = 22050.0f * iFs * (float)exp(0.05776226505 * l);
60 delta = (uint32_t)(65536.0f * l);
61 frac = 0;
62 pos = 0;
63 end = samples[sample_index].size;
64 loop = kgrp[sample_index].loop;
65
66 env = (0.5f + velsens) * (float)pow(0.0078f * velocity, velsens); //velocity
67
68 l = 50.0f + *p(p_muffling_filter) * *p(p_muffling_filter) * muff + muffvel * (float)(velocity - 64); //muffle
69 if(l < (55.0f + 0.25f * (float)key)) l = 55.0f + 0.25f * (float)key;
70 if(l > 210.0f) l = 210.0f;
71 ff = l * l * iFs;
72 f0 = f1 = 0.0f;
73
74 // note->pan
75 if(key < 12) key = 12;
76 if(key > 108) key = 108;
77 l = volume * trim;
78 outr = l + l * width * (float)(key - 60);
79 outl = l + l - outr;
80
81 if(key < 44) key = 44; //limit max decay length
82 l = 2.0f * *p(p_envelope_decay);
83 if(l < 1.0f) l += 0.25f - 0.5f * *p(p_envelope_decay);
84 dec = (float)exp(-iFs * exp(-0.6 + 0.033 * (double)key - l));
85 } else {
86 // some keyboards send note off events as 'note on' with velocity 0
87 release(0);
88 }
89 }
90
91
92 void mdaPianoVoice::reset() {
93 env = 0.0f;
94 dec = 0.99f;
95 muff = 160.0f;
96 volume = 0.2f;
97 sustain = 0;
98 cpos = 0;
99 m_key = LV2::INVALID_KEY;
100 }
101
102
103 void mdaPianoVoice::release(unsigned char velocity) {
104 if(sustain==0) {
105 //no release on highest notes
106 if(m_key < 94 || m_key == SUSTAIN) {
107 dec = (float)exp(-iFs * exp(2.0 + 0.017 * (double)m_key - 2.0 * *p(p_envelope_release)));
108 }
109 } else {
110 m_key = SUSTAIN;
111 }
112
113 //Mark the voice to be turned off later. It may not be set to
114 //INVALID_KEY yet, because the release sound still needs to be
115 //rendered. m_key is finally set to INVALID_KEY by 'render' when
116 //env < SILENCE
117 m_key = SUSTAIN;
118 }
119
120
121 void mdaPianoVoice::render(uint32_t from, uint32_t to) {
122 // abort if no key is pressed
123 // initially m_key is INVALID_KEY, so no sound will be rendered
124 if (m_key == LV2::INVALID_KEY)
125 return;
126
127 float x, l, r;
128 uint32_t i;
129
130 update(Current);
131 for (uint32_t frame = from; frame < to; ++frame) {
132 // initialize left and right output
133 l = r = 0.0f;
134
135 frac += delta; // integer-based linear interpolation
136 pos += frac >> 16;
137 frac &= 0xFFFF;
138 if(pos > end) pos -= loop;
139
140 i = samples[sample_index].buffer[pos];
141 i = (i << 7) + (frac >> 9) * (samples[sample_index].buffer[pos + 1] - i) + 0x40400000;
142 x = env * (*(float *)&i - 3.0f); //fast int->float
143
144 env = env * dec; //envelope
145 f0 += ff * (x + f1 - f0); //muffle filter
146 f1 = x;
147
148 l += outl * f0;
149 r += outr * f0;
150
151 comb[cpos] = l + r;
152 ++cpos &= 0x7F;
153 x = cdep * comb[cpos]; //stereo simulator
154
155 // write to output
156 p(p_left)[frame] += l + x;
157 p(p_right)[frame] += r - x;
158 }
159
160 // turn off further processing when the envelope has rendered the voice silent
161 if (env < SILENCE) {
162 m_key = LV2::INVALID_KEY;
163 }
164 }
165
166
167 void mdaPianoVoice::update(Param par) {
168 size = (uint32_t)(12.0f * p_helper(p_hardness_offset, par) - 6.0f);
169 sizevel = 0.12f * p_helper(p_velocity_to_hardness, par);
170 muffvel = p_helper(p_velocity_to_muffling, par) * p_helper(p_velocity_to_muffling, par) * 5.0f;
171
172 velsens = 1.0f + p_helper(p_velocity_sensitivity, par) + p_helper(p_velocity_sensitivity, par);
173 if(p_helper(p_velocity_sensitivity, par) < 0.25f) {
174 velsens -= 0.75f - 3.0f * p_helper(p_velocity_sensitivity, par);
175 }
176
177 fine = p_helper(p_fine_tuning, par) - 0.5f;
178 random = 0.077f * p_helper(p_random_detuning, par) * p_helper(p_random_detuning, par);
179 stretch = 0.000434f * (p_helper(p_stretch_tuning, par) - 0.5f);
180
181 cdep = p_helper(p_stereo_width, par) * p_helper(p_stereo_width, par);
182 trim = 1.50f - 0.79f * cdep;
183 width = 0.04f * p_helper(p_stereo_width, par); if(width > 0.03f) width = 0.03f;
184
185 poly = 8 + (uint32_t)(24.9f * p_helper(p_polyphony, par));
186 }