1 // Copyright 2014 Emilie Gillet.
2 //
3 // Author: Emilie Gillet (emilie.o.gillet@gmail.com)
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 // THE SOFTWARE.
22 //
23 // See http://creativecommons.org/licenses/MIT/ for more information.
24 //
25 // -----------------------------------------------------------------------------
26 //
27 // Modal synthesis voice.
28 
29 #include "elements/dsp/voice.h"
30 
31 #include "stmlib/dsp/dsp.h"
32 #include "stmlib/dsp/units.h"
33 
34 #include <algorithm>
35 
36 namespace elements {
37 
38 using namespace std;
39 using namespace stmlib;
40 
Init()41 void Voice::Init() {
42   envelope_.Init();
43   bow_.Init();
44   blow_.Init();
45   strike_.Init();
46   diffuser_.Init(diffuser_buffer_);
47 
48   ResetResonator();
49 
50   bow_.set_model(EXCITER_MODEL_FLOW);
51   bow_.set_parameter(0.7f);
52   bow_.set_timbre(0.5f);
53 
54   blow_.set_model(EXCITER_MODEL_GRANULAR_SAMPLE_PLAYER);
55 
56   envelope_.set_adsr(0.5f, 0.5f, 0.5f, 0.5f);
57 
58   previous_gate_ = false;
59   strength_ = 0.0f;
60   exciter_level_ = 0.0f;
61   envelope_value_ = 0.0f;
62   chord_index_ = 0.0f;
63 
64   resonator_model_ = RESONATOR_MODEL_MODAL;
65 }
66 
ResetResonator()67 void Voice::ResetResonator() {
68   resonator_.Init();
69   for (size_t i = 0; i < kNumStrings; ++i) {
70     string_[i].Init(true);
71   }
72   dc_blocker_.Init(1.0f - 10.0f / kSampleRate);
73   resonator_.set_resolution(52);  // Runs with 56 extremely tightly.
74 }
75 
76 float chords[11][5] = {
77     { 0.0f, -12.0f, 0.0f, 0.01f, 12.0f },
78     { 0.0f, -12.0f, 3.0f, 7.0f,  10.0f },
79     { 0.0f, -12.0f, 3.0f, 7.0f,  12.0f },
80     { 0.0f, -12.0f, 3.0f, 7.0f,  14.0f },
81     { 0.0f, -12.0f, 3.0f, 7.0f,  17.0f },
82     { 0.0f, -12.0f, 7.0f, 12.0f, 19.0f },
83     { 0.0f, -12.0f, 4.0f, 7.0f,  17.0f },
84     { 0.0f, -12.0f, 4.0f, 7.0f,  14.0f },
85     { 0.0f, -12.0f, 4.0f, 7.0f,  12.0f },
86     { 0.0f, -12.0f, 4.0f, 7.0f,  11.0f },
87     { 0.0f, -12.0f, 5.0f, 7.0f,  12.0f },
88 };
89 
Process(const Patch & patch,float frequency,float strength,const bool gate_in,const float * blow_in,const float * strike_in,float * raw,float * center,float * sides,size_t size)90 void Voice::Process(
91     const Patch& patch,
92     float frequency,
93     float strength,
94     const bool gate_in,
95     const float* blow_in,
96     const float* strike_in,
97     float* raw,
98     float* center,
99     float* sides,
100     size_t size) {
101   uint8_t flags = GetGateFlags(gate_in);
102 
103   // Compute the envelope.
104   float envelope_gain = 1.0f;
105   if (patch.exciter_envelope_shape < 0.4f) {
106     float a = patch.exciter_envelope_shape * 0.75f + 0.15f;
107     float dr = a * 1.8f;
108     envelope_.set_adsr(a, dr, 0.0f, dr);
109     envelope_gain = 5.0f - patch.exciter_envelope_shape * 10.0f;
110   } else if (patch.exciter_envelope_shape < 0.6f) {
111     float s = (patch.exciter_envelope_shape - 0.4f) * 5.0f;
112     envelope_.set_adsr(0.45f, 0.81f, s, 0.81f);
113   } else {
114     float a = (1.0f - patch.exciter_envelope_shape) * 0.75f + 0.15f;
115     float dr = a * 1.8f;
116     envelope_.set_adsr(a, dr, 1.0f, dr);
117   }
118   float envelope_value = envelope_.Process(flags) * envelope_gain;
119   float envelope_increment = (envelope_value - envelope_value_) / size;
120 
121   // Configure and evaluate exciters.
122   float brightness_factor = 0.4f + 0.6f * patch.resonator_brightness;
123   bow_.set_timbre(patch.exciter_bow_timbre * brightness_factor);
124 
125   blow_.set_parameter(patch.exciter_blow_meta);
126   blow_.set_timbre(patch.exciter_blow_timbre);
127   blow_.set_signature(patch.exciter_signature);
128 
129   float strike_meta = patch.exciter_strike_meta;
130   strike_.set_meta(
131       strike_meta <= 0.4f ? strike_meta * 0.625f : strike_meta * 1.25f - 0.25f,
132       EXCITER_MODEL_SAMPLE_PLAYER,
133       EXCITER_MODEL_PARTICLES);
134   strike_.set_timbre(patch.exciter_strike_timbre);
135   strike_.set_signature(patch.exciter_signature);
136 
137   bow_.Process(flags, bow_buffer_, size);
138 
139   float blow_level, tube_level;
140   blow_level = patch.exciter_blow_level * 1.5f;
141   tube_level = blow_level > 1.0f ? (blow_level - 1.0f) * 2.0f : 0.0f;
142   blow_level = blow_level < 1.0f ? blow_level * 0.4f : 0.4f;
143   blow_.Process(flags, blow_buffer_, size);
144   tube_.Process(
145       frequency,
146       envelope_value,
147       patch.resonator_damping,
148       tube_level,
149       blow_buffer_,
150       tube_level * 0.5f,
151       size);
152 
153   for (size_t i = 0; i < size; ++i) {
154     blow_buffer_[i] = blow_buffer_[i] * blow_level + blow_in[i];
155   }
156   diffuser_.Process(blow_buffer_, size);
157   strike_.Process(flags, strike_buffer_, size);
158 
159   // The Strike exciter is implemented in such a way that raising the level
160   // beyond a certain point doesn't change the exciter amplitude, but instead,
161   // increasingly mixes the raw exciter signal into the resonator output.
162   float strike_level, strike_bleed;
163   strike_level = patch.exciter_strike_level * 1.25f;
164   strike_bleed = strike_level > 1.0f ? (strike_level - 1.0f) * 2.0f : 0.0f;
165   strike_level = strike_level < 1.0f ? strike_level : 1.0f;
166   strike_level *= 1.5f;
167 
168   // The strength parameter is very sensitive to zipper noise.
169   strength *= 256.0f;
170   float strength_increment = (strength - strength_) / size;
171 
172   // Sum all sources of excitation.
173   for (size_t i = 0; i < size; ++i) {
174     strength_ += strength_increment;
175     envelope_value_ += envelope_increment;
176     float input_sample = 0.0f;
177     float e = envelope_value_;
178     float strength_lut = strength_;
179     MAKE_INTEGRAL_FRACTIONAL(strength_lut);
180     float accent = lut_accent_gain_coarse[strength_lut_integral] *
181        lut_accent_gain_fine[
182            static_cast<int32_t>(256.0f * strength_lut_fractional)];
183     bow_strength_buffer_[i] = e * patch.exciter_bow_level;
184 
185     strike_buffer_[i] *= accent;
186     e *= accent;
187 
188     input_sample += bow_buffer_[i] * bow_strength_buffer_[i] * 0.125f * accent;
189     input_sample += blow_buffer_[i] * e;
190     input_sample += strike_buffer_[i] * strike_level;
191     input_sample += strike_in[i];
192     raw[i] = input_sample * 0.5f;
193   }
194 
195   // Update meter for exciter.
196   for (size_t i = 0; i < size; ++i) {
197     float error = raw[i] * raw[i] - exciter_level_;
198     exciter_level_ += error * (error > 0.0f ? 0.5f : 0.001f);
199   }
200 
201   // Some exciters can cause palm mutes on release.
202   float damping = patch.resonator_damping;
203   damping -= strike_.damping() * strike_level * 0.125f;
204   damping -= (1.0f - bow_strength_buffer_[0]) * \
205       patch.exciter_bow_level * 0.0625f;
206 
207   if (damping <= 0.0f) {
208     damping = 0.0f;
209   }
210 
211   // Configure resonator.
212   if (resonator_model_ == RESONATOR_MODEL_MODAL) {
213     resonator_.set_frequency(frequency);
214     resonator_.set_geometry(patch.resonator_geometry);
215     resonator_.set_brightness(patch.resonator_brightness);
216     resonator_.set_position(patch.resonator_position);
217     resonator_.set_damping(damping);
218     resonator_.set_modulation_frequency(patch.resonator_modulation_frequency);
219     resonator_.set_modulation_offset(patch.resonator_modulation_offset);
220 
221     // Process through resonator.
222     resonator_.Process(bow_strength_buffer_, raw, center, sides, size);
223   } else {
224     size_t num_notes = resonator_model_ == RESONATOR_MODEL_STRING
225         ? 1
226         : kNumStrings;
227 
228     float normalization = 1.0f / static_cast<float>(num_notes);
229     dc_blocker_.Process(raw, size);
230     for (size_t i = 0; i < size; ++i) {
231       raw[i] *= normalization;
232     }
233 
234     float chord = patch.resonator_geometry * 10.0f;
235     float hysteresis = chord > chord_index_ ? -0.1f : 0.1f;
236     int chord_index = static_cast<int>(chord + hysteresis + 0.5f);
237     CONSTRAIN(chord_index, 0, 10);
238     chord_index_ = static_cast<float>(chord_index);
239 
240     fill(&center[0], &center[size], 0.0f);
241     fill(&sides[0], &sides[size], 0.0f);
242     for (size_t i = 0; i < num_notes; ++i) {
243       float transpose = chords[chord_index][i];
244       string_[i].set_frequency(frequency * SemitonesToRatio(transpose));
245       string_[i].set_brightness(patch.resonator_brightness);
246       string_[i].set_position(patch.resonator_position);
247       string_[i].set_damping(damping);
248       if (num_notes == 1) {
249         string_[i].set_dispersion(patch.resonator_geometry);
250       } else {
251         float b = patch.resonator_brightness;
252         string_[i].set_dispersion(b < 0.5f ? 0.0f : (b - 0.5f) * -0.4f);
253       }
254       string_[i].Process(raw, center, sides, size);
255     }
256     for (size_t i = 0; i < size; ++i) {
257       float left = center[i];
258       float right = sides[i];
259       center[i] = left - right;
260       sides[i] = left + right;
261     }
262   }
263 
264   // This is where the raw mallet signal bleeds through the exciter output.
265   for (size_t i = 0; i < size; ++i) {
266     center[i] += strike_bleed * strike_buffer_[i];
267   }
268 }
269 
270 }  // namespace elements
271