1 /*
2  * Bypass.cpp
3  *
4  *  Created on: 22 янв. 2020 г.
5  *      Author: Vladimir Sadovnikov <lsp.plugin@gmail.com>
6  *
7  * This file is part of tamgamp.lv2 <https://github.com/sadko4u/tamgamp.lv2>.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22  */
23 
24 #include "../../../include/tamgamp.lv2/util/Bypass.h"
25 
26 #include <string.h>
27 
28 namespace tamgamp_lv2
29 {
30 
Bypass()31     Bypass::Bypass()
32     {
33         nState      = S_OFF;
34         fDelta      = 0;
35         fGain       = 0;
36     }
37 
~Bypass()38     Bypass::~Bypass()
39     {
40     }
41 
set_bypass(bool bypass)42     bool Bypass::set_bypass(bool bypass)
43     {
44         // Trigger state change
45         switch (nState)
46         {
47             case S_ON:
48                 if (bypass)
49                     return false;
50                 nState  = S_ACTIVE;
51                 break;
52             case S_OFF:
53                 if (!bypass)
54                     return false;
55                 nState  = S_ACTIVE;
56                 break;
57             case S_ACTIVE:
58             {
59                 bool off    = (fDelta < 0.0f);
60                 if (bypass == off)
61                     return false;
62                 break;
63             }
64             default:
65                 return false;
66         }
67 
68         // Change sign of the applying delta
69         fDelta  = -fDelta;
70         return true;
71     }
72 
bypassing() const73     bool Bypass::bypassing() const
74     {
75         switch (nState)
76         {
77             case S_ON: return true;
78             case S_OFF: return false;
79             case S_ACTIVE: return fDelta < 0.0f;
80             default: return false;
81         }
82     }
83 
init(int sample_rate,float time)84     void Bypass::init(int sample_rate, float time)
85     {
86         // Off by default
87         float length= sample_rate * time;
88         if (length < 1.0f)
89             length      = 1.0f;
90         nState      = S_OFF;
91         fDelta      = 1.0 / length;
92         fGain       = 1.0;
93     }
94 
process(float * dst,const float * dry,const float * wet,size_t count)95     void Bypass::process(float *dst, const float *dry, const float *wet, size_t count)
96     {
97         // Skip empty buffers
98         if (count == 0)
99             return;
100 
101         if (dry != NULL)
102         {
103             // Analyze direction
104             if (fDelta > 0.0f)
105             {
106                 // Process transition
107                 while (fGain < 1.0)
108                 {
109                     *dst    =   *dry + (*wet - *dry) * fGain;
110 
111                     fGain  +=  fDelta;
112                     dry    ++;
113                     wet    ++;
114                     dst    ++;
115 
116                     if ((--count) <= 0) // Last sample?
117                         return;
118                 }
119 
120                 // Copy wet data
121                 fGain   = 1.0;
122                 nState  = S_OFF;
123                 if (count > 0)
124                     ::memcpy(dst, wet, count*sizeof(float));
125             }
126             else
127             {
128                 // Process transition
129                 while (fGain > 0.0)
130                 {
131                     *dst    =   *dry + (*wet - *dry) * fGain;
132 
133                     fGain  +=  fDelta;
134                     dry    ++;
135                     wet    ++;
136                     dst    ++;
137 
138                     if ((--count) <= 0) // Last sample?
139                         return;
140                 }
141 
142                 // Copy dry data
143                 fGain   = 0.0;
144                 nState  = S_ON;
145                 if (count > 0)
146                     ::memcpy(dst, dry, count*sizeof(float));
147             }
148         }
149         else
150         {
151             // Analyze direction
152             if (fDelta > 0.0f)
153             {
154                 // Process transition
155                 while (fGain < 1.0)
156                 {
157                     *dst    =   (*wet) * fGain;
158 
159                     fGain  +=  fDelta;
160                     wet    ++;
161                     dst    ++;
162 
163                     if ((--count) <= 0) // Last sample?
164                         return;
165                 }
166 
167                 // Copy wet data
168                 fGain   = 1.0;
169                 nState  = S_OFF;
170                 if (count > 0)
171                     ::memcpy(dst, wet, count*sizeof(float));
172             }
173             else
174             {
175                 // Process transition
176                 while (fGain > 0.0)
177                 {
178                     *dst    =   (*wet) * fGain;
179 
180                     fGain  +=  fDelta;
181                     wet    ++;
182                     dst    ++;
183 
184                     if ((--count) <= 0) // Last sample?
185                         return;
186                 }
187 
188                 // Zero dry data
189                 fGain   = 0.0;
190                 nState  = S_ON;
191                 if (count > 0)
192                     ::bzero(dst, count*sizeof(float));
193             }
194         }
195     }
196 
197 }
198 
199 
200