Files
lmms/plugins/LadspaEffect/cmt/src/sine.cpp
T

297 lines
9.7 KiB
C++

/* sine.cpp
Computer Music Toolkit - a library of LADSPA plugins. Copyright (C)
2000-2002 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"
/*****************************************************************************/
/* Sine table size is given by (1 << SINE_TABLE_BITS). */
#define SINE_TABLE_BITS 14
#define SINE_TABLE_SHIFT (8 * sizeof(unsigned long) - SINE_TABLE_BITS)
/*****************************************************************************/
LADSPA_Data * g_pfSineTable = NULL;
LADSPA_Data g_fPhaseStepBase = 0;
/*****************************************************************************/
void
initialise_sine_wavetable() {
if (g_pfSineTable == NULL) {
long lTableSize = (1 << SINE_TABLE_BITS);
double dShift = (double(M_PI) * 2) / lTableSize;
g_pfSineTable = new float[lTableSize];
if (g_pfSineTable != NULL)
for (long lIndex = 0; lIndex < lTableSize; lIndex++)
g_pfSineTable[lIndex] = LADSPA_Data(sin(dShift * lIndex));
}
if (g_fPhaseStepBase == 0) {
g_fPhaseStepBase = (LADSPA_Data)pow(2, sizeof(unsigned long) * 8);
}
}
/*****************************************************************************/
#define OSC_FREQUENCY 0
#define OSC_AMPLITUDE 1
#define OSC_OUTPUT 2
/* This class provides sine wavetable oscillator
plugins. Band-limiting to avoid aliasing is trivial because of the
waveform in use. Four versions of the oscillator are provided,
allowing the amplitude and frequency inputs of the oscillator to be
audio signals rather than controls (for use in AM and FM
synthesis). */
class SineOscillator : public CMT_PluginInstance{
private:
/* Oscillator state: */
unsigned long m_lPhase;
unsigned long m_lPhaseStep;
LADSPA_Data m_fCachedFrequency;
const LADSPA_Data m_fLimitFrequency;
const LADSPA_Data m_fPhaseStepScalar;
void setPhaseStepFromFrequency(const LADSPA_Data fFrequency) {
if (fFrequency != m_fCachedFrequency) {
if (fFrequency >= 0 && fFrequency < m_fLimitFrequency)
m_lPhaseStep = (unsigned long)(m_fPhaseStepScalar * fFrequency);
else
m_lPhaseStep = 0;
m_fCachedFrequency = fFrequency;
}
}
public:
SineOscillator(const LADSPA_Descriptor *,
unsigned long lSampleRate)
: CMT_PluginInstance(3),
m_lPhaseStep(0),
m_fCachedFrequency(0),
m_fLimitFrequency(LADSPA_Data(lSampleRate * 0.5)),
m_fPhaseStepScalar(LADSPA_Data(g_fPhaseStepBase / lSampleRate)) {
}
friend void activateSineOscillator(void * pvHandle);
friend void runSineOscillator_FreqAudio_AmpAudio(LADSPA_Handle Instance,
unsigned long SampleCount);
friend void runSineOscillator_FreqAudio_AmpCtrl(LADSPA_Handle Instance,
unsigned long SampleCount);
friend void runSineOscillator_FreqCtrl_AmpAudio(LADSPA_Handle Instance,
unsigned long SampleCount);
friend void runSineOscillator_FreqCtrl_AmpCtrl(LADSPA_Handle Instance,
unsigned long SampleCount);
};
/*****************************************************************************/
void
activateSineOscillator(void * pvHandle) {
((SineOscillator *)pvHandle)->m_lPhase = 0;
}
/*****************************************************************************/
void
runSineOscillator_FreqAudio_AmpAudio(LADSPA_Handle Instance,
unsigned long SampleCount) {
SineOscillator * poSineOscillator = (SineOscillator *)Instance;
LADSPA_Data * pfFrequency = poSineOscillator->m_ppfPorts[OSC_FREQUENCY];
LADSPA_Data * pfAmplitude = poSineOscillator->m_ppfPorts[OSC_AMPLITUDE];
LADSPA_Data * pfOutput = poSineOscillator->m_ppfPorts[OSC_OUTPUT];
for (unsigned long lIndex = 0; lIndex < SampleCount; lIndex++) {
/* Extract frequency at this point to guarantee inplace
support. */
LADSPA_Data fFrequency = *(pfFrequency++);
*(pfOutput++)
= (g_pfSineTable[poSineOscillator->m_lPhase >> SINE_TABLE_SHIFT]
* *(pfAmplitude++));
poSineOscillator->setPhaseStepFromFrequency(fFrequency);
poSineOscillator->m_lPhase
+= poSineOscillator->m_lPhaseStep;
}
}
/*****************************************************************************/
void
runSineOscillator_FreqAudio_AmpCtrl(LADSPA_Handle Instance,
unsigned long SampleCount) {
SineOscillator * poSineOscillator = (SineOscillator *)Instance;
LADSPA_Data fAmplitude = *(poSineOscillator->m_ppfPorts[OSC_AMPLITUDE]);
LADSPA_Data * pfFrequency = poSineOscillator->m_ppfPorts[OSC_FREQUENCY];
LADSPA_Data * pfOutput = poSineOscillator->m_ppfPorts[OSC_OUTPUT];
for (unsigned long lIndex = 0; lIndex < SampleCount; lIndex++) {
/* Extract frequency at this point to guarantee inplace
support. */
LADSPA_Data fFrequency = *(pfFrequency++);
*(pfOutput++)
= (g_pfSineTable[poSineOscillator->m_lPhase >> SINE_TABLE_SHIFT]
* fAmplitude);
poSineOscillator->setPhaseStepFromFrequency(fFrequency);
poSineOscillator->m_lPhase
+= poSineOscillator->m_lPhaseStep;
}
}
/*****************************************************************************/
void
runSineOscillator_FreqCtrl_AmpAudio(LADSPA_Handle Instance,
unsigned long SampleCount) {
SineOscillator * poSineOscillator = (SineOscillator *)Instance;
poSineOscillator->setPhaseStepFromFrequency
(*(poSineOscillator->m_ppfPorts[OSC_FREQUENCY]));
LADSPA_Data * pfAmplitude = poSineOscillator->m_ppfPorts[OSC_AMPLITUDE];
LADSPA_Data * pfOutput = poSineOscillator->m_ppfPorts[OSC_OUTPUT];
for (unsigned long lIndex = 0; lIndex < SampleCount; lIndex++) {
*(pfOutput++)
= (g_pfSineTable[poSineOscillator->m_lPhase >> SINE_TABLE_SHIFT]
* *(pfAmplitude++));
poSineOscillator->m_lPhase
+= poSineOscillator->m_lPhaseStep;
}
}
/*****************************************************************************/
void
runSineOscillator_FreqCtrl_AmpCtrl(LADSPA_Handle Instance,
unsigned long SampleCount) {
SineOscillator * poSineOscillator = (SineOscillator *)Instance;
LADSPA_Data fAmplitude = *(poSineOscillator->m_ppfPorts[OSC_AMPLITUDE]);
poSineOscillator->setPhaseStepFromFrequency
(*(poSineOscillator->m_ppfPorts[OSC_FREQUENCY]));
LADSPA_Data * pfOutput = poSineOscillator->m_ppfPorts[OSC_OUTPUT];
for (unsigned long lIndex = 0; lIndex < SampleCount; lIndex++) {
*(pfOutput++)
= (g_pfSineTable[poSineOscillator->m_lPhase >> SINE_TABLE_SHIFT]
* fAmplitude);
poSineOscillator->m_lPhase
+= poSineOscillator->m_lPhaseStep;
}
}
/*****************************************************************************/
void
initialise_sine() {
initialise_sine_wavetable();
const char * apcLabels[] = {
"sine_faaa",
"sine_faac",
"sine_fcaa",
"sine_fcac"
};
const char * apcNames[] = {
"Sine Oscillator (Freq:audio, Amp:audio)",
"Sine Oscillator (Freq:audio, Amp:control)",
"Sine Oscillator (Freq:control, Amp:audio)",
"Sine Oscillator (Freq:control, Amp:control)"
};
LADSPA_Run_Function afRunFunction[] = {
runSineOscillator_FreqAudio_AmpAudio,
runSineOscillator_FreqAudio_AmpCtrl,
runSineOscillator_FreqCtrl_AmpAudio,
runSineOscillator_FreqCtrl_AmpCtrl
};
LADSPA_PortDescriptor piFrequencyPortProperties[] = {
LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO,
LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO,
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL
};
LADSPA_PortDescriptor piAmplitudePortProperties[] = {
LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO,
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO,
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL
};
for (long lPluginIndex = 0; lPluginIndex < 4; lPluginIndex++) {
CMT_Descriptor * psDescriptor;
psDescriptor = new CMT_Descriptor
(1063 + lPluginIndex,
apcLabels[lPluginIndex],
LADSPA_PROPERTY_HARD_RT_CAPABLE,
apcNames[lPluginIndex],
CMT_MAKER("Richard W.E. Furse"),
CMT_COPYRIGHT("2000-2002", "Richard W.E. Furse"),
NULL,
CMT_Instantiate<SineOscillator>,
activateSineOscillator,
afRunFunction[lPluginIndex],
NULL,
NULL,
NULL);
psDescriptor->addPort
(piFrequencyPortProperties[lPluginIndex],
"Frequency",
(LADSPA_HINT_BOUNDED_BELOW
| LADSPA_HINT_BOUNDED_ABOVE
| LADSPA_HINT_SAMPLE_RATE
| LADSPA_HINT_LOGARITHMIC
| LADSPA_HINT_DEFAULT_440),
0,
0.5);
psDescriptor->addPort
(piAmplitudePortProperties[lPluginIndex],
"Amplitude",
(LADSPA_HINT_BOUNDED_BELOW
| LADSPA_HINT_LOGARITHMIC
| LADSPA_HINT_DEFAULT_1),
0,
0);
psDescriptor->addPort
(LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
"Output");
registerNewPluginDescriptor(psDescriptor);
}
}
/*****************************************************************************/
void
finalise_sine() {
delete [] g_pfSineTable;
}
/*****************************************************************************/
/* EOF */