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 bypass
= *params
[param_bypass
] > 0.5f
;
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
);
149 while(offset
< numsamples
) {
150 // cycle through samples
151 float out
[2], in
[2] = {0.f
, 0.f
};
153 float maxDrive
= 0.f
;
154 if(in_count
> 1 && out_count
> 1) {
155 // stereo in/stereo out
156 // handle full stereo
157 in
[0] = ins
[0][offset
];
158 in
[1] = ins
[1][offset
];
161 // in and/or out mono
163 in
[0] = ins
[0][offset
];
169 proc
[0] = in
[0] * *params
[param_level_in
];
170 proc
[1] = in
[1] * *params
[param_level_in
];
172 float onedivlevelin
= 1.0 / *params
[param_level_in
];
174 for (int i
= 0; i
< c
; ++i
) {
175 // all pre filters in chain
176 proc
[i
] = lp
[i
][1].process(lp
[i
][0].process(proc
[i
]));
177 proc
[i
] = hp
[i
][1].process(hp
[i
][0].process(proc
[i
]));
180 proc
[i
] = dist
[i
].process(proc
[i
]);
183 proc
[i
] = p
[i
].process(proc
[i
]);
185 // all post filters in chain
186 proc
[i
] = lp
[i
][2].process(lp
[i
][3].process(proc
[i
]));
187 proc
[i
] = hp
[i
][2].process(hp
[i
][3].process(proc
[i
]));
190 proc
[i
] *= onedivlevelin
;
192 if (*params
[param_level_in
] > 1)
193 proc
[i
] *= 1 + (*params
[param_level_in
] - 1) / 32;
196 maxDrive
= dist
[0].get_distortion_level() * *params
[param_blend
];
198 if(in_count
> 1 && out_count
> 1) {
199 maxDrive
= dist
[1].get_distortion_level() * *params
[param_blend
];
201 out
[0] = ((proc
[0] * *params
[param_mix
]) + in
[0] * (1 - *params
[param_mix
])) * *params
[param_level_out
];
202 outs
[0][offset
] = out
[0];
203 out
[1] = ((proc
[1] * *params
[param_mix
]) + in
[1] * (1 - *params
[param_mix
])) * *params
[param_level_out
];
204 outs
[1][offset
] = out
[1];
205 } else if(out_count
> 1) {
206 // mono -> pseudo stereo
207 out
[0] = ((proc
[0] * *params
[param_mix
]) + in
[0] * (1 - *params
[param_mix
])) * *params
[param_level_out
];
208 outs
[0][offset
] = out
[0];
210 outs
[1][offset
] = out
[1];
214 out
[0] = ((proc
[0] * *params
[param_mix
]) + in
[0] * (1 - *params
[param_mix
])) * *params
[param_level_out
];
215 outs
[0][offset
] = out
[0];
217 float values
[] = {(in
[0] + in
[1]) / 2, (out
[0] + out
[1]) / 2, maxDrive
/ 20};
218 meters
.process(values
);
222 } // cycle trough samples
244 meters
.fall(numsamples
);
248 /**********************************************************************
249 * EXCITER by Markus Schmidt
250 **********************************************************************/
252 exciter_audio_module::exciter_audio_module()
256 ceil_active_old
= false;
262 void exciter_audio_module::activate()
269 void exciter_audio_module::deactivate()
274 void exciter_audio_module::params_changed()
276 // set the params of all filters
277 if(*params
[param_freq
] != freq_old
) {
278 hp
[0][0].set_hp_rbj(*params
[param_freq
], 0.707, (float)srate
);
279 hp
[0][1].copy_coeffs(hp
[0][0]);
280 hp
[0][2].copy_coeffs(hp
[0][0]);
281 hp
[0][3].copy_coeffs(hp
[0][0]);
282 if(in_count
> 1 && out_count
> 1) {
283 hp
[1][0].copy_coeffs(hp
[0][0]);
284 hp
[1][1].copy_coeffs(hp
[0][0]);
285 hp
[1][2].copy_coeffs(hp
[0][0]);
286 hp
[1][3].copy_coeffs(hp
[0][0]);
288 freq_old
= *params
[param_freq
];
290 // set the params of all filters
291 if(*params
[param_ceil
] != ceil_old
or *params
[param_ceil_active
] != ceil_active_old
) {
292 lp
[0][0].set_lp_rbj(*params
[param_ceil
], 0.707, (float)srate
);
293 lp
[0][1].copy_coeffs(lp
[0][0]);
294 lp
[1][0].copy_coeffs(lp
[0][0]);
295 lp
[1][1].copy_coeffs(lp
[0][0]);
296 ceil_old
= *params
[param_ceil
];
297 ceil_active_old
= *params
[param_ceil_active
];
300 dist
[0].set_params(*params
[param_blend
], *params
[param_drive
]);
301 if(in_count
> 1 && out_count
> 1)
302 dist
[1].set_params(*params
[param_blend
], *params
[param_drive
]);
305 void exciter_audio_module::set_sample_rate(uint32_t sr
)
308 dist
[0].set_sample_rate(sr
);
309 if(in_count
> 1 && out_count
> 1)
310 dist
[1].set_sample_rate(sr
);
311 int meter
[] = {param_meter_in
, param_meter_out
, param_meter_drive
};
312 int clip
[] = {param_clip_in
, param_clip_out
, -1};
313 meters
.init(params
, meter
, clip
, 3, srate
);
316 uint32_t exciter_audio_module::process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
)
318 bool bypass
= *params
[param_bypass
] > 0.5f
;
319 numsamples
+= offset
;
321 // everything bypassed
322 while(offset
< numsamples
) {
323 if(in_count
> 1 && out_count
> 1) {
324 outs
[0][offset
] = ins
[0][offset
];
325 outs
[1][offset
] = ins
[1][offset
];
326 } else if(in_count
> 1) {
327 outs
[0][offset
] = (ins
[0][offset
] + ins
[1][offset
]) / 2;
328 } else if(out_count
> 1) {
329 outs
[0][offset
] = ins
[0][offset
];
330 outs
[1][offset
] = ins
[0][offset
];
332 outs
[0][offset
] = ins
[0][offset
];
334 float values
[] = {0, 0, 0, 0, 0};
335 meters
.process(values
);
344 float in2out
= *params
[param_listen
] > 0.f
? 0.f
: 1.f
;
347 while(offset
< numsamples
) {
348 // cycle through samples
349 float out
[2], in
[2] = {0.f
, 0.f
};
350 float maxDrive
= 0.f
;
353 if(in_count
> 1 && out_count
> 1) {
354 // stereo in/stereo out
355 // handle full stereo
356 in
[0] = ins
[0][offset
];
357 in
[0] *= *params
[param_level_in
];
358 in
[1] = ins
[1][offset
];
359 in
[1] *= *params
[param_level_in
];
362 // in and/or out mono
364 in
[0] = ins
[0][offset
];
365 in
[0] *= *params
[param_level_in
];
374 for (int i
= 0; i
< c
; ++i
) {
375 // all pre filters in chain
376 proc
[i
] = hp
[i
][1].process(hp
[i
][0].process(proc
[i
]));
379 proc
[i
] = dist
[i
].process(proc
[i
]);
381 // all post filters in chain
382 proc
[i
] = hp
[i
][2].process(hp
[i
][3].process(proc
[i
]));
384 if(*params
[param_ceil_active
] > 0.5f
) {
385 // all H/P post filters in chain
386 proc
[i
] = lp
[i
][0].process(lp
[i
][1].process(proc
[i
]));
390 maxDrive
= dist
[0].get_distortion_level() * *params
[param_amount
];
392 if(in_count
> 1 && out_count
> 1) {
393 maxDrive
= std::max(maxDrive
, dist
[1].get_distortion_level() * *params
[param_amount
]);
395 out
[0] = (proc
[0] * *params
[param_amount
] + in2out
* in
[0]) * *params
[param_level_out
];
396 out
[1] = (proc
[1] * *params
[param_amount
] + in2out
* in
[1]) * *params
[param_level_out
];
397 outs
[0][offset
] = out
[0];
398 outs
[1][offset
] = out
[1];
399 } else if(out_count
> 1) {
400 // mono -> pseudo stereo
401 out
[1] = out
[0] = (proc
[0] * *params
[param_amount
] + in2out
* in
[0]) * *params
[param_level_out
];
402 outs
[0][offset
] = out
[0];
403 outs
[1][offset
] = out
[1];
407 out
[0] = (proc
[0] * *params
[param_amount
] + in2out
* in
[0]) * *params
[param_level_out
];
408 outs
[0][offset
] = out
[0];
410 float values
[] = {(in
[0] + in
[1]) / 2, (out
[0] + out
[1]) / 2, maxDrive
};
411 meters
.process(values
);
414 } // cycle trough samples
430 meters
.fall(numsamples
);
434 /**********************************************************************
435 * BASS ENHANCER by Markus Schmidt
436 **********************************************************************/
438 bassenhancer_audio_module::bassenhancer_audio_module()
442 floor_active_old
= false;
448 void bassenhancer_audio_module::activate()
454 void bassenhancer_audio_module::deactivate()
459 void bassenhancer_audio_module::params_changed()
461 // set the params of all filters
462 if(*params
[param_freq
] != freq_old
) {
463 lp
[0][0].set_lp_rbj(*params
[param_freq
], 0.707, (float)srate
);
464 lp
[0][1].copy_coeffs(lp
[0][0]);
465 lp
[0][2].copy_coeffs(lp
[0][0]);
466 lp
[0][3].copy_coeffs(lp
[0][0]);
467 if(in_count
> 1 && out_count
> 1) {
468 lp
[1][0].copy_coeffs(lp
[0][0]);
469 lp
[1][1].copy_coeffs(lp
[0][0]);
470 lp
[1][2].copy_coeffs(lp
[0][0]);
471 lp
[1][3].copy_coeffs(lp
[0][0]);
473 freq_old
= *params
[param_freq
];
475 // set the params of all filters
476 if(*params
[param_floor
] != floor_old
or *params
[param_floor_active
] != floor_active_old
) {
477 hp
[0][0].set_hp_rbj(*params
[param_floor
], 0.707, (float)srate
);
478 hp
[0][1].copy_coeffs(hp
[0][0]);
479 hp
[1][0].copy_coeffs(hp
[0][0]);
480 hp
[1][1].copy_coeffs(hp
[0][0]);
481 floor_old
= *params
[param_floor
];
482 floor_active_old
= *params
[param_floor_active
];
485 dist
[0].set_params(*params
[param_blend
], *params
[param_drive
]);
486 if(in_count
> 1 && out_count
> 1)
487 dist
[1].set_params(*params
[param_blend
], *params
[param_drive
]);
490 void bassenhancer_audio_module::set_sample_rate(uint32_t sr
)
493 dist
[0].set_sample_rate(sr
);
494 if(in_count
> 1 && out_count
> 1)
495 dist
[1].set_sample_rate(sr
);
496 int meter
[] = {param_meter_in
, param_meter_out
, param_meter_drive
};
497 int clip
[] = {param_clip_in
, param_clip_out
, -1};
498 meters
.init(params
, meter
, clip
, 3, srate
);
501 uint32_t bassenhancer_audio_module::process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
)
503 bool bypass
= *params
[param_bypass
] > 0.5f
;
504 numsamples
+= offset
;
506 // everything bypassed
507 while(offset
< numsamples
) {
508 if(in_count
> 1 && out_count
> 1) {
509 outs
[0][offset
] = ins
[0][offset
];
510 outs
[1][offset
] = ins
[1][offset
];
511 } else if(in_count
> 1) {
512 outs
[0][offset
] = (ins
[0][offset
] + ins
[1][offset
]) / 2;
513 } else if(out_count
> 1) {
514 outs
[0][offset
] = ins
[0][offset
];
515 outs
[1][offset
] = ins
[0][offset
];
517 outs
[0][offset
] = ins
[0][offset
];
519 float values
[] = {0, 0, 0};
520 meters
.process(values
);
525 while(offset
< numsamples
) {
526 // cycle through samples
527 float out
[2], in
[2] = {0.f
, 0.f
};
528 float maxDrive
= 0.f
;
531 if(in_count
> 1 && out_count
> 1) {
532 // stereo in/stereo out
533 // handle full stereo
534 in
[0] = ins
[0][offset
];
535 in
[0] *= *params
[param_level_in
];
536 in
[1] = ins
[1][offset
];
537 in
[1] *= *params
[param_level_in
];
540 // in and/or out mono
542 in
[0] = ins
[0][offset
];
543 in
[0] *= *params
[param_level_in
];
552 for (int i
= 0; i
< c
; ++i
) {
553 // all pre filters in chain
554 proc
[i
] = lp
[i
][1].process(lp
[i
][0].process(proc
[i
]));
557 proc
[i
] = dist
[i
].process(proc
[i
]);
559 // all post filters in chain
560 proc
[i
] = lp
[i
][2].process(lp
[i
][3].process(proc
[i
]));
562 if(*params
[param_floor_active
] > 0.5f
) {
563 // all H/P post filters in chain
564 proc
[i
] = hp
[i
][0].process(hp
[i
][1].process(proc
[i
]));
569 if(in_count
> 1 && out_count
> 1) {
571 if(*params
[param_listen
] > 0.f
)
572 out
[0] = proc
[0] * *params
[param_amount
] * *params
[param_level_out
];
574 out
[0] = (proc
[0] * *params
[param_amount
] + in
[0]) * *params
[param_level_out
];
575 outs
[0][offset
] = out
[0];
576 if(*params
[param_listen
] > 0.f
)
577 out
[1] = proc
[1] * *params
[param_amount
] * *params
[param_level_out
];
579 out
[1] = (proc
[1] * *params
[param_amount
] + in
[1]) * *params
[param_level_out
];
580 outs
[1][offset
] = out
[1];
581 maxDrive
= std::max(dist
[0].get_distortion_level() * *params
[param_amount
],
582 dist
[1].get_distortion_level() * *params
[param_amount
]);
583 } else if(out_count
> 1) {
584 // mono -> pseudo stereo
585 if(*params
[param_listen
] > 0.f
)
586 out
[0] = proc
[0] * *params
[param_amount
] * *params
[param_level_out
];
588 out
[0] = (proc
[0] * *params
[param_amount
] + in
[0]) * *params
[param_level_out
];
589 outs
[0][offset
] = out
[0];
591 outs
[1][offset
] = out
[1];
592 maxDrive
= dist
[0].get_distortion_level() * *params
[param_amount
];
596 if(*params
[param_listen
] > 0.f
)
597 out
[0] = proc
[0] * *params
[param_amount
] * *params
[param_level_out
];
599 out
[0] = (proc
[0] * *params
[param_amount
] + in
[0]) * *params
[param_level_out
];
600 outs
[0][offset
] = out
[0];
601 maxDrive
= dist
[0].get_distortion_level() * *params
[param_amount
];
604 float values
[] = {(in
[0] + in
[1]) / 2, (out
[0] + out
[1]) / 2, maxDrive
};
605 meters
.process(values
);
608 } // cycle trough samples
623 meters
.fall(numsamples
);
627 /**********************************************************************
628 * TAPESIMULATOR by Markus Schmidt
629 **********************************************************************/
631 tapesimulator_audio_module::tapesimulator_audio_module() {
644 transients
.set_channels(channels
);
647 void tapesimulator_audio_module::activate() {
651 void tapesimulator_audio_module::deactivate() {
655 void tapesimulator_audio_module::params_changed() {
656 if(*params
[param_lp
] != lp_old
or *params
[param_mechanical
] != mech_old
) {
657 lp
[0][0].set_lp_rbj(*params
[param_lp
], 0.707, (float)srate
);
658 lp
[0][1].copy_coeffs(lp
[0][0]);
659 lp
[1][0].copy_coeffs(lp
[0][0]);
660 lp
[1][1].copy_coeffs(lp
[0][0]);
661 lp_old
= *params
[param_lp
];
662 mech_old
= *params
[param_mechanical
] > 0.5;
664 transients
.set_params(50.f
/ (*params
[param_speed
] + 1),
665 -0.05f
/ (*params
[param_speed
] + 1),
671 lfo1
.set_params((*params
[param_speed
] + 1) / 2, 0, 0.f
, srate
, 1.f
);
672 lfo2
.set_params((*params
[param_speed
] + 1) / 9.38, 0, 0.f
, srate
, 1.f
);
675 uint32_t tapesimulator_audio_module::process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
) {
676 for(uint32_t i
= offset
; i
< offset
+ numsamples
; i
++) {
679 float Lin
= ins
[0][i
];
680 float Rin
= ins
[1][i
];
681 if(*params
[param_bypass
] > 0.5) {
682 outs
[0][i
] = ins
[0][i
];
683 outs
[1][i
] = ins
[1][i
];
693 // let meters fall a bit
694 clip_inL
-= std::min(clip_inL
, numsamples
);
695 clip_inR
-= std::min(clip_inR
, numsamples
);
696 clip_outL
-= std::min(clip_outL
, numsamples
);
697 clip_outR
-= std::min(clip_outR
, numsamples
);
704 if(L
> meter_inL
) meter_inL
= L
;
705 if(R
> meter_inR
) meter_inR
= R
;
706 if(L
> 1.f
) clip_inL
= srate
>> 3;
707 if(R
> 1.f
) clip_inR
= srate
>> 3;
710 if(*params
[param_magnetical
] > 0.5f
) {
711 float values
[] = {L
, R
};
712 transients
.process(values
);
718 if (*params
[param_noise
]) {
719 float Lnoise
= rand() % 2 - 1;
720 float Rnoise
= rand() % 2 - 1;
721 Lnoise
= noisefilters
[0][2].process(noisefilters
[0][1].process(noisefilters
[0][0].process(Lnoise
)));
722 Rnoise
= noisefilters
[1][2].process(noisefilters
[1][1].process(noisefilters
[1][0].process(Rnoise
)));
723 L
+= Lnoise
* *params
[param_noise
] / 12.f
;
724 R
+= Rnoise
* *params
[param_noise
] / 12.f
;
727 // lfo filters / phasing
728 if (*params
[param_mechanical
]) {
730 float freqL1
= *params
[param_lp
] * (1 - ((lfo1
.get_value() + 1) * 0.3 * *params
[param_mechanical
]));
731 float freqL2
= *params
[param_lp
] * (1 - ((lfo2
.get_value() + 1) * 0.2 * *params
[param_mechanical
]));
733 float freqR1
= *params
[param_lp
] * (1 - ((lfo1
.get_value() * -1 + 1) * 0.3 * *params
[param_mechanical
]));
734 float freqR2
= *params
[param_lp
] * (1 - ((lfo2
.get_value() * -1 + 1) * 0.2 * *params
[param_mechanical
]));
736 lp
[0][0].set_lp_rbj(freqL1
, 0.707, (float)srate
);
737 lp
[0][1].set_lp_rbj(freqL2
, 0.707, (float)srate
);
739 lp
[1][0].set_lp_rbj(freqR1
, 0.707, (float)srate
);
740 lp
[1][1].set_lp_rbj(freqR2
, 0.707, (float)srate
);
743 float _phase
= lfo1
.get_value() * *params
[param_mechanical
] * -36;
745 float _phase_cos_coef
= cos(_phase
/ 180 * M_PI
);
746 float _phase_sin_coef
= sin(_phase
/ 180 * M_PI
);
748 float _l
= L
* _phase_cos_coef
- R
* _phase_sin_coef
;
749 float _r
= L
* _phase_sin_coef
+ R
* _phase_cos_coef
;
755 L
*= *params
[param_level_in
];
756 R
*= *params
[param_level_in
];
758 // save for drawing input/output curve
765 if (*params
[param_post
] < 0.5) {
766 L
= lp
[0][1].process(lp
[0][0].process(L
));
767 R
= lp
[1][1].process(lp
[1][0].process(R
));
771 if (L
) L
= L
/ fabs(L
) * (1 - exp((-1) * 3 * fabs(L
)));
772 if (R
) R
= R
/ fabs(R
) * (1 - exp((-1) * 3 * fabs(R
)));
774 if (Lo
) Lo
= Lo
/ fabs(Lo
) * (1 - exp((-1) * 3 * fabs(Lo
)));
775 if (Ro
) Ro
= Ro
/ fabs(Ro
) * (1 - exp((-1) * 3 * fabs(Ro
)));
778 if (*params
[param_post
] >= 0.5) {
779 L
= lp
[0][1].process(lp
[0][0].process(L
));
780 R
= lp
[1][1].process(lp
[1][0].process(R
));
784 L
= L
* *params
[param_mix
] + Lin
* (*params
[param_mix
] * -1 + 1);
785 R
= R
* *params
[param_mix
] + Rin
* (*params
[param_mix
] * -1 + 1);
788 L
*= *params
[param_level_out
];
789 R
*= *params
[param_level_out
];
796 if(L
> 1.f
) clip_outL
= srate
>> 3;
797 if(R
> 1.f
) clip_outR
= srate
>> 3;
798 if(L
> meter_outL
) meter_outL
= L
;
799 if(R
> meter_outR
) meter_outR
= R
;
807 // LFO's should go on
811 float s
= (fabs(Lo
) + fabs(Ro
)) / 2;
815 float in
= (fabs(Lc
) + fabs(Rc
)) / 2;
822 SET_IF_CONNECTED(clip_inL
);
823 SET_IF_CONNECTED(clip_inR
);
824 SET_IF_CONNECTED(clip_outL
);
825 SET_IF_CONNECTED(clip_outR
);
826 SET_IF_CONNECTED(meter_inL
);
827 SET_IF_CONNECTED(meter_inR
);
828 SET_IF_CONNECTED(meter_outL
);
829 SET_IF_CONNECTED(meter_outR
);
833 void tapesimulator_audio_module::set_sample_rate(uint32_t sr
)
836 transients
.set_sample_rate(srate
);
837 noisefilters
[0][0].set_hp_rbj(120.f
, 0.707, (float)srate
);
838 noisefilters
[1][0].copy_coeffs(noisefilters
[0][0]);
839 noisefilters
[0][1].set_lp_rbj(5500.f
, 0.707, (float)srate
);
840 noisefilters
[1][1].copy_coeffs(noisefilters
[0][1]);
841 noisefilters
[0][2].set_highshelf_rbj(1000.f
, 0.707, 0.5, (float)srate
);
842 noisefilters
[1][2].copy_coeffs(noisefilters
[0][2]);
845 bool tapesimulator_audio_module::get_graph(int index
, int subindex
, int phase
, float *data
, int points
, cairo_iface
*context
, int *mode
) const
849 if(index
== param_lp
and phase
) {
850 set_channel_color(context
, subindex
);
851 return ::get_graph(*this, subindex
, data
, points
);
852 } else if (index
== param_level_in
and !phase
) {
854 context
->set_source_rgba(0.15, 0.2, 0.0, 0.3);
855 context
->set_line_width(1);
857 for (int i
= 0; i
< points
; i
++) {
859 float input
= dB_grid_inv(-1.0 + (float)i
* 2.0 / ((float)points
- 1.f
));
860 data
[i
] = dB_grid(input
);
862 float output
= 1 - exp(-3 * (pow(2, -10 + 14 * (float)i
/ (float) points
)));
863 data
[i
] = dB_grid(output
* *params
[param_level_out
]);
870 float tapesimulator_audio_module::freq_gain(int index
, double freq
) const
872 return lp
[index
][0].freq_gain(freq
, srate
) * lp
[index
][1].freq_gain(freq
, srate
);
875 bool tapesimulator_audio_module::get_gridline(int index
, int subindex
, int phase
, float &pos
, bool &vertical
, std::string
&legend
, cairo_iface
*context
) const
879 if (index
== param_level_in
) {
881 vertical
= (subindex
& 1) != 0;
882 bool result
= get_freq_gridline(subindex
>> 1, pos
, tmp
, legend
, context
, false);
883 if (result
&& vertical
) {
884 if ((subindex
& 4) && !legend
.empty()) {
888 size_t pos
= legend
.find(" dB");
889 if (pos
!= std::string::npos
)
892 pos
= 0.5 + 0.5 * pos
;
895 } else if (index
== param_lp
) {
896 return get_freq_gridline(subindex
, pos
, vertical
, legend
, context
);
900 bool tapesimulator_audio_module::get_dot(int index
, int subindex
, int phase
, float &x
, float &y
, int &size
, cairo_iface
*context
) const
902 if (index
== param_level_in
and !subindex
and phase
) {
903 x
= log(input
) / log(2) / 14.f
+ 5.f
/ 7.f
;
911 bool tapesimulator_audio_module::get_layers(int index
, int generation
, unsigned int &layers
) const
914 // always draw grid on cache if surfaces are new on both widgets
916 layers
|= LG_CACHE_GRID
;
917 // compression: dot in realtime, graphs as cache on new surfaces
918 if (index
== param_level_in
and !generation
)
919 layers
|= LG_CACHE_GRAPH
;
920 if (index
== param_level_in
)
921 layers
|= LG_REALTIME_DOT
;
922 // frequency: both graphs in realtime
923 if (index
== param_lp
)
924 layers
|= LG_REALTIME_GRAPH
;
931 /**********************************************************************
932 * CRUSHER by Markus Schmidt and Christian Holschuh
933 **********************************************************************/
936 crusher_audio_module::crusher_audio_module()
941 void crusher_audio_module::activate()
945 void crusher_audio_module::deactivate()
950 void crusher_audio_module::params_changed()
952 bitreduction
.set_params(*params
[param_bits
],
953 *params
[param_morph
],
954 *params
[param_bypass
] > 0.5,
958 samplereduction
[0].set_params(*params
[param_samples
]);
959 samplereduction
[1].set_params(*params
[param_samples
]);
960 lfo
.set_params(*params
[param_lforate
], 0, 0.f
, srate
, 0.5f
);
962 float rad
= *params
[param_lforange
] / 2.f
;
963 smin
= std::max(*params
[param_samples
] - rad
, 1.f
);
964 float sun
= *params
[param_samples
] - rad
- smin
;
965 float smax
= std::min(*params
[param_samples
] + rad
, 250.f
);
966 float sov
= *params
[param_samples
] + rad
- smax
;
972 void crusher_audio_module::set_sample_rate(uint32_t sr
)
975 int meter
[] = {param_meter_inL
, param_meter_inR
, param_meter_outL
, param_meter_outR
};
976 int clip
[] = {param_clip_inL
, param_clip_inR
, param_clip_outL
, param_clip_outR
};
977 meters
.init(params
, meter
, clip
, 4, srate
);
978 bitreduction
.set_sample_rate(srate
);
981 uint32_t crusher_audio_module::process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
)
983 bool bypass
= *params
[param_bypass
] > 0.5f
;
984 numsamples
+= offset
;
986 // everything bypassed
987 while(offset
< numsamples
) {
988 outs
[0][offset
] = ins
[0][offset
];
989 outs
[1][offset
] = ins
[1][offset
];
990 float values
[] = {0, 0, 0, 0};
991 meters
.process(values
);
996 while(offset
< numsamples
) {
997 // cycle through samples
998 if (*params
[param_lfo
] > 0.5) {
999 samplereduction
[0].set_params(smin
+ sdiff
* (lfo
.get_value() + 0.5));
1000 samplereduction
[1].set_params(smin
+ sdiff
* (lfo
.get_value() + 0.5));
1002 outs
[0][offset
] = samplereduction
[0].process(ins
[0][offset
] * *params
[param_level_in
]);
1003 outs
[1][offset
] = samplereduction
[1].process(ins
[1][offset
] * *params
[param_level_in
]);
1004 outs
[0][offset
] = outs
[0][offset
] * *params
[param_morph
] + ins
[0][offset
] * (*params
[param_morph
] * -1 + 1) * *params
[param_level_in
];
1005 outs
[1][offset
] = outs
[1][offset
] * *params
[param_morph
] + ins
[1][offset
] * (*params
[param_morph
] * -1 + 1) * *params
[param_level_in
];
1006 outs
[0][offset
] = bitreduction
.process(outs
[0][offset
]) * *params
[param_level_out
];
1007 outs
[1][offset
] = bitreduction
.process(outs
[1][offset
]) * *params
[param_level_out
];
1008 float values
[] = {ins
[0][offset
], ins
[1][offset
], outs
[0][offset
], outs
[1][offset
]};
1009 meters
.process(values
);
1012 if (*params
[param_lforate
])
1014 } // cycle trough samples
1016 meters
.fall(numsamples
);
1017 return outputs_mask
;
1019 bool crusher_audio_module::get_graph(int index
, int subindex
, int phase
, float *data
, int points
, cairo_iface
*context
, int *mode
) const
1021 return bitreduction
.get_graph(subindex
, phase
, data
, points
, context
, mode
);
1023 bool crusher_audio_module::get_layers(int index
, int generation
, unsigned int &layers
) const
1025 return bitreduction
.get_layers(index
, generation
, layers
);
1027 bool crusher_audio_module::get_gridline(int index
, int subindex
, int phase
, float &pos
, bool &vertical
, std::string
&legend
, cairo_iface
*context
) const
1029 return bitreduction
.get_gridline(subindex
, phase
, pos
, vertical
, legend
, context
);