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 // Main processing class.
28 
29 #include "clouds/dsp/granular_processor.h"
30 
31 #include <cstring>
32 
33 #include "clouds/drivers/debug_pin.h"
34 
35 #include "stmlib/dsp/parameter_interpolator.h"
36 #include "stmlib/utils/buffer_allocator.h"
37 
38 #include "clouds/resources.h"
39 
40 namespace clouds {
41 
42 using namespace std;
43 using namespace stmlib;
44 
Init(void * large_buffer,size_t large_buffer_size,void * small_buffer,size_t small_buffer_size)45 void GranularProcessor::Init(
46     void* large_buffer, size_t large_buffer_size,
47     void* small_buffer, size_t small_buffer_size) {
48   buffer_[0] = large_buffer;
49   buffer_[1] = small_buffer;
50   buffer_size_[0] = large_buffer_size;
51   buffer_size_[1] = small_buffer_size;
52 
53   num_channels_ = 2;
54   low_fidelity_ = false;
55   bypass_ = false;
56 
57   src_down_.Init();
58   src_up_.Init();
59 
60   ResetFilters();
61 
62   previous_playback_mode_ = PLAYBACK_MODE_LAST;
63   reset_buffers_ = true;
64   dry_wet_ = 0.0f;
65 }
66 
ResetFilters()67 void GranularProcessor::ResetFilters() {
68   for (int32_t i = 0; i < 2; ++i) {
69     fb_filter_[i].Init();
70     lp_filter_[i].Init();
71     hp_filter_[i].Init();
72   }
73 }
74 
ProcessGranular(FloatFrame * input,FloatFrame * output,size_t size)75 void GranularProcessor::ProcessGranular(
76     FloatFrame* input,
77     FloatFrame* output,
78     size_t size) {
79   // At the exception of the spectral mode, all modes require the incoming
80   // audio signal to be written to the recording buffer.
81   if (playback_mode_ != PLAYBACK_MODE_SPECTRAL) {
82     const float* input_samples = &input[0].l;
83     for (int32_t i = 0; i < num_channels_; ++i) {
84       if (resolution() == 8) {
85         buffer_8_[i].WriteFade(
86             &input_samples[i], size, 2, !parameters_.freeze);
87       } else {
88         buffer_16_[i].WriteFade(
89             &input_samples[i], size, 2, !parameters_.freeze);
90       }
91     }
92   }
93 
94   switch (playback_mode_) {
95     case PLAYBACK_MODE_GRANULAR:
96       // In Granular mode, DENSITY is a meta parameter.
97       parameters_.granular.use_deterministic_seed = parameters_.density < 0.5f;
98       if (parameters_.density >= 0.53f) {
99         parameters_.granular.overlap = (parameters_.density - 0.53f) * 2.12f;
100       } else if (parameters_.density <= 0.47f) {
101         parameters_.granular.overlap = (0.47f - parameters_.density) * 2.12f;
102       } else {
103         parameters_.granular.overlap = 0.0f;
104       }
105       // And TEXTURE too.
106       parameters_.granular.window_shape = parameters_.texture < 0.75f
107           ? parameters_.texture * 1.333f : 1.0f;
108 
109       if (resolution() == 8) {
110         player_.Play(buffer_8_, parameters_, &output[0].l, size);
111       } else {
112         player_.Play(buffer_16_, parameters_, &output[0].l, size);
113       }
114       break;
115 
116     case PLAYBACK_MODE_STRETCH:
117       if (resolution() == 8) {
118         ws_player_.Play(buffer_8_, parameters_, &output[0].l, size);
119       } else {
120         ws_player_.Play(buffer_16_, parameters_, &output[0].l, size);
121       }
122       break;
123 
124     case PLAYBACK_MODE_LOOPING_DELAY:
125       if (resolution() == 8) {
126         looper_.Play(buffer_8_, parameters_, &output[0].l, size);
127       } else {
128         looper_.Play(buffer_16_, parameters_, &output[0].l, size);
129       }
130       break;
131 
132     case PLAYBACK_MODE_SPECTRAL:
133       {
134         parameters_.spectral.quantization = parameters_.texture;
135         parameters_.spectral.refresh_rate = 0.01f + 0.99f * parameters_.density;
136         float warp = parameters_.size - 0.5f;
137         parameters_.spectral.warp = 4.0f * warp * warp * warp + 0.5f;
138 
139         float randomization = parameters_.density - 0.5f;
140         randomization *= randomization * 4.2f;
141         randomization -= 0.05f;
142         CONSTRAIN(randomization, 0.0f, 1.0f);
143         parameters_.spectral.phase_randomization = randomization;
144         phase_vocoder_.Process(parameters_, input, output, size);
145 
146         if (num_channels_ == 1) {
147           for (size_t i = 0; i < size; ++i) {
148             output[i].r = output[i].l;
149           }
150         }
151       }
152       break;
153 
154     default:
155       break;
156   }
157 }
158 
Process(ShortFrame * input,ShortFrame * output,size_t size)159 void GranularProcessor::Process(
160     ShortFrame* input,
161     ShortFrame* output,
162     size_t size) {
163   // TIC
164   if (bypass_) {
165     copy(&input[0], &input[size], &output[0]);
166     return;
167   }
168 
169   if (silence_ || reset_buffers_ ||
170       previous_playback_mode_ != playback_mode_) {
171     short* output_samples = &output[0].l;
172     fill(&output_samples[0], &output_samples[size << 1], 0);
173     return;
174   }
175 
176   // Convert input buffers to float, and mixdown for mono processing.
177   for (size_t i = 0; i < size; ++i) {
178     in_[i].l = static_cast<float>(input[i].l) / 32768.0f;
179     in_[i].r = static_cast<float>(input[i].r) / 32768.0f;
180   }
181   if (num_channels_ == 1) {
182     for (size_t i = 0; i < size; ++i) {
183       in_[i].l = (in_[i].l + in_[i].r) * 0.5f;
184       in_[i].r = in_[i].l;
185     }
186   }
187 
188   // Apply feedback, with high-pass filtering to prevent build-ups at very
189   // low frequencies (causing large DC swings).
190   ONE_POLE(freeze_lp_, parameters_.freeze ? 1.0f : 0.0f, 0.0005f)
191   float feedback = parameters_.feedback;
192   float cutoff = (20.0f + 100.0f * feedback * feedback) / sample_rate();
193   fb_filter_[0].set_f_q<FREQUENCY_FAST>(cutoff, 1.0f);
194   fb_filter_[1].set(fb_filter_[0]);
195   fb_filter_[0].Process<FILTER_MODE_HIGH_PASS>(&fb_[0].l, &fb_[0].l, size, 2);
196   fb_filter_[1].Process<FILTER_MODE_HIGH_PASS>(&fb_[0].r, &fb_[0].r, size, 2);
197   float fb_gain = feedback * (1.0f - freeze_lp_);
198   for (size_t i = 0; i < size; ++i) {
199     in_[i].l += fb_gain * (
200         SoftLimit(fb_gain * 1.4f * fb_[i].l + in_[i].l) - in_[i].l);
201     in_[i].r += fb_gain * (
202         SoftLimit(fb_gain * 1.4f * fb_[i].r + in_[i].r) - in_[i].r);
203   }
204 
205   if (low_fidelity_) {
206     size_t downsampled_size = size / kDownsamplingFactor;
207     src_down_.Process(in_, in_downsampled_,size);
208     ProcessGranular(in_downsampled_, out_downsampled_, downsampled_size);
209     src_up_.Process(out_downsampled_, out_, downsampled_size);
210   } else {
211     ProcessGranular(in_, out_, size);
212   }
213 
214   // Diffusion and pitch-shifting post-processings.
215   if (playback_mode_ != PLAYBACK_MODE_SPECTRAL) {
216     float texture = parameters_.texture;
217     float diffusion = playback_mode_ == PLAYBACK_MODE_GRANULAR
218         ? texture > 0.75f ? (texture - 0.75f) * 4.0f : 0.0f
219         : parameters_.density;
220     diffuser_.set_amount(diffusion);
221     diffuser_.Process(out_, size);
222   }
223 
224   if (playback_mode_ == PLAYBACK_MODE_LOOPING_DELAY &&
225       (!parameters_.freeze || looper_.synchronized())) {
226     pitch_shifter_.set_ratio(SemitonesToRatio(parameters_.pitch));
227     pitch_shifter_.set_size(parameters_.size);
228     pitch_shifter_.Process(out_, size);
229   }
230 
231   // Apply filters.
232   if (playback_mode_ == PLAYBACK_MODE_LOOPING_DELAY ||
233       playback_mode_ == PLAYBACK_MODE_STRETCH) {
234     float cutoff = parameters_.texture;
235     float lp_cutoff = 0.5f * SemitonesToRatio(
236         (cutoff < 0.5f ? cutoff - 0.5f : 0.0f) * 216.0f);
237     float hp_cutoff = 0.25f * SemitonesToRatio(
238         (cutoff < 0.5f ? -0.5f : cutoff - 1.0f) * 216.0f);
239     CONSTRAIN(lp_cutoff, 0.0f, 0.499f);
240     CONSTRAIN(hp_cutoff, 0.0f, 0.499f);
241     float lpq = 1.0f + 3.0f * (1.0f - feedback) * (0.5f - lp_cutoff);
242     lp_filter_[0].set_f_q<FREQUENCY_FAST>(lp_cutoff, lpq);
243     lp_filter_[0].Process<FILTER_MODE_LOW_PASS>(
244         &out_[0].l, &out_[0].l, size, 2);
245 
246     lp_filter_[1].set(lp_filter_[0]);
247     lp_filter_[1].Process<FILTER_MODE_LOW_PASS>(
248         &out_[0].r, &out_[0].r, size, 2);
249 
250     hp_filter_[0].set_f_q<FREQUENCY_FAST>(hp_cutoff, 1.0f);
251     hp_filter_[0].Process<FILTER_MODE_HIGH_PASS>(
252         &out_[0].l, &out_[0].l, size, 2);
253 
254     hp_filter_[1].set(hp_filter_[0]);
255     hp_filter_[1].Process<FILTER_MODE_HIGH_PASS>(
256         &out_[0].r, &out_[0].r, size, 2);
257   }
258 
259   // This is what is fed back. Reverb is not fed back.
260   copy(&out_[0], &out_[size], &fb_[0]);
261 
262   // Apply reverb.
263   float reverb_amount = parameters_.reverb * 0.95f;
264   reverb_amount += feedback * (2.0f - feedback) * freeze_lp_;
265   CONSTRAIN(reverb_amount, 0.0f, 1.0f);
266 
267   reverb_.set_amount(reverb_amount * 0.54f);
268   reverb_.set_diffusion(0.7f);
269   reverb_.set_time(0.35f + 0.63f * reverb_amount);
270   reverb_.set_input_gain(0.2f);
271   reverb_.set_lp(0.6f + 0.37f * feedback);
272   reverb_.Process(out_, size);
273 
274   const float post_gain = 1.2f;
275   ParameterInterpolator dry_wet_mod(&dry_wet_, parameters_.dry_wet, size);
276   for (size_t i = 0; i < size; ++i) {
277     float dry_wet = dry_wet_mod.Next();
278     float fade_in = Interpolate(lut_xfade_in, dry_wet, 16.0f);
279     float fade_out = Interpolate(lut_xfade_out, dry_wet, 16.0f);
280     float l = static_cast<float>(input[i].l) / 32768.0f * fade_out;
281     float r = static_cast<float>(input[i].r) / 32768.0f * fade_out;
282     l += out_[i].l * post_gain * fade_in;
283     r += out_[i].r * post_gain * fade_in;
284     output[i].l = SoftConvert(l);
285     output[i].r = SoftConvert(r);
286   }
287 }
288 
PreparePersistentData()289 void GranularProcessor::PreparePersistentData() {
290   persistent_state_.write_head[0] = low_fidelity_ ?
291       buffer_8_[0].head() : buffer_16_[0].head();
292   persistent_state_.write_head[1] = low_fidelity_ ?
293       buffer_8_[1].head() : buffer_16_[1].head();
294   persistent_state_.quality = quality();
295   persistent_state_.spectral = playback_mode() == PLAYBACK_MODE_SPECTRAL;
296 }
297 
GetPersistentData(PersistentBlock * block,size_t * num_blocks)298 void GranularProcessor::GetPersistentData(
299       PersistentBlock* block, size_t *num_blocks) {
300   PersistentBlock* first_block = block;
301 
302   block->tag = FourCC<'s', 't', 'a', 't'>::value;
303   block->data = &persistent_state_;
304   block->size = sizeof(PersistentState);
305   ++block;
306 
307   // Create save block holding the audio buffers.
308   for (int32_t i = 0; i < num_channels_; ++i) {
309     block->tag = FourCC<'b', 'u', 'f', 'f'>::value;
310     block->data = buffer_[i];
311     block->size = buffer_size_[num_channels_ - 1];
312     ++block;
313   }
314   *num_blocks = block - first_block;
315 }
316 
LoadPersistentData(const uint32_t * data)317 bool GranularProcessor::LoadPersistentData(const uint32_t* data) {
318   // Force a silent output while the swapping of buffers takes place.
319   silence_ = true;
320 
321   PersistentBlock block[4];
322   size_t num_blocks;
323   GetPersistentData(block, &num_blocks);
324 
325   for (size_t i = 0; i < num_blocks; ++i) {
326     // Check that the format is correct.
327     if (block[i].tag != data[0] || block[i].size != data[1]) {
328       silence_ = false;
329       return false;
330     }
331 
332     // All good. Load the data. 2 words have already been used for the block tag
333     // and the block size.
334     data += 2;
335     memcpy(block[i].data, data, block[i].size);
336     data += block[i].size / sizeof(uint32_t);
337 
338     if (i == 0) {
339       // We now know from which mode the data was saved.
340       bool currently_spectral = playback_mode_ == PLAYBACK_MODE_SPECTRAL;
341       bool requires_spectral = persistent_state_.spectral;
342       if (currently_spectral ^ requires_spectral) {
343         set_playback_mode(requires_spectral
344             ? PLAYBACK_MODE_SPECTRAL
345             : PLAYBACK_MODE_GRANULAR);
346       }
347       set_quality(persistent_state_.quality);
348 
349       // We can force a switch to this mode, and once everything has been
350       // initialized for this mode, we continue with the loop to copy the
351       // actual buffer data - with all state variables correctly initialized.
352       Prepare();
353       GetPersistentData(block, &num_blocks);
354     }
355   }
356 
357   // We can finally reset the position of the write heads.
358   if (low_fidelity_) {
359     buffer_8_[0].Resync(persistent_state_.write_head[0]);
360     buffer_8_[1].Resync(persistent_state_.write_head[1]);
361   } else {
362     buffer_16_[0].Resync(persistent_state_.write_head[0]);
363     buffer_16_[1].Resync(persistent_state_.write_head[1]);
364   }
365   parameters_.freeze = true;
366   silence_ = false;
367   return true;
368 }
369 
Prepare()370 void GranularProcessor::Prepare() {
371   bool playback_mode_changed = previous_playback_mode_ != playback_mode_;
372   bool benign_change = previous_playback_mode_ != PLAYBACK_MODE_SPECTRAL
373       && playback_mode_ != PLAYBACK_MODE_SPECTRAL
374       && previous_playback_mode_ != PLAYBACK_MODE_LAST;
375 
376   if (!reset_buffers_ && playback_mode_changed && benign_change) {
377     ResetFilters();
378     pitch_shifter_.Clear();
379     previous_playback_mode_ = playback_mode_;
380   }
381 
382   if ((playback_mode_changed && !benign_change) || reset_buffers_) {
383     parameters_.freeze = false;
384   }
385 
386   if (reset_buffers_ || (playback_mode_changed && !benign_change)) {
387     void* buffer[2];
388     size_t buffer_size[2];
389     void* workspace;
390     size_t workspace_size;
391     if (num_channels_ == 1) {
392       // Large buffer: 120k of sample memory.
393       // small buffer: fully allocated to FX workspace.
394       buffer[0] = buffer_[0];
395       buffer_size[0] = buffer_size_[0];
396       buffer[1] = NULL;
397       buffer_size[1] = 0;
398       workspace = buffer_[1];
399       workspace_size = buffer_size_[1];
400     } else {
401       // Large buffer: 64k of sample memory + FX workspace.
402       // small buffer: 64k of sample memory.
403       buffer_size[0] = buffer_size[1] = buffer_size_[1];
404       buffer[0] = buffer_[0];
405       buffer[1] = buffer_[1];
406 
407       workspace_size = buffer_size_[0] - buffer_size_[1];
408       workspace = static_cast<uint8_t*>(buffer[0]) + buffer_size[0];
409     }
410     float sr = sample_rate();
411 
412     BufferAllocator allocator(workspace, workspace_size);
413     diffuser_.Init(allocator.Allocate<float>(2048));
414     reverb_.Init(allocator.Allocate<uint16_t>(16384));
415 
416     size_t correlator_block_size = (kMaxWSOLASize / 32) + 2;
417     uint32_t* correlator_data = allocator.Allocate<uint32_t>(
418         correlator_block_size * 3);
419     correlator_.Init(
420         &correlator_data[0],
421         &correlator_data[correlator_block_size]);
422     pitch_shifter_.Init((uint16_t*)correlator_data);
423 
424     if (playback_mode_ == PLAYBACK_MODE_SPECTRAL) {
425       phase_vocoder_.Init(
426           buffer, buffer_size,
427           lut_sine_window_4096, 4096,
428           num_channels_, resolution(), sr);
429     } else {
430       for (int32_t i = 0; i < num_channels_; ++i) {
431         if (resolution() == 8) {
432           buffer_8_[i].Init(
433               buffer[i],
434               (buffer_size[i]),
435               tail_buffer_[i]);
436         } else {
437           buffer_16_[i].Init(
438               buffer[i],
439               ((buffer_size[i]) >> 1),
440               tail_buffer_[i]);
441         }
442       }
443       int32_t num_grains = (num_channels_ == 1 ? 40 : 32) * \
444           (low_fidelity_ ? 23 : 16) >> 4;
445       player_.Init(num_channels_, num_grains);
446       ws_player_.Init(&correlator_, num_channels_);
447       looper_.Init(num_channels_);
448     }
449     reset_buffers_ = false;
450     previous_playback_mode_ = playback_mode_;
451   }
452 
453   if (playback_mode_ == PLAYBACK_MODE_SPECTRAL) {
454     phase_vocoder_.Buffer();
455   } else if (playback_mode_ == PLAYBACK_MODE_STRETCH) {
456     if (resolution() == 8) {
457       ws_player_.LoadCorrelator(buffer_8_);
458     } else {
459       ws_player_.LoadCorrelator(buffer_16_);
460     }
461     correlator_.EvaluateSomeCandidates();
462   }
463 }
464 
465 }  // namespace clouds
466