mirror of
https://github.com/LMMS/lmms.git
synced 2026-04-28 18:10:37 -04:00
224 lines
6.3 KiB
C++
224 lines
6.3 KiB
C++
/* canyondelay.cpp
|
|
|
|
Canyon Delay - Deep Stereo Cross Delay
|
|
Copyright (c) 1999, 2000 David A. Bartold
|
|
|
|
Computer Music Toolkit - a library of LADSPA plugins. Copyright (C)
|
|
2000 Richard W.E. Furse. The author may be contacted at
|
|
richard@muse.demon.co.uk.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public Licence as
|
|
published by the Free Software Foundation; either version 2 of the
|
|
Licence, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
02111-1307, USA. */
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include "cmt.h"
|
|
|
|
#define PORT_IN_LEFT 0
|
|
#define PORT_IN_RIGHT 1
|
|
#define PORT_OUT_LEFT 2
|
|
#define PORT_OUT_RIGHT 3
|
|
#define PORT_LTR_TIME 4
|
|
#define PORT_LTR_FEEDBACK 5
|
|
#define PORT_RTL_TIME 6
|
|
#define PORT_RTL_FEEDBACK 7
|
|
#define PORT_CUTOFF 8
|
|
|
|
#define NUM_PORTS 9
|
|
|
|
#ifndef PI
|
|
#define PI 3.14159265358979
|
|
#endif
|
|
|
|
class CanyonDelay : public CMT_PluginInstance {
|
|
LADSPA_Data sample_rate;
|
|
|
|
long datasize;
|
|
LADSPA_Data *data_l;
|
|
LADSPA_Data *data_r;
|
|
LADSPA_Data accum_l;
|
|
LADSPA_Data accum_r;
|
|
|
|
int pos;
|
|
|
|
public:
|
|
CanyonDelay(const LADSPA_Descriptor *,
|
|
unsigned long s_rate)
|
|
: CMT_PluginInstance(NUM_PORTS),
|
|
sample_rate(s_rate),
|
|
datasize(s_rate),
|
|
data_l(new LADSPA_Data[datasize]),
|
|
data_r(new LADSPA_Data[datasize]),
|
|
accum_l(0.0),
|
|
accum_r(0.0),
|
|
pos(0) {
|
|
for (long i = 0; i < datasize; i++)
|
|
data_l[i] = data_r[i] = 0.0;
|
|
}
|
|
|
|
~CanyonDelay() {
|
|
delete[] data_l;
|
|
delete[] data_r;
|
|
}
|
|
|
|
static void
|
|
activate(LADSPA_Handle Instance) {
|
|
CanyonDelay *delay = (CanyonDelay*) Instance;
|
|
|
|
for (long i = 0; i < delay->datasize; i++)
|
|
delay->data_l[i] = delay->data_r[i] = 0.0;
|
|
|
|
delay->accum_l = 0.0;
|
|
delay->accum_r = 0.0;
|
|
delay->pos = 0;
|
|
}
|
|
|
|
static void
|
|
run(LADSPA_Handle Instance,
|
|
unsigned long SampleCount) {
|
|
CanyonDelay *delay = (CanyonDelay*) Instance;
|
|
LADSPA_Data **ports;
|
|
unsigned long i;
|
|
int l_to_r_offset, r_to_l_offset;
|
|
LADSPA_Data ltr_invmag, rtl_invmag;
|
|
LADSPA_Data filter_mag, filter_invmag;
|
|
|
|
ports = delay->m_ppfPorts;
|
|
|
|
l_to_r_offset = (int) (*ports[PORT_LTR_TIME] * delay->sample_rate);
|
|
r_to_l_offset = (int) (*ports[PORT_RTL_TIME] * delay->sample_rate);
|
|
|
|
ltr_invmag = 1.0 - fabs (*ports[PORT_LTR_FEEDBACK]);
|
|
rtl_invmag = 1.0 - fabs (*ports[PORT_RTL_FEEDBACK]);
|
|
|
|
filter_invmag = pow (0.5, (4.0 * PI * *ports[PORT_CUTOFF]) / delay->sample_rate);
|
|
filter_mag = 1.0 - filter_invmag;
|
|
|
|
for (i = 0; i < SampleCount; i++)
|
|
{
|
|
LADSPA_Data accum_l, accum_r;
|
|
int pos1, pos2;
|
|
|
|
accum_l = ports[PORT_IN_LEFT][i];
|
|
accum_r = ports[PORT_IN_RIGHT][i];
|
|
|
|
pos1 = delay->pos - r_to_l_offset + delay->datasize;
|
|
while (pos1 >= delay->datasize)
|
|
pos1 -= delay->datasize;
|
|
|
|
pos2 = delay->pos - l_to_r_offset + delay->datasize;
|
|
while (pos2 >= delay->datasize)
|
|
pos2 -= delay->datasize;
|
|
|
|
/* Mix channels with past samples. */
|
|
accum_l = accum_l * rtl_invmag + delay->data_r[pos1] * *ports[PORT_RTL_FEEDBACK];
|
|
accum_r = accum_r * ltr_invmag + delay->data_l[pos2] * *ports[PORT_LTR_FEEDBACK];
|
|
|
|
/* Low-pass filter output. */
|
|
accum_l = delay->accum_l * filter_invmag + accum_l * filter_mag;
|
|
accum_r = delay->accum_r * filter_invmag + accum_r * filter_mag;
|
|
|
|
/* Store IIR samples. */
|
|
delay->accum_l = accum_l;
|
|
delay->accum_r = accum_r;
|
|
|
|
/* Store samples in arrays. */
|
|
delay->data_l[delay->pos] = accum_l;
|
|
delay->data_r[delay->pos] = accum_r;
|
|
|
|
ports[PORT_OUT_LEFT][i] = accum_l;
|
|
ports[PORT_OUT_RIGHT][i] = accum_r;
|
|
|
|
delay->pos++;
|
|
if (delay->pos >= delay->datasize)
|
|
delay->pos -= delay->datasize;
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
static LADSPA_PortDescriptor g_psPortDescriptors[] =
|
|
{
|
|
LADSPA_PORT_AUDIO | LADSPA_PORT_INPUT,
|
|
LADSPA_PORT_AUDIO | LADSPA_PORT_INPUT,
|
|
LADSPA_PORT_AUDIO | LADSPA_PORT_OUTPUT,
|
|
LADSPA_PORT_AUDIO | LADSPA_PORT_OUTPUT,
|
|
LADSPA_PORT_CONTROL | LADSPA_PORT_INPUT,
|
|
LADSPA_PORT_CONTROL | LADSPA_PORT_INPUT,
|
|
LADSPA_PORT_CONTROL | LADSPA_PORT_INPUT,
|
|
LADSPA_PORT_CONTROL | LADSPA_PORT_INPUT,
|
|
LADSPA_PORT_CONTROL | LADSPA_PORT_INPUT
|
|
};
|
|
|
|
static const char * const g_psPortNames[] =
|
|
{
|
|
"In (Left)",
|
|
"In (Right)",
|
|
"Out (Left)",
|
|
"Out (Right)",
|
|
"Left to Right Time (Seconds)",
|
|
"Left to Right Feedback (Percent)",
|
|
"Right to Left Time (Seconds)",
|
|
"Right to Left Feedback (Percent)",
|
|
"Low-Pass Cutoff (Hz)"
|
|
};
|
|
|
|
static LADSPA_PortRangeHint g_psPortRangeHints[] =
|
|
{
|
|
/* Hints, Lower bound, Upper bound */
|
|
{ 0, 0.0, 0.0 },
|
|
{ 0, 0.0, 0.0 },
|
|
{ 0, 0.0, 0.0 },
|
|
{ 0, 0.0, 0.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.01, 0.99 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, -1.0, 1.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.01, 0.99 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, -1.0, 1.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 1.0, 5000.0 }
|
|
};
|
|
|
|
void
|
|
initialise_canyondelay() {
|
|
CMT_Descriptor * psDescriptor;
|
|
|
|
psDescriptor = new CMT_Descriptor
|
|
(1225,
|
|
"canyon_delay",
|
|
LADSPA_PROPERTY_HARD_RT_CAPABLE,
|
|
"Canyon Delay",
|
|
CMT_MAKER("David A. Bartold"),
|
|
CMT_COPYRIGHT("1999, 2000", "David A. Bartold"),
|
|
NULL,
|
|
CMT_Instantiate<CanyonDelay>,
|
|
CanyonDelay::activate,
|
|
CanyonDelay::run,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
|
|
for (int i = 0; i < NUM_PORTS; i++)
|
|
psDescriptor->addPort(
|
|
g_psPortDescriptors[i],
|
|
g_psPortNames[i],
|
|
g_psPortRangeHints[i].HintDescriptor,
|
|
g_psPortRangeHints[i].LowerBound,
|
|
g_psPortRangeHints[i].UpperBound);
|
|
|
|
registerNewPluginDescriptor(psDescriptor);
|
|
}
|