1 /*
2 Rakarrack Guitar FX
3
4 Sustainer.C - Simple compressor/sustainer effect with easy interface, minimal controls
5 Copyright (C) 2010 Ryan Billing
6 Author: Ryan Billing
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of version 3 of the GNU General Public License
10 as published by the Free Software Foundation.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License (version 2) for more details.
16
17 You should have received a copy of the GNU General Public License (version 2)
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <math.h>
26 #include "Sustainer.h"
27
Sustainer(float * efxoutl_,float * efxoutr_,double sample_rate)28 Sustainer::Sustainer (float * efxoutl_, float * efxoutr_, double sample_rate)
29 {
30 float cSAMPLE_RATE = 1/sample_rate;
31 efxoutl = efxoutl_;
32 efxoutr = efxoutr_;
33
34 Pvolume = 64;
35 Psustain = 64;
36 fsustain = 0.5f;
37 level = 0.5f;
38
39 float tmp = 0.01f; //10 ms decay time on peak detectorS
40 prls = 1.0f - (cSAMPLE_RATE/(cSAMPLE_RATE + tmp));
41
42 tmp = 0.05f; //50 ms att/rel on compressor
43 calpha = cSAMPLE_RATE/(cSAMPLE_RATE + tmp);
44 cbeta = 1.0f - calpha;
45 cthresh = 0.25f;
46 cratio = 0.25f;
47
48 timer = 0;
49 hold = (int) (sample_rate*0.0125); //12.5ms
50 cleanup ();
51 };
52
~Sustainer()53 Sustainer::~Sustainer ()
54 {
55
56 };
57
58 /*
59 * Cleanup the effect
60 */
61 void
cleanup()62 Sustainer::cleanup ()
63 {
64 compeak = 0.0f;
65 compenv = 0.0f;
66 oldcompenv = 0.0f;
67 cpthresh = cthresh; //dynamic threshold
68 };
69
70
71
72
73 /*
74 * Effect output
75 */
76 void
out(float * smpsl,float * smpsr,uint32_t period)77 Sustainer::out (float * smpsl, float * smpsr, uint32_t period)
78 {
79 unsigned int i;
80 float auxtempl = 0.0f;
81 float auxtempr = 0.0f;
82 float auxcombi = 0.0f;
83
84 for (i = 0; i<period; i++) { //apply compression to auxresampled
85 auxtempl = input * smpsl[i];
86 auxtempr = input * smpsr[i];
87 auxcombi = 0.5f * (auxtempl + auxtempr);
88 if(fabs(auxcombi) > compeak) {
89 compeak = fabs(auxcombi); //First do peak detection on the signal
90 timer = 0;
91 }
92 if(timer>hold) {
93 compeak *= prls;
94 timer--;
95 }
96 timer++;
97 compenv = cbeta * oldcompenv + calpha * compeak; //Next average into envelope follower
98 oldcompenv = compenv;
99
100 if(compenv > cpthresh) { //if envelope of signal exceeds thresh, then compress
101 compg = cpthresh + cpthresh*(compenv - cpthresh)/compenv;
102 cpthresh = cthresh + cratio*(compg - cpthresh); //cpthresh changes dynamically
103 tmpgain = compg/compenv;
104 } else {
105 tmpgain = 1.0f;
106 }
107
108 if(compenv < cpthresh) cpthresh = compenv;
109 if(cpthresh < cthresh) cpthresh = cthresh;
110
111 smpsl[i] = auxtempl * tmpgain * level;
112 smpsr[i] = auxtempr * tmpgain * level;
113 };
114 //End compression
115 };
116
117
118 /*
119 * Parameter control
120 */
121
122
123 void
setpreset(int npreset)124 Sustainer::setpreset (int npreset)
125 {
126 const int PRESET_SIZE = 2;
127 const int NUM_PRESETS = 3;
128 int pdata[PRESET_SIZE];
129 int presets[NUM_PRESETS][PRESET_SIZE] = {
130 //Moderate
131 {79, 54},
132 //Extreme
133 {16, 127},
134 //Mild
135 {120, 15},
136
137 };
138
139 if(npreset>NUM_PRESETS-1) {
140 Fpre->ReadPreset(36,npreset-NUM_PRESETS+1, pdata);
141 for (int n = 0; n < PRESET_SIZE; n++)
142 changepar (n, pdata[n]);
143 } else {
144 for (int n = 0; n < PRESET_SIZE; n++)
145 changepar (n, presets[npreset][n]);
146 }
147 Ppreset = npreset;
148 };
149
150
151 void
changepar(int npar,int value)152 Sustainer::changepar (int npar, int value)
153 {
154 switch (npar) {
155 case 0:
156 Pvolume = value;
157 level = dB2rap(-30.0f * (1.0f - ((float) Pvolume/127.0f)));
158 break;
159 case 1:
160 Psustain = value;
161 fsustain = (float) Psustain/127.0f;
162 cratio = 1.25f - fsustain;
163 input = dB2rap (42.0f * fsustain - 6.0f);
164 cthresh = 0.25 + fsustain;
165 break;
166
167 };
168 };
169
170 int
getpar(int npar)171 Sustainer::getpar (int npar)
172 {
173 switch (npar) {
174 case 0:
175 return (Pvolume);
176 break;
177 case 1:
178 return (Psustain);
179 break;
180 };
181 return (0); //in case of bogus parameter number
182 };
183
184