505 lines
15 KiB
C++
505 lines
15 KiB
C++
/* analogue.cpp
|
|
|
|
Analogue Voice - Analog synthesizer voice
|
|
Copyright (c) 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 <math.h>
|
|
#include <stdlib.h>
|
|
#include "cmt.h"
|
|
|
|
#define PORT_OUT 0
|
|
#define PORT_GATE 1
|
|
#define PORT_VELOCITY 2
|
|
#define PORT_FREQ 3
|
|
#define PORT_DCO1_OCTAVE 4
|
|
#define PORT_DCO1_WAVEFORM 5
|
|
#define PORT_DCO1_FM 6
|
|
#define PORT_DCO1_PWM 7
|
|
#define PORT_DCO1_ATTACK 8
|
|
#define PORT_DCO1_DECAY 9
|
|
#define PORT_DCO1_SUSTAIN 10
|
|
#define PORT_DCO1_RELEASE 11
|
|
#define PORT_DCO2_OCTAVE 12
|
|
#define PORT_DCO2_WAVEFORM 13
|
|
#define PORT_DCO2_FM 14
|
|
#define PORT_DCO2_PWM 15
|
|
#define PORT_DCO2_ATTACK 16
|
|
#define PORT_DCO2_DECAY 17
|
|
#define PORT_DCO2_SUSTAIN 18
|
|
#define PORT_DCO2_RELEASE 19
|
|
#define PORT_LFO_FREQ 20
|
|
#define PORT_LFO_FADEIN 21
|
|
#define PORT_FILT_ENV_MOD 22
|
|
#define PORT_FILT_LFO_MOD 23
|
|
#define PORT_FILT_RES 24
|
|
#define PORT_FILT_ATTACK 25
|
|
#define PORT_FILT_DECAY 26
|
|
#define PORT_FILT_SUSTAIN 27
|
|
#define PORT_FILT_RELEASE 28
|
|
|
|
#define NUM_PORTS 29
|
|
|
|
#ifndef PI
|
|
#define PI 3.14159265358979F
|
|
#endif
|
|
|
|
typedef struct Envelope
|
|
{
|
|
int envelope_decay;
|
|
LADSPA_Data envelope;
|
|
|
|
Envelope () : envelope_decay (0), envelope (0.0) {}
|
|
} Envelope;
|
|
|
|
class Analogue : public CMT_PluginInstance
|
|
{
|
|
LADSPA_Data sample_rate;
|
|
|
|
int trigger;
|
|
Envelope dco1_env;
|
|
Envelope dco2_env;
|
|
Envelope filt_env;
|
|
LADSPA_Data d1;
|
|
LADSPA_Data d2;
|
|
|
|
LADSPA_Data dco1_accum;
|
|
LADSPA_Data dco2_accum;
|
|
LADSPA_Data lfo_accum;
|
|
|
|
LADSPA_Data lfo_vol;
|
|
|
|
public:
|
|
Analogue(const LADSPA_Descriptor * Descriptor,
|
|
unsigned long SampleRate)
|
|
: CMT_PluginInstance(NUM_PORTS),
|
|
sample_rate (SampleRate),
|
|
trigger (0),
|
|
d1 (0.0), d2 (0.0),
|
|
dco1_accum (0.0), dco2_accum (0.0), lfo_accum (0.0) {
|
|
}
|
|
|
|
~Analogue () {
|
|
}
|
|
|
|
/* Third-order approximation of a sine wave. */
|
|
static inline LADSPA_Data
|
|
fast_sin(LADSPA_Data x) {
|
|
if (x > PI)
|
|
x = (x < PI * 1.5F) ? (PI - x) : (x - 2.0F * PI);
|
|
else if (x > PI * 0.5F)
|
|
x = PI - x;
|
|
|
|
return x * (1.05F - x * x * 0.175F);
|
|
}
|
|
|
|
static inline LADSPA_Data
|
|
tri(LADSPA_Data x) {
|
|
if (x > 0.75F)
|
|
x = x - 1.0F;
|
|
else if (x > 0.25F)
|
|
x = 0.5F - x;
|
|
|
|
return x * 4.0F;
|
|
}
|
|
|
|
static inline LADSPA_Data
|
|
envelope(Envelope *env,
|
|
int gate,
|
|
LADSPA_Data attack,
|
|
LADSPA_Data decay,
|
|
LADSPA_Data sustain,
|
|
LADSPA_Data release)
|
|
{
|
|
if (gate)
|
|
if (env->envelope_decay == 0)
|
|
{
|
|
env->envelope += (1.0F - env->envelope) * attack;
|
|
if (env->envelope >= 0.95F)
|
|
env->envelope_decay = 1;
|
|
}
|
|
else
|
|
env->envelope += (sustain - env->envelope) * decay;
|
|
else
|
|
env->envelope += -env->envelope * release;
|
|
|
|
return env->envelope;
|
|
}
|
|
|
|
static void
|
|
activate(LADSPA_Handle Instance) {
|
|
Analogue *analogue = (Analogue*) Instance;
|
|
|
|
analogue->trigger = 0;
|
|
analogue->dco1_env.envelope_decay = 0;
|
|
analogue->dco1_env.envelope = 0.0;
|
|
analogue->dco2_env.envelope_decay = 0;
|
|
analogue->dco2_env.envelope = 0.0;
|
|
analogue->filt_env.envelope_decay = 0;
|
|
analogue->filt_env.envelope = 0.0;
|
|
analogue->d1 = 0.0F;
|
|
analogue->d2 = 0.0F;
|
|
|
|
analogue->dco1_accum = 0.0F;
|
|
analogue->dco2_accum = 0.0F;
|
|
analogue->lfo_accum = 0.0F;
|
|
analogue->lfo_vol = 0.0F;
|
|
}
|
|
|
|
static inline LADSPA_Data
|
|
osc(int waveform,
|
|
LADSPA_Data inc,
|
|
LADSPA_Data width,
|
|
LADSPA_Data *accum) {
|
|
*accum += inc;
|
|
while (*accum >= 1.0F)
|
|
*accum -= 1.0F;
|
|
|
|
/* 0 = Sine wave */
|
|
if (waveform == 0)
|
|
if (*accum < width)
|
|
return fast_sin (*accum / width * PI);
|
|
else
|
|
return fast_sin (PI + (*accum - width) / (1.0F - width) * PI);
|
|
|
|
/* 1 = Triangle wave */
|
|
else if (waveform == 1)
|
|
if (*accum < width)
|
|
return tri (*accum / width * 0.5);
|
|
else
|
|
return tri (0.5 + (*accum - width) * 0.5 / (1.0F - width));
|
|
|
|
/* 2 = Square wave */
|
|
else if (waveform == 2)
|
|
return (*accum > width) ? 1.0F : -1.0F;
|
|
|
|
/* 3 = Sawtooth wave */
|
|
else if (waveform == 3)
|
|
if (*accum < width)
|
|
return *accum / width * 2.0F - 1.0F;
|
|
else
|
|
return (*accum - width) / (1.0F - width) * 2.0F - 1.0F;
|
|
|
|
/* 4 = Fullwave Rectified Sine wave */
|
|
else if (waveform == 4)
|
|
if (*accum < width)
|
|
return fast_sin (*accum / width * PI);
|
|
else
|
|
return fast_sin ((*accum - width) / (1.0F - width) * PI);
|
|
|
|
/* 5 = Static */
|
|
else
|
|
return (rand () & 1) ? -1.0F : 1.0F;
|
|
}
|
|
|
|
static LADSPA_Data
|
|
inc(LADSPA_Data oct,
|
|
LADSPA_Data freq,
|
|
LADSPA_Data sample_rate) {
|
|
return pow (2.0, oct) * freq / sample_rate;
|
|
}
|
|
|
|
static void
|
|
calc_a_b_c(Analogue *analogue,
|
|
LADSPA_Data freq,
|
|
LADSPA_Data *a,
|
|
LADSPA_Data *b,
|
|
LADSPA_Data *c) {
|
|
LADSPA_Data top_freq, k, res;
|
|
|
|
top_freq = freq;
|
|
top_freq *= PI / analogue->sample_rate;
|
|
res = exp (-1.20 + 3.455 * *analogue->m_ppfPorts[PORT_FILT_RES]);
|
|
|
|
k = exp (-top_freq / res);
|
|
|
|
*a = 2.0 * cos (2.0 * top_freq) * k;
|
|
*b = -k * k;
|
|
*c = (1.0 - *a - *b) * 0.2;
|
|
}
|
|
|
|
static inline LADSPA_Data
|
|
multiplier(Analogue *analogue,
|
|
LADSPA_Data value) {
|
|
return 1.0 - pow (0.05, 1.0 / (analogue->sample_rate * value));
|
|
}
|
|
|
|
static void
|
|
run(LADSPA_Handle Instance,
|
|
unsigned long SampleCount) {
|
|
Analogue *analogue = (Analogue*) Instance;
|
|
unsigned long i;
|
|
int waveform1, waveform2;
|
|
int gate;
|
|
LADSPA_Data lfo_inc, inc1, inc2;
|
|
LADSPA_Data attack1, decay1, release1;
|
|
LADSPA_Data attack2, decay2, release2;
|
|
LADSPA_Data filt_attack, filt_decay, filt_release;
|
|
LADSPA_Data lfo_fadein, a = 0, b = 0, c = 0;
|
|
LADSPA_Data dco1_pwm, dco2_pwm;
|
|
LADSPA_Data dco1_fm, dco2_fm;
|
|
LADSPA_Data filt_lfo_mod;
|
|
LADSPA_Data **ports;
|
|
|
|
ports = analogue->m_ppfPorts;
|
|
gate = (*ports[PORT_GATE] > 0.0);
|
|
if (gate == 1 && analogue->trigger == 0)
|
|
{
|
|
analogue->lfo_vol = 0.0F;
|
|
analogue->dco1_env.envelope_decay = 0;
|
|
analogue->dco1_env.envelope = 0.0;
|
|
analogue->dco2_env.envelope_decay = 0;
|
|
analogue->dco2_env.envelope = 0.0;
|
|
analogue->filt_env.envelope_decay = 0;
|
|
analogue->filt_env.envelope = 0.0;
|
|
}
|
|
|
|
analogue->trigger = gate;
|
|
|
|
waveform1 = (int) *ports[PORT_DCO1_WAVEFORM];
|
|
waveform2 = (int) *ports[PORT_DCO2_WAVEFORM];
|
|
|
|
inc1 = inc (*ports[PORT_DCO1_OCTAVE],
|
|
*ports[PORT_FREQ],
|
|
analogue->sample_rate);
|
|
inc2 = inc (*ports[PORT_DCO2_OCTAVE],
|
|
*ports[PORT_FREQ],
|
|
analogue->sample_rate);
|
|
lfo_inc = 2.0F * PI * *ports[PORT_LFO_FREQ] / analogue->sample_rate;
|
|
|
|
attack1 = multiplier (analogue, *ports[PORT_DCO1_ATTACK]);
|
|
decay1 = multiplier (analogue, *ports[PORT_DCO1_DECAY]);
|
|
release1 = multiplier (analogue, *ports[PORT_DCO1_RELEASE]);
|
|
|
|
attack2 = multiplier (analogue, *ports[PORT_DCO2_ATTACK]);
|
|
decay2 = multiplier (analogue, *ports[PORT_DCO2_DECAY]);
|
|
release2 = multiplier (analogue, *ports[PORT_DCO2_RELEASE]);
|
|
|
|
filt_attack = multiplier (analogue, *ports[PORT_FILT_ATTACK]);
|
|
filt_decay = multiplier (analogue, *ports[PORT_FILT_DECAY]);
|
|
filt_release = multiplier (analogue, *ports[PORT_FILT_RELEASE]);
|
|
|
|
lfo_fadein = 1.0 / (*ports[PORT_LFO_FADEIN] * analogue->sample_rate);
|
|
|
|
dco1_pwm = *analogue->m_ppfPorts[PORT_DCO1_PWM] * 0.225F;
|
|
dco2_pwm = *analogue->m_ppfPorts[PORT_DCO2_PWM] * 0.225F;
|
|
dco1_fm = *analogue->m_ppfPorts[PORT_DCO1_FM] * inc1 * 0.45F;
|
|
dco2_fm = *analogue->m_ppfPorts[PORT_DCO2_FM] * inc2 * 0.45F;
|
|
filt_lfo_mod = *analogue->m_ppfPorts[PORT_FILT_LFO_MOD] * 0.45F;
|
|
|
|
for (i = 0; i < SampleCount; i++)
|
|
{
|
|
LADSPA_Data lfo, sample;
|
|
|
|
analogue->lfo_accum += lfo_inc;
|
|
while (analogue->lfo_accum >= 2.0F * PI)
|
|
analogue->lfo_accum -= 2.0F * PI;
|
|
|
|
lfo = fast_sin (analogue->lfo_accum) * analogue->lfo_vol;
|
|
|
|
analogue->lfo_vol += lfo_fadein;
|
|
if (analogue->lfo_vol >= 1.0F)
|
|
analogue->lfo_vol = 1.0F;
|
|
|
|
envelope (&analogue->filt_env,
|
|
gate, filt_attack, filt_decay,
|
|
*ports[PORT_FILT_SUSTAIN], filt_release);
|
|
|
|
if ((i & 0x000f) == 0)
|
|
calc_a_b_c (analogue,
|
|
*ports[PORT_FREQ] * 0.25F + (analogue->filt_env.envelope *
|
|
*ports[PORT_FILT_ENV_MOD] * *ports[PORT_VELOCITY] *
|
|
(1.5 + filt_lfo_mod * lfo)) * *ports[PORT_FREQ] * 10.0F, &a, &b, &c);
|
|
|
|
sample = osc (waveform1, inc1 * (1.0 + lfo * dco1_fm),
|
|
0.5F + lfo * dco1_pwm,
|
|
&analogue->dco1_accum)
|
|
* envelope (&analogue->dco1_env,
|
|
gate, attack1, decay1,
|
|
*ports[PORT_DCO1_SUSTAIN], release1)
|
|
+ osc (waveform2, inc2 * (1.0 + lfo * dco2_fm),
|
|
0.5F + lfo * dco2_pwm,
|
|
&analogue->dco2_accum)
|
|
* envelope (&analogue->dco2_env,
|
|
gate, attack2, decay2,
|
|
*ports[PORT_DCO2_SUSTAIN], release2);
|
|
|
|
sample = a * analogue->d1 +
|
|
b * analogue->d2 +
|
|
c * *ports[PORT_VELOCITY] * sample;
|
|
|
|
analogue->d2 = analogue->d1;
|
|
analogue->d1 = sample;
|
|
ports[PORT_OUT][i] = sample;
|
|
}
|
|
}
|
|
};
|
|
|
|
static LADSPA_PortDescriptor g_psPortDescriptors[] =
|
|
{
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
LADSPA_PORT_CONTROL | LADSPA_PORT_INPUT,
|
|
LADSPA_PORT_CONTROL | LADSPA_PORT_INPUT,
|
|
LADSPA_PORT_CONTROL | LADSPA_PORT_INPUT
|
|
};
|
|
|
|
static const char * const g_psPortNames[] =
|
|
{
|
|
"Out",
|
|
"Gate",
|
|
"Velocity",
|
|
"Frequency (Hz)",
|
|
|
|
"DCO1 Octave",
|
|
"DCO1 Waveform",
|
|
"DCO1 LFO Frequency Modulation",
|
|
"DCO1 LFO Pulse Width Modulation",
|
|
|
|
"DCO1 Attack",
|
|
"DCO1 Decay",
|
|
"DCO1 Sustain",
|
|
"DCO1 Release",
|
|
|
|
"DCO2 Octave",
|
|
"DCO2 Waveform",
|
|
"DCO2 LFO Frequency Modulation",
|
|
"DCO2 LFO Pulse Width Modulation",
|
|
|
|
"DCO2 Attack",
|
|
"DCO2 Decay",
|
|
"DCO2 Sustain",
|
|
"DCO2 Release",
|
|
|
|
"LFO Frequency (Hz)",
|
|
"LFO Fadein",
|
|
|
|
"Filter Envelope Modulation",
|
|
"Filter LFO Modulation",
|
|
"Filter Resonance",
|
|
|
|
"Filter Attack",
|
|
"Filter Decay",
|
|
"Filter Sustain",
|
|
"Filter Release"
|
|
};
|
|
|
|
static LADSPA_PortRangeHint g_psPortRangeHints[] =
|
|
{
|
|
/* Hints, Lower bound, Upper bound */
|
|
{ 0, 0.0, 0.0 },
|
|
{ LADSPA_HINT_TOGGLED, 0.0, 0.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.0, 1.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.0, 20000.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.001, 1.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.0, 10.0 },
|
|
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, -2.0, 2.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW |
|
|
LADSPA_HINT_INTEGER, -0.1, 5.1 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.0, 1.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.0, 1.0 },
|
|
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.01, 8.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.01, 8.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.00, 1.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.01, 8.0 },
|
|
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, -2.0, 2.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW |
|
|
LADSPA_HINT_INTEGER, -0.1, 5.1 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.0, 1.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.0, 1.0 },
|
|
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.01, 8.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.01, 8.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.00, 1.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.01, 8.0 },
|
|
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.0, 20.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.01, 8.0 },
|
|
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.0, 1.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.0, 1.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.0, 1.0 },
|
|
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.01, 8.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.01, 8.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.00, 1.0 },
|
|
{ LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW, 0.01, 8.0 }
|
|
};
|
|
|
|
void
|
|
initialise_analogue() {
|
|
CMT_Descriptor * psDescriptor;
|
|
|
|
psDescriptor = new CMT_Descriptor
|
|
(1221,
|
|
"analogue",
|
|
LADSPA_PROPERTY_HARD_RT_CAPABLE,
|
|
"Analogue Voice",
|
|
CMT_MAKER("David A. Bartold"),
|
|
CMT_COPYRIGHT("2000", "David A. Bartold"),
|
|
NULL,
|
|
CMT_Instantiate<Analogue>,
|
|
Analogue::activate,
|
|
Analogue::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);
|
|
}
|