forked from fluffyaudio/MultiVersio
-
Notifications
You must be signed in to change notification settings - Fork 0
/
MultiEffect.cpp
2387 lines (1901 loc) · 82.8 KB
/
MultiEffect.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#include "daisysp.h"
#include "daisy_versio.h"
#include <string>
#include "arm_math.h"
#include "shy_fft.h"
#include "dsp/filter.h"
using namespace daisy;
using namespace daisysp;
DaisyVersio versio;
#define FFT_LENGTH 1024
#define MAX_SPECTRA_FREQUENCIES 6
#define MAX_DELAY static_cast<size_t>(48000 * 2.5f) //2.5 seconds max delay in the fast ram
#define LOOPER_MAX_SIZE (48000 * 60 * 1) // 1 minutes stereo of floats at 48 khz
//TO ADD: COMPLETE VOICE (ADSR + VCA + FILTER + REVERB)
//NATURAL GATE: LPG with SPECTRAL ANALISYS FOR NOTE HEIGHT, NOTE REPETITION DISTANCE
//CLOCKED DELAY NORMALE
#define REV 0
#define RESONATOR 1
#define FILTER 2
#define LOFI 3
#define MLOOPER 4
#define DELAY 5
#define SPECTRA 6
#define SPECTRINGS 7
#define NATURAL_GATE 8
#define NUM_MODES 9
const char *modes[NUM_MODES] = { "Reverb", "Resonator",
"Filter", "LO-FI", "MicroLooper", "Delay", "Spectra", "Spectrings", "Natural Gate"};
#define NUM_DELAY_TIMES 17
#define RMS_SIZE 48
#define NUM_OF_STRINGS 2
const float delay_times[NUM_DELAY_TIMES] = {0.0078125,0.015625, 0.03125, 0.25/6.f, 0.046875, 0.0625,
0.25/3.f, 0.09375, 0.125, 0.5/3.f, 0.1875, 0.25, 1.f/3.f,
0.375, 0.5f, 0.75f, 1.f};
//These are reusable between effects to save memory
static ReverbSc rev;
static DelayLine<float, MAX_DELAY> DSY_SDRAM_BSS dell;
static DelayLine<float, MAX_DELAY> DSY_SDRAM_BSS delr;
static Svf svfl;
static Svf svfr;
static stmlib::Svf svf2l;
static stmlib::Svf svf2r;
static Tone tonel;
static Tone toner;
static Biquad biquad;
static StringVoice string_voice[NUM_OF_STRINGS];
const size_t kMaxFftSize = FFT_LENGTH;
typedef ShyFFT<float, kMaxFftSize, RotationPhasor> FFT;
const size_t FFT_SIZE = FFT_LENGTH;
//Individual parameters for each effect
//static Parameter crusher_cutoff_par, crusher_crushrate_par;
static Parameter lofi_tone_par, lofi_rate_par;
static Parameter lofi_reverb_tone_par,lofi_reverb_rate_par;
static Parameter filter_cutoff_l_par, filter_cutoff_r_par;
static Parameter delay_cutoff_par;
static DcBlock dcblock_l, dcblock_r;
static DcBlock dcblock_2l, dcblock_2r;
int CHRM_SCALE[128] = {8176 ,8662 ,9177 ,9723 ,10301 ,10913 ,11562 ,12250 ,12978 ,13750 ,14568 ,15434 ,16352 ,17324 ,18354 ,19445 ,20602 ,21827 ,23125 ,24500 ,25957 ,27500 ,29135 ,30868 ,32703 ,34648 ,36708 ,38891 ,41203 ,43654 ,46249 ,48999 ,51913 ,55000 ,58270 ,61735 ,65406 ,69296 ,73416 ,77782 ,82407 ,87307 ,92499 ,97999 ,103826 ,110000 ,116541 ,123471 ,130813 ,138591 ,146832 ,155563 ,164814 ,174614 ,184997 ,195998 ,207652 ,220000 ,233082 ,246942 ,261626 ,277183 ,293665 ,311127 ,329628 ,349228 ,369994 ,391995 ,415305 ,440000 ,466164 ,493883 ,523251 ,554365 ,587330 ,622254 ,659255 ,698456 ,739989 ,783991 ,830609 ,880000 ,932328 ,987767 ,1046502 ,1108731 ,1174659 ,1244508 ,1318510 ,1396913 ,1479978 ,1567982 ,1661219 ,1760000 ,1864655 ,1975533 ,2093005 ,2217461 ,2349318 ,2489016 ,2637020 ,2793826 ,2959955 ,3135963 ,3322438 ,3520000 ,3729310 ,3951066 ,4186009 ,4434922 ,4698636 ,4978032 ,5274041 ,5587652 ,5919911 ,6271927 ,6644875 ,7040000 ,7458620 ,7902133 ,8372018 ,8869844 ,9397273 ,9956063 ,10548080 ,11175300 ,11839820 ,12543850} ;
bool scale_12[12] = {1,1,1,1,1,1,1,1,1,1,1,1};
bool scale_7[12] = {1,0,1,0,1,1,0,1,0,1,0,1};
bool scale_6[12] = {1,0,1,0,1,1,0,1,0,1,0,0};
bool scale_5[12] = {1,0,1,0,0,1,0,1,0,1,0,0};
bool scale_4[12] = {1,0,1,0,0,1,0,1,0,0,0,0};
bool scale_3[12] = {1,0,0,0,0,1,0,1,0,0,0,0};
bool scale_2[12] = {1,0,0,0,0,0,0,1,0,0,0,0};
bool scale_1[12] = {1,0,0,0,0,0,0,0,0,0,0,0};
int mode = REV;
int previous_mode = mode;
float attack_lut[300];
//Individual Variables for each effect
float reverb_drywet, reverb_feedback,reverb_lowpass, reverb_shimmer = 0;
int reverb_shimmer_write_pos1l, reverb_shimmer_write_pos1r,
reverb_shimmer_write_pos2 = 0;
int reverb_shimmer_play_pos1l, reverb_shimmer_play_pos1r;
float reverb_shimmer_play_pos2=0.f ;
int reverb_shimmer_buffer_size1l = 24000*0.773;
int reverb_shimmer_buffer_size1r = 24000*0.802;
int reverb_shimmer_buffer_size2 = 48000*0.753*2;
float reverb_previous_inl, reverb_previous_inr = 0;
float reverb_current_outl, reverb_current_outr = 0;
int reverb_feedback_display = 0;
int reverb_rmsCount;
float reverb_current_RMS, reverb_target_RMS, reverb_feedback_RMS=0.f;
float reverb_target_compression, reverb_compression = 1.0f;
float resonator_note = 20.f;
float resonator_tone = 12000.f;
int resonator_feedback_display = 0;
float resonator_current_regen = 0.5f;
float target_resonator_feedback = 0.001f;
int resonator_rmsCount;
float resonator_previous_l, resonator_previous_r = 0.f;
float resonator_current_RMS, resonator_target_RMS, resonator_feedback_RMS=0.f;
float resonator_current_delay, resonator_feedback, resonator_target, resonator_drywet =0.f;
int resonator_octave = 1;
float resonator_glide = 0.f;
int resonator_glide_mode = 0;
//int crusher_crushmod, crusher_crushcount;
//float crusher_crushsl, crusher_crushsr;
//float crusher_cutoff;
float filter_mode_l = 0.f;
float filter_mode_r = 0.f;
float filter_path = 0.f;
float filter_target_l_freq, filter_target_r_freq, filter_current_l_freq, filter_current_r_freq = 0.5f;
float lofi_current_RMS, lofi_target_RMS;
float lofi_damp_speed, lofi_depth;
int lofi_mod, lofi_rate_count;
int lofi_rmsCount;
float lofi_cutoff, lofi_target_Lofi_LFO_Freq, lofi_current_Lofi_LFO_Freq;
float lofi_previous_variable_compressor;
float global_sample_rate;
float lofi_previous_left_saturation, lofi_previous_right_saturation;
float lofi_current_left_saturation, lofi_current_right_saturation;
float lofi_drywet = 0.0f;
float lofi_lpg_amount =1.0f;
float lofi_lpg_decay =1.0f;
bool mlooper_play = false; //currently playing
float mlooper_pos_1 = 0;
float mlooper_pos_2 = 0;
int modified_buffer_length_l, modified_buffer_length_r;
int modified_frozen_buffer_length_l, modified_frozen_buffer_length_r;
float DSY_SDRAM_BSS mlooper_buf_1l[LOOPER_MAX_SIZE];
float DSY_SDRAM_BSS mlooper_buf_1r[LOOPER_MAX_SIZE];
float DSY_SDRAM_BSS mlooper_frozen_buf_1l[LOOPER_MAX_SIZE];
float DSY_SDRAM_BSS mlooper_frozen_buf_1r[LOOPER_MAX_SIZE];
int mlooper_len = LOOPER_MAX_SIZE-1;
int mlooper_len_count = 0;
float mlooper_drywet = 0.f;
float mlooper_frozen_pos_1 = 0;
float mlooper_frozen_pos_2 = 0;
int mlooper_frozen_len = LOOPER_MAX_SIZE-1;
bool mlooper_frozen = false;
int mlooper_writer_pos = 0;
int mlooper_writer_outside_pos = 0;
float mlooper_division_1 = 1.f;
float mlooper_division_2 = 1.f;
std::string mlooper_division_string_1 = "";
std::string mlooper_division_string_2 = "";
float mlooper_play_speed_1 = 1.f;
float mlooper_play_speed_2 = 1.f;
float mlooper_volume_att_1 = 1.f;
float mlooper_volume_att_2 = 1.f;
std::string mlooper_play_speed_string_1 = "";
std::string mlooper_play_speed_string_2 = "";
float delay_mult_l[2], delay_mult_r[2];
float delay_feedback = 0.0f;
int delay_time_count = 0;
int delay_write_pos = 0;
int delay_control_counter,delay_time_trig = 0;
int delay_control_latency_ms = 20;
int delay_pos_l[2], delay_pos_r[2];
int delay_time[2];
float delay_outl[2], delay_outr[2];
int delay_left_counter, delay_right_counter = 0;
int delay_left_counter_4, delay_right_counter_4 = 0;
int delay_main_counter = 0;
int delay_active = 0;
int delay_inactive = 1;
float delay_xfade_current = 0;
float delay_xfade_target = 0;
int delay_frozen_start;
int delay_frozen_end;
int delay_frozen_pos;
float delay_target_cutoff =0.0f;
float delay_cutoff, delay_drywet = 0.f;
bool delay_frozen = false;
float delay_prev_sample_l, delay_prev_sample_r = 0.f;
bool delay_reduce_spikes_l, delay_reduce_spikes_r = false;
float delay_spike_counter_l, delay_spike_counter_r = 1.f;
int delay_rmsCount = 0;
float delay_target_RMS, delay_feedback_RMS, delay_fast_feedback_RMS = 0.0f;
int spectra_waveform = 0;
float spectra_r,spectra_g,spectra_b = 0.f;
float spectra_prev_knob_wave_knob = 0.f;
int spectra_num_active = MAX_SPECTRA_FREQUENCIES;
const int spectra_max_num_frequencies = MAX_SPECTRA_FREQUENCIES;
int spectra_oct = 0;
int spectra_hop = 1;
float spectra_drywet;
float spectra_lower_harmonics = 0.f;
float spectra_oct_mult;
std::string spectra_oct_string;
float spectra_reverb_amount= 0.f;
bool spectra_do_analisys = false;
int spectra_rmsCount = 0;
float spectra_current_RMS, spectra_target_RMS = 1.f;
float spectra_spread= 1.0f;
float spectra_rotate_harmonics = 0.0f;
int spectra_transpose = 0;
int spectra_quantize = 0;
bool *spectra_selected_scale;
int spectrings_num_models = 2;
int spectrings_active_voices = 2;
int spectrings_current_voice = 0;
bool spectrings_trigger_next_cycle = false;
float spectrings_drywet = 0.0f;
size_t spectrings_attack_step[NUM_OF_STRINGS];
size_t spectrings_attack_last_step[NUM_OF_STRINGS];
float spectrings_accent_amount [NUM_OF_STRINGS];
float spectrings_decay_amount [NUM_OF_STRINGS];
float spectrings_pan_spread = 0.0f;
//Helper functions
void Controls();
void GetReverbSample(float &outl, float &outr, float inl, float inr);
void GetResonatorSample(float &outl, float &outr, float inl, float inr);
void GetFilterSamples(float outl[], float outr[], float inl[], float inr[], size_t size);
void GetLofiSample(float &outl, float &outr, float inl, float inr);
void GetLooperSample(float &out1l, float &out1r, float in1l, float in1r);
void GetDelaySample(float &out1l, float &out1r, float in1l, float in1r);
void GetSpectraSample(float &outl, float &outr, float inl, float inr);
void GetSpectringsSample(float &outl, float &outr, float inl, float inr);
void ResetLooperBuffer();
void FreezeLooperBuffer();
void SelectLooperDivision(float knob_value_1, float knob_value_2);
void SelectLooperPlaySpeed(float knob_value_1, float knob_value_2);
void SelectDelayDivision(float knob1, float knob2);
float clamp(float value,float min,float max) {
if (value < min){
return min;
}
if (value > max){
return max;
}
return value;
};
float map(float value, float start1, float stop1, float start2, float stop2) {
return start2 + ((stop2 - start2) * (value - start1) )/ (stop1 - start1);
};
void leftRotatebyOne(float arr[], int n)
{
float temp = arr[0];
for (int i = 0; i < n - 1; i++)
arr[i] = arr[i + 1];
arr[n-1] = temp;
}
void rightRotatebyOne(float arr[], int n)
{
float temp = arr[n-1];
for (int i = n-1; i > 0; i--)
arr[i] = arr[i - 1];
arr[0] = temp;
}
/*Function to left rotate arr[] of size n by d*/
void leftRotate(float arr[], float amount, int n)
{
for (int i = 0; i < amount*n; i++)
leftRotatebyOne(arr, n);
}
/*Function to left rotate arr[] of size n by d*/
void rightRotate(float arr[], float amount, int n)
{
for (int i = 0; i < amount*n; i++)
rightRotatebyOne(arr, n);
}
int getClosest(int, int, int);
// Returns element closest to target in arr[]
int findClosest(int arr[],bool filter[], int n, int target, int offset)
{
int lower = 0;
int higher = n;
int reverse_counter = 0;
for (int i = 0; i< n; i++) {
if ((arr[i] < target) & filter[(i+offset)%12]) {
lower = arr[i];
}
reverse_counter = (n-1)-i;
if ((arr[reverse_counter] > target) & filter[(reverse_counter+offset)%12]) {
higher = arr[reverse_counter];
}
}
return getClosest(lower, higher, target);
};
// Method to compare which one is the more close.
// We find the closest by taking the difference
// between the target and both values. It assumes
// that val2 is greater than val1 and target lies
// between these two.
int getClosest(int val1, int val2,
int target)
{
if (target - val1 >= val2 - target)
return val2;
else
return val1;
}
void SelectSpectraOctave(float knob_value_1){
//sets the octave shift
if (knob_value_1 < 0.2f){
spectra_oct_mult = 0.25f;
spectra_oct_string = "-2";
} else if (knob_value_1 < 0.4f){
spectra_oct_mult = 0.5f;
spectra_oct_string = "-1";
} else if (knob_value_1 < 0.6f){
spectra_oct_mult = 1.f;
spectra_oct_string = " 0";
} else if (knob_value_1 < 0.8f){
spectra_oct_mult = 2.f;
spectra_oct_string = "+1";
} else if (knob_value_1 > 0.8f){
spectra_oct_mult = 4.f;
spectra_oct_string = "+2";
}
};
void swap(float *xp, float *yp)
{
int temp = *xp;
*xp = *yp;
*yp = temp;
}
// A function to implement bubble sort
void bubbleSort(float arr[],float arr2[], int n)
{
int i, j;
for (i = 0; i < n-1; i++)
// Last i elements are already in place
for (j = 0; j < n-i-1; j++)
if (arr[j] < arr[j+1]){
swap(&arr[j], &arr[j+1]);
swap(&arr2[j], &arr2[j+1]);
}
}
float ApplyWindow(float i, size_t pos, size_t FFT_SIZE) {
float multiplier = 0.5 * (1 - cos(2*PI*pos/(FFT_SIZE-1)));
return i * multiplier;
}
class LedsControl {
//Helper Class to handle leds easily.
int times[4];
float flash_color[4][3];
float base_color[4][3];
public:
LedsControl(){
Reset();
};
~LedsControl() {};
void Reset() {
SwitchAllOff();
//trick to initialize everything to black
for (int i = 0; i < 4; i++) {
SetForXCycles(i,-1,0,0,0);
}
}
void SetForXCycles(int idx, int _times, float r, float g, float b) {
flash_color[idx][0] = r;
flash_color[idx][1] = g;
flash_color[idx][2] = b;
times[idx] = _times;
};
void SwitchAllOff() {
SetAllLeds(0,0,0);
};
void SwitchOffLed(int idx) {
versio.SetLed(idx,0,0,0);
};
void SetAllLeds(float r, float g, float b) {
for (int i = 0; i < 4; i++) {
SetBaseColor(i,r,g,b);
}
}
void SetBaseColor(int idx, float r, float g, float b) {
base_color[idx][0] = r;
base_color[idx][1] = g;
base_color[idx][2] = b;
}
void UpdateLeds() {
//handle flashing leds
for (int i = 0; i < 4; i++) {
versio.SetLed(i,base_color[i][0],base_color[i][1],base_color[i][2]);
if (times[i] > 0) {
times[i]--;
versio.SetLed(i, flash_color[i][0],flash_color[i][1],flash_color[i][2]);
}
}
versio.UpdateLeds();
};
};
class OscBank {
static const int number_of_osc = spectra_max_num_frequencies;
Oscillator osc[number_of_osc];
float freq[number_of_osc];
float magn[number_of_osc];
float current_freq[number_of_osc];
float current_magn[number_of_osc];
size_t num_of_passes;
float fftinbuff[FFT_SIZE];
float window[FFT_SIZE];
float window_fftinbuff[FFT_SIZE];
float fftoutbuff[FFT_SIZE];
float magni_fftoutbuff[FFT_SIZE/2];
float bandSize;
float maxAmp = 0;
int num_active = spectra_num_active;
float output_mult, prev_output_mult = 0.f;
int firstUsableBin;
float amp_attenuation = 1.f;
int previous_wave = 0;
int current_wave = 0;
FFT fft;
size_t attack_step[number_of_osc];
bool mark_to_change_waveform[number_of_osc];
public:
size_t hop = 8;
OscBank(){
for (size_t t = FFT_SIZE; t > 1; t >>= 1) {
++num_of_passes;
}
};
~OscBank() {};
void Init(float sample_rate) {
for (int i = 0; i< number_of_osc; i++) {
osc[i].Init(sample_rate);
//float randomPhase = (rand() %1000)/1000.f;
//osc[i].PhaseAdd(randomPhase);
freq[i] = 0;
magn[i] = 0;
current_freq[i] = 0;
current_magn[i] = 0;
osc[i].SetWaveform(0);
attack_step[i] = 0;
mark_to_change_waveform[i] = false;
};
for (size_t i = 0; i < FFT_SIZE; i++) {
fftinbuff[i] = 0;
fftoutbuff[i] = 0;
if (i < FFT_SIZE/2){
magni_fftoutbuff[i] = 0;
}
window[i] = ApplyWindow(1.0f, i,FFT_SIZE );
}
fft.Init();
bandSize = sample_rate/(FFT_SIZE*hop);
};
void SetFreq(int index, float frequency) {
osc[index].SetFreq(frequency);
};
void SetAmp(int index, float amplitude) {
osc[index].SetAmp(amplitude);
};
float SetAllWaveforms(int waveform) {
current_wave = 0;
float centre_of_position = 0.f;
switch(waveform) {
case 0:
current_wave = 0;
amp_attenuation = 1.f;
centre_of_position = 0.5f/9.f;
break;
case 1:
current_wave = 8;
amp_attenuation = 1.f;
centre_of_position = 1.5f/9.f;
break;
case 2:
current_wave = 1;
amp_attenuation = 0.9f;
centre_of_position = 2.5f/9.f;
break;
case 3:
current_wave = 5;
amp_attenuation = 0.9f;
centre_of_position = 3.5f/9.f;
break;
case 4:
current_wave = 7;
amp_attenuation = 0.35f;
centre_of_position = 4.5f/9.f;
break;
case 5:
current_wave = 2;
amp_attenuation = 0.40f;
centre_of_position = 5.5f/9.f;
break;
case 6:
current_wave = 3;
amp_attenuation = 0.45f;
centre_of_position = 6.5f/9.f;
break;
case 7:
current_wave = 6;
amp_attenuation = 0.45f;
centre_of_position = 7.5f/9.f;
break;
case 8:
current_wave = 4;
amp_attenuation = 0.4f;
centre_of_position = 8.5f/9.f;
break;
}
for (int i = 0; i< number_of_osc; i++) {
//the second time it actually changes the waveform, so the attack lut can avoid clicks
if (mark_to_change_waveform[i]) {
osc[i].SetWaveform(current_wave);
mark_to_change_waveform[i] = false;
}
//the first time it just marks the waveform to be changed
if (previous_wave != current_wave) {
mark_to_change_waveform[i] = true;
attack_step[i] = 0;
};
}
if (previous_wave != current_wave) {
previous_wave= current_wave;
}
return centre_of_position;
};
float Process() {
float output = 0;
for (int i = 0; i< spectra_max_num_frequencies; i++) {
output_mult = ((0.5 + 0.2/num_active) + prev_output_mult*47.f) /48.f;
output = output + osc[i].Process()* output_mult * attack_lut[attack_step[i]];
attack_step[i] = clamp(attack_step[i]+1, 0, 299);
prev_output_mult = output_mult;
};
return output;
}
size_t GetPasses() {
return num_of_passes;
}
void FillInputBuffer(float *in1,float *in2, size_t size) {
bandSize = global_sample_rate/(FFT_SIZE*hop);
size_t real_size = size / hop;
svfl.SetRes(0.1);
svfl.SetFreq(global_sample_rate/(2*hop));
svfr.SetRes(0.1);
svfr.SetFreq(bandSize*(32/hop));
//shift left the input array of "size" n of samples
for (size_t i = 0; i<FFT_LENGTH-real_size; i++) {
fftinbuff[i] = fftinbuff[i+real_size];
};
//add the samples to the input buffer
for (size_t i = 0; i<real_size; i++) {
float sum = 0.f;
for (size_t j = 0; j < hop; j++) {
float sample = (in1[i*hop + j] + in2[i*hop + j])*0.707;
svfl.Process(sample);
svfr.Process(svfl.Low());
sum = sum + svfr.High() / hop;
}
float sample = sum;
fftinbuff[i + FFT_SIZE - real_size] = sample;
};
for (size_t i = 0; i<FFT_SIZE; i++) {
window_fftinbuff[i] = window[i]*fftinbuff[i];
}
fft.Direct(window_fftinbuff, fftoutbuff);
}
void CalculateSpectralAnalisys() {
for (size_t i = 0; i<FFT_SIZE / 2; i++){
if (i<32/hop){
fftoutbuff[i] =fftoutbuff[i] * 0.5;
}
float real = fftoutbuff[i];
float imag = fftoutbuff[i+(FFT_SIZE / 2)];
magni_fftoutbuff[i] = sqrt(real*real+imag*imag);
}
const int N = sizeof(magni_fftoutbuff) / sizeof(float);
int num_frequencies = MAX_SPECTRA_FREQUENCIES;
float max_amp = 20.0f;
for(int i = 0; i < spectra_max_num_frequencies; i++) {
int a = std::distance(magni_fftoutbuff, std::max_element(magni_fftoutbuff, magni_fftoutbuff + (N/2)));
freq[i] = a*bandSize*spectra_oct_mult;
if (spectra_quantize >0) {
freq[i] = findClosest(CHRM_SCALE, spectra_selected_scale,128, ((int)freq[i]*1000), spectra_transpose) /1000.f;
};
max_amp = std::max(magni_fftoutbuff[a], max_amp) ;
magn[i] = ((magni_fftoutbuff[a]/max_amp)*(1-spectra_lower_harmonics) + spectra_lower_harmonics);
if (freq[i] > global_sample_rate / 2) {
freq[i] = 0.0f;
magn[i] = 0.0f;
}
RemoveNearestBands(a*bandSize, a);
}
for(int i = num_active; i < num_frequencies; i++) {
magn[i] = 0.f;
}
//rightRotate(magn,spectra_rotate_harmonics, num_active);
}
void RemoveNearestBands(float frequency, size_t start_band) {
magni_fftoutbuff[start_band] = 0.f;
float upper_frequency = mtof((int)((12.f*log2(frequency/440.f) + 69 + 1)));
for (size_t i = start_band; (((i*bandSize/spectra_spread)< upper_frequency) & (i<FFT_SIZE/2) & (-i>0)) ; i++) {
float mult = map((i*bandSize/spectra_spread),(1*bandSize/spectra_spread), upper_frequency, 0.0f, 1.0f);
magni_fftoutbuff[i] = magni_fftoutbuff[i] * mult;
magni_fftoutbuff[-i] = magni_fftoutbuff[-i] * mult;
}
}
float getFrequency(int value) {
return current_freq[value];
}
float getMagnitudo(int value) {
return current_magn[value];
}
void updateFreqAndMagn() {
for (int i = 0; i< spectra_max_num_frequencies; i++ ) {
float new_freq = (freq[i] + current_freq[i]*47)/48;
SetFreq(i,new_freq);
current_freq[i] = new_freq;
float new_magn = ((magn[i] + current_magn[i]*47)/48);
SetAmp(i,current_magn[i]*amp_attenuation);
current_magn[i] = new_magn;
}
}
void calculatedSuggestedHop() {
//if ((current_freq[0]/spectra_oct_mult) > 110) {
hop = 16;
//}
//if ((current_freq[0]) > 880) {
// hop = 8;
//}
//if ((current_freq[0]) > 1760) {
// hop = 4;
//}
}
void SetNumActive(int value) {
num_active = value;
};
};
class Averager {
float buffer[RMS_SIZE];
int cursor;
public:
Averager() {
Clear();
}
~Averager() {}
float ProcessRMS() {
float sum = 0.f;
for (int i =0; i< cursor; i++) {
sum = sum + buffer[i];
}
float result = sqrt(sum/cursor);
Clear();
return result;
}
void Clear() {
for (int i =0; i< RMS_SIZE; i++) {
buffer[i] = 0.f;
}
cursor = 0;
}
void Add(float sample){
buffer[cursor] = sample;
cursor++;
}
};
static Averager lofi_averager;
static Averager reverb_averager;
static Averager delay_averager;
static Averager resonator_averager;
static OscBank spectra_oscbank;
static Averager spectra_averager;
static LedsControl leds;
void SelectResonatorOctave(float knob_value_1){
//sets the octave shift
if (knob_value_1 < 0.2f){
resonator_octave = 1;
} else if (knob_value_1 < 0.4f){
resonator_octave = 2;
} else if (knob_value_1 < 0.6f){
resonator_octave = 4;
} else if (knob_value_1 < 0.8f){
resonator_octave = 8;
} else if (knob_value_1 > 0.8f){
resonator_octave = 16;
}
};
void SelectSpectraQuality(float knob_value_1){
//sets the octave shift
if (knob_value_1 < 0.25f){
spectra_oscbank.hop = 2;
} else if (knob_value_1 < 0.5f){
spectra_oscbank.hop = 4;
} else if (knob_value_1 < 0.75f){
spectra_oscbank.hop = 8;
} else if (knob_value_1 > 0.75f){
spectra_oscbank.hop = 16;
}
};
static void AudioCallback(float **in, float **out, size_t size)
{
float out1, out2, in1, in2;
Controls();
leds.UpdateLeds();
if ((mode == SPECTRA) or (mode == SPECTRINGS)) {
spectra_oscbank.FillInputBuffer(in[0],in[1] , size);
if (spectra_do_analisys) {
spectra_do_analisys = false;
spectra_oscbank.CalculateSpectralAnalisys();
}
if (mode == SPECTRINGS) {
string_voice[spectrings_current_voice].SetFreq(spectra_oscbank.getFrequency(spectrings_current_voice));
}
};
//audio
for(size_t i = 0; i < size; i += 1)
{
in1 = in[0][i];
in2 = in[1][i];
out1 = 0.f;
out2 = 0.f;
switch(mode)
{
case REV: GetReverbSample(out1, out2, in1, in2); break;
case RESONATOR: GetResonatorSample(out1, out2, in1, in2); break;
case LOFI:
GetReverbSample(out1, out2, in1, in2);
GetLofiSample(out1, out2, out1, out2);
break;
case MLOOPER: GetLooperSample(out1, out2, in1, in2); break;
case SPECTRA: GetSpectraSample(out1, out2, in1, in2);
GetReverbSample(out1, out2, out1, out2);
break;
case DELAY: GetDelaySample(out1, out2, in1, in2);
break;
case SPECTRINGS: GetSpectringsSample(out1, out2, in1, in2);
GetReverbSample(out1, out2, out1, out2);
break;
default: out1 = out2= 0.f;
}
out[0][i] = out1;
out[1][i] = out2;
}
if (mode == FILTER) {
GetFilterSamples(out[0],out[1], in[0], in[1], size);
}
};
//void UpdateOled();
int main(void)
{
float sample_rate;
//Inits and sample rate
versio.Init(true);
sample_rate = versio.AudioSampleRate();
rev.Init(sample_rate);
dell.Init();
delr.Init();
tonel.Init(sample_rate);
toner.Init(sample_rate);
svfl.Init(sample_rate);
svfl.SetFreq(0.0);
svfl.SetRes(0.5);
svfr.Init(sample_rate);
svfr.SetFreq(0.0);
svfr.SetRes(0.5);
svf2l.Init();
svf2r.Init();
biquad.Init(sample_rate);
biquad.SetCutoff(0.0);
biquad.SetRes(0.5);
//arm_rfft_fast_init_f32(&fft, FFT_SIZE);
global_sample_rate = sample_rate;
dcblock_l.Init(sample_rate);
dcblock_r.Init(sample_rate);
dcblock_2l.Init(sample_rate);
dcblock_2r.Init(sample_rate);
lofi_damp_speed = sample_rate;
lofi_target_Lofi_LFO_Freq = lofi_current_Lofi_LFO_Freq = sample_rate;
lofi_current_RMS = lofi_target_RMS = 0.f;
lofi_previous_left_saturation = lofi_previous_right_saturation = 0.5f;
lofi_current_left_saturation = lofi_current_right_saturation = 0.5f;
lofi_previous_variable_compressor = 0.0f;
//crusher_cutoff_par.Init(versio.knobs[DaisyVersio::KNOB_0], 60, 20000, crusher_cutoff_par.LOGARITHMIC);
//crusher_crushrate_par.Init(versio.knobs[DaisyVersio::KNOB_1], 1, 50, crusher_crushrate_par.LOGARITHMIC);
filter_cutoff_l_par.Init(versio.knobs[DaisyVersio::KNOB_0], 60, 20000, filter_cutoff_l_par.LOGARITHMIC);
filter_cutoff_r_par.Init(versio.knobs[DaisyVersio::KNOB_4], 60, 20000, filter_cutoff_r_par.LOGARITHMIC);
delay_cutoff_par.Init(versio.knobs[DaisyVersio::KNOB_1], 400, 20000, delay_cutoff_par.LOGARITHMIC);
delay_pos_l[0] = 0;
delay_pos_r[1] = 0;
delay_time[0] = -1;
delay_time[1] = -1;
delay_outl[0] = 0;
delay_outr[0] = 0;
delay_outl[1] = 0;
delay_outr[1] = 0;
delay_mult_l[0] = 1;
delay_mult_r[0] = 1;
delay_mult_l[1] = 1;
delay_mult_r[1] = 1;
lofi_tone_par.Init(versio.knobs[DaisyVersio::KNOB_2], 20, 20000, lofi_tone_par.LOGARITHMIC);
lofi_rate_par.Init(versio.knobs[DaisyVersio::KNOB_1], sample_rate*4, sample_rate/16, lofi_rate_par.LOGARITHMIC);
//reverb parameters
rev.SetLpFreq(9000.0f);
rev.SetFeedback(0.85f);
//delay parameters
resonator_current_delay = resonator_target = sample_rate * 0.75f;
dell.SetDelay(resonator_current_delay);
delr.SetDelay(resonator_current_delay);
for (size_t i = 0; i<300; i++) {
if (i<48) {
attack_lut[i] = map(i, 0, 48, 1.0f, 0.f);
}
else
{
attack_lut[i] = map(i, 48, 300, 0.0f, 1.f) ;
}
};
ResetLooperBuffer();
spectra_oscbank.Init(sample_rate);
for (int i = 0; i < NUM_OF_STRINGS; i++) {
string_voice[i].Init(sample_rate);
}
// start callback
versio.StartAdc();
versio.StartAudio(AudioCallback);
while(1) {
//UpdateOled();
}
}
float randomFloat() {
int randomNumber = std::rand() % 10000;
return randomNumber / 10000.f;