1 // Copyright 2014 Olivier Gillet.
2 //
3 // Author: Olivier Gillet (ol.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       playback_mode_ != PLAYBACK_MODE_RESONESTOR) {
83     const float* input_samples = &input[0].l;
84     const bool play = !parameters_.freeze ||
85       playback_mode_ == PLAYBACK_MODE_OLIVERB;
86     for (int32_t i = 0; i < num_channels_; ++i) {
87       if (resolution() == 8) {
88         buffer_8_[i].WriteFade(&input_samples[i], size, 2, play);
89       } else {
90         buffer_16_[i].WriteFade(&input_samples[i], size, 2, play);
91       }
92     }
93   }
94 
95   switch (playback_mode_) {
96     case PLAYBACK_MODE_GRANULAR:
97       // In Granular mode, DENSITY is a meta parameter.
98       parameters_.granular.use_deterministic_seed = parameters_.density < 0.5f;
99       if (parameters_.density >= 0.53f) {
100         parameters_.granular.overlap = (parameters_.density - 0.53f) * 2.12f;
101       } else if (parameters_.density <= 0.47f) {
102         parameters_.granular.overlap = (0.47f - parameters_.density) * 2.12f;
103       } else {
104         parameters_.granular.overlap = 0.0f;
105       }
106 
107 #ifdef CLOUDS_QUANTIZE_SEMITONES
108       // Quantize pitch to closest semitone
109       if (parameters_.pitch < 0.5f) parameters_.pitch -= 0.5f;
110       parameters_.pitch = static_cast<int>(parameters_.pitch + 0.5f);
111 #endif
112 
113       // And TEXTURE too.
114       parameters_.granular.window_shape = parameters_.texture < 0.75f
115           ? parameters_.texture * 1.333f : 1.0f;
116 
117       if (resolution() == 8) {
118         player_.Play(buffer_8_, parameters_, &output[0].l, size);
119       } else {
120         player_.Play(buffer_16_, parameters_, &output[0].l, size);
121       }
122       break;
123 
124     case PLAYBACK_MODE_STRETCH:
125       if (resolution() == 8) {
126         ws_player_.Play(buffer_8_, parameters_, &output[0].l, size);
127       } else {
128         ws_player_.Play(buffer_16_, parameters_, &output[0].l, size);
129       }
130       break;
131 
132     case PLAYBACK_MODE_LOOPING_DELAY:
133       if (resolution() == 8) {
134         looper_.Play(buffer_8_, parameters_, &output[0].l, size);
135       } else {
136         looper_.Play(buffer_16_, parameters_, &output[0].l, size);
137       }
138       break;
139 
140     case PLAYBACK_MODE_SPECTRAL:
141       {
142         parameters_.spectral.quantization = parameters_.texture;
143         parameters_.spectral.refresh_rate = 0.01f + 0.99f * parameters_.density;
144         float warp = parameters_.size - 0.5f;
145         parameters_.spectral.warp = 4.0f * warp * warp * warp + 0.5f;
146 
147         float randomization = parameters_.density - 0.5f;
148         randomization *= randomization * 4.2f;
149         randomization -= 0.05f;
150         CONSTRAIN(randomization, 0.0f, 1.0f);
151         parameters_.spectral.phase_randomization = randomization;
152         phase_vocoder_.Process(parameters_, input, output, size);
153 
154         if (num_channels_ == 1) {
155           for (size_t i = 0; i < size; ++i) {
156             output[i].r = output[i].l;
157           }
158         }
159       }
160       break;
161 
162     case PLAYBACK_MODE_OLIVERB:
163       {
164 
165         // Pre-delay, controlled by position or tap tempo sync
166         Parameters p = {
167           ws_player_.synchronized() ?
168           parameters_.position :
169           parameters_.position * 0.25f, // position;
170           0.1f, // size;
171           0.0f, // pitch;
172           0.0f, // density;
173           0.5f, // texture;
174           1.0f, // dry_wet;
175           0.0f, // stereo_spread;
176           0.0f, // feedback;
177           0.0f, // reverb;
178           false, // freeze;
179           parameters_.trigger, // trigger;
180           false // gate;
181         };
182 
183         if (resolution() == 8) {
184           ws_player_.Play(buffer_8_, p, &output[0].l, size);
185         } else {
186           ws_player_.Play(buffer_16_, p, &output[0].l, size);
187         }
188 
189         // Settings of the reverb
190         oliverb_.set_diffusion(0.3f + 0.5f * parameters_.stereo_spread);
191         oliverb_.set_size(0.05f + 0.94f * parameters_.size);
192         oliverb_.set_mod_rate(parameters_.feedback);
193         oliverb_.set_mod_amount(parameters_.reverb * 300.0f);
194         oliverb_.set_ratio(SemitonesToRatio(parameters_.pitch));
195 
196         float x = parameters_.pitch;
197         const float limit = 0.7f;
198         const float slew = 0.4f;
199 
200         float wet =
201           x < -limit ? 1.0f :
202           x < -limit + slew ? 1.0f - (x + limit) / slew:
203           x < limit - slew ? 0.0f :
204           x < limit ? 1.0f + (x - limit) / slew:
205           1.0f;
206         oliverb_.set_pitch_shift_amount(wet);
207 
208         if (parameters_.freeze) {
209           oliverb_.set_input_gain(0.0f);
210           oliverb_.set_decay(1.0f);
211           oliverb_.set_lp(1.0f);
212           oliverb_.set_hp(0.0f);
213         } else {
214           oliverb_.set_decay(parameters_.density * 1.3f
215                            + 0.15f * abs(parameters_.pitch) / 24.0f);
216           oliverb_.set_input_gain(0.5f);
217           float lp = parameters_.texture < 0.5f ?
218             parameters_.texture * 2.0f : 1.0f;
219           float hp = parameters_.texture > 0.5f ?
220             (parameters_.texture - 0.5f) * 2.0f : 0.0f;
221           oliverb_.set_lp(0.03f + 0.9f * lp);
222           oliverb_.set_hp(0.01f + 0.2f * hp); // the small offset
223                                                   // gets rid of
224                                                   // feedback of large
225                                                   // DC offset.
226         }
227         oliverb_.Process(output, size);
228       }
229       break;
230 
231   case PLAYBACK_MODE_RESONESTOR:
232     {
233       copy(&input[0], &input[size], &output[0]);
234 
235       resonestor_.set_pitch(parameters_.pitch);
236       resonestor_.set_chord(parameters_.size);
237       resonestor_.set_trigger(parameters_.trigger);
238       resonestor_.set_burst_damp(parameters_.position);
239       resonestor_.set_burst_comb((1.0f - parameters_.position));
240       resonestor_.set_burst_duration((1.0f - parameters_.position));
241       resonestor_.set_spread_amount(parameters_.reverb);
242       resonestor_.set_stereo(parameters_.stereo_spread < 0.5f ? 0.0f :
243         (parameters_.stereo_spread - 0.5f) * 2.0f);
244       resonestor_.set_separation(parameters_.stereo_spread > 0.5f ? 0.0f :
245                                 (0.5f - parameters_.stereo_spread) * 2.0f);
246       resonestor_.set_freeze(parameters_.freeze);
247       resonestor_.set_harmonicity(1.0f - (parameters_.feedback * 0.5f));
248       resonestor_.set_distortion(parameters_.dry_wet);
249 
250       float t = parameters_.texture;
251       if (t < 0.5f) {
252         resonestor_.set_narrow(0.001f);
253         float l = 1.0f - (0.5f - t) / 0.5f;
254         l = l * (1.0f - 0.08f) + 0.08f;
255         resonestor_.set_damp(l * l);
256       } else {
257         resonestor_.set_damp(1.0f);
258         float n = (t - 0.5f) / 0.5f * 1.35f;
259         n *= n * n * n;
260         resonestor_.set_narrow(0.001f + n * n * 0.6f);
261       }
262 
263       float d = (parameters_.density - 0.05f) / 0.9f;
264       if (d < 0.0f) d = 0.0f;
265       d *= d * d;
266       d *= d * d;
267       d *= d * d;
268       resonestor_.set_feedback(d * 20.0f);
269 
270       resonestor_.Process(output, size);
271     }
272     break;
273 
274     default:
275       break;
276   }
277 }
278 
Process(ShortFrame * input,ShortFrame * output,size_t size)279 void GranularProcessor::Process(
280     ShortFrame* input,
281     ShortFrame* output,
282     size_t size) {
283   // TIC
284   if (bypass_) {
285     copy(&input[0], &input[size], &output[0]);
286     return;
287   }
288 
289   if (silence_ || reset_buffers_ ||
290       previous_playback_mode_ != playback_mode_) {
291     short* output_samples = &output[0].l;
292     fill(&output_samples[0], &output_samples[size << 1], 0);
293     return;
294   }
295 
296   // Convert input buffers to float, and mixdown for mono processing.
297   for (size_t i = 0; i < size; ++i) {
298     in_[i].l = static_cast<float>(input[i].l) / 32768.0f;
299     in_[i].r = static_cast<float>(input[i].r) / 32768.0f;
300   }
301 
302   if (num_channels_ == 1) {
303     for (size_t i = 0; i < size; ++i) {
304       float xfade = 0.5f;
305       // in mono delay modes, stereo spread controls input crossfade
306       if (playback_mode_ == PLAYBACK_MODE_LOOPING_DELAY ||
307           playback_mode_ == PLAYBACK_MODE_STRETCH)
308         xfade = parameters_.stereo_spread;
309 
310       in_[i].l = in_[i].l * (1.0f - xfade) + in_[i].r * xfade;
311       in_[i].r = in_[i].l;
312     }
313   }
314 
315   // Apply feedback, with high-pass filtering to prevent build-ups at very
316   // low frequencies (causing large DC swings).
317   float feedback = parameters_.feedback;
318 
319   if (playback_mode_ != PLAYBACK_MODE_OLIVERB &&
320       playback_mode_ != PLAYBACK_MODE_RESONESTOR) {
321     ONE_POLE(freeze_lp_, parameters_.freeze ? 1.0f : 0.0f, 0.0005f)
322     float cutoff = (20.0f + 100.0f * feedback * feedback) / sample_rate();
323     fb_filter_[0].set_f_q<FREQUENCY_FAST>(cutoff, 0.75f);
324     fb_filter_[1].set(fb_filter_[0]);
325     fb_filter_[0].Process<FILTER_MODE_HIGH_PASS>(&fb_[0].l, &fb_[0].l, size, 2);
326     fb_filter_[1].Process<FILTER_MODE_HIGH_PASS>(&fb_[0].r, &fb_[0].r, size, 2);
327     float fb_gain = feedback * (2.0f - feedback) * (1.0f - freeze_lp_);
328     for (size_t i = 0; i < size; ++i) {
329       in_[i].l += fb_gain * (
330                              SoftLimit(fb_gain * 1.4f * fb_[i].l + in_[i].l) - in_[i].l);
331       in_[i].r += fb_gain * (
332                              SoftLimit(fb_gain * 1.4f * fb_[i].r + in_[i].r) - in_[i].r);
333     }
334   }
335 
336   if (low_fidelity_) {
337     size_t downsampled_size = size / kDownsamplingFactor;
338     src_down_.Process(in_, in_downsampled_,size);
339     ProcessGranular(in_downsampled_, out_downsampled_, downsampled_size);
340     src_up_.Process(out_downsampled_, out_, downsampled_size);
341   } else {
342     ProcessGranular(in_, out_, size);
343   }
344 
345   // Diffusion and pitch-shifting post-processings.
346   if (playback_mode_ != PLAYBACK_MODE_SPECTRAL &&
347       playback_mode_ != PLAYBACK_MODE_OLIVERB &&
348       playback_mode_ != PLAYBACK_MODE_RESONESTOR) {
349     float texture = parameters_.texture;
350     float diffusion = playback_mode_ == PLAYBACK_MODE_GRANULAR
351         ? texture > 0.75f ? (texture - 0.75f) * 4.0f : 0.0f
352         : parameters_.density;
353     diffuser_.set_amount(diffusion);
354     diffuser_.Process(out_, size);
355   }
356 
357   if (playback_mode_ == PLAYBACK_MODE_LOOPING_DELAY &&
358       (!parameters_.freeze || looper_.synchronized())) {
359     pitch_shifter_.set_ratio(SemitonesToRatio(parameters_.pitch));
360     pitch_shifter_.set_size(parameters_.size);
361     float x = parameters_.pitch;
362     const float limit = 0.7f;
363     const float slew = 0.4f;
364     float wet =
365       x < -limit ? 1.0f :
366       x < -limit + slew ? 1.0f - (x + limit) / slew:
367       x < limit - slew ? 0.0f :
368       x < limit ? 1.0f + (x - limit) / slew:
369       1.0f;
370     pitch_shifter_.set_dry_wet(wet);
371     pitch_shifter_.Process(out_, size);
372   }
373 
374   // Apply filters.
375   if (playback_mode_ == PLAYBACK_MODE_LOOPING_DELAY ||
376       playback_mode_ == PLAYBACK_MODE_STRETCH) {
377     float cutoff = parameters_.texture;
378     float lp_cutoff = 0.5f * SemitonesToRatio(
379         (cutoff < 0.5f ? cutoff - 0.5f : 0.0f) * 216.0f);
380     float hp_cutoff = 0.25f * SemitonesToRatio(
381         (cutoff < 0.5f ? -0.5f : cutoff - 1.0f) * 216.0f);
382     CONSTRAIN(lp_cutoff, 0.0f, 0.499f);
383     CONSTRAIN(hp_cutoff, 0.0f, 0.499f);
384 
385     lp_filter_[0].set_f_q<FREQUENCY_FAST>(lp_cutoff, 0.9f);
386     lp_filter_[0].Process<FILTER_MODE_LOW_PASS>(
387         &out_[0].l, &out_[0].l, size, 2);
388 
389     lp_filter_[1].set(lp_filter_[0]);
390     lp_filter_[1].Process<FILTER_MODE_LOW_PASS>(
391         &out_[0].r, &out_[0].r, size, 2);
392 
393     hp_filter_[0].set_f_q<FREQUENCY_FAST>(hp_cutoff, 0.9f);
394     hp_filter_[0].Process<FILTER_MODE_HIGH_PASS>(
395         &out_[0].l, &out_[0].l, size, 2);
396 
397     hp_filter_[1].set(hp_filter_[0]);
398     hp_filter_[1].Process<FILTER_MODE_HIGH_PASS>(
399         &out_[0].r, &out_[0].r, size, 2);
400   }
401 
402   // This is what is fed back. Reverb is not fed back.
403   copy(&out_[0], &out_[size], &fb_[0]);
404 
405   const float post_gain = 1.2f;
406 
407   if (playback_mode_ != PLAYBACK_MODE_RESONESTOR) {
408     ParameterInterpolator dry_wet_mod(&dry_wet_, parameters_.dry_wet, size);
409     for (size_t i = 0; i < size; ++i) {
410       float dry_wet = dry_wet_mod.Next();
411       float fade_in = Interpolate(lut_xfade_in, dry_wet, 16.0f);
412       float fade_out = Interpolate(lut_xfade_out, dry_wet, 16.0f);
413       float l = static_cast<float>(input[i].l) / 32768.0f;
414       float r = static_cast<float>(input[i].r) / 32768.0f;
415       out_[i].l = l * fade_out + out_[i].l * post_gain * fade_in;
416       out_[i].r = r * fade_out + out_[i].r * post_gain * fade_in;
417     }
418   }
419 
420   // Apply the simple post-processing reverb.
421   if (playback_mode_ != PLAYBACK_MODE_OLIVERB &&
422       playback_mode_ != PLAYBACK_MODE_RESONESTOR) {
423     float reverb_amount = parameters_.reverb;
424 
425     reverb_.set_amount(reverb_amount * 0.54f);
426     reverb_.set_diffusion(0.7f);
427     reverb_.set_time(0.35f + 0.63f * reverb_amount);
428     reverb_.set_input_gain(0.2f);
429     reverb_.set_lp(0.6f + 0.37f * feedback);
430 
431     reverb_.Process(out_, size);
432   }
433 
434   for (size_t i = 0; i < size; ++i) {
435     output[i].l = SoftConvert(out_[i].l);
436     output[i].r = SoftConvert(out_[i].r);
437   }
438 
439   // TOC
440 }
441 
PreparePersistentData()442 void GranularProcessor::PreparePersistentData() {
443   persistent_state_.write_head[0] = low_fidelity_ ?
444       buffer_8_[0].head() : buffer_16_[0].head();
445   persistent_state_.write_head[1] = low_fidelity_ ?
446       buffer_8_[1].head() : buffer_16_[1].head();
447   persistent_state_.quality = quality();
448   persistent_state_.spectral = playback_mode() == PLAYBACK_MODE_SPECTRAL;
449 }
450 
GetPersistentData(PersistentBlock * block,size_t * num_blocks)451 void GranularProcessor::GetPersistentData(
452       PersistentBlock* block, size_t *num_blocks) {
453   PersistentBlock* first_block = block;
454 
455   block->tag = FourCC<'s', 't', 'a', 't'>::value;
456   block->data = &persistent_state_;
457   block->size = sizeof(PersistentState);
458   ++block;
459 
460   // Create save block holding the audio buffers.
461   for (int32_t i = 0; i < num_channels_; ++i) {
462     block->tag = FourCC<'b', 'u', 'f', 'f'>::value;
463     block->data = buffer_[i];
464     block->size = buffer_size_[num_channels_ - 1];
465     ++block;
466   }
467   *num_blocks = block - first_block;
468 }
469 
LoadPersistentData(const uint32_t * data)470 bool GranularProcessor::LoadPersistentData(const uint32_t* data) {
471   // Force a silent output while the swapping of buffers takes place.
472   silence_ = true;
473 
474   PersistentBlock block[4];
475   size_t num_blocks;
476   GetPersistentData(block, &num_blocks);
477 
478   for (size_t i = 0; i < num_blocks; ++i) {
479     // Check that the format is correct.
480     if (block[i].tag != data[0] || block[i].size != data[1]) {
481       silence_ = false;
482       return false;
483     }
484 
485     // All good. Load the data. 2 words have already been used for the block tag
486     // and the block size.
487     data += 2;
488     memcpy(block[i].data, data, block[i].size);
489     data += block[i].size / sizeof(uint32_t);
490 
491     if (i == 0) {
492       // We now know from which mode the data was saved.
493       bool currently_spectral = playback_mode_ == PLAYBACK_MODE_SPECTRAL;
494       bool requires_spectral = persistent_state_.spectral;
495       if (currently_spectral ^ requires_spectral) {
496         set_playback_mode(requires_spectral
497             ? PLAYBACK_MODE_SPECTRAL
498             : PLAYBACK_MODE_GRANULAR);
499       }
500       set_quality(persistent_state_.quality);
501 
502       // We can force a switch to this mode, and once everything has been
503       // initialized for this mode, we continue with the loop to copy the
504       // actual buffer data - with all state variables correctly initialized.
505       Prepare();
506       GetPersistentData(block, &num_blocks);
507     }
508   }
509 
510   // We can finally reset the position of the write heads.
511   if (low_fidelity_) {
512     buffer_8_[0].Resync(persistent_state_.write_head[0]);
513     buffer_8_[1].Resync(persistent_state_.write_head[1]);
514   } else {
515     buffer_16_[0].Resync(persistent_state_.write_head[0]);
516     buffer_16_[1].Resync(persistent_state_.write_head[1]);
517   }
518   parameters_.freeze = true;
519   silence_ = false;
520   return true;
521 }
522 
Prepare()523 void GranularProcessor::Prepare() {
524   bool playback_mode_changed = previous_playback_mode_ != playback_mode_;
525   bool benign_change = previous_playback_mode_ != PLAYBACK_MODE_SPECTRAL
526     && playback_mode_ != PLAYBACK_MODE_SPECTRAL
527     && playback_mode_ != PLAYBACK_MODE_RESONESTOR
528     && previous_playback_mode_ != PLAYBACK_MODE_RESONESTOR
529     && playback_mode_ != PLAYBACK_MODE_OLIVERB
530     && previous_playback_mode_ != PLAYBACK_MODE_OLIVERB
531     && previous_playback_mode_ != PLAYBACK_MODE_LAST;
532 
533   if (!reset_buffers_ && playback_mode_changed && benign_change) {
534     ResetFilters();
535     pitch_shifter_.Clear();
536     previous_playback_mode_ = playback_mode_;
537   }
538 
539   if ((playback_mode_changed && !benign_change) || reset_buffers_) {
540     parameters_.freeze = false;
541   }
542 
543   if (reset_buffers_ || (playback_mode_changed && !benign_change)) {
544     void* buffer[2];
545     size_t buffer_size[2];
546     void* workspace;
547     size_t workspace_size;
548     if (num_channels_ == 1) {
549       // Large buffer: 120k of sample memory.
550       // small buffer: fully allocated to FX workspace.
551       buffer[0] = buffer_[0];
552       buffer_size[0] = buffer_size_[0];
553       buffer[1] = NULL;
554       buffer_size[1] = 0;
555       workspace = buffer_[1];
556       workspace_size = buffer_size_[1];
557     } else {
558       // Large buffer: 64k of sample memory + FX workspace.
559       // small buffer: 64k of sample memory.
560       buffer_size[0] = buffer_size[1] = buffer_size_[1];
561       buffer[0] = buffer_[0];
562       buffer[1] = buffer_[1];
563 
564       workspace_size = buffer_size_[0] - buffer_size_[1];
565       workspace = static_cast<uint8_t*>(buffer[0]) + buffer_size[0];
566     }
567     float sr = sample_rate();
568 
569     BufferAllocator allocator(workspace, workspace_size);
570     diffuser_.Init(allocator.Allocate<float>(2048));
571 
572     uint16_t* reverb_buffer = allocator.Allocate<uint16_t>(16384);
573     if (playback_mode_ == PLAYBACK_MODE_OLIVERB) {
574       oliverb_.Init(reverb_buffer);
575     } else {
576       reverb_.Init(reverb_buffer);
577     }
578 
579     size_t correlator_block_size = (kMaxWSOLASize / 32) + 2;
580     uint32_t* correlator_data = allocator.Allocate<uint32_t>(
581         correlator_block_size * 3);
582     correlator_.Init(
583         &correlator_data[0],
584         &correlator_data[correlator_block_size]);
585     pitch_shifter_.Init((uint16_t*)correlator_data);
586 
587     if (playback_mode_ == PLAYBACK_MODE_SPECTRAL) {
588       phase_vocoder_.Init(
589           buffer, buffer_size,
590           lut_sine_window_4096, 4096,
591           num_channels_, resolution(), sr);
592     } else if (playback_mode_ == PLAYBACK_MODE_RESONESTOR) {
593       float* buf = (float*)buffer[0];
594       resonestor_.Init(buf);
595     } else {
596       for (int32_t i = 0; i < num_channels_; ++i) {
597         if (resolution() == 8) {
598           buffer_8_[i].Init(
599               buffer[i],
600               (buffer_size[i]),
601               tail_buffer_[i]);
602         } else {
603           buffer_16_[i].Init(
604               buffer[i],
605               ((buffer_size[i]) >> 1),
606               tail_buffer_[i]);
607         }
608       }
609       int32_t num_grains = (num_channels_ == 1 ? 32 : 26) * \
610           (low_fidelity_ ? 20 : 16) >> 4;
611       player_.Init(num_channels_, num_grains);
612       ws_player_.Init(&correlator_, num_channels_);
613       looper_.Init(num_channels_);
614     }
615     reset_buffers_ = false;
616     previous_playback_mode_ = playback_mode_;
617   }
618 
619   if (playback_mode_ == PLAYBACK_MODE_SPECTRAL) {
620     phase_vocoder_.Buffer();
621   } else if (playback_mode_ == PLAYBACK_MODE_STRETCH ||
622              playback_mode_ == PLAYBACK_MODE_OLIVERB) {
623     if (resolution() == 8) {
624       ws_player_.LoadCorrelator(buffer_8_);
625     } else {
626       ws_player_.LoadCorrelator(buffer_16_);
627     }
628     correlator_.EvaluateSomeCandidates();
629   }
630 }
631 
632 }  // namespace clouds
633