caps库分析笔记
来源:互联网 发布:如何注册淘宝店 编辑:程序博客网 时间:2024/06/18 11:36
- 接口封装
caps是一个由C++语言编写,依赖GNU编译器拓展的音频处理算法共享库。这里需要普及一下attribute ((constructor))和attribute ((destructor)) 两个属性。constructor属性指定函数在执行程序main前(共享库则在加载时)自动执行。destructor属性指定函数在执行程序结束后(共享库则在卸载时)自动执行。
文件interface.cc
static DescriptorStub * descriptors[N+1];......const LADSPA_Descriptor * ladspa_descriptor (unsigned long i) { return i < N ? descriptors[i] : 0; }
上述代码片是caps对外提供对象指针(并非直接访问)和接口。容易注意到对外提供接口的返回对象指针和定义对外提供的对象指针并不一致。这是因为LADSPA_Descriptor是DescriptorStub的基类。对于C++,子类对象可以强制转换成基类对象(不可以反过来)。
DescriptorStub对象对LADSPA_Descriptor进行封装的目的是为了方便对LADSPA_Descriptor对象的管理(仅仅删除)。上文的对象指针指向的内容通过constructor属性创建和通过destructor属性删除。
创建
__attribute__ ((constructor)) void caps_so_init(){ DescriptorStub ** d = descriptors; /* make sure uninitialised array members are safe to pass to the host */ memset (d, 0, sizeof (descriptors)); *d++ = new Descriptor<Noisegate>(2602); *d++ = new Descriptor<Compress>(1772); *d++ = new Descriptor<CompressX2>(2598); *d++ = new Descriptor<ToneStack>(2589); *d++ = new Descriptor<AmpVTS>(2592); #ifdef SUMMER *d++ = new Descriptor<AmpVI>(1789); #endif *d++ = new Descriptor<CabinetIII>(2601); *d++ = new Descriptor<CabinetIV>(2606); #ifdef WITH_JVREV *d++ = new Descriptor<JVRev>(1778); #endif *d++ = new Descriptor<Plate>(1779); *d++ = new Descriptor<PlateX2>(1795); *d++ = new Descriptor<Saturate>(1771); *d++ = new Descriptor<Spice>(2603); *d++ = new Descriptor<SpiceX2>(2607); *d++ = new Descriptor<ChorusI>(1767); *d++ = new Descriptor<PhaserII>(2586); *d++ = new Descriptor<AutoFilter>(2593); *d++ = new Descriptor<Scape>(2588); *d++ = new Descriptor<Eq10>(1773); *d++ = new Descriptor<Eq10X2>(2594); *d++ = new Descriptor<Eq4p>(2608); *d++ = new Descriptor<EqFA4p>(2609); *d++ = new Descriptor<Wider>(1788); *d++ = new Descriptor<Narrower>(2595); *d++ = new Descriptor<Sin>(1781); *d++ = new Descriptor<White>(1785); *d++ = new Descriptor<Fractal>(1774); *d++ = new Descriptor<Click>(1769); *d++ = new Descriptor<CEO>(1770); assert (d - descriptors <= N);}
删除
__attribute__ ((destructor)) void caps_so_fini(){ DescriptorStub ** d = descriptors; while (*d) delete *d++;}
从上述两段代码可以证实上面的观点。Descriptor引用模板,访问是需要指定模板类型。程序结束时,libc++是不会知道模板的具体类型的(caps_so_fini没有形参)。但是,真正创建的对象却是Descriptor,不是LADSPA_Descriptor,也不是DescriptorStub。原因后面解释。
其实笔者想要利用的是EQ部分(音频均衡器算法),所以笔者只分析EQ相应部分(其中的Eq10)。
*d++ = new Descriptor<Eq10>(1773);
- 对象Descriptor
继承关系
class Descriptor <= class DescriptorStub <= struct LADSPA_Descriptor
Descriptor引用模板,访问是需要指定模板类型,所以需要DescriptorStub。但是DescriptorStub是Descriptor的基类,无法访问Descriptor的拓展成员,所以需要LADSPA_Descriptor存储数据。同时,为了方便C访问,LADSPA_Descriptor采用struct而不是class。LADSPA_Descriptor存储了最关键的数据和接口,自然而言就是核心。笔者比较单纯,对于如此复杂的关系深恶痛绝。
成员
通过继承关系,可知Descriptor的成员应该包括(关心)自身,DescriptorStub和LADSPA_Descriptor的共有成员。DescriptorStub设计的目的仅仅是为了清理工作。没有值得关心的成员。LADSPA_Descriptor是结构体类型,所有成员都为共有成员。Descriptor的函数成员都会赋值到LADSPA_Descriptor的函数指针成员。这里没有用虚函数,笔者为C++所痛心,caps作者心里还是只有C。既然心里只有C,为何还用C++实现,大抵天下负心人都如此,奉承着一个,心里却是别人。抛却七情六欲,冷眼看待一下LADSPA_Descriptor。
typedef struct _LADSPA_Descriptor { /* This numeric identifier indicates the plugin type uniquely. Plugin programmers may reserve ranges of IDs from a central body to avoid clashes. Hosts may assume that IDs are below 0x1000000. */ unsigned long UniqueID; /* This identifier can be used as a unique, case-sensitive identifier for the plugin type within the plugin file. Plugin types should be identified by file and label rather than by index or plugin name, which may be changed in new plugin versions. Labels must not contain white-space characters. */ const char * Label; /* This indicates a number of properties of the plugin. */ LADSPA_Properties Properties; /* This member points to the null-terminated name of the plugin (e.g. "Sine Oscillator"). */ const char * Name; /* This member points to the null-terminated string indicating the maker of the plugin. This can be an empty string but not NULL. */ const char * Maker; /* This member points to the null-terminated string indicating any copyright applying to the plugin. If no Copyright applies the string "None" should be used. */ const char * Copyright; /* This indicates the number of ports (input AND output) present on the plugin. */ unsigned long PortCount; /* This member indicates an array of port descriptors. Valid indices vary from 0 to PortCount-1. */ const LADSPA_PortDescriptor * PortDescriptors; /* This member indicates an array of null-terminated strings describing ports (e.g. "Frequency (Hz)"). Valid indices vary from 0 to PortCount-1. */ const char * const * PortNames; /* This member indicates an array of range hints for each port (see above). Valid indices vary from 0 to PortCount-1. */ const LADSPA_PortRangeHint * PortRangeHints; /* This may be used by the plugin developer to pass any custom implementation data into an instantiate call. It must not be used or interpreted by the host. It is expected that most plugin writers will not use this facility as LADSPA_Handle should be used to hold instance data. */ void * ImplementationData; /* This member is a function pointer that instantiates a plugin. A handle is returned indicating the new plugin instance. The instantiation function accepts a sample rate as a parameter. The plugin descriptor from which this instantiate function was found must also be passed. This function must return NULL if instantiation fails. Note that instance initialisation should generally occur in activate() rather than here. */ LADSPA_Handle (*instantiate)(const struct _LADSPA_Descriptor * Descriptor, unsigned long SampleRate); /* This member is a function pointer that connects a port on an instantiated plugin to a memory location at which a block of data for the port will be read/written. The data location is expected to be an array of LADSPA_Data for audio ports or a single LADSPA_Data value for control ports. Memory issues will be managed by the host. The plugin must read/write the data at these locations every time run() or run_adding() is called and the data present at the time of this connection call should not be considered meaningful. connect_port() may be called more than once for a plugin instance to allow the host to change the buffers that the plugin is reading or writing. These calls may be made before or after activate() or deactivate() calls. connect_port() must be called at least once for each port before run() or run_adding() is called. When working with blocks of LADSPA_Data the plugin should pay careful attention to the block size passed to the run function as the block allocated may only just be large enough to contain the block of samples. Plugin writers should be aware that the host may elect to use the same buffer for more than one port and even use the same buffer for both input and output (see LADSPA_PROPERTY_INPLACE_BROKEN). However, overlapped buffers or use of a single buffer for both audio and control data may result in unexpected behaviour. */ void (*connect_port)(LADSPA_Handle Instance, unsigned long Port, LADSPA_Data * DataLocation); /* This member is a function pointer that initialises a plugin instance and activates it for use. This is separated from instantiate() to aid real-time support and so that hosts can reinitialise a plugin instance by calling deactivate() and then activate(). In this case the plugin instance must reset all state information dependent on the history of the plugin instance except for any data locations provided by connect_port() and any gain set by set_run_adding_gain(). If there is nothing for activate() to do then the plugin writer may provide a NULL rather than an empty function. When present, hosts must call this function once before run() (or run_adding()) is called for the first time. This call should be made as close to the run() call as possible and indicates to real-time plugins that they are now live. Plugins should not rely on a prompt call to run() after activate(). activate() may not be called again unless deactivate() is called first. Note that connect_port() may be called before or after a call to activate(). */ void (*activate)(LADSPA_Handle Instance); /* This method is a function pointer that runs an instance of a plugin for a block. Two parameters are required: the first is a handle to the particular instance to be run and the second indicates the block size (in samples) for which the plugin instance may run. Note that if an activate() function exists then it must be called before run() or run_adding(). If deactivate() is called for a plugin instance then the plugin instance may not be reused until activate() has been called again. If the plugin has the property LADSPA_PROPERTY_HARD_RT_CAPABLE then there are various things that the plugin should not do within the run() or run_adding() functions (see above). */ void (*run)(LADSPA_Handle Instance, unsigned long SampleCount); /* This method is a function pointer that runs an instance of a plugin for a block. This has identical behaviour to run() except in the way data is output from the plugin. When run() is used, values are written directly to the memory areas associated with the output ports. However when run_adding() is called, values must be added to the values already present in the memory areas. Furthermore, output values written must be scaled by the current gain set by set_run_adding_gain() (see below) before additioCn. run_adding() is optional. When it is not provided by a plugin, this function pointer must be set to NULL. When it is provided, the function set_run_adding_gain() must be provided also. */ void (*run_adding)(LADSPA_Handle Instance, unsigned long SampleCount); /* This method is a function pointer that sets the output gain for use when run_adding() is called (see above). If this function is never called the gain is assumed to default to 1. Gain information should be retained when activate() or deactivate() are called. This function should be provided by the plugin if and only if the run_adding() function is provided. When it is absent this function pointer must be set to NULL. */ void (*set_run_adding_gain)(LADSPA_Handle Instance, LADSPA_Data Gain); /* This is the counterpart to activate() (see above). If there is nothing for deactivate() to do then the plugin writer may provide a NULL rather than an empty function. Hosts must deactivate all activated units after they have been run() (or run_adding()) for the last time. This call should be made as close to the last run() call as possible and indicates to real-time plugins that they are no longer live. Plugins should not rely on prompt deactivation. Note that connect_port() may be called before or after a call to deactivate(). Deactivation is not similar to pausing as the plugin instance will be reinitialised when activate() is called to reuse it. */ void (*deactivate)(LADSPA_Handle Instance); /* Once an instance of a plugin has been finished with it can be deleted using the following function. The instance handle passed ceases to be valid after this call. If activate() was called for a plugin instance then a corresponding call to deactivate() must be made before cleanup() is called. */ void (*cleanup)(LADSPA_Handle Instance);} LADSPA_Descriptor;/**********************************************************************//* Accessing a Plugin: *//* The exact mechanism by which plugins are loaded is host-dependent, however all most hosts will need to know is the name of shared object file containing the plugin types. To allow multiple hosts to share plugin types, hosts may wish to check for environment variable LADSPA_PATH. If present, this should contain a colon-separated path indicating directories that should be searched (in order) when loading plugin types. A plugin programmer must include a function called "ladspa_descriptor" with the following function prototype within the shared object file. This function will have C-style linkage (if you are using C++ this is taken care of by the `extern "C"' clause at the top of the file). A host will find the plugin shared object file by one means or another, find the ladspa_descriptor() function, call it, and proceed from there. Plugin types are accessed by index (not ID) using values from 0 upwards. Out of range indexes must result in this function returning NULL, so the plugin count can be determined by checking for the least index that results in NULL being returned. */const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index);/* Datatype corresponding to the ladspa_descriptor() function. */typedef const LADSPA_Descriptor * (*LADSPA_Descriptor_Function)(unsigned long Index);/**********************************************************************/#ifdef __cplusplus}
- caps库分析笔记
- CAPS
- D3D9 CAPS
- tps & caps
- mulitmedia caps
- Button caps
- cAPS lOCK
- [学习笔记]Linux下使用Emacs:交换Ctrl和Caps lock键
- 薪水上限 pay caps
- CSU 1093: Caps Lock
- HOJ 3072 cAPS LOCK
- A. cAPS lOCK
- Gstreamer之Caps协商
- 131A - cAPS lOCK
- 131A - cAPS lOCK
- ChangeKeyBoad Caps ctrl
- CSU1093: Caps Lock
- 监听caps lock问题
- VC++MFC开发中的鼠标事件的信号传递
- Posts Tagged 【dfs】Restore IP Addresses
- mysql limit使用注意项
- 2015微软编程之美挑战赛初赛第1场
- 经典的分配问题12态
- caps库分析笔记
- JNDI
- scrollLeft() 妙用 鼠标移动 反方向图片滚动
- 重装win7后,所有USB接口无法使用(鼠标、键盘、U盘)
- js css文件压缩
- ArrayList用法
- 使用过滤器进行文件压缩
- linux文件合并、去重、拆分
- linux黑客笔记