Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Scroll Documents: Update page title prefix

...

Steps 1 and 3 are automated using the awe_generate_library.m command.  Many other MATLAB functions are internally called. Only a few other functions are documented here to help you better understand the code generation process.  Step 4 is done separately in VisualStudio and described in Generating Documentation.

awe_generate_library.m

awe_generate_library(MM, DIR, LIBNAME, USESDLLS, GENDOC)

...

  • MM — cell array of audio module structures.

  • DIR — base directory in which the generated files should be placed.  Files are written here and in several other subdirectories.

  • LIBNAME — string specifying the name of the library.  For example, 'Advanced'.

  • USESDLLS — structure specifying other module libraries that the newly built library depends upon.  A library has a dependencies when it internally utilizes a module contained in another library.  By default, USESDLLS=[] and the library is independent of others.

  • GENDOC — integer indicating whether module documentation should be generated.  By default, GENDOC=0 and no documentation is generated.  If GENDOC=1, then a single document is created for the entire module library.  If GENDOC=2, then a separate document is created for each audio module.

Creating the Cell Array of Modules

The argument MM, is a cell array populated with modules to be placed in the final library.  For example, it might contain:

Code Block
MM=cell(0,0);
MM{end+1}=downsampler_example_module('temp');
MM{end+1}=fader_example_fract32_module('temp');
MM{end+1}=fader_example_module('temp');
MM{end+1}=lah_limiter_example_module('temp');
MM{end+1}=peak_hold_example_fract32_module('temp');
MM{end+1}=peak_hold_example_module('temp');
MM{end+1}=scaler_example_module('temp');
MM{end+1}=scaler_smoothed_example_module('temp');

Specifying Dependencies

USESDLLS is a cell array of structures that specifies dependencies.  Each structure contains the fields:

...

The error message indicates that the FaderExample module has a dependency on ScalerSmoothed and that ScalerSmoothed is not in the dependency list.  Similarly, LAHLimiter has 3 unsatisfied dependencies.

Specifying the Output Directory

The argument DIR to awe_generate_library.m specifies the directory in which to generate the modules.  There are different ways to specify the directory including hard coding it.

...

Code Block
MFILE=mfilename('fullpath');
[pathstr, name]=fileparts(MFILE);
 
% Remove the last directory level
ind=find(pathstr == filesep);
ind=max(ind);

Generated Files

Let DIR be the base directory for the audio module library and let 'Examples' be the name of the library.  awe_generate_library.m creates the following files and folders:

  • <DIR>\Examples.h — Header file containing extern definitions for each module class object.  It also has macros defining the entire list of modules and all dependencies.

  • <DIR>\Examples.sch — Overall schema file for the library.

  • <DIR>\ExamplesSchema.cpp — Compiled schema file.

  • 📁 <DIR>\Doc — Location of generated documentation

  • 📁 <DIR>\Include — Location of generated module include files

  • 📁 <DIR>\matlab — Location of the module m-files.  This also contains the master library make script.

  • 📁 <DIR>\matlab\code — Suggested location for the inner code pieces.

  • 📁 <DIR>\matlab\process — Suggested location of the MATLAB versions of the processing functions.

  • 📁 <DIR>\matlab\test — Suggested location of MATLAB test scripts which validate the operation of the modules.

  • 📁 <DIR>\Source – Location of the generated module source files.

  • 📁 <DIR>\xml – Module XML file for AWE Designer, explained in get_variable.m and set_variable.m .

SchemaBuilder.exe

You'll notice this executable within the Audio Weaver Bin directory.  This executable compiles the schema information.  That is, it takes a .sch file and compiles into a .cpp file.  The .cpp file is then included in the project for building the module DLL.  SchemaBuilder.exe is automatically called by awe_generate_library.m and there is no need to call it separately.

AWE_INFO.buildControl

The global variable AWE_INFO contain the structure .buildControl which controls the library generation process. AWE_INFO.buildControl contains many fields which are used internally.  We point out the user settable values.

  • AWE_INFO.buildControl.combineSourceFiles — this Boolean specifies whether each audio module should be placed into a separate source file.  By default, combineSourceFiles=0 and each module is written to a separate file.

  • AWE_INFO.buildControl.indentSourceFiles — this Boolean specifies whether the source code should be formatted after generation using the executable indent.exe.  Formatting the code regularizes identing, line breaks, etc.  By default, indentSourceFiles=0.  Formatting the source code significantly slows down the module generation process.

Setting the Audio Module Search Path

When you are developing a custom audio module, you must add the base module directory to the Audio Weaver module search path.

...

Code Block
add_module_path(PATH, '-begin');
add_module_path(PATH, '-end');

Specifying Class IDs
Anchor
SpecifyingClassIDs
SpecifyingClassIDs

Every audio module in the library must have a unique class ID.  This 32-bit integer is specified in the file

...

For each directory, the file classids.csv is opened and examined.  The function classid_lookup.m uses internal caching to speed up the search process.

Reordering of Render Variables
Anchor
ReorderingofRenderVariables
ReorderingofRenderVariables

As part of the build process, Audio Weaver reorders the variables in a module or subsystem to match the manner in which modules are instantiated by the Server.  The reordering is performed by the function

...

The ordering enforces that all scalar variables, which are initialized by the base module constructor function, are located at the start of the instance structure.  Refer to Module Function Details for additional information.

Overwriting Existing Source Files

Audio Weaver is frequently used in conjunction with a source code control system.  The awe_generate_library.m function overwrites generated files only if there is an actual change to the file.  If nothing has changed, the file is untouched.

Each generated file is first written to a temporary file.  Then the temporary file is compared with the existing version.  If the files are identical, then the existing file is untouched and the temporary file is deleted.  If the temporary file differs from the existing file, then the existing file is overwritten.

Specifying Wiring Constraints
Anchor
SpecifyingWiringConstraints
SpecifyingWiringConstraints

The .wireAllocation field of an audio module allows you to specify wiring constraints for the routing algorithm.  There are two possible values

...

The most common situation when 'across' wiring cannot be applied is when a module sits between the input and output of a system.  For routing reasons, the wires attached to the input and output of a subsystem have to be distinct.  Placing a module with .wireAllocation='across' between them will still lead to distinct buffer allocation.

AudioWeaverModule Tag

The function awe_help.m displays a list of all Audio Weaver modules on the current module search path.  In order for a module m-file to be picked up, you need to add the tag AudioWeaverModule somewhere within the m-file.  This tag allows you to differentiate between actual module m-files and other MATLAB files contained in the same directories.  The tag can be placed anywhere within the file, usually in a comment as shown below:

% AudioWeaverModule [This tag makes it appear under awe_help]

Code Markers and Template Substitution
Anchor
CodeMarkersandTemplateSubstitution
CodeMarkersandTemplateSubstitution

Template substitution is an automated method of replacing strings within a file to generate an output file.  The process starts with a template file and Audio Weaver provides separate templates for the generated .c and .h files:

...

where IDENTIFIER is a string.  The template substitution function is given a list of identifiers together with their replacements.  The substitutions are performed and a new output file is created.  If an identifier within a file is not defined, then it is deleted and does not appear in the output.

Adding Code Markers

A "code marker" is an identifier together with a replacement string.  Each module and subsystem has its own list of code markers.  The MATLAB function

...

Code Block
>> M=scaler_module('fred');
>> M.codeMarker{1}

ans = 

    name: 'processFunction'
    text: 'Insert:code\InnerScaler_Process.c'

>> M.codeMarker{2}

ans = 

    name: 'discussion'
    text: {1x9 cell}

Inserting Files

In many cases, the SUBSTITUTION string contains many lines and it is unwieldy to represent in MATLAB.  Instead, it is easier to copy the SUBSTITUTION text from another file.  If the SUBSTITUTION string has the form "Insert:filename.txt" then the text will be copied from filename.txt.  filename.txt is referenced relative to the location of the module's m-file.  You can specify subdirectories as well.  For example:

...

inserts the file InnerPeakHold_Process.c located in the subdirectory "Inner".

awe_lookupcodemarker.m

The MATLAB function

STR=awe_lookupcodemarker(M, IDENTIFIER)

returns the contents of a code marker.  If IDENTIFIER is not defined, then the function returns an empty string.  The returned value STR is either a string, for simple replacements, or a cell array in the case of multi-line replacements.

awe_deletecodemarker.m

M=awe_deletecodemarker(M, IDENTIFIER)

...

Deletes all code markers associated with a module or subsystem.

Template Substitution Preprocessor

The template files also contain their own preprocessor directives.  These directives are similar to those used by the C preprocessor but are handled by the template substitution function.  The directives are identified by ## and only a few variations are supported.

...

Code Block
##if $combineSourceFiles$
#include "$combinedIncludeName$"
##else
#include "$baseHFileName$"
##endif

Frequently Defined Code Markers

This section lists out code markers that are frequently defined when developing custom audio modules.

$bypassFunction$

C code which specifies the inner portion of the bypass function.  When this is defined, the bypass function is written into generated C file.

$bypassFunctionName$

Allows you to specify a bypass function by name.  This is typically used in conjunction with one of the predefined bypass functions listed in Bypass Function. For example,

...

  1. If $bypassFunction$ is defined, then the code is placed into the generated .c file and $bypassFunctionName$ is set to awe_modClassNameBypass,

  2. If $bypassFunctionName$ is defined, then this function is used for bypass behavior.  No additional code is placed into the generated .c file.

  3. Otherwise, the default bypass function IOMatchUpModule_Bypass() is used.  No additional code is placed into the generated .c file.

$constructorFunction$

Specifies the inner portion of a custom constructor function.  The function must follow the calling convention outlined in Constructor Function.

  • Simple audio modules without indirect arrays: No need to define the constructor function.  The BaseClassModule_Constructor() usually does everything needed.

  • Audio modules with direct arrays: Set the .arrayHeap and .arraySizeConstructor fields of the array variables in MATLAB.  Audio Weaver will then auto generate a suitable constructor function.

  • Complex modules requiring further initialization: Write a custom $constructorFunction$ or use the $postConstructorFunction$ shown below.

  • Modules created out of subsystems: Audio Weaver automatically generates code for these systems.  If you need further initialization, use the $postConstructorFunction$ shown below.

$postConstructorFunction$

This code marker follows immediately after the $constructorFunction$ code marker in awe_module_template.c.  This marker allows you to add your own code in cases where Audio Weaver generates the memory allocation and instantiation code but further initialization is needed.  It is particularly useful for subsystems.

$discussion$

Defines the discussion section of the help documentation.  This has been grandfathered for backwards compatibility.  When writing new modules, set the M.docInfo.discussion field of the audio module instead.

$getFunction$

Specifies the inner portion of a module's Get function.  Follows the calling convention outlined in Get Function .

$setFunction$

Specifies the inner portion of a module's Set function.  Follows the calling convention outlined in Set Function.

$hFileDefine$

Located near the top of the template file awe_module_template.h.  Allows you to add additional preprocessor directives (or anything else) at the start of the header file.  Example,

awe_addcodemarker(M, 'hFileDefine', '#define TRUE 1');

$hFileInclude$

Located near the top of the template file awe_module_template.h.  Allows you to include additional header files.

awe_addcodemarker(M, 'hFileInclude', '#define <stdlib.h>');

$processFunction$

Specifies the inner code for the module's processing function.  This must always be defined for modules.  For subsystems, the auto-generated should be used.  Refer to Processing Function for a discussion of how to define this function.

$preProcessFunction$

This code marker is located immediately before the $processFunction$ marker.  It is typically used with subsystems when you want to insert your code custom code immediately prior to the auto-generated $processFunction$.

$postProcessFunction$

Similar to $preProcessFunction$ but the code here is inserted immediately after the $processFunction$.  It is typically used with subsystems when you want to insert your custom code immediately after the auto-generated $processFunction$.

$srcFileDefine$

Located near the top of the template file awe_module_template.c.  Allows you to add additional preprocessor directives (or anything else) at the start of the source file. 

$srcFileInclude$

Located near the top of the template file awe_module_template.c.  Allows you to specify additional included files. 

$hFileTemplate$ and $srcFileTemplate$

Audio Weaver uses the default template files specified at the start of Code Markers and Template Substitution.  You can override the templates used by a particular module by setting these code markers.  There are separate markers for the header file, $hFileTemplate$, and the source file, $srcFileTemplate$.  It is handy to override these values if you want to change copyright information in the generated files.

Fine Tuning Code Generation

This section contains further instructions for fine tuning code generation.  Many of the items apply to modules generated using compiled subsystems.

Automatically Generated Array Initializers

In many cases, an audio module requires a custom constructor function solely for the purpose of allocating indirect arrays.  If the size of the allocated memory can be defined using existing module variables, then Audio Weaver can automatically generate a constructor function.

...

ARRAYVAR and TYPE are already known to MATLAB.  SIZE and HEAP must be separately specified as C code to embed into the generated code.  The string SIZE is specified in MATLAB by setting .arraySizeConstructor field of the array variable.  Similarly, HEAP is specified by setting the .arrayHeap field of the array variable.  For an example, see Peak Hold Module.

Specifying Module Constructor Arguments in Subsystems
Anchor
SpecifyingModuleConstructorArgumentsinSubsystems
SpecifyingModuleConstructorArgumentsinSubsystems

This advanced technique is frequently used when compiling subsystems to generate new module classes.  Audio Weaver automatically generates a Constructor function for the compiled subsystem, and this constructor in turn calls the constructor functions of the internal modules.   The difficulty arises because the arguments to the internal constructor functions are hard coded in the generated file based on the values at code generation time.  This is not always the desired behavior.

To get around this problem, Audio Weaver allows you to specify a piece of C code which overrides the default numeric initializer for an internal module variable.  The C code is written to the .constructorCode field of the variable.  For an example, refer to the Look Ahead Limiter Module

Avoiding Wire Allocation Problems with Subsystems

This issue also applies to the case of compiling subsystems to form new module classes.  If your subsystem has .flattenOnBuild=1 (which means that it is not compiled), then you can ignore this section. This problem arises because Audio Weaver modules can operate on an arbitrary number of channels. In certain circumstances, the routing algorithm incorrectly allocates wire buffers during code generation such that audio processing crashes at run-time.  In these cases, you need to be careful how you specify default channel counts and block sizes within modules. Look Ahead Limiter Module demonstrates the problem and presents a solution.

unique_classes.m

C=unique_classes(SYS)

where

...

This text can be pasted directly into TargetInfo.h.

awe_generate_module.m

M=awe_generate_module(M, DIRECTORY, WRITEFILES)

...

  • M — @awe_module object.

  • DIRECTORY — directory in which the generated files should be written to.  By default, this is set to MATLAB's current working directory (returned by the pwd command).

  • WRITEFILES — an optional Boolean argument which specifies whether the generated files should actually be written.  If you set WRITEFILES=0, then the module M will be updated with code markers, but no output files will be written.  Use WRITEFILES=0 when generating documentation as described in Generating Documentation.