1 // Copyright 2012 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 // Macro-oscillator.
28 
29 #include "braids/macro_oscillator.h"
30 
31 #include <algorithm>
32 
33 #include "stmlib/utils/dsp.h"
34 
35 #include "braids/parameter_interpolation.h"
36 #include "braids/resources.h"
37 
38 namespace braids {
39 
40 using namespace stmlib;
41 
Render(const uint8_t * sync,int16_t * buffer,size_t size)42 void MacroOscillator::Render(
43     const uint8_t* sync,
44     int16_t* buffer,
45     size_t size) {
46   RenderFn fn = fn_table_[shape_];
47   (this->*fn)(sync, buffer, size);
48 }
49 
RenderCSaw(const uint8_t * sync,int16_t * buffer,size_t size)50 void MacroOscillator::RenderCSaw(
51     const uint8_t* sync,
52     int16_t* buffer,
53     size_t size) {
54   analog_oscillator_[0].set_pitch(pitch_);
55   analog_oscillator_[0].set_shape(OSC_SHAPE_CSAW);
56   analog_oscillator_[0].set_parameter(parameter_[0]);
57   analog_oscillator_[0].set_aux_parameter(parameter_[1]);
58   analog_oscillator_[0].Render(sync, buffer, NULL, size);
59   int16_t shift = -(parameter_[1] - 32767) >> 4;
60   while (size--) {
61     int32_t s = *buffer + shift;
62     *buffer++ = (s * 13) >> 3;
63   }
64 }
65 
RenderMorph(const uint8_t * sync,int16_t * buffer,size_t size)66 void MacroOscillator::RenderMorph(
67     const uint8_t* sync,
68     int16_t* buffer,
69     size_t size) {
70   analog_oscillator_[0].set_pitch(pitch_);
71   analog_oscillator_[1].set_pitch(pitch_);
72 
73   uint16_t balance;
74   if (parameter_[0] <= 10922) {
75     analog_oscillator_[0].set_parameter(0);
76     analog_oscillator_[1].set_parameter(0);
77     analog_oscillator_[0].set_shape(OSC_SHAPE_TRIANGLE);
78     analog_oscillator_[1].set_shape(OSC_SHAPE_SAW);
79     balance = parameter_[0] * 6;
80   } else if (parameter_[0] <= 21845) {
81     analog_oscillator_[0].set_parameter(0);
82     analog_oscillator_[1].set_parameter(0);
83     analog_oscillator_[0].set_shape(OSC_SHAPE_SQUARE);
84     analog_oscillator_[1].set_shape(OSC_SHAPE_SAW);
85     balance = 65535 - (parameter_[0] - 10923) * 6;
86   } else {
87     analog_oscillator_[0].set_parameter((parameter_[0] - 21846) * 3);
88     analog_oscillator_[1].set_parameter(0);
89     analog_oscillator_[0].set_shape(OSC_SHAPE_SQUARE);
90     analog_oscillator_[1].set_shape(OSC_SHAPE_SINE);
91     balance = 0;
92   }
93 
94   int16_t* shape_1 = buffer;
95   int16_t* shape_2 = temp_buffer_;
96   analog_oscillator_[0].Render(sync, shape_1, NULL, size);
97   analog_oscillator_[1].Render(sync, shape_2, NULL, size);
98 
99   int32_t lp_cutoff = pitch_ - (parameter_[1] >> 1) + 128 * 128;
100   if (lp_cutoff < 0) {
101     lp_cutoff = 0;
102   } else if (lp_cutoff > 32767) {
103     lp_cutoff = 32767;
104   }
105   int32_t f = Interpolate824(lut_svf_cutoff, lp_cutoff << 17);
106   int32_t lp_state = lp_state_;
107   int32_t fuzz_amount = parameter_[1] << 1;
108   if (pitch_ > (80 << 7)) {
109     fuzz_amount -= (pitch_ - (80 << 7)) << 4;
110     if (fuzz_amount < 0) {
111       fuzz_amount = 0;
112     }
113   }
114   while (size--) {
115     int16_t sample = Mix(*shape_1++, *shape_2++, balance);
116     int32_t shifted_sample = sample;
117     shifted_sample += (parameter_[1] >> 2) + (parameter_[0] >> 4);
118 
119     lp_state += (sample - lp_state) * f >> 15;
120     CLIP(lp_state)
121     shifted_sample = lp_state + 32768;
122 
123     int16_t fuzzed = Interpolate88(ws_violent_overdrive, shifted_sample);
124     *buffer++ = Mix(sample, fuzzed, fuzz_amount);
125   }
126   lp_state_ = lp_state;
127 }
128 
RenderSawSquare(const uint8_t * sync,int16_t * buffer,size_t size)129 void MacroOscillator::RenderSawSquare(
130     const uint8_t* sync,
131     int16_t* buffer,
132     size_t size) {
133   analog_oscillator_[0].set_parameter(parameter_[0]);
134   analog_oscillator_[1].set_parameter(parameter_[0]);
135   analog_oscillator_[0].set_pitch(pitch_);
136   analog_oscillator_[1].set_pitch(pitch_);
137 
138   analog_oscillator_[0].set_shape(OSC_SHAPE_VARIABLE_SAW);
139   analog_oscillator_[1].set_shape(OSC_SHAPE_SQUARE);
140 
141   int16_t* saw_buffer = buffer;
142   int16_t* square_buffer = temp_buffer_;
143 
144   analog_oscillator_[0].Render(sync, saw_buffer, NULL, size);
145   analog_oscillator_[1].Render(sync, square_buffer, NULL, size);
146 
147   BEGIN_INTERPOLATE_PARAMETER_1
148   while (size--) {
149     INTERPOLATE_PARAMETER_1
150     uint16_t balance = parameter_1 << 1;
151     int16_t attenuated_square = static_cast<int32_t>(
152           *square_buffer++) * 148 >> 8;
153     *buffer++ = Mix(*saw_buffer++, attenuated_square, balance);
154   }
155   END_INTERPOLATE_PARAMETER_1
156 }
157 
158 #define SEMI * 128
159 
160 const int16_t intervals[65] = {
161   -24 SEMI, -24 SEMI, -24 SEMI + 4,
162   -23 SEMI, -22 SEMI, -21 SEMI, -20 SEMI, -19 SEMI, -18 SEMI,
163   -17 SEMI - 4, -17 SEMI,
164   -16 SEMI, -15 SEMI, -14 SEMI, -13 SEMI,
165   -12 SEMI - 4, -12 SEMI,
166   -11 SEMI, -10 SEMI, -9 SEMI, -8 SEMI,
167   -7 SEMI - 4, -7 SEMI,
168   -6 SEMI, -5 SEMI, -4 SEMI, -3 SEMI, -2 SEMI, -1 SEMI,
169   -24, -8, -4, 0, 4, 8, 24,
170   1 SEMI, 2 SEMI, 3 SEMI, 4 SEMI, 5 SEMI, 6 SEMI,
171   7 SEMI, 7 SEMI + 4,
172   8 SEMI, 9 SEMI, 10 SEMI, 11 SEMI,
173   12 SEMI, 12 SEMI + 4,
174   13 SEMI, 14 SEMI, 15 SEMI, 16 SEMI,
175   17 SEMI, 17 SEMI + 4,
176   18 SEMI, 19 SEMI, 20 SEMI, 21 SEMI, 22 SEMI, 23 SEMI,
177   24 SEMI - 4, 24 SEMI, 24 SEMI
178 };
179 
RenderTriple(const uint8_t * sync,int16_t * buffer,size_t size)180 void MacroOscillator::RenderTriple(
181     const uint8_t* sync,
182     int16_t* buffer,
183     size_t size) {
184   AnalogOscillatorShape base_shape;
185   switch (shape_) {
186     case MACRO_OSC_SHAPE_TRIPLE_SAW:
187       base_shape = OSC_SHAPE_SAW;
188       break;
189     case MACRO_OSC_SHAPE_TRIPLE_TRIANGLE:
190       base_shape = OSC_SHAPE_TRIANGLE;
191       break;
192     case MACRO_OSC_SHAPE_TRIPLE_SQUARE:
193       base_shape = OSC_SHAPE_SQUARE;
194       break;
195     default:
196       base_shape = OSC_SHAPE_SINE;
197       break;
198   }
199 
200   analog_oscillator_[0].set_parameter(0);
201   analog_oscillator_[1].set_parameter(0);
202   analog_oscillator_[2].set_parameter(0);
203 
204   analog_oscillator_[0].set_pitch(pitch_);
205   for (size_t i = 0; i < 2; ++i) {
206     int16_t detune_1 = intervals[parameter_[i] >> 9];
207     int16_t detune_2 = intervals[((parameter_[i] >> 8) + 1) >> 1];
208     uint16_t xfade = parameter_[i] << 8;
209     int16_t detune = detune_1 + ((detune_2 - detune_1) * xfade >> 16);
210     analog_oscillator_[i + 1].set_pitch(pitch_ + detune);
211   }
212 
213   analog_oscillator_[0].set_shape(base_shape);
214   analog_oscillator_[1].set_shape(base_shape);
215   analog_oscillator_[2].set_shape(base_shape);
216 
217   std::fill(&buffer[0], &buffer[size], 0);
218   for (size_t i = 0; i < 3; ++i) {
219     analog_oscillator_[i].Render(sync, temp_buffer_, NULL, size);
220     for (size_t j = 0; j < size; ++j) {
221       buffer[j] += temp_buffer_[j] * 21 >> 6;
222     }
223   }
224 }
225 
RenderSub(const uint8_t * sync,int16_t * buffer,size_t size)226 void MacroOscillator::RenderSub(
227     const uint8_t* sync,
228     int16_t* buffer,
229     size_t size) {
230   AnalogOscillatorShape base_shape = shape_ == MACRO_OSC_SHAPE_SQUARE_SUB ?
231       OSC_SHAPE_SQUARE : OSC_SHAPE_VARIABLE_SAW;
232   analog_oscillator_[0].set_parameter(parameter_[0]);
233   analog_oscillator_[0].set_shape(base_shape);
234   analog_oscillator_[0].set_pitch(pitch_);
235 
236   analog_oscillator_[1].set_parameter(0);
237   analog_oscillator_[1].set_shape(OSC_SHAPE_SQUARE);
238   int16_t octave = parameter_[1] < 16384 ? (24 << 7) : (12 << 7);
239   analog_oscillator_[1].set_pitch(pitch_ - octave);
240 
241   analog_oscillator_[0].Render(sync, buffer, NULL, size);
242   analog_oscillator_[1].Render(sync, temp_buffer_, NULL, size);
243 
244   BEGIN_INTERPOLATE_PARAMETER_1
245 
246   int16_t* temp_buffer = temp_buffer_;
247   while (size--) {
248     INTERPOLATE_PARAMETER_1
249     uint16_t sub_gain = (parameter_1 < 16384
250         ? (16383 - parameter_1) : (parameter_1 - 16384)) << 1;
251     *buffer = Mix(*buffer, *temp_buffer, sub_gain);
252     buffer++;
253     temp_buffer++;
254   }
255 
256   END_INTERPOLATE_PARAMETER_1
257 }
258 
RenderDualSync(const uint8_t * sync,int16_t * buffer,size_t size)259 void MacroOscillator::RenderDualSync(
260     const uint8_t* sync,
261     int16_t* buffer,
262     size_t size) {
263   AnalogOscillatorShape base_shape = shape_ == MACRO_OSC_SHAPE_SQUARE_SYNC ?
264       OSC_SHAPE_SQUARE : OSC_SHAPE_SAW;
265   analog_oscillator_[0].set_parameter(0);
266   analog_oscillator_[0].set_shape(base_shape);
267   analog_oscillator_[0].set_pitch(pitch_);
268 
269   analog_oscillator_[1].set_parameter(0);
270   analog_oscillator_[1].set_shape(base_shape);
271   analog_oscillator_[1].set_pitch(pitch_ + (parameter_[0] >> 2));
272 
273   analog_oscillator_[0].Render(sync, buffer, sync_buffer_, size);
274   analog_oscillator_[1].Render(sync_buffer_, temp_buffer_, NULL, size);
275 
276   BEGIN_INTERPOLATE_PARAMETER_1
277 
278   int16_t* temp_buffer = temp_buffer_;
279   while (size--) {
280     INTERPOLATE_PARAMETER_1
281     uint16_t balance = parameter_1 << 1;
282 
283     *buffer = (Mix(*buffer, *temp_buffer, balance) >> 2) * 3;
284     buffer++;
285     temp_buffer++;
286   }
287 
288   END_INTERPOLATE_PARAMETER_1
289 }
290 
RenderSineTriangle(const uint8_t * sync,int16_t * buffer,size_t size)291 void MacroOscillator::RenderSineTriangle(
292     const uint8_t* sync,
293     int16_t* buffer,
294     size_t size) {
295   int32_t attenuation_sine = 32767 - 6 * (pitch_ - (92 << 7));
296   int32_t attenuation_tri = 32767 - 7 * (pitch_ - (80 << 7));
297   if (attenuation_tri < 0) attenuation_tri = 0;
298   if (attenuation_sine < 0) attenuation_sine = 0;
299   if (attenuation_tri > 32767) attenuation_tri = 32767;
300   if (attenuation_sine > 32767) attenuation_sine = 32767;
301 
302   int32_t timbre = parameter_[0];
303 
304   analog_oscillator_[0].set_parameter(timbre * attenuation_sine >> 15);
305   analog_oscillator_[1].set_parameter(timbre * attenuation_tri >> 15);
306   analog_oscillator_[0].set_pitch(pitch_);
307   analog_oscillator_[1].set_pitch(pitch_);
308 
309   analog_oscillator_[0].set_shape(OSC_SHAPE_SINE_FOLD);
310   analog_oscillator_[1].set_shape(OSC_SHAPE_TRIANGLE_FOLD);
311 
312   analog_oscillator_[0].Render(sync, buffer, NULL, size);
313   analog_oscillator_[1].Render(sync, temp_buffer_, NULL, size);
314 
315   int16_t* temp_buffer = temp_buffer_;
316 
317   BEGIN_INTERPOLATE_PARAMETER_1
318 
319   while (size--) {
320     INTERPOLATE_PARAMETER_1
321     uint16_t balance = parameter_1 << 1;
322 
323     *buffer = Mix(*buffer, *temp_buffer, balance);
324     buffer++;
325     temp_buffer++;
326   }
327 
328   END_INTERPOLATE_PARAMETER_1
329 }
330 
RenderBuzz(const uint8_t * sync,int16_t * buffer,size_t size)331 void MacroOscillator::RenderBuzz(
332     const uint8_t* sync,
333     int16_t* buffer,
334     size_t size) {
335   analog_oscillator_[0].set_parameter(parameter_[0]);
336   analog_oscillator_[0].set_shape(OSC_SHAPE_BUZZ);
337   analog_oscillator_[0].set_pitch(pitch_);
338 
339   analog_oscillator_[1].set_parameter(parameter_[0]);
340   analog_oscillator_[1].set_shape(OSC_SHAPE_BUZZ);
341   analog_oscillator_[1].set_pitch(pitch_ + (parameter_[1] >> 8));
342 
343   analog_oscillator_[0].Render(sync, buffer, NULL, size);
344   analog_oscillator_[1].Render(sync, temp_buffer_, NULL, size);
345   int16_t* temp_buffer = temp_buffer_;
346   while (size--) {
347     *buffer >>= 1;
348     *buffer += *temp_buffer >> 1;
349     buffer++;
350     temp_buffer++;
351   }
352 }
353 
RenderDigital(const uint8_t * sync,int16_t * buffer,size_t size)354 void MacroOscillator::RenderDigital(
355     const uint8_t* sync,
356     int16_t* buffer,
357     size_t size) {
358   digital_oscillator_.set_parameters(parameter_[0], parameter_[1]);
359   digital_oscillator_.set_pitch(pitch_);
360   digital_oscillator_.set_shape(static_cast<DigitalOscillatorShape>(
361       shape_ - MACRO_OSC_SHAPE_TRIPLE_RING_MOD));
362   digital_oscillator_.Render(sync, buffer, size);
363 }
364 
RenderSawComb(const uint8_t * sync,int16_t * buffer,size_t size)365 void MacroOscillator::RenderSawComb(
366   const uint8_t* sync,
367   int16_t* buffer,
368   size_t size) {
369   analog_oscillator_[0].set_parameter(0);
370   analog_oscillator_[0].set_pitch(pitch_);
371   analog_oscillator_[0].set_shape(OSC_SHAPE_SAW);
372   analog_oscillator_[0].Render(sync, buffer, NULL, size);
373 
374   digital_oscillator_.set_parameters(parameter_[0], parameter_[1]);
375   digital_oscillator_.set_pitch(pitch_);
376   digital_oscillator_.set_shape(OSC_SHAPE_COMB_FILTER);
377   digital_oscillator_.Render(sync, buffer, size);
378 }
379 
380 /* static */
381 MacroOscillator::RenderFn MacroOscillator::fn_table_[] = {
382   &MacroOscillator::RenderCSaw,
383   &MacroOscillator::RenderMorph,
384   &MacroOscillator::RenderSawSquare,
385   &MacroOscillator::RenderSineTriangle,
386   &MacroOscillator::RenderBuzz,
387   &MacroOscillator::RenderSub,
388   &MacroOscillator::RenderSub,
389   &MacroOscillator::RenderDualSync,
390   &MacroOscillator::RenderDualSync,
391   &MacroOscillator::RenderTriple,
392   &MacroOscillator::RenderTriple,
393   &MacroOscillator::RenderTriple,
394   &MacroOscillator::RenderTriple,
395   &MacroOscillator::RenderDigital,
396   &MacroOscillator::RenderDigital,
397   &MacroOscillator::RenderSawComb,
398   &MacroOscillator::RenderDigital,
399   &MacroOscillator::RenderDigital,
400   &MacroOscillator::RenderDigital,
401   &MacroOscillator::RenderDigital,
402   &MacroOscillator::RenderDigital,
403   &MacroOscillator::RenderDigital,
404   &MacroOscillator::RenderDigital,
405   &MacroOscillator::RenderDigital,
406   &MacroOscillator::RenderDigital,
407   &MacroOscillator::RenderDigital,
408   &MacroOscillator::RenderDigital,
409   &MacroOscillator::RenderDigital,
410   &MacroOscillator::RenderDigital,
411   &MacroOscillator::RenderDigital,
412   &MacroOscillator::RenderDigital,
413   &MacroOscillator::RenderDigital,
414   &MacroOscillator::RenderDigital,
415   &MacroOscillator::RenderDigital,
416   &MacroOscillator::RenderDigital,
417   &MacroOscillator::RenderDigital,
418   &MacroOscillator::RenderDigital,
419   &MacroOscillator::RenderDigital,
420   &MacroOscillator::RenderDigital,
421   &MacroOscillator::RenderDigital,
422   &MacroOscillator::RenderDigital,
423   &MacroOscillator::RenderDigital,
424   &MacroOscillator::RenderDigital,
425   &MacroOscillator::RenderDigital,
426   &MacroOscillator::RenderDigital,
427   &MacroOscillator::RenderDigital,
428   &MacroOscillator::RenderDigital,
429   &MacroOscillator::RenderDigital,
430   // &MacroOscillator::RenderDigital
431 };
432 
433 }  // namespace braids
434