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