-
Notifications
You must be signed in to change notification settings - Fork 2
Creating Sound Components
Sound components are compiled as shared libraries and can be dynamically loaded at runtime. Using such an approach, the sound components exist separately from the implementation of the Synthesizer framework with only the necessary core headers included. Developers can therefore easily create new sound components and distribute them to users of the Soundgates system.
The following sections describe implementation details of a sound component.
Each sound component needs to be a subclass of SoundComponentImpl. Some constraints have to be met to create a fully functional component. A template component is available, that includes most of the following things:
- There needs to be a
public static const char*fieldnameand agetName()method. These will be used determine which component to initialize when a TGF file is parsed and in logging. MacrosDECLARE_COMPONENTNAMEandDEFINE_COMPONENTNAME(<classname>, <exported name>)can be used to facilitate the inclusion of this. - Ports need to added to their respective list (input or output). The macros
DECLARE_PORT3( SoundPort|ControlPort, <port name>, <port number>)andCREATE_AND_REGISTER_PORT3(<classname>, In|Out, SoundPort|ControlPort, <port name>, <port number>)facilitate this process. These macros declare and initialize ports with namesm_<portname>_<Direction>_Port. - The numbering on the ports should start at one have no gaps. The numbering only contributes to the variable name, but wrong numbering might lead to confusion in other places.
- Input ports and output ports are added to different lists, while control and sound ports are added to the same.
- Depending on whether or not the component should only be available as software, hardware or as both, the remaining procedure differs a bit, to offer corresponding create methods:
- If the component will only ever be a software component, the actual processing and initialization can happen within the same class by implementing the
init()andprocess()functions.EXPORT_SOUNDCOMPONENT_NO_IMPL(<classname>)needs to be added to the header file in this case. - Otherwise,
EXPORT_SOUNDCOMPONENT_SW_ONLY,..._HW_ONLYor..._MIXED_IMPLneed to be used and a subfolder impl with subclasses called<classname>_SWor<classname>_HWneed to created.
- Usually a sound component will touch all samples. The number of samples in each processing step can be retrieved from
Synthesizer::config::blocksize - Access a the i-th sample:
(*sound_port_variable)[i] - Write the i-th sample:
<sound_port_variable>->writeSample(<value>,i) - Or operate directly on the underlying arrays with
sound_port_variable->getRead/WriteBuffer() - When operating directly on the buffers, it is important to note that they are of type char. Casting to int might be required.
- All control values are of type float.
- Access a control value:
control_port_variable->pop() - Write a control value:
control_port_variable->push(<value>) - Sound components should register a callback interface to react on changing incoming control values instead of accessing them directly in their process methods.
- Changing values are therefore propagated immediately if incoming control values trigger changes in outgoing control values.
- Calculations on control values only need to be done each time an input changes and not in every process() step.
Static parameters (e.g. the value of a constant) are passed in to the sound components constructor as std::vector<std::string> params. The float values need to be parsed from this string.
The makefile for a component only needs to include makefiles/common.mk, specify the OBJECTS to build and a rule for a shared library (cf. template makefile) Note that you must have the core library and includes (libsynthesizercore) in your SoundComponents projects to build components, which described in the project settings.
What steps are necessary to bring the component to an FPGA?
What do I have to do to create a pd equivalent to our component?
How do I make the component appear in our editor?