SigmaStudio modules can be of two types: Modules supporting sample/stream processing and Modules supporting block processing. Algorithm Designer can generate both sample processing and block processing Plug-Ins, whereas Designer Control can be used only on block processing schematics and thus supports only block processing.
Algorithm source used for implementing a Module using Algorithm Designer or for generating SigmaStudio Plug-Ins (*.dll) has to be either DLBs generated using CrossCore Embedded Studio or C source code directly entered in the source editor of Algorithm Designer or a combination of both DLB and source code. Direct insertion of C source code in the Algorithm Designer source editor is supported only for block processing Modules. This section gives the general rules, guidelines and conventions to be followed while implementing modules compatible with the Algorithm Designer.
Include file ‘adi_ss_extmod.h’ should be included by the source files.
The entry-point function must have a prefix ‘PROCESS_’ to indicate that it is a sample processing Plug-In function for SigmaStudio. Sub-functions in the source file which are referenced only from the main Plug-In function or other sub-functions need not follow any convention. The general prototype of any Plug-In entry-point function performing sample processing is shown below.
void PROCESS_<algorithm_name> (float pInput[], float pOutput[], float pState[], float pParameter[], int nRepCount)
Assembly entry-point function names must have the ‘PROCESS’ prefix. The general template of any Plug-In sample processing assembly function should be as shown below. It is compulsory to end the function with ‘PROCESS_<algorithm_name>..end’ in case of byte addressed Plug-Ins and ‘_PROCESS_<algorithm_name>.end’ in case of word addressed Plug-Ins.
.section/pm seg_swco; .global PROCESS_<algorithm_name>.; PROCESS_<algorithm_name>.: modify(i7,0xfffffffc); /* offset depends on the required frame space */ /* custom code */ i12 = dm(0xffffffff,i6); jump (m9,i12)(db); rframe; nop; PROCESS_<algorithm_name>..end:
When word addressed mode is used, the template is as shown below.
.section/pm seg_swco; .global _PROCESS_<algorithm_name>; _PROCESS_<algorithm_name>: modify(i7,0xfffffffc); /* offset depends on the required frame space */ /* custom code */ i12 = dm(0xffffffff,i6); jump (m9,i12)(db); rframe; nop; _PROCESS_<algorithm_name>.end:
General rules to be followed are:
The entry-point function must have a prefix ‘BPROCESS_’ to indicate that it is a block processing Plug-In function for SigmaStudio. Sub-functions in the source file which are referenced only from the main Plug-In function or other sub-functions need not follow any convention. The general prototype of a block processing Plug-In entry-point function is as shown below.
void BPROCESS_<algorithm_name> (SSBlockAlgo* pBlockAlgo)
Assembly entry-point function names must have the prefix ‘BPROCESS_’. The general template of any Plug-In block processing assembly function should be as shown below. It is compulsory to end the function with ‘BPROCESS_<algorithm_name>..end’ in case of byte addressed Plug-Ins and ‘_BPROCESS_<algorithm_name>.end’ in case of word addressed Plug-Ins.
.section/pm seg_swco; .global BPROCESS_<algorithm_name>.; BPROCESS_<algorithm_name>.: modify(i7,0xfffffffc); /* offset depends on the required frame space */ /* custom code */ i12 = dm(0xffffffff,i6); jump (m9,i12)(db); rframe; nop; BPROCESS_<algorithm_name>..end:
Same function when implemented in word addressed mode must follow the below template.
.section/pm seg_pmco; .global _BPROCESS_<algorithm_name>; _BPROCESS_<algorithm_name>: modify(i7,0xfffffffc); /* offset depends on the required frame space */ /* custom code */ i12 = dm(0xffffffff,i6); jump (m9,i12)(db); rframe; nop; _BPROCESS_<algorithm_name>.end:
In addition to the process function, block Algorithms can also have an initialization function. Initialization functions are used to initialize the Module in case of decoders and 3rd party post processing Modules. The function name must have the prefix ‘INIT_’ to indicate that it is the initialization function of the Module. The general prototype of a block processing Plug-In initialization function is as shown below.
void INIT_<algorithm_name> (SSBlockAlgo* pBlockAlgo)
If a Module must process a specific number of samples that is different to what SigmaStudio passes in, then BPROCESS wrapper function should deal with it by internal buffering.
typedef struct _SSBlockAlgo { int32_t nInputs; int32_t nOutputs; Block *pInputs; Block *pOutputs; int32_t nGrowth; int32_t nGrowthB; void *pParam; float32_t *pState; float32_t *pScratchDM; float32_t *pScratchPM; float32_t *pStateB; float32_t *pStateC; float32_t *pExtPreState; int32_t *pExtSymbols; }SSBlockAlgo;
Description
The structure SSBlockAlgo is used to pass Module properties as arguments to a block processing Plug-In.
Fields
typedef struct _Block { BlockProperties *pBlockProperties; float *pSamples; } Block; \\
Description
The structure Block is used to define the properties of each input/output channel.
Fields
typedef struct _BlockProperties { int32_t nSamplingRate; int32_t nBlockSize; int32_t nReserve0; int32_t nReserve1; } BlockProperties;
Description
The structure BlockProperties is used to define the properties of each memory block.
Fields
Four different types of data memory are used in the externally coded Algorithm. They are explained below.
Parameters are data generated based on the control data received from the Cell. Runtime Tuning is achieved by modifying the parameter data. Parameters are stored in the parameter buffer and memory is allocated per instance of the Module. Memory for storing parameters in the parameter buffer is allocated by SigmaStudio and the pointer to the memory is passed as an argument to the Plug-In function.
State memory is used to store the internal state of the Algorithm. Every instance of the function/Algorithm has dedicated state memory. This memory is allocated by SigmaStudio and the pointer to the memory is passed as an argument to the Plug-In function. The size of the state memory required by the Algorithm should be mentioned in the Algorithm Designer. Refer to section 7.4 for more details. The state memory is initialized with zeros by SigmaStudio every time before downloading a new Schematic. Four state buffers (pointers) are available for the Plug-In to use.
All global variables and global tables in the Module are treated as constant tables by SigmaStudio. In case of ADSP-SC5xx only one instance of this memory is allocated per schematic. This memory is mapped on to the parameter buffer.
Note: Modification of this memory is allowed even though this is treated as constant table by SigmaStudio. This memory is shared across all modules in any given schematic.
Temporary buffers or variables required by the Algorithm can be mapped to the scratch memory. This memory is shared by all the Modules in the Schematic. There are 2 types of Scratch memory; memory mapped to DM block and memory mapped to PM block. An Algorithm can choose to use either or both based on the requirement. Both scratch memories are allocated by SigmaStudio and the pointer to the memory is passed as a parameter to the Plug-In function. The size of the scratch memory required by the Algorithm should be specified in the Algorithm Designer. Scratch memory is available only for block processing Algorithms. Total amount of scratch Memory reserved by SigmaStudio is the maximum of scratch memory requirement by Modules that are part of the Schematic.
The example code below shows a block processing implementation of a volume control function.
#include "adi_ss_extmod.h" #pragma section("seg_pmco") void BPROCESS_Scale (SSBlockAlgo* pBlkAlgoInfo) { int index, sample, gain, blockSize, repCount; float *pInput, *pOutput; repCount = pBlkAlgoInfo->nGrowth; for(index = 0; index < repCount; index++) { blockSize = pBlkAlgoInfo->pInputs[index].pBlockProperties->nBlockSize; gain = ((float *)pBlkAlgoInfo->pParam)[index]; pInput = pBlkAlgoInfo->pInputs[index].pSamples; pOutput = pBlkAlgoInfo->pOutputs[index].pSamples; for(sample = 0; sample < blockSize; sample++) { pOutput[sample] = pInput[sample] * gain; } } }
The example code below shows a sample processing implementation of a volume control function.
#include "adi_ss_extmod.h" #pragma section("seg_pmco") void PROCESS_Scale (float pInput[], float pOutput[], float pState[], float pParameter[], int nRepCount) { int index; float gain; for(index = 0; index < nRepCount; index++) { gain = pParameter[index]; pOutput[index] = pInput[index] * gain; } }