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