Files
lmms/plugins/LadspaEffect/caps/Descriptor.h
Dalton Messmer 0768f5ad2f Fix a few memory issues found with ASan (#6843)
* Fix LADSPA effects memory leak

* Fix buffer overflow in PianoView

* Avoid using invalid iterators in AutomationClip

* Fix memory leaks in SimpleTextFloat

* Handle potential case where QMap::lowerBound(...) returns end iterator

* Implement suggestions from review
2023-09-03 17:29:31 -04:00

224 lines
5.4 KiB
C++

/*
Descriptor.h
Copyright 2004-10 Tim Goetze <tim@quitte.de>
http://quitte.de/dsp/
Creating a LADSPA_Descriptor for a CAPS plugin via a C++ template,
saving a virtual function call compared to the usual method used
for C++ plugins in a C context.
Descriptor<P> expects P to declare some common methods, like init(),
activate() etc, plus a static port_info[] and LADSPA_Data * ports[]
and adding_gain. (P should derive from Plugin, too.)
*/
/*
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program 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 program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA or point your web browser to http://www.gnu.org.
*/
#ifndef _DESCRIPTOR_H_
#define _DESCRIPTOR_H_
#ifdef __SSE__
#include <xmmintrin.h>
#endif
#ifdef __SSE3__
#include <pmmintrin.h>
#endif
/* common stub for Descriptor makes it possible to delete() without special-
* casing for every plugin class.
*/
class DescriptorStub
: public LADSPA_Descriptor
{
public:
DescriptorStub()
{
PortCount = 0;
}
virtual ~DescriptorStub()
{
if (PortCount)
{
delete [] PortNames;
delete [] PortDescriptors;
delete [] PortRangeHints;
}
}
};
inline void
processor_specific_denormal_measures()
{
#ifdef __SSE3__
/* this one works reliably on a 6600 Core2 */
_MM_SET_DENORMALS_ZERO_MODE (_MM_DENORMALS_ZERO_ON);
#endif
#ifdef __SSE__
/* this one doesn't ... */
_MM_SET_FLUSH_ZERO_MODE (_MM_FLUSH_ZERO_ON);
#endif
}
template <class T>
class Descriptor
: public DescriptorStub
{
public:
LADSPA_PortRangeHint * ranges;
public:
Descriptor() { setup(); }
~Descriptor() override = default;
void setup();
void autogen()
{
PortCount = (sizeof (T::port_info) / sizeof (PortInfo));
/* unroll PortInfo members */
const char ** names = new const char * [PortCount];
LADSPA_PortDescriptor * desc = new LADSPA_PortDescriptor [PortCount];
ranges = new LADSPA_PortRangeHint [PortCount];
/* could also assign directly but const_cast is ugly. */
for (int i = 0; i < (int) PortCount; ++i)
{
names[i] = T::port_info[i].name;
desc[i] = T::port_info[i].descriptor;
ranges[i] = T::port_info[i].range;
}
PortNames = names;
PortDescriptors = desc;
PortRangeHints = ranges;
/* LADSPA_Descriptor vtable entries */
instantiate = _instantiate;
connect_port = _connect_port;
activate = _activate;
run = _run;
run_adding = _run_adding;
set_run_adding_gain = _set_run_adding_gain;
deactivate = 0;
cleanup = _cleanup;
}
static LADSPA_Handle _instantiate (
const struct _LADSPA_Descriptor * d, ulong fs)
{
T * plugin = new T();
int n = (int) d->PortCount;
LADSPA_PortRangeHint * ranges = ((Descriptor *) d)->ranges;
plugin->ranges = ranges;
plugin->ports = new sample_t * [n];
/* connect to lower bound as a safety measure */
for (int i = 0; i < n; ++i)
plugin->ports[i] = &(ranges[i].LowerBound);
plugin->fs = fs;
plugin->normal = NOISE_FLOOR;
plugin->init();
return plugin;
}
static void _connect_port (LADSPA_Handle h, ulong i, LADSPA_Data * p)
{
((T *) h)->ports[i] = p;
}
static void _activate (LADSPA_Handle h)
{
T * plugin = (T *) h;
plugin->first_run = 1;
/* since none of the plugins do any RT-critical work in
* activate(), it's safe to defer the actual call to the
* plugin's activate() method for the first run() after
* the host called in here.
*
* It's the simplest way to prevent a parameter smoothing sweep
* in the first audio block after activation.
plugin->activate();
*/
}
static void _run (LADSPA_Handle h, ulong n)
{
T * plugin = (T *) h;
/* We don't reset the processor flags later, it's true. */
processor_specific_denormal_measures();
/* If this is the first audio block after activation,
* initialize the plugin from the current set of parameters. */
if (plugin->first_run)
{
plugin->activate();
plugin->first_run = 0;
}
plugin->run (n);
plugin->normal = -plugin->normal;
}
static void _run_adding (LADSPA_Handle h, ulong n)
{
T * plugin = (T *) h;
/* We don't reset the processor flags later, it's true. */
processor_specific_denormal_measures();
/* If this is the first audio block after activation,
* initialize the plugin from the current set of parameters. */
if (plugin->first_run)
{
plugin->activate();
plugin->first_run = 0;
}
plugin->run_adding (n);
plugin->normal = -plugin->normal;
}
static void _set_run_adding_gain (LADSPA_Handle h, LADSPA_Data g)
{
T * plugin = (T *) h;
plugin->adding_gain = g;
}
static void _cleanup (LADSPA_Handle h)
{
T * plugin = (T *) h;
delete [] plugin->ports;
delete plugin;
}
};
#endif /* _DESCRIPTOR_H_ */