1 /*
2  * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/>
3  *           (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com>
4  *
5  * This file is part of lsp-plugins
6  * Created on: 28 сент. 2015 г.
7  *
8  * lsp-plugins is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * any later version.
12  *
13  * lsp-plugins is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <dsp/dsp.h>
23 
24 #include <core/debug.h>
25 #include <plugins/comp_delay.h>
26 #include <math.h>
27 
28 #include <string.h>
29 
30 #define BUFFER_SIZE         (0x10000 / sizeof(float))
31 
32 namespace lsp
33 {
comp_delay_base()34     comp_delay_base::comp_delay_base()
35     {
36         lsp_trace("constructor");
37         nMode           = comp_delay_base_metadata::M_SAMPLES;
38         fSamples        = 0;
39         fDistance       = 0;
40         fTemperature    = 0;
41         fTime           = 0;
42         nSampleRate     = 0;
43         fDry            = 0.0;
44         fWet            = 1.0;
45         vBuffer         = NULL;
46         nBufSize        = 0;
47         nDelay          = 0;
48         nNewDelay       = 0;
49         bRamping        = false;
50         pIn             = NULL;
51         pOut            = NULL;
52     }
53 
~comp_delay_base()54     comp_delay_base::~comp_delay_base()
55     {
56         destroy();
57     }
58 
init(long sample_rate,float * buffer,size_t buf_size)59     void comp_delay_base::init(long sample_rate, float *buffer, size_t buf_size)
60     {
61         nSampleRate             = sample_rate;
62         size_t samples          = comp_delay_base_metadata::SAMPLES_MAX;
63         size_t time_samples     = comp_delay_base_metadata::TIME_MAX * 0.001 * nSampleRate;
64         size_t dist_samples     = (comp_delay_base_metadata::METERS_MAX + comp_delay_base_metadata::CENTIMETERS_MAX * 0.01) /
65                                     sound_speed(comp_delay_base_metadata::TEMPERATURE_MAX);
66 
67         lsp_trace("samples=%d, time_samples=%d, dist_samples=%d", int(samples), int(time_samples), int(dist_samples));
68         if (samples < time_samples)
69             samples     = time_samples;
70         if (samples < dist_samples)
71             samples     = dist_samples;
72 
73         vBuffer                 = buffer;
74         nBufSize                = buf_size;
75 
76         vLine.init(samples);
77         vBypass.init(sample_rate);
78     }
79 
destroy()80     void comp_delay_base::destroy()
81     {
82         lsp_trace("destroy");
83         vLine.destroy();
84 
85         vBuffer         = NULL;
86         nBufSize        = 0;
87     }
88 
configure()89     void comp_delay_base::configure()
90     {
91         // Calculate delay in samples
92         float snd_speed     = sound_speed(fTemperature);
93 
94         lsp_trace("mode=%d, distance=%.3f, time=%.3f, samples=%.3f, snd_speed=%.3f", int(nMode), fDistance, fTime, fSamples, snd_speed);
95 
96         if (nMode == comp_delay_base_metadata::M_DISTANCE)
97             nNewDelay   = (nSampleRate * fDistance) / snd_speed;
98         else if (nMode == comp_delay_base_metadata::M_TIME)
99             nNewDelay   = fTime * 0.001f * nSampleRate;
100         else
101             nNewDelay   = fSamples;
102 
103         // Update delay parameter for delay line
104         if (nNewDelay < 0)
105             nNewDelay       = 0;
106         if (!bRamping)
107             nDelay          = nNewDelay;
108         lsp_trace("final delay=%d, new_delay=%d", int(nDelay), int(nNewDelay));
109         vLine.set_delay(nDelay);
110 
111         // Re-calculate parameters
112         fSamples        = nNewDelay;
113         fDistance       = (nNewDelay * snd_speed * 100.0) / float(nSampleRate);
114         fTime           = (nNewDelay * 1000.0f) / float(nSampleRate);
115     }
116 
process(size_t samples)117     void comp_delay_base::process(size_t samples)
118     {
119 //        lsp_trace("samples = %d", int(samples));
120 
121         // Get input and output buffers
122         const float *in     = reinterpret_cast<const float *>(pIn->getBuffer());
123         float *out          = reinterpret_cast<float *>(pOut->getBuffer());
124 
125         if ((in == NULL) || (out == NULL))
126             return;
127 
128         while (samples > 0)
129         {
130             size_t count = (samples > nBufSize) ? nBufSize : samples;
131 
132             // Pre-process signal (fill buffer)
133             vLine.process_ramping(vBuffer, in, fWet, nNewDelay, samples);
134             nDelay      = nNewDelay;
135 
136             // Apply 'dry' control
137             if (fDry > 0.0)
138                 dsp::fmadd_k3(vBuffer, in, fDry, count);
139 
140             vBypass.process(out, in, vBuffer, count);
141 
142             // Increment pointers
143             in          +=  count;
144             out         +=  count;
145             samples     -=  count;
146         }
147     }
148 
comp_delay_impl(const plugin_metadata_t & mdata)149     comp_delay_impl::comp_delay_impl(const plugin_metadata_t &mdata): plugin_t(mdata)
150     {
151         vBuffer     = NULL;
152     }
153 
~comp_delay_impl()154     comp_delay_impl::~comp_delay_impl()
155     {
156     }
157 
init(IWrapper * wrapper)158     void comp_delay_impl::init(IWrapper *wrapper)
159     {
160         // Pass wrapper
161         plugin_t::init(wrapper);
162 
163         if (vBuffer == NULL)
164             vBuffer     = new float[BUFFER_SIZE];
165     }
166 
update_sample_rate(long sr)167     void comp_delay_impl::update_sample_rate(long sr)
168     {
169         dropBuffers();
170         createBuffers();
171     }
172 
dropBuffers()173     void comp_delay_impl::dropBuffers()
174     {
175     }
176 
createBuffers()177     void comp_delay_impl::createBuffers()
178     {
179     }
180 
destroy()181     void comp_delay_impl::destroy()
182     {
183         dropBuffers();
184 
185         if (vBuffer != NULL)
186         {
187             delete [] vBuffer;
188             vBuffer = NULL;
189         }
190         plugin_t::destroy();
191     }
192 
comp_delay_mono()193     comp_delay_mono::comp_delay_mono(): comp_delay_impl(metadata)
194     {
195 
196     }
197 
~comp_delay_mono()198     comp_delay_mono::~comp_delay_mono()
199     {
200     }
201 
createBuffers()202     void comp_delay_mono::createBuffers()
203     {
204         vDelay.init(fSampleRate, vBuffer, BUFFER_SIZE);
205         vDelay.set_ports(vPorts[A_IN], vPorts[A_OUT]);
206     }
207 
dropBuffers()208     void comp_delay_mono::dropBuffers()
209     {
210         vDelay.destroy();
211     }
212 
update_settings()213     void comp_delay_mono::update_settings()
214     {
215         float out_gain      = vPorts[OUT_GAIN]->getValue();
216         bool bypass         = vPorts[BYPASS]->getValue() >= 0.5;
217 
218         vDelay.set_bypass(bypass);
219 
220         vDelay.set_mode(vPorts[MODE]->getValue());
221         vDelay.set_ramping(vPorts[RAMPING]->getValue() >= 0.5f);
222         vDelay.set_samples(vPorts[SAMPLES]->getValue());
223         vDelay.set_time(vPorts[TIME]->getValue());
224         vDelay.set_distance(vPorts[METERS]->getValue() + (vPorts[CENTIMETERS]->getValue() * 0.01));
225         vDelay.set_temperature(vPorts[TEMPERATURE]->getValue());
226         vDelay.set_dry(vPorts[DRY]->getValue() * out_gain);
227         vDelay.set_wet(vPorts[WET]->getValue() * out_gain);
228 
229         vDelay.configure();
230 
231         vPorts[DEL_TIME]        -> setValue(vDelay.get_time());
232         vPorts[DEL_SAMPLES]     -> setValue(vDelay.get_samples());
233         vPorts[DEL_DISTANCE]    -> setValue(vDelay.get_distance());
234 
235         // TEST for latency compensation
236 //        set_latency(vDelay.get_samples());
237     }
238 
process(size_t samples)239     void comp_delay_mono::process(size_t samples)
240     {
241         vDelay.process(samples);
242     }
243 
244 
comp_delay_stereo()245     comp_delay_stereo::comp_delay_stereo(): comp_delay_impl(metadata)
246     {
247     }
248 
~comp_delay_stereo()249     comp_delay_stereo::~comp_delay_stereo()
250     {
251     }
252 
createBuffers()253     void comp_delay_stereo::createBuffers()
254     {
255         vDelay[0].init(fSampleRate, vBuffer, BUFFER_SIZE);
256         vDelay[0].set_ports(vPorts[IN_L], vPorts[OUT_L]);
257 
258         vDelay[1].init(fSampleRate, vBuffer, BUFFER_SIZE);
259         vDelay[1].set_ports(vPorts[IN_R], vPorts[OUT_R]);
260     }
261 
dropBuffers()262     void comp_delay_stereo::dropBuffers()
263     {
264         vDelay[0].destroy();
265         vDelay[1].destroy();
266     }
267 
update_settings()268     void comp_delay_stereo::update_settings()
269     {
270         float out_gain      = vPorts[OUT_GAIN]->getValue();
271         bool bypass         = vPorts[BYPASS]->getValue() >= 0.5;
272 
273         for (size_t i=0; i<2; ++i)
274         {
275             comp_delay_base *d    = &vDelay[i];
276 
277             d   -> set_bypass(bypass);
278 
279             d   -> set_mode(vPorts[MODE]->getValue());
280             d   -> set_ramping(vPorts[RAMPING]->getValue() >= 0.5f);
281             d   -> set_samples(vPorts[SAMPLES]->getValue());
282             d   -> set_time(vPorts[TIME]->getValue());
283             d   -> set_distance(vPorts[METERS]->getValue() + (vPorts[CENTIMETERS]->getValue() * 0.01));
284             d   -> set_temperature(vPorts[TEMPERATURE]->getValue());
285             d   -> set_dry(vPorts[DRY]->getValue() * out_gain);
286             d   -> set_wet(vPorts[WET]->getValue() * out_gain);
287 
288             d   -> configure();
289         }
290 
291         vPorts[DEL_TIME]        -> setValue(vDelay[0].get_time());
292         vPorts[DEL_SAMPLES]     -> setValue(vDelay[0].get_samples());
293         vPorts[DEL_DISTANCE]    -> setValue(vDelay[0].get_distance());
294     }
295 
process(size_t samples)296     void comp_delay_stereo::process(size_t samples)
297     {
298         vDelay[0].process(samples);
299         vDelay[1].process(samples);
300     }
301 
comp_delay_x2_stereo()302     comp_delay_x2_stereo::comp_delay_x2_stereo(): comp_delay_impl(metadata)
303     {
304     }
305 
~comp_delay_x2_stereo()306     comp_delay_x2_stereo::~comp_delay_x2_stereo()
307     {
308     }
309 
createBuffers()310     void comp_delay_x2_stereo::createBuffers()
311     {
312         vDelay[0].init(fSampleRate, vBuffer, BUFFER_SIZE);
313         vDelay[0].set_ports(vPorts[IN_L], vPorts[OUT_L]);
314 
315         vDelay[1].init(fSampleRate, vBuffer, BUFFER_SIZE);
316         vDelay[1].set_ports(vPorts[IN_R], vPorts[OUT_R]);
317     }
318 
dropBuffers()319     void comp_delay_x2_stereo::dropBuffers()
320     {
321         vDelay[0].destroy();
322         vDelay[1].destroy();
323     }
324 
update_settings()325     void comp_delay_x2_stereo::update_settings()
326     {
327         float out_gain      = vPorts[OUT_GAIN]->getValue();
328         bool bypass         = vPorts[BYPASS]->getValue() >= 0.5;
329 
330         vDelay[0].set_bypass( bypass );
331         vDelay[1].set_bypass( bypass );
332 
333         vDelay[0].set_mode(vPorts[MODE_L]->getValue());
334         vDelay[0].set_ramping(vPorts[RAMPING_L]->getValue());
335         vDelay[0].set_samples(vPorts[SAMPLES_L]->getValue());
336         vDelay[0].set_time(vPorts[TIME_L]->getValue());
337         vDelay[0].set_distance(vPorts[METERS_L]->getValue() + (vPorts[CENTIMETERS_L]->getValue() * 0.01));
338         vDelay[0].set_temperature(vPorts[TEMPERATURE_L]->getValue());
339         vDelay[0].set_dry(vPorts[DRY_L]->getValue() * out_gain);
340         vDelay[0].set_wet(vPorts[WET_L]->getValue() * out_gain);
341 
342         vDelay[1].set_mode(vPorts[MODE_R]->getValue());
343         vDelay[1].set_ramping(vPorts[RAMPING_R]->getValue());
344         vDelay[1].set_samples(vPorts[SAMPLES_R]->getValue());
345         vDelay[1].set_time(vPorts[TIME_R]->getValue());
346         vDelay[1].set_distance(vPorts[METERS_R]->getValue() + (vPorts[CENTIMETERS_R]->getValue() * 0.01));
347         vDelay[1].set_temperature(vPorts[TEMPERATURE_R]->getValue());
348         vDelay[1].set_dry(vPorts[DRY_R]->getValue() * out_gain);
349         vDelay[1].set_wet(vPorts[WET_R]->getValue() * out_gain);
350 
351         vDelay[0].configure();
352         vDelay[1].configure();
353 
354         vPorts[DEL_TIME_L]      -> setValue(vDelay[0].get_time());
355         vPorts[DEL_SAMPLES_L]   -> setValue(vDelay[0].get_samples());
356         vPorts[DEL_DISTANCE_L]  -> setValue(vDelay[0].get_distance());
357 
358         vPorts[DEL_TIME_R]      -> setValue(vDelay[1].get_time());
359         vPorts[DEL_SAMPLES_R]   -> setValue(vDelay[1].get_samples());
360         vPorts[DEL_DISTANCE_R]  -> setValue(vDelay[1].get_distance());
361     }
362 
process(size_t samples)363     void comp_delay_x2_stereo::process(size_t samples)
364     {
365         vDelay[0].process(samples);
366         vDelay[1].process(samples);
367     }
368 } /* namespace ddb */
369 
370 
371