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