1 /* Calf DSP plugin pack
2 * Distortion related plugins
4 * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
23 #include <calf/giface.h>
24 #include <calf/modules_dist.h>
27 using namespace calf_plugins
;
29 #define SET_IF_CONNECTED(name) if (params[AM::param_##name] != NULL) *params[AM::param_##name] = name;
31 /**********************************************************************
32 * SATURATOR by Markus Schmidt
33 **********************************************************************/
35 saturator_audio_module::saturator_audio_module()
42 lp_post_freq_old
= -1;
43 hp_post_freq_old
= -1;
49 void saturator_audio_module::activate()
56 void saturator_audio_module::deactivate()
61 void saturator_audio_module::params_changed()
63 // set the params of all filters
64 if(*params
[param_lp_pre_freq
] != lp_pre_freq_old
) {
65 lp
[0][0].set_lp_rbj(*params
[param_lp_pre_freq
], 0.707, (float)srate
);
66 if(in_count
> 1 && out_count
> 1)
67 lp
[1][0].copy_coeffs(lp
[0][0]);
68 lp
[0][1].copy_coeffs(lp
[0][0]);
69 if(in_count
> 1 && out_count
> 1)
70 lp
[1][1].copy_coeffs(lp
[0][0]);
71 lp_pre_freq_old
= *params
[param_lp_pre_freq
];
73 if(*params
[param_hp_pre_freq
] != hp_pre_freq_old
) {
74 hp
[0][0].set_hp_rbj(*params
[param_hp_pre_freq
], 0.707, (float)srate
);
75 if(in_count
> 1 && out_count
> 1)
76 hp
[1][0].copy_coeffs(hp
[0][0]);
77 hp
[0][1].copy_coeffs(hp
[0][0]);
78 if(in_count
> 1 && out_count
> 1)
79 hp
[1][1].copy_coeffs(hp
[0][0]);
80 hp_pre_freq_old
= *params
[param_hp_pre_freq
];
82 if(*params
[param_lp_post_freq
] != lp_post_freq_old
) {
83 lp
[0][2].set_lp_rbj(*params
[param_lp_post_freq
], 0.707, (float)srate
);
84 if(in_count
> 1 && out_count
> 1)
85 lp
[1][2].copy_coeffs(lp
[0][2]);
86 lp
[0][3].copy_coeffs(lp
[0][2]);
87 if(in_count
> 1 && out_count
> 1)
88 lp
[1][3].copy_coeffs(lp
[0][2]);
89 lp_post_freq_old
= *params
[param_lp_post_freq
];
91 if(*params
[param_hp_post_freq
] != hp_post_freq_old
) {
92 hp
[0][2].set_hp_rbj(*params
[param_hp_post_freq
], 0.707, (float)srate
);
93 if(in_count
> 1 && out_count
> 1)
94 hp
[1][2].copy_coeffs(hp
[0][2]);
95 hp
[0][3].copy_coeffs(hp
[0][2]);
96 if(in_count
> 1 && out_count
> 1)
97 hp
[1][3].copy_coeffs(hp
[0][2]);
98 hp_post_freq_old
= *params
[param_hp_post_freq
];
100 if(*params
[param_p_freq
] != p_freq_old
or *params
[param_p_level
] != p_level_old
or *params
[param_p_q
] != p_q_old
) {
101 p
[0].set_peakeq_rbj((float)*params
[param_p_freq
], (float)*params
[param_p_q
], (float)*params
[param_p_level
], (float)srate
);
102 if(in_count
> 1 && out_count
> 1)
103 p
[1].copy_coeffs(p
[0]);
104 p_freq_old
= *params
[param_p_freq
];
105 p_level_old
= *params
[param_p_level
];
106 p_q_old
= *params
[param_p_q
];
109 dist
[0].set_params(*params
[param_blend
], *params
[param_drive
]);
110 if(in_count
> 1 && out_count
> 1)
111 dist
[1].set_params(*params
[param_blend
], *params
[param_drive
]);
114 void saturator_audio_module::set_sample_rate(uint32_t sr
)
117 dist
[0].set_sample_rate(sr
);
118 if(in_count
> 1 && out_count
> 1)
119 dist
[1].set_sample_rate(sr
);
120 int meter
[] = {param_meter_in
, param_meter_out
, param_meter_drive
};
121 int clip
[] = {param_clip_in
, param_clip_out
, -1};
122 meters
.init(params
, meter
, clip
, 3, srate
);
125 uint32_t saturator_audio_module::process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
)
127 bool bypassed
= bypass
.update(*params
[param_bypass
] > 0.5f
, numsamples
);
128 numsamples
+= offset
;
130 // everything bypassed
131 while(offset
< numsamples
) {
132 if(in_count
> 1 && out_count
> 1) {
133 outs
[0][offset
] = ins
[0][offset
];
134 outs
[1][offset
] = ins
[1][offset
];
135 } else if(in_count
> 1) {
136 outs
[0][offset
] = (ins
[0][offset
] + ins
[1][offset
]) / 2;
137 } else if(out_count
> 1) {
138 outs
[0][offset
] = ins
[0][offset
];
139 outs
[1][offset
] = ins
[0][offset
];
141 outs
[0][offset
] = ins
[0][offset
];
143 float values
[] = {0, 0, 0};
144 meters
.process(values
);
148 uint32_t orig_offset
= offset
;
150 while(offset
< numsamples
) {
151 // cycle through samples
152 float out
[2], in
[2] = {0.f
, 0.f
};
154 float maxDrive
= 0.f
;
155 if(in_count
> 1 && out_count
> 1) {
156 // stereo in/stereo out
157 // handle full stereo
158 in
[0] = ins
[0][offset
];
159 in
[1] = ins
[1][offset
];
162 // in and/or out mono
164 in
[0] = ins
[0][offset
];
170 proc
[0] = in
[0] * *params
[param_level_in
];
171 proc
[1] = in
[1] * *params
[param_level_in
];
173 float onedivlevelin
= 1.0 / *params
[param_level_in
];
175 for (int i
= 0; i
< c
; ++i
) {
176 // all pre filters in chain
177 proc
[i
] = lp
[i
][1].process(lp
[i
][0].process(proc
[i
]));
178 proc
[i
] = hp
[i
][1].process(hp
[i
][0].process(proc
[i
]));
181 proc
[i
] = dist
[i
].process(proc
[i
]);
184 proc
[i
] = p
[i
].process(proc
[i
]);
186 // all post filters in chain
187 proc
[i
] = lp
[i
][2].process(lp
[i
][3].process(proc
[i
]));
188 proc
[i
] = hp
[i
][2].process(hp
[i
][3].process(proc
[i
]));
191 proc
[i
] *= onedivlevelin
;
193 if (*params
[param_level_in
] > 1)
194 proc
[i
] *= 1 + (*params
[param_level_in
] - 1) / 32;
197 maxDrive
= dist
[0].get_distortion_level() * *params
[param_blend
];
199 if(in_count
> 1 && out_count
> 1) {
200 maxDrive
= dist
[1].get_distortion_level() * *params
[param_blend
];
202 out
[0] = ((proc
[0] * *params
[param_mix
]) + in
[0] * (1 - *params
[param_mix
])) * *params
[param_level_out
];
203 outs
[0][offset
] = out
[0];
204 out
[1] = ((proc
[1] * *params
[param_mix
]) + in
[1] * (1 - *params
[param_mix
])) * *params
[param_level_out
];
205 outs
[1][offset
] = out
[1];
206 } else if(out_count
> 1) {
207 // mono -> pseudo stereo
208 out
[0] = ((proc
[0] * *params
[param_mix
]) + in
[0] * (1 - *params
[param_mix
])) * *params
[param_level_out
];
209 outs
[0][offset
] = out
[0];
211 outs
[1][offset
] = out
[1];
215 out
[0] = ((proc
[0] * *params
[param_mix
]) + in
[0] * (1 - *params
[param_mix
])) * *params
[param_level_out
];
216 outs
[0][offset
] = out
[0];
218 float values
[] = {(in
[0] + in
[1]) / 2, (out
[0] + out
[1]) / 2, maxDrive
/ 20};
219 meters
.process(values
);
223 } // cycle trough samples
244 bypass
.crossfade(ins
, outs
, 2, orig_offset
, numsamples
);
246 meters
.fall(numsamples
);
250 /**********************************************************************
251 * EXCITER by Markus Schmidt
252 **********************************************************************/
254 exciter_audio_module::exciter_audio_module()
258 ceil_active_old
= false;
264 void exciter_audio_module::activate()
271 void exciter_audio_module::deactivate()
276 void exciter_audio_module::params_changed()
278 // set the params of all filters
279 if(*params
[param_freq
] != freq_old
) {
280 hp
[0][0].set_hp_rbj(*params
[param_freq
], 0.707, (float)srate
);
281 hp
[0][1].copy_coeffs(hp
[0][0]);
282 hp
[0][2].copy_coeffs(hp
[0][0]);
283 hp
[0][3].copy_coeffs(hp
[0][0]);
284 if(in_count
> 1 && out_count
> 1) {
285 hp
[1][0].copy_coeffs(hp
[0][0]);
286 hp
[1][1].copy_coeffs(hp
[0][0]);
287 hp
[1][2].copy_coeffs(hp
[0][0]);
288 hp
[1][3].copy_coeffs(hp
[0][0]);
290 freq_old
= *params
[param_freq
];
292 // set the params of all filters
293 if(*params
[param_ceil
] != ceil_old
or *params
[param_ceil_active
] != ceil_active_old
) {
294 lp
[0][0].set_lp_rbj(*params
[param_ceil
], 0.707, (float)srate
);
295 lp
[0][1].copy_coeffs(lp
[0][0]);
296 lp
[1][0].copy_coeffs(lp
[0][0]);
297 lp
[1][1].copy_coeffs(lp
[0][0]);
298 ceil_old
= *params
[param_ceil
];
299 ceil_active_old
= *params
[param_ceil_active
];
302 dist
[0].set_params(*params
[param_blend
], *params
[param_drive
]);
303 if(in_count
> 1 && out_count
> 1)
304 dist
[1].set_params(*params
[param_blend
], *params
[param_drive
]);
307 void exciter_audio_module::set_sample_rate(uint32_t sr
)
310 dist
[0].set_sample_rate(sr
);
311 if(in_count
> 1 && out_count
> 1)
312 dist
[1].set_sample_rate(sr
);
313 int meter
[] = {param_meter_in
, param_meter_out
, param_meter_drive
};
314 int clip
[] = {param_clip_in
, param_clip_out
, -1};
315 meters
.init(params
, meter
, clip
, 3, srate
);
318 uint32_t exciter_audio_module::process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
)
320 bool bypass
= *params
[param_bypass
] > 0.5f
;
321 numsamples
+= offset
;
323 // everything bypassed
324 while(offset
< numsamples
) {
325 if(in_count
> 1 && out_count
> 1) {
326 outs
[0][offset
] = ins
[0][offset
];
327 outs
[1][offset
] = ins
[1][offset
];
328 } else if(in_count
> 1) {
329 outs
[0][offset
] = (ins
[0][offset
] + ins
[1][offset
]) / 2;
330 } else if(out_count
> 1) {
331 outs
[0][offset
] = ins
[0][offset
];
332 outs
[1][offset
] = ins
[0][offset
];
334 outs
[0][offset
] = ins
[0][offset
];
336 float values
[] = {0, 0, 0, 0, 0};
337 meters
.process(values
);
346 float in2out
= *params
[param_listen
] > 0.f
? 0.f
: 1.f
;
349 while(offset
< numsamples
) {
350 // cycle through samples
351 float out
[2], in
[2] = {0.f
, 0.f
};
352 float maxDrive
= 0.f
;
355 if(in_count
> 1 && out_count
> 1) {
356 // stereo in/stereo out
357 // handle full stereo
358 in
[0] = ins
[0][offset
];
359 in
[0] *= *params
[param_level_in
];
360 in
[1] = ins
[1][offset
];
361 in
[1] *= *params
[param_level_in
];
364 // in and/or out mono
366 in
[0] = ins
[0][offset
];
367 in
[0] *= *params
[param_level_in
];
376 for (int i
= 0; i
< c
; ++i
) {
377 // all pre filters in chain
378 proc
[i
] = hp
[i
][1].process(hp
[i
][0].process(proc
[i
]));
381 proc
[i
] = dist
[i
].process(proc
[i
]);
383 // all post filters in chain
384 proc
[i
] = hp
[i
][2].process(hp
[i
][3].process(proc
[i
]));
386 if(*params
[param_ceil_active
] > 0.5f
) {
387 // all H/P post filters in chain
388 proc
[i
] = lp
[i
][0].process(lp
[i
][1].process(proc
[i
]));
392 maxDrive
= dist
[0].get_distortion_level() * *params
[param_amount
];
394 if(in_count
> 1 && out_count
> 1) {
395 maxDrive
= std::max(maxDrive
, dist
[1].get_distortion_level() * *params
[param_amount
]);
397 out
[0] = (proc
[0] * *params
[param_amount
] + in2out
* in
[0]) * *params
[param_level_out
];
398 out
[1] = (proc
[1] * *params
[param_amount
] + in2out
* in
[1]) * *params
[param_level_out
];
399 outs
[0][offset
] = out
[0];
400 outs
[1][offset
] = out
[1];
401 } else if(out_count
> 1) {
402 // mono -> pseudo stereo
403 out
[1] = out
[0] = (proc
[0] * *params
[param_amount
] + in2out
* in
[0]) * *params
[param_level_out
];
404 outs
[0][offset
] = out
[0];
405 outs
[1][offset
] = out
[1];
409 out
[0] = (proc
[0] * *params
[param_amount
] + in2out
* in
[0]) * *params
[param_level_out
];
410 outs
[0][offset
] = out
[0];
412 float values
[] = {(in
[0] + in
[1]) / 2, (out
[0] + out
[1]) / 2, maxDrive
};
413 meters
.process(values
);
416 } // cycle trough samples
432 meters
.fall(numsamples
);
436 /**********************************************************************
437 * BASS ENHANCER by Markus Schmidt
438 **********************************************************************/
440 bassenhancer_audio_module::bassenhancer_audio_module()
444 floor_active_old
= false;
450 void bassenhancer_audio_module::activate()
456 void bassenhancer_audio_module::deactivate()
461 void bassenhancer_audio_module::params_changed()
463 // set the params of all filters
464 if(*params
[param_freq
] != freq_old
) {
465 lp
[0][0].set_lp_rbj(*params
[param_freq
], 0.707, (float)srate
);
466 lp
[0][1].copy_coeffs(lp
[0][0]);
467 lp
[0][2].copy_coeffs(lp
[0][0]);
468 lp
[0][3].copy_coeffs(lp
[0][0]);
469 if(in_count
> 1 && out_count
> 1) {
470 lp
[1][0].copy_coeffs(lp
[0][0]);
471 lp
[1][1].copy_coeffs(lp
[0][0]);
472 lp
[1][2].copy_coeffs(lp
[0][0]);
473 lp
[1][3].copy_coeffs(lp
[0][0]);
475 freq_old
= *params
[param_freq
];
477 // set the params of all filters
478 if(*params
[param_floor
] != floor_old
or *params
[param_floor_active
] != floor_active_old
) {
479 hp
[0][0].set_hp_rbj(*params
[param_floor
], 0.707, (float)srate
);
480 hp
[0][1].copy_coeffs(hp
[0][0]);
481 hp
[1][0].copy_coeffs(hp
[0][0]);
482 hp
[1][1].copy_coeffs(hp
[0][0]);
483 floor_old
= *params
[param_floor
];
484 floor_active_old
= *params
[param_floor_active
];
487 dist
[0].set_params(*params
[param_blend
], *params
[param_drive
]);
488 if(in_count
> 1 && out_count
> 1)
489 dist
[1].set_params(*params
[param_blend
], *params
[param_drive
]);
492 void bassenhancer_audio_module::set_sample_rate(uint32_t sr
)
495 dist
[0].set_sample_rate(sr
);
496 if(in_count
> 1 && out_count
> 1)
497 dist
[1].set_sample_rate(sr
);
498 int meter
[] = {param_meter_in
, param_meter_out
, param_meter_drive
};
499 int clip
[] = {param_clip_in
, param_clip_out
, -1};
500 meters
.init(params
, meter
, clip
, 3, srate
);
503 uint32_t bassenhancer_audio_module::process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
)
505 bool bypass
= *params
[param_bypass
] > 0.5f
;
506 numsamples
+= offset
;
508 // everything bypassed
509 while(offset
< numsamples
) {
510 if(in_count
> 1 && out_count
> 1) {
511 outs
[0][offset
] = ins
[0][offset
];
512 outs
[1][offset
] = ins
[1][offset
];
513 } else if(in_count
> 1) {
514 outs
[0][offset
] = (ins
[0][offset
] + ins
[1][offset
]) / 2;
515 } else if(out_count
> 1) {
516 outs
[0][offset
] = ins
[0][offset
];
517 outs
[1][offset
] = ins
[0][offset
];
519 outs
[0][offset
] = ins
[0][offset
];
521 float values
[] = {0, 0, 0};
522 meters
.process(values
);
527 while(offset
< numsamples
) {
528 // cycle through samples
529 float out
[2], in
[2] = {0.f
, 0.f
};
530 float maxDrive
= 0.f
;
533 if(in_count
> 1 && out_count
> 1) {
534 // stereo in/stereo out
535 // handle full stereo
536 in
[0] = ins
[0][offset
];
537 in
[0] *= *params
[param_level_in
];
538 in
[1] = ins
[1][offset
];
539 in
[1] *= *params
[param_level_in
];
542 // in and/or out mono
544 in
[0] = ins
[0][offset
];
545 in
[0] *= *params
[param_level_in
];
554 for (int i
= 0; i
< c
; ++i
) {
555 // all pre filters in chain
556 proc
[i
] = lp
[i
][1].process(lp
[i
][0].process(proc
[i
]));
559 proc
[i
] = dist
[i
].process(proc
[i
]);
561 // all post filters in chain
562 proc
[i
] = lp
[i
][2].process(lp
[i
][3].process(proc
[i
]));
564 if(*params
[param_floor_active
] > 0.5f
) {
565 // all H/P post filters in chain
566 proc
[i
] = hp
[i
][0].process(hp
[i
][1].process(proc
[i
]));
571 if(in_count
> 1 && out_count
> 1) {
573 if(*params
[param_listen
] > 0.f
)
574 out
[0] = proc
[0] * *params
[param_amount
] * *params
[param_level_out
];
576 out
[0] = (proc
[0] * *params
[param_amount
] + in
[0]) * *params
[param_level_out
];
577 outs
[0][offset
] = out
[0];
578 if(*params
[param_listen
] > 0.f
)
579 out
[1] = proc
[1] * *params
[param_amount
] * *params
[param_level_out
];
581 out
[1] = (proc
[1] * *params
[param_amount
] + in
[1]) * *params
[param_level_out
];
582 outs
[1][offset
] = out
[1];
583 maxDrive
= std::max(dist
[0].get_distortion_level() * *params
[param_amount
],
584 dist
[1].get_distortion_level() * *params
[param_amount
]);
585 } else if(out_count
> 1) {
586 // mono -> pseudo stereo
587 if(*params
[param_listen
] > 0.f
)
588 out
[0] = proc
[0] * *params
[param_amount
] * *params
[param_level_out
];
590 out
[0] = (proc
[0] * *params
[param_amount
] + in
[0]) * *params
[param_level_out
];
591 outs
[0][offset
] = out
[0];
593 outs
[1][offset
] = out
[1];
594 maxDrive
= dist
[0].get_distortion_level() * *params
[param_amount
];
598 if(*params
[param_listen
] > 0.f
)
599 out
[0] = proc
[0] * *params
[param_amount
] * *params
[param_level_out
];
601 out
[0] = (proc
[0] * *params
[param_amount
] + in
[0]) * *params
[param_level_out
];
602 outs
[0][offset
] = out
[0];
603 maxDrive
= dist
[0].get_distortion_level() * *params
[param_amount
];
606 float values
[] = {(in
[0] + in
[1]) / 2, (out
[0] + out
[1]) / 2, maxDrive
};
607 meters
.process(values
);
610 } // cycle trough samples
625 meters
.fall(numsamples
);
629 /**********************************************************************
630 * TAPESIMULATOR by Markus Schmidt
631 **********************************************************************/
633 tapesimulator_audio_module::tapesimulator_audio_module() {
646 transients
.set_channels(channels
);
649 void tapesimulator_audio_module::activate() {
653 void tapesimulator_audio_module::deactivate() {
657 void tapesimulator_audio_module::params_changed() {
658 if(*params
[param_lp
] != lp_old
or *params
[param_mechanical
] != mech_old
) {
659 lp
[0][0].set_lp_rbj(*params
[param_lp
], 0.707, (float)srate
);
660 lp
[0][1].copy_coeffs(lp
[0][0]);
661 lp
[1][0].copy_coeffs(lp
[0][0]);
662 lp
[1][1].copy_coeffs(lp
[0][0]);
663 lp_old
= *params
[param_lp
];
664 mech_old
= *params
[param_mechanical
] > 0.5;
666 transients
.set_params(50.f
/ (*params
[param_speed
] + 1),
667 -0.05f
/ (*params
[param_speed
] + 1),
673 lfo1
.set_params((*params
[param_speed
] + 1) / 2, 0, 0.f
, srate
, 1.f
);
674 lfo2
.set_params((*params
[param_speed
] + 1) / 9.38, 0, 0.f
, srate
, 1.f
);
677 uint32_t tapesimulator_audio_module::process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
) {
678 for(uint32_t i
= offset
; i
< offset
+ numsamples
; i
++) {
681 float Lin
= ins
[0][i
];
682 float Rin
= ins
[1][i
];
683 if(*params
[param_bypass
] > 0.5) {
684 outs
[0][i
] = ins
[0][i
];
685 outs
[1][i
] = ins
[1][i
];
695 // let meters fall a bit
696 clip_inL
-= std::min(clip_inL
, numsamples
);
697 clip_inR
-= std::min(clip_inR
, numsamples
);
698 clip_outL
-= std::min(clip_outL
, numsamples
);
699 clip_outR
-= std::min(clip_outR
, numsamples
);
706 if(L
> meter_inL
) meter_inL
= L
;
707 if(R
> meter_inR
) meter_inR
= R
;
708 if(L
> 1.f
) clip_inL
= srate
>> 3;
709 if(R
> 1.f
) clip_inR
= srate
>> 3;
712 if(*params
[param_magnetical
] > 0.5f
) {
713 float values
[] = {L
, R
};
714 transients
.process(values
);
720 if (*params
[param_noise
]) {
721 float Lnoise
= rand() % 2 - 1;
722 float Rnoise
= rand() % 2 - 1;
723 Lnoise
= noisefilters
[0][2].process(noisefilters
[0][1].process(noisefilters
[0][0].process(Lnoise
)));
724 Rnoise
= noisefilters
[1][2].process(noisefilters
[1][1].process(noisefilters
[1][0].process(Rnoise
)));
725 L
+= Lnoise
* *params
[param_noise
] / 12.f
;
726 R
+= Rnoise
* *params
[param_noise
] / 12.f
;
729 // lfo filters / phasing
730 if (*params
[param_mechanical
]) {
732 float freqL1
= *params
[param_lp
] * (1 - ((lfo1
.get_value() + 1) * 0.3 * *params
[param_mechanical
]));
733 float freqL2
= *params
[param_lp
] * (1 - ((lfo2
.get_value() + 1) * 0.2 * *params
[param_mechanical
]));
735 float freqR1
= *params
[param_lp
] * (1 - ((lfo1
.get_value() * -1 + 1) * 0.3 * *params
[param_mechanical
]));
736 float freqR2
= *params
[param_lp
] * (1 - ((lfo2
.get_value() * -1 + 1) * 0.2 * *params
[param_mechanical
]));
738 lp
[0][0].set_lp_rbj(freqL1
, 0.707, (float)srate
);
739 lp
[0][1].set_lp_rbj(freqL2
, 0.707, (float)srate
);
741 lp
[1][0].set_lp_rbj(freqR1
, 0.707, (float)srate
);
742 lp
[1][1].set_lp_rbj(freqR2
, 0.707, (float)srate
);
745 float _phase
= lfo1
.get_value() * *params
[param_mechanical
] * -36;
747 float _phase_cos_coef
= cos(_phase
/ 180 * M_PI
);
748 float _phase_sin_coef
= sin(_phase
/ 180 * M_PI
);
750 float _l
= L
* _phase_cos_coef
- R
* _phase_sin_coef
;
751 float _r
= L
* _phase_sin_coef
+ R
* _phase_cos_coef
;
757 L
*= *params
[param_level_in
];
758 R
*= *params
[param_level_in
];
760 // save for drawing input/output curve
767 if (*params
[param_post
] < 0.5) {
768 L
= lp
[0][1].process(lp
[0][0].process(L
));
769 R
= lp
[1][1].process(lp
[1][0].process(R
));
773 if (L
) L
= L
/ fabs(L
) * (1 - exp((-1) * 3 * fabs(L
)));
774 if (R
) R
= R
/ fabs(R
) * (1 - exp((-1) * 3 * fabs(R
)));
776 if (Lo
) Lo
= Lo
/ fabs(Lo
) * (1 - exp((-1) * 3 * fabs(Lo
)));
777 if (Ro
) Ro
= Ro
/ fabs(Ro
) * (1 - exp((-1) * 3 * fabs(Ro
)));
780 if (*params
[param_post
] >= 0.5) {
781 L
= lp
[0][1].process(lp
[0][0].process(L
));
782 R
= lp
[1][1].process(lp
[1][0].process(R
));
786 L
= L
* *params
[param_mix
] + Lin
* (*params
[param_mix
] * -1 + 1);
787 R
= R
* *params
[param_mix
] + Rin
* (*params
[param_mix
] * -1 + 1);
790 L
*= *params
[param_level_out
];
791 R
*= *params
[param_level_out
];
798 if(L
> 1.f
) clip_outL
= srate
>> 3;
799 if(R
> 1.f
) clip_outR
= srate
>> 3;
800 if(L
> meter_outL
) meter_outL
= L
;
801 if(R
> meter_outR
) meter_outR
= R
;
809 // LFO's should go on
813 float s
= (fabs(Lo
) + fabs(Ro
)) / 2;
817 float in
= (fabs(Lc
) + fabs(Rc
)) / 2;
824 SET_IF_CONNECTED(clip_inL
);
825 SET_IF_CONNECTED(clip_inR
);
826 SET_IF_CONNECTED(clip_outL
);
827 SET_IF_CONNECTED(clip_outR
);
828 SET_IF_CONNECTED(meter_inL
);
829 SET_IF_CONNECTED(meter_inR
);
830 SET_IF_CONNECTED(meter_outL
);
831 SET_IF_CONNECTED(meter_outR
);
835 void tapesimulator_audio_module::set_sample_rate(uint32_t sr
)
838 transients
.set_sample_rate(srate
);
839 noisefilters
[0][0].set_hp_rbj(120.f
, 0.707, (float)srate
);
840 noisefilters
[1][0].copy_coeffs(noisefilters
[0][0]);
841 noisefilters
[0][1].set_lp_rbj(5500.f
, 0.707, (float)srate
);
842 noisefilters
[1][1].copy_coeffs(noisefilters
[0][1]);
843 noisefilters
[0][2].set_highshelf_rbj(1000.f
, 0.707, 0.5, (float)srate
);
844 noisefilters
[1][2].copy_coeffs(noisefilters
[0][2]);
847 bool tapesimulator_audio_module::get_graph(int index
, int subindex
, int phase
, float *data
, int points
, cairo_iface
*context
, int *mode
) const
851 if(index
== param_lp
and phase
) {
852 set_channel_color(context
, subindex
);
853 return ::get_graph(*this, subindex
, data
, points
);
854 } else if (index
== param_level_in
and !phase
) {
856 context
->set_source_rgba(0.15, 0.2, 0.0, 0.3);
857 context
->set_line_width(1);
859 for (int i
= 0; i
< points
; i
++) {
861 float input
= dB_grid_inv(-1.0 + (float)i
* 2.0 / ((float)points
- 1.f
));
862 data
[i
] = dB_grid(input
);
864 float output
= 1 - exp(-3 * (pow(2, -10 + 14 * (float)i
/ (float) points
)));
865 data
[i
] = dB_grid(output
* *params
[param_level_out
]);
872 float tapesimulator_audio_module::freq_gain(int index
, double freq
) const
874 return lp
[index
][0].freq_gain(freq
, srate
) * lp
[index
][1].freq_gain(freq
, srate
);
877 bool tapesimulator_audio_module::get_gridline(int index
, int subindex
, int phase
, float &pos
, bool &vertical
, std::string
&legend
, cairo_iface
*context
) const
881 if (index
== param_level_in
) {
883 vertical
= (subindex
& 1) != 0;
884 bool result
= get_freq_gridline(subindex
>> 1, pos
, tmp
, legend
, context
, false);
885 if (result
&& vertical
) {
886 if ((subindex
& 4) && !legend
.empty()) {
890 size_t pos
= legend
.find(" dB");
891 if (pos
!= std::string::npos
)
894 pos
= 0.5 + 0.5 * pos
;
897 } else if (index
== param_lp
) {
898 return get_freq_gridline(subindex
, pos
, vertical
, legend
, context
);
902 bool tapesimulator_audio_module::get_dot(int index
, int subindex
, int phase
, float &x
, float &y
, int &size
, cairo_iface
*context
) const
904 if (index
== param_level_in
and !subindex
and phase
) {
905 x
= log(input
) / log(2) / 14.f
+ 5.f
/ 7.f
;
913 bool tapesimulator_audio_module::get_layers(int index
, int generation
, unsigned int &layers
) const
916 // always draw grid on cache if surfaces are new on both widgets
918 layers
|= LG_CACHE_GRID
;
919 // compression: dot in realtime, graphs as cache on new surfaces
920 if (index
== param_level_in
and !generation
)
921 layers
|= LG_CACHE_GRAPH
;
922 if (index
== param_level_in
)
923 layers
|= LG_REALTIME_DOT
;
924 // frequency: both graphs in realtime
925 if (index
== param_lp
)
926 layers
|= LG_REALTIME_GRAPH
;
933 /**********************************************************************
934 * CRUSHER by Markus Schmidt and Christian Holschuh
935 **********************************************************************/
938 crusher_audio_module::crusher_audio_module()
943 void crusher_audio_module::activate()
947 void crusher_audio_module::deactivate()
952 void crusher_audio_module::params_changed()
954 bitreduction
.set_params(*params
[param_bits
],
955 *params
[param_morph
],
956 *params
[param_bypass
] > 0.5,
960 samplereduction
[0].set_params(*params
[param_samples
]);
961 samplereduction
[1].set_params(*params
[param_samples
]);
962 lfo
.set_params(*params
[param_lforate
], 0, 0.f
, srate
, 0.5f
);
964 float rad
= *params
[param_lforange
] / 2.f
;
965 smin
= std::max(*params
[param_samples
] - rad
, 1.f
);
966 float sun
= *params
[param_samples
] - rad
- smin
;
967 float smax
= std::min(*params
[param_samples
] + rad
, 250.f
);
968 float sov
= *params
[param_samples
] + rad
- smax
;
974 void crusher_audio_module::set_sample_rate(uint32_t sr
)
977 int meter
[] = {param_meter_inL
, param_meter_inR
, param_meter_outL
, param_meter_outR
};
978 int clip
[] = {param_clip_inL
, param_clip_inR
, param_clip_outL
, param_clip_outR
};
979 meters
.init(params
, meter
, clip
, 4, srate
);
980 bitreduction
.set_sample_rate(srate
);
983 uint32_t crusher_audio_module::process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
)
985 bool bypass
= *params
[param_bypass
] > 0.5f
;
986 numsamples
+= offset
;
988 // everything bypassed
989 while(offset
< numsamples
) {
990 outs
[0][offset
] = ins
[0][offset
];
991 outs
[1][offset
] = ins
[1][offset
];
992 float values
[] = {0, 0, 0, 0};
993 meters
.process(values
);
998 while(offset
< numsamples
) {
999 // cycle through samples
1000 if (*params
[param_lfo
] > 0.5) {
1001 samplereduction
[0].set_params(smin
+ sdiff
* (lfo
.get_value() + 0.5));
1002 samplereduction
[1].set_params(smin
+ sdiff
* (lfo
.get_value() + 0.5));
1004 outs
[0][offset
] = samplereduction
[0].process(ins
[0][offset
] * *params
[param_level_in
]);
1005 outs
[1][offset
] = samplereduction
[1].process(ins
[1][offset
] * *params
[param_level_in
]);
1006 outs
[0][offset
] = outs
[0][offset
] * *params
[param_morph
] + ins
[0][offset
] * (*params
[param_morph
] * -1 + 1) * *params
[param_level_in
];
1007 outs
[1][offset
] = outs
[1][offset
] * *params
[param_morph
] + ins
[1][offset
] * (*params
[param_morph
] * -1 + 1) * *params
[param_level_in
];
1008 outs
[0][offset
] = bitreduction
.process(outs
[0][offset
]) * *params
[param_level_out
];
1009 outs
[1][offset
] = bitreduction
.process(outs
[1][offset
]) * *params
[param_level_out
];
1010 float values
[] = {ins
[0][offset
], ins
[1][offset
], outs
[0][offset
], outs
[1][offset
]};
1011 meters
.process(values
);
1014 if (*params
[param_lforate
])
1016 } // cycle trough samples
1018 meters
.fall(numsamples
);
1019 return outputs_mask
;
1021 bool crusher_audio_module::get_graph(int index
, int subindex
, int phase
, float *data
, int points
, cairo_iface
*context
, int *mode
) const
1023 return bitreduction
.get_graph(subindex
, phase
, data
, points
, context
, mode
);
1025 bool crusher_audio_module::get_layers(int index
, int generation
, unsigned int &layers
) const
1027 return bitreduction
.get_layers(index
, generation
, layers
);
1029 bool crusher_audio_module::get_gridline(int index
, int subindex
, int phase
, float &pos
, bool &vertical
, std::string
&legend
, cairo_iface
*context
) const
1031 return bitreduction
.get_gridline(subindex
, phase
, pos
, vertical
, legend
, context
);