-
Notifications
You must be signed in to change notification settings - Fork 2
AudYoFlo: Behavior: Processing Subchains
A chain of components can be included as part of another component by using the appropriate base class. Typically, the data flow graph with a fixed subchain as part of another component has the following architecture:
This text is about how to realize the "Integrating Component" in the Figure and how to specify the integrated components, "Component 1", "Component 2" and "Component 3". The idea to combine components within another component, a component chain nesting, is of particular interest when using complex data flows in the AudYoFlo system as well as in another environment such as, e.g., a VST host.
There are two options how to integrate the sub chain of components: it may be realized as a fixed connection or as a flexible connection. The fixed connection is the more efficient approach to integrate the chained components whereas the flexible connection is more flexible since the inner chain can be established and deallocated while the component is already running. Therefore, it demands a little more computationally effort as memory buffers must be copied.
In this section, the use of a fixed connection sub chain will be explained. A fixed connection sub chain must be setup in ACTIVE state and will be operated when in state PROCESSING just as efficiently as a native chain in the AudYoFlo system. Indeed, from the dataflow graph principle, the fixed connection is identical to a native chain as shown in the following Figure:
From the host point of view, the native chain is rather simple as a device connects to and from a single component only. In the dataflow graph, however, multiple components are involved. And while the outer connection is fixed (device-component-device) the internal connection may be diffferent as long as the changes happen in the state ACTIVE. The fixed connection is denoted as fixed as the inner chain is fixed as soon as processing is started.
In order to create the "Integrating Component", a new class must be implemented on the basis of the base class CayfAuNSubChain.
This class is located in the library ayf-node-connections
and is a template implementation. In order to realize the component, the template must be setup according to the needs, e.g., by deriving from the class CjvxBareNode1io_rearrange
or the class CjvxBareNode1io_zerocopy
to select the appropriate processing principle.
In order to realize a fixed connection and to derive from the CjvxBareNode1io_rearrange
base class, the new class requires to include the header files
#include "CjvxAuNSubChain.h"
#include "jvxNodes/CjvxBareNode1io_rearrange.h"
#include "CayfAuNFixedConnection.h"
Then, the new class is declared as
class CayfAuNMyNewClass :
public CayfAuNSubChain<AyfConnection::CayfAuNFixedConnection<CjvxBareNode1io_rearrange> >
{
...
}
This class can be realized with all hints and tricks as described in the documentation for the base class CjvxBareNode1io_rearrange
. However, the sub chain may be involved as desired when processing is performed. In the configuration phase, the components to be involved may be specified by calling the function call
jvxErrorType CayfAuNConnection::attach_component_chain(
const char* str, jvxComponentType tp,
jvxBool activateBeforeAttach, jvxSize* uniqueId = nullptr) override;
In that call, the name of the component module is specified in parameter str
, the type in tp
. The component that may be addressed can be already in state ACTIVE when involved. In that case argument activateBeforeAttach
may be false. A unique id may be returned in case mulitple components from the same module are involved.
The call to attach the components may be called from within the new component but may also happen from the outside app via the property /iface/ex_interface
which can be adressed through the property interface, e.g.,
IjvxPropertyExtender* pExt = nullptr;
jvx::propertyRawPointerType::CjvxRawPointerTypeExternalPointer rPtr(&pExt);
jvxErrorType resL = propRef->get_property(jvxCallManagerProperties(), rPtr,
jPAD("/iface/ex_interface"), jPD(true));
if (pExt)
{
IjvxPropertyExtenderChainControl* propExtSpec =
castPropIfExtender< IjvxPropertyExtenderChainControl>(pExt);
if (propExtSpec)
{
propExtSpec->attach_component_chain("ayfAuNComponent1", JVX_COMPONENT_AUDIO_NODE, false);
propExtSpec->attach_component_chain("ayfAuNComponent2", JVX_COMPONENT_AUDIO_NODE, false);
propExtSpec->attach_component_chain("ayfAuNComponent3", JVX_COMPONENT_AUDIO_NODE, false);
propExtSpec->attach_component_chain("ayfAuNComponent4", JVX_COMPONENT_AUDIO_NODE, false);
}
}
The four involved components are linked in a chain in the order as specified. The specification of the involved components typically must be performed in the state SELECTED. The inverse to the specification of the components is done on unselect and can be realized as follows:
IjvxPropertyExtender* pExt = nullptr;
jvx::propertyRawPointerType::CjvxRawPointerTypeExternalPointer<IjvxPropertyExtender> rPtr(&pExt);
jvxErrorType resL = propRef->get_property(jvxCallManagerProperties(),
rPtr, jPAD("/iface/ex_interface"), jPD(true));
if (pExt)
{
IjvxPropertyExtenderChainControl* propExtSpec =
castPropIfExtender< IjvxPropertyExtenderChainControl>(pExt);
if (propExtSpec)
{
propExtSpec->detach_component_chain("ayfAuNComponent1", JVX_SIZE_UNSELECTED);
propExtSpec->detach_component_chain("ayfAuNComponent2", JVX_SIZE_UNSELECTED);
propExtSpec->detach_component_chain("ayfAuNComponent3", JVX_SIZE_UNSELECTED);
propExtSpec->detach_component_chain("ayfAuNComponent4", JVX_SIZE_UNSELECTED);
}
}
The fixed subchain internally involves an instance of type HjvxMicroConnection
. The micro connection is configured to be operated as type
jvxConnectionType::JVX_MICROCONNECTION_ENGAGE
with the interface references passed in the connect function set to this
in the class CayfAuNFixedConnection
.
As such, the inplace arguments play no role. For more details, refer to the chapter on the micro connections.