1 /* sine.cpp
2
3 Free software by Richard W.E. Furse. Do with as you will. No
4 warranty.
5
6 This LADSPA plugin is written in C++ and provides a class that
7 implements a sine oscillator using a wavetable. Band-limiting to
8 avoid aliasing is trivial because of the waveform in use. Four
9 versions of the oscillator are provided, allowing the amplitude and
10 frequency inputs of the oscillator to be audio signals rather than
11 controls (for use in AM and FM synthesis).
12
13 This file has poor memory protection. Failures during new() will
14 not recover nicely. */
15
16 /*****************************************************************************/
17
18 #include <cmath>
19 #include <cstdlib>
20 #include <cstring>
21
22 /*****************************************************************************/
23
24 #include "ladspa.h"
25
26 /*****************************************************************************/
27
28 /* The port numbers for the plugin: */
29
30 #define OSC_FREQUENCY 0
31 #define OSC_AMPLITUDE 1
32 #define OSC_OUTPUT 2
33
34 /*****************************************************************************/
35
36 /* Sine table size is given by (1<<SINE_TABLE_BITS). */
37 #define SINE_TABLE_BITS 14
38 #define SINE_TABLE_SHIFT (8 * sizeof(unsigned long) - SINE_TABLE_BITS)
39
40 static LADSPA_Data * g_pfSineTable = NULL;
41 static LADSPA_Data g_fPhaseStepBase = 0;
42
43 /*****************************************************************************/
44
45 static inline char *
localStrdup(const char * input)46 localStrdup(const char * input) {
47 char * output = new char[strlen(input) + 1];
48 strcpy(output, input);
49 return output;
50 }
51
52 /*****************************************************************************/
53
54 static void
initialise_sine_table()55 initialise_sine_table() {
56 if (g_pfSineTable == NULL) {
57 long lTableSize = (1 << SINE_TABLE_BITS);
58 double dShift = (double(M_PI) * 2) / lTableSize;
59 g_pfSineTable = new float[lTableSize];
60 if (g_pfSineTable != NULL)
61 for (long lIndex = 0; lIndex < lTableSize; lIndex++)
62 g_pfSineTable[lIndex] = LADSPA_Data(sin(dShift * lIndex));
63 }
64 if (g_fPhaseStepBase == 0) {
65 g_fPhaseStepBase = (LADSPA_Data)pow(2, sizeof(unsigned long) * 8);
66 }
67 }
68
69 /*****************************************************************************/
70
71 static LADSPA_Handle instantiateSineOscillator(const LADSPA_Descriptor *,
72 unsigned long SampleRate);
73 static void connectPortToSineOscillator(LADSPA_Handle Instance,
74 unsigned long Port,
75 LADSPA_Data * DataLocation);
76 static void activateSineOscillator(void * pvHandle);
77 static void runSineOscillator_FreqAudio_AmpAudio(LADSPA_Handle Instance,
78 unsigned long SampleCount);
79 static void runSineOscillator_FreqAudio_AmpCtrl(LADSPA_Handle Instance,
80 unsigned long SampleCount);
81 static void runSineOscillator_FreqCtrl_AmpAudio(LADSPA_Handle Instance,
82 unsigned long SampleCount);
83 static void runSineOscillator_FreqCtrl_AmpCtrl(LADSPA_Handle Instance,
84 unsigned long SampleCount);
85 static void cleanupSineOscillator(void *pvHandle);
86
87 class SineOscillator {
88 private:
89
90 /* Ports: */
91 LADSPA_Data * m_pfFrequency;
92 LADSPA_Data * m_pfAmplitude;
93 LADSPA_Data * m_pfOutput;
94
95 /* Oscillator state: */
96 unsigned long m_lPhase;
97 unsigned long m_lPhaseStep;
98 LADSPA_Data m_fCachedFrequency;
99 const LADSPA_Data m_fLimitFrequency;
100 const LADSPA_Data m_fPhaseStepScalar;
101
SineOscillator(const long lSampleRate)102 SineOscillator(const long lSampleRate)
103 : m_lPhaseStep(0),
104 m_fCachedFrequency(0),
105 m_fLimitFrequency(LADSPA_Data(lSampleRate * 0.5)),
106 m_fPhaseStepScalar(LADSPA_Data(g_fPhaseStepBase / lSampleRate)) {
107 }
108
setPhaseStepFromFrequency(const LADSPA_Data fFrequency)109 void setPhaseStepFromFrequency(const LADSPA_Data fFrequency) {
110 if (fFrequency != m_fCachedFrequency) {
111 if (fFrequency >= 0 && fFrequency < m_fLimitFrequency)
112 m_lPhaseStep = (unsigned long)(m_fPhaseStepScalar * fFrequency);
113 else
114 m_lPhaseStep = 0;
115 m_fCachedFrequency = fFrequency;
116 }
117 }
118
119 friend LADSPA_Handle instantiateSineOscillator(const LADSPA_Descriptor *,
120 unsigned long SampleRate);
121 friend void connectPortToSineOscillator(LADSPA_Handle Instance,
122 unsigned long Port,
123 LADSPA_Data * DataLocation);
124 friend void activateSineOscillator(void * pvHandle);
125 friend void runSineOscillator_FreqAudio_AmpAudio(LADSPA_Handle Instance,
126 unsigned long SampleCount);
127 friend void runSineOscillator_FreqAudio_AmpCtrl(LADSPA_Handle Instance,
128 unsigned long SampleCount);
129 friend void runSineOscillator_FreqCtrl_AmpAudio(LADSPA_Handle Instance,
130 unsigned long SampleCount);
131 friend void runSineOscillator_FreqCtrl_AmpCtrl(LADSPA_Handle Instance,
132 unsigned long SampleCount);
133 friend void cleanupSineOscillator(void *pvHandle);
134
135 };
136
137 /*****************************************************************************/
138
139 static LADSPA_Handle
instantiateSineOscillator(const LADSPA_Descriptor *,unsigned long SampleRate)140 instantiateSineOscillator(const LADSPA_Descriptor *,
141 unsigned long SampleRate) {
142 return new SineOscillator(SampleRate);
143 }
144
145 /*****************************************************************************/
146
147 static void
connectPortToSineOscillator(LADSPA_Handle Instance,unsigned long Port,LADSPA_Data * DataLocation)148 connectPortToSineOscillator(LADSPA_Handle Instance,
149 unsigned long Port,
150 LADSPA_Data * DataLocation) {
151 switch (Port) {
152 case OSC_FREQUENCY:
153 ((SineOscillator *)Instance)->m_pfFrequency = DataLocation;
154 break;
155 case OSC_AMPLITUDE:
156 ((SineOscillator *)Instance)->m_pfAmplitude = DataLocation;
157 break;
158 case OSC_OUTPUT:
159 ((SineOscillator *)Instance)->m_pfOutput = DataLocation;
160 break;
161 }
162 }
163
164 /*****************************************************************************/
165
166 static void
activateSineOscillator(void * pvHandle)167 activateSineOscillator(void * pvHandle) {
168 ((SineOscillator *)pvHandle)->m_lPhase = 0;
169 }
170
171 /*****************************************************************************/
172
173 static void
runSineOscillator_FreqAudio_AmpAudio(LADSPA_Handle Instance,unsigned long SampleCount)174 runSineOscillator_FreqAudio_AmpAudio(LADSPA_Handle Instance,
175 unsigned long SampleCount) {
176 SineOscillator * poSineOscillator = (SineOscillator *)Instance;
177 for (unsigned long lIndex = 0; lIndex < SampleCount; lIndex++) {
178 /* Extract frequency at this point to guarantee inplace
179 support. */
180 LADSPA_Data fFrequency
181 = (poSineOscillator->m_pfFrequency[lIndex]);
182 poSineOscillator->m_pfOutput[lIndex]
183 = (g_pfSineTable[poSineOscillator->m_lPhase >> SINE_TABLE_SHIFT]
184 * poSineOscillator->m_pfAmplitude[lIndex]);
185 poSineOscillator->setPhaseStepFromFrequency(fFrequency);
186 poSineOscillator->m_lPhase
187 += poSineOscillator->m_lPhaseStep;
188 }
189 }
190
191 /*****************************************************************************/
192
193 static void
runSineOscillator_FreqAudio_AmpCtrl(LADSPA_Handle Instance,unsigned long SampleCount)194 runSineOscillator_FreqAudio_AmpCtrl(LADSPA_Handle Instance,
195 unsigned long SampleCount) {
196 SineOscillator * poSineOscillator = (SineOscillator *)Instance;
197 LADSPA_Data fAmplitude = *(poSineOscillator->m_pfAmplitude);
198 for (unsigned long lIndex = 0; lIndex < SampleCount; lIndex++) {
199 /* Extract frequency at this point to guarantee inplace
200 support. */
201 LADSPA_Data fFrequency
202 = (poSineOscillator->m_pfFrequency[lIndex]);
203 poSineOscillator->m_pfOutput[lIndex]
204 = (g_pfSineTable[poSineOscillator->m_lPhase >> SINE_TABLE_SHIFT]
205 * fAmplitude);
206 poSineOscillator->setPhaseStepFromFrequency(fFrequency);
207 poSineOscillator->m_lPhase
208 += poSineOscillator->m_lPhaseStep;
209 }
210 }
211
212 /*****************************************************************************/
213
214 static void
runSineOscillator_FreqCtrl_AmpAudio(LADSPA_Handle Instance,unsigned long SampleCount)215 runSineOscillator_FreqCtrl_AmpAudio(LADSPA_Handle Instance,
216 unsigned long SampleCount) {
217 SineOscillator * poSineOscillator = (SineOscillator *)Instance;
218 poSineOscillator->setPhaseStepFromFrequency
219 (*(poSineOscillator->m_pfFrequency));
220 for (unsigned long lIndex = 0; lIndex < SampleCount; lIndex++) {
221 poSineOscillator->m_pfOutput[lIndex]
222 = (g_pfSineTable[poSineOscillator->m_lPhase >> SINE_TABLE_SHIFT]
223 * poSineOscillator->m_pfAmplitude[lIndex]);
224 poSineOscillator->m_lPhase
225 += poSineOscillator->m_lPhaseStep;
226 }
227 }
228
229 /*****************************************************************************/
230
231 static void
runSineOscillator_FreqCtrl_AmpCtrl(LADSPA_Handle Instance,unsigned long SampleCount)232 runSineOscillator_FreqCtrl_AmpCtrl(LADSPA_Handle Instance,
233 unsigned long SampleCount) {
234 SineOscillator * poSineOscillator = (SineOscillator *)Instance;
235 LADSPA_Data fAmplitude = *(poSineOscillator->m_pfAmplitude);
236 poSineOscillator->setPhaseStepFromFrequency
237 (*(poSineOscillator->m_pfFrequency));
238 for (unsigned long lIndex = 0; lIndex < SampleCount; lIndex++) {
239 poSineOscillator->m_pfOutput[lIndex]
240 = (g_pfSineTable[poSineOscillator->m_lPhase >> SINE_TABLE_SHIFT]
241 * fAmplitude);
242 poSineOscillator->m_lPhase
243 += poSineOscillator->m_lPhaseStep;
244 }
245 }
246
247 /*****************************************************************************/
248
249 static void
cleanupSineOscillator(void * pvHandle)250 cleanupSineOscillator(void *pvHandle) {
251 delete (SineOscillator *)pvHandle;
252 }
253
254 /*****************************************************************************/
255
256 typedef char * char_ptr;
257
258 static LADSPA_Descriptor * g_psDescriptors[4] = { NULL, NULL, NULL, NULL };
259
260 /*****************************************************************************/
261
262 /* Global object used handle startup initialisation and shut down
263 tidying. Performs the function of the _init() and _fini() calls in
264 the C modules. */
265 class StartupShutdownHandler {
266 public:
267
StartupShutdownHandler()268 StartupShutdownHandler() {
269
270 char ** pcPortNames;
271 LADSPA_PortDescriptor * piPortDescriptors;
272 LADSPA_PortRangeHint * psPortRangeHints;
273
274 initialise_sine_table();
275
276 for (long lPluginIndex = 0; lPluginIndex < 4; lPluginIndex++) {
277
278 g_psDescriptors[lPluginIndex] = new LADSPA_Descriptor;
279 if (g_psDescriptors[lPluginIndex] == NULL)
280 break;
281
282 g_psDescriptors[lPluginIndex]->UniqueID
283 = 1044 + lPluginIndex; /* 1044-1047. */
284 g_psDescriptors[lPluginIndex]->Properties
285 = LADSPA_PROPERTY_HARD_RT_CAPABLE;
286 g_psDescriptors[lPluginIndex]->Maker
287 = localStrdup("Richard Furse (LADSPA example plugins)");
288 g_psDescriptors[lPluginIndex]->Copyright
289 = localStrdup("None");
290 g_psDescriptors[lPluginIndex]->PortCount
291 = 3;
292 piPortDescriptors
293 = new LADSPA_PortDescriptor[3];
294 g_psDescriptors[lPluginIndex]->PortDescriptors
295 = (const LADSPA_PortDescriptor *)piPortDescriptors;
296 piPortDescriptors[OSC_OUTPUT]
297 = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
298 pcPortNames
299 = new char_ptr[3];
300 g_psDescriptors[lPluginIndex]->PortNames
301 = (const char **)pcPortNames;
302 pcPortNames[OSC_FREQUENCY]
303 = localStrdup("Frequency (Hz)");
304 pcPortNames[OSC_AMPLITUDE]
305 = localStrdup("Amplitude");
306 pcPortNames[OSC_OUTPUT]
307 = localStrdup("Output");
308 psPortRangeHints
309 = new LADSPA_PortRangeHint[3];
310 g_psDescriptors[lPluginIndex]->PortRangeHints
311 = (const LADSPA_PortRangeHint *)psPortRangeHints;
312 psPortRangeHints[OSC_FREQUENCY].HintDescriptor
313 = (LADSPA_HINT_BOUNDED_BELOW
314 | LADSPA_HINT_BOUNDED_ABOVE
315 | LADSPA_HINT_SAMPLE_RATE
316 | LADSPA_HINT_LOGARITHMIC
317 | LADSPA_HINT_DEFAULT_440);
318 psPortRangeHints[OSC_FREQUENCY].LowerBound
319 = 0;
320 psPortRangeHints[OSC_FREQUENCY].UpperBound
321 = 0.5;
322 psPortRangeHints[OSC_AMPLITUDE].HintDescriptor
323 = (LADSPA_HINT_BOUNDED_BELOW
324 | LADSPA_HINT_LOGARITHMIC
325 | LADSPA_HINT_DEFAULT_1);
326 psPortRangeHints[OSC_AMPLITUDE].LowerBound
327 = 0;
328 psPortRangeHints[OSC_OUTPUT].HintDescriptor
329 = 0;
330 g_psDescriptors[lPluginIndex]->instantiate
331 = instantiateSineOscillator;
332 g_psDescriptors[lPluginIndex]->connect_port
333 = connectPortToSineOscillator;
334 g_psDescriptors[lPluginIndex]->activate
335 = activateSineOscillator;
336 g_psDescriptors[lPluginIndex]->run_adding
337 = NULL;
338 g_psDescriptors[lPluginIndex]->set_run_adding_gain
339 = NULL;
340 g_psDescriptors[lPluginIndex]->deactivate
341 = NULL;
342 g_psDescriptors[lPluginIndex]->cleanup
343 = cleanupSineOscillator;
344
345 switch (lPluginIndex) {
346 case 0:
347 g_psDescriptors[lPluginIndex]->Label
348 = localStrdup("sine_faaa");
349 g_psDescriptors[lPluginIndex]->Name
350 = localStrdup("Sine Oscillator (Freq:audio, Amp:audio)");
351 piPortDescriptors[OSC_FREQUENCY]
352 = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
353 piPortDescriptors[OSC_AMPLITUDE]
354 = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
355 g_psDescriptors[lPluginIndex]->run
356 = runSineOscillator_FreqAudio_AmpAudio;
357 break;
358 case 1:
359 g_psDescriptors[lPluginIndex]->Label
360 = localStrdup("sine_faac");
361 g_psDescriptors[lPluginIndex]->Name
362 = localStrdup("Sine Oscillator (Freq:audio, Amp:control)");
363 piPortDescriptors[OSC_FREQUENCY]
364 = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
365 piPortDescriptors[OSC_AMPLITUDE]
366 = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
367 g_psDescriptors[lPluginIndex]->run
368 = runSineOscillator_FreqAudio_AmpCtrl;
369 break;
370 case 2:
371 g_psDescriptors[lPluginIndex]->Label
372 = localStrdup("sine_fcaa");
373 g_psDescriptors[lPluginIndex]->Name
374 = localStrdup("Sine Oscillator (Freq:control, Amp:audio)");
375 piPortDescriptors[OSC_FREQUENCY]
376 = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
377 piPortDescriptors[OSC_AMPLITUDE]
378 = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
379 g_psDescriptors[lPluginIndex]->run
380 = runSineOscillator_FreqCtrl_AmpAudio;
381 break;
382 case 3:
383 g_psDescriptors[lPluginIndex]->Label
384 = localStrdup("sine_fcac");
385 g_psDescriptors[lPluginIndex]->Name
386 = localStrdup("Sine Oscillator (Freq:control, Amp:control)");
387 piPortDescriptors[OSC_FREQUENCY]
388 = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
389 piPortDescriptors[OSC_AMPLITUDE]
390 = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
391 g_psDescriptors[lPluginIndex]->run
392 = runSineOscillator_FreqCtrl_AmpCtrl;
393 break;
394 }
395 }
396 }
397
deleteDescriptor(LADSPA_Descriptor * psDescriptor)398 void deleteDescriptor(LADSPA_Descriptor * psDescriptor) {
399 unsigned long lIndex;
400 if (psDescriptor) {
401 delete [] psDescriptor->Label;
402 delete [] psDescriptor->Name;
403 delete [] psDescriptor->Maker;
404 delete [] psDescriptor->Copyright;
405 delete [] psDescriptor->PortDescriptors;
406 for (lIndex = 0; lIndex < psDescriptor->PortCount; lIndex++)
407 delete [] psDescriptor->PortNames[lIndex];
408 delete [] psDescriptor->PortNames;
409 delete [] psDescriptor->PortRangeHints;
410 delete psDescriptor;
411 }
412 }
413
~StartupShutdownHandler()414 ~StartupShutdownHandler() {
415 deleteDescriptor(g_psDescriptors[0]);
416 deleteDescriptor(g_psDescriptors[1]);
417 deleteDescriptor(g_psDescriptors[2]);
418 deleteDescriptor(g_psDescriptors[3]);
419 delete [] g_pfSineTable;
420 }
421
422 };
423
424 static StartupShutdownHandler g_oShutdownStartupHandler;
425
426 /*****************************************************************************/
427
428 const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index)429 ladspa_descriptor(unsigned long Index) {
430 if (Index < 4)
431 return g_psDescriptors[Index];
432 else
433 return NULL;
434 }
435
436 /*****************************************************************************/
437
438 /* EOF */
439