Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

This section walks through a complete example of an audio module, starting from the high-level MATLAB model and continuing through the generated code. This example is identical to the scaler_smoothed_module.m contained in the Deprecated module library. We go through this module in a systematic fashion and reference the source files listed in Section 2.9. Section 7 contains additional module examples which highlight advanced features.

This module example is part of a larger audio module DLL containing several example modules. The base directory for the audio module examples is

<AWE>\AWEModules\Source\Examples\

where <AWE> refers to the root directory of the Audio Weaver Designer installation. The directory contains several subdirectories and this directory structure must be followed when creating other custom audio module libraries. In order to build the examples modules, the above path must be on the Audio Weaver module path variable, which can be retrieved in MATLAB with the ‘add_module_path’ command. The correct path should already be included in a normal installation of Designer, but if it is not, or if another path needs to be added, the module path can be updated using the ‘add_module_path’ command or with the File->Set Module Path menu in Designer.

Module M-files

Each audio module has an associated module M-file, item 1 shown in Figure 1. For this example, the file is found in

<AWE>\AWEModules\Source\Examples\matlab\scaler_smoothed_example_module.m

and a listing is shown in Section 2.9.1. When you first initialize Audio Weaver using awe_init.m, this file will be placed on your MATLAB path. The module m-file completely describes the audio module to MATLAB. It contains:

Input and output pins descriptions - Data types, number of channels, block sizes, sample rates, etc.

Instance structure variables – Date types, variable names, array sizes, memory allocation rules.

Documentation – Descriptions of variables, pins, and text describing the overall audio model.

MATLAB implementation of the module – Processing function (optional), and if needed, set function, bypass function, and get function. There may also be a prebuild function which is called when a system is built.

User interface – Individual variables are exposed and tied to controls. Controls are positioned and configured.

Browser information – This is the information for AWE Designer window to list under specific folder, search tag, bit map image of the module in Designer window etc.

All of these items above are documented in the Audio Weaver Matlab API. The specific items in the module m-file pertaining to module generation are variables, code markers, and wiring allocation guidelines described in Sections 5.1.11 and 5.2.

Subsystems are very similar to modules, but also contain a list of internal modules and a list of connections between modules.

Audio Module Instance Structure

Every audio module has an associated instance data structure that holds the variables – state and parameters – needed by the module. In this example, there are 4 variables described in the module m-file:

add_variable(M, 'gain', 'float', 0, 'parameter', 'Target gain');

M.gain.range=[-10 10];

M.gain.units='linear';

add_variable(M, 'smoothingTime', 'float', 10, 'parameter', 'Time constant of the smoothing process');

M.smoothingTime.range=[0 1000];

M.smoothingTime.units='msec';

add_variable(M, 'currentGain', 'float', M.gain, 'state', 'Instantaneous gain applied by the module. This is also the starting gain of the module.', 1);

M.currentGain.range=M.gain.range;

M.currentGain.units='linear';

add_variable(M, 'smoothingCoeff', 'float', NaN, 'derived', 'Smoothing coefficient', 1);

The type definition for the instance data structure is contained in the file ModScalerSmoothedExample.h and is automatically generated by Audio Weaver:

typedef struct _awe_modScalerSmoothedExampleInstance

{

ModuleInstanceDescriptor instance;

float gain; // Target gain

float smoothingTime; // Time constant of the ...

float currentGain; // Instantaneous gain applied ...

float smoothingCoeff; // Smoothing coefficient

} awe_modScalerSmoothedExampleInstance;

The instance structure begins with a common substructure of type ModuleInstanceDescriptor. This substructure points to the module's input and output wires, points to the real-time function currently used by the module (Processing, Bypassed, Muted, etc.), and points to the class instance structure.

The module header is followed by the instance variables described in the MATLAB file. There is a one-to-one correspondence between the variables shown in the instance structure and those added by MATLAB. The description of each variable is used as a comment.

The header file also contains a few other items. First, there is a bit mask for each variable in the data structure. The mask corresponds to the position of the variable within the instance structure. Note that the module header is 8 words long and thus the first bit starts in the 9th bit position. These bit masks can be used by the _Set() and _Get() functions to determine which variable within the instance structure has been modified.

#define MASK_ScalerSmoothedExample_gain 0x00000100

#define MASK_ScalerSmoothedExample_smoothingTime 0x00000400

#define MASK_ScalerSmoothedExample_currentGain 0x00000200

#define MASK_ScalerSmoothedExample_smoothingCoeff 0x00000800

The header file also defines an offset for each instance variable. Again, this is the offset from the start of the data structure, in 32-bit words. These offsets are provided to help implement system control using a host interface.

#define OFFSET_ScalerSmoothedExample_gain 0x00000008

#define OFFSET_ScalerSmoothedExample_smoothingTime 0x0000000A

#define OFFSET_ScalerSmoothedExample_currentGain 0x00000009

#define OFFSET_ScalerSmoothedExample_smoothingCoeff 0x0000000B

There is a unique class ID.

#define CLASSID_SCALERSMOOTHEDEXAMPLE (CLASS_ID_MODBASE + 32768)

This integer uniquely defines the module class to the Server. Next is the definition of the module's constructor function. In this case, since the module does not have any arrays, the generic module constructor ClassModule_Constructor is used.

The generic module constructor applies to modules that do not have indirect arrays in the instance data structure.  It is used by a large number of modules.  The constructor function awe_modScalerSmoothedExample_Constructor() is provided as a macro so that the module can be constructed within subsystems.  We'll see shortly that the constructor function is defined as NULL within the module's class structure.

#ifndef AWE_STATIC_CODE

// This points the constructor for this class to the base constructor

#define awe_modScalerSmoothedExampleConstructor(ARG1, ARG2, ARG3, ARG4, ARG5) ClassModule_Constructor(CLASSID_SCALERSMOOTHEDEXAMPLE, ARG1, ARG2, ARG3, ARG4, ARG5)

#endif

And finally, there are definitions for the processing and set functions:

void awe_modScalerSmoothedExampleProcess(void *pInstance);

UINT awe_modScalerSmoothedExampleSet(void *pInstance, UINT mask);

Note that many of the items are surrounded by #ifdef / #endif pairs. This allows various features of the modules to be enabled or disabled at compile time.

Audio Module Source Code (.c and .h files)

Each audio module has a set of associated functions. These functions, and their definitions, are placed in .c and .h files, respectively. At a minimum, every audio module requires a processing function. In addition, a module may specify several optional functions:

  • Constructor() – Performs additional memory allocation or initialization when a module is instantiated. If a module has an indirect array, such as an FIR filter, then a constructor function is required. In many cases, MATLAB can generate the constructor function automatically.

  • Set() – Implements a module's control functions which translate high-level interface variables to low-level variables. The Set() function is automatically called whenever an internal variable of a module is written by the Server during tuning.

  • Get() – Implements a module's control functions which translate low-level variables to high-level interface variables. The Get() function is automatically called by the Server whenever an internal variable of a module is read during tuning. Very few modules actually implement this function.

  • Bypass() – Implements custom bypass functionality. Required when one of the standard bypass functions is not suitable.

The module .c source file also contains a single class structure that describes the module to the Audio Weaver run-time and dynamic memory allocation functions. For example, this module contains the class structure:

AWE_MOD_SLOW_ANY_CONST

const Class_awe_modScalerSmoothedExample awe_modScalerSmoothedExampleClass =

{

{

{ NULL, CLASSID_SCALERSMOOTHEDEXAMPLE, }, // Constructor

awe_modScalerSmoothedExampleProcess, // Processing function

IOMatchUpModule_Bypass, // Bypass function

awe_modScalerSmoothedExampleSet, // Set function

0, // Get function

0x00000007, // Module version info

ClassModule_PackArgCounts(4, 0), // (Public words, private words)

{0x0000000F, 0x00000000}, // Specifies which variables are floating-point

},

#ifdef BUILD64

{

offsetof(awe_modScalerSmoothedExampleInstance, gain),

offsetof(awe_modScalerSmoothedExampleInstance, smoothingTime),

offsetof(awe_modScalerSmoothedExampleInstance, currentGain),

offsetof(awe_modScalerSmoothedExampleInstance, smoothingCoeff),

}

#endif

};

The class structure contains pointers to the 5 functions listed above. The constructor function is NULL indicating that the module requires no memory outside of its instance structure and that the generic constructor should be used instead.

The #ifdef BUILD64 section is required internally by Designer to correctly access the module’s variables in 64-bit architectures. Make sure that BUILD64 is defined in the VisualStudio and embedded projects if a 64-bit architecture is being targeted. Failure to add the BUILD64 macro to 64-bit architectures can cause the application to crash while accessing module variables using the control interface.

The class ID, CLASSID_SCALERSMOOTHEDEXAMPLE which is defined above, is a unique integer identifying the module to the Server. When instantiating a module of this class, the Server is told to instantiate a module of class "ModuleScalerSmoothedExample". This string identifier is then translated to the underlying class ID through the module DLL shown as item 9 in Figure 1. Ensuring that each audio module has a unique classID can be tedious. To facilitate this process, each module library has a text file named classids.csv, shown as item 3 in Figure 1, containing a comma separated list of audio modules and their class IDs. A portion of the file is shown below:

IDOFFSET=32768

ScalerSmoothedExample,0

ScalerExample,1

FaderExample,2

FaderExampleFract32,3

PeakHoldExample,4

DownsamplerExample,5

The classID for the ScalerSmoothedExample module equals the IDOFFSET (32768) plus the value listed next to its class name below (0). Class IDs starting with 32768 are reserved for custom audio modules.

Audio Module Schema File

The generated schema file ExamplesSchema.sch provides a "blueprint" of all of the available objects on the target processor to the Server. This enables the Audio Weaver Server to instantiate and manipulate objects by name rather than hexadecimal IDs or offsets. The schema file for each module pack is embedded in the module DLL and is shown as item 9 in Figure 1. It contains definitions for all of the available audio modules in the module pack.

The entire schema file for the example module library is shown in Section 2.9.7. The portion corresponding to the ScalerSmoothedExample module is shown below.

ModuleScalerSmoothedExample 0x0xBEEF8800, BaseModule

{

gain float // Target gain

smoothingTime float // Time constant ...

currentGain float // Instantaneous gain ...

smoothingCoeff float // Smoothing coefficient

}

Note the one-to-one correspondence between the schema description and the C type definition shown above. Furthermore, the C substructure ModuleInstanceDescriptor maps to the BaseModule descriptor in the schema file.

To create an instance of a smoothly varying scaler on the target, the Server is told "create an instance of class ModuleScalerSmoothedExample and call it Scale1". The Server converts this to the command "create an instance of object 0xBEEF8800" via the schema file. The hexadecimal value 0xBEEF0C16 corresponds to the unique class ID

CLASS_ID_MODBASE + 32768

contained in the class structure .

As a side note, CLASS_ID_MODBASE = 0x BEEF0800, which is defined in Framework.h.

On the target, the array of module class objects is traversed looking for class ID 0xBEEF8800. Once the class object is found, the corresponding constructor function, stored as a pointer in the class structure, is used to allocate one instance of the object. The address of the newly instantiated object is returned to the Server, and the Server associates the object's address with the name "Scale1". The Server maintains this mapping between symbol names and actual memory addresses.

The schema file also lists the module's instance variables and is used to compute offsets from the start of an object. When the value "Scale1.gain" is set during tuning, the Server translates this to a specific address on the DSP (PC) using the "Scale1" object address as a base, and then adding an appropriate offset. In this case, the offset equals 8, the size of BaseModule.

Generating Module Code

The MATLAB file scaler_smoothed_example_module.m has a complete description of the audio module with sufficient information to generate all of the source files and documentation. You can generate the source files for a smoothly varying scaler using the commands:

will be created in MATLAB's current working directory. Specify the directories for code generation with the second argument:

homeDir = awe_home('awecore');

SRC_DIR = [homeDir '\Source\Examples\Source'];

INC_DIR = [homeDir '\Source\Examples\Include'];

DOC_DIR = [homeDir '\Source\Examples\Doc'];

INNER_DIR = [homeDir '\Source\Examples\Inner'];

DIR = {SRC_DIR; INC_DIR; DOC_DIR; INNER_DIR};

M = scaler_smoothed_example_module('temp');

awe_generate_module(M, DIR);

The files

Include/ModScalerSmoothedExample.h

Source/ModScalerSmoothedExample.c

will be created in the directories specified by DIR.

You can also specify that the C code should be formatted using the ident.exe utility (supplied) via a third argument:

awe_generate_module(M, DIR, 1);

Modules are usually not created in isolation, but are part of a particular module pack library. Modules need to be created as a unified library so that the combined schema file ExamplesSchema.sch can be written. The MATLAB script make_examples.m generates code for the entire Examples module library. The script first creates a cell array of audio modules:

MM=cell(0,0);

MM{end+1}=downsampler_example_module('temp', 2); % 100% instantiation

MM{end+1}=fader_example_fract32_module('temp');

MM{end+1}=fader_example_module('temp');

MM{end+1}=lah_limiter_example_module('temp', 5); % 100% instantiation

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');

Important point to be noted here is that the module must be added to cell array with all the arguments required. This is mandatory for new AWE Designer.

Some other example audio modules are subsystems that utilize modules found in other libraries. We indicate this dependency relationship using the lines

[DependMM, DependName]=make_standardmodulepack(0);

USESLIB{1}.MM=DependMM;

USESLIB{1}.str=DependName;

[DependMM, DependName]=make_deprecatedmodulepack(0);

USESLIB{2}.MM=DependMM;

USESLIB{2}.str=DependName;

[DependMM, DependName]=make_advancedmodulepack(0);

USESLIB{3}.MM=DependMM;

USESLIB{3}.str=DependName;

Then call a function to generate the source code for the overall library:

awe_generate_library(MM, DIR, 'Examples', USESLIB, GENDOC);

Code for each module in a module pack is separately generated followed by the combined schema file. The third argument, 'Examples', specifies the module pack name and the forth argument specifies the dependencies on other module packs. The fifth argument, GENDOC, controls whether documentation in HTML format should be generated.

When you run the MATLAB script ‘make_examples’ you'll see something similar to the following written to your MATLAB output window

Generating code for module: DownsamplerExample

Unchanged output file:

<DIR >\Source\Modules\Examples\include\ModDownsamplerExample.h

Unchanged output file:

<DIR >\Source\Modules\Examples\Source\ModDownsamplerExample.c

Generating code for module: FaderExampleFract32

Unchanged output file:

<DIR>\Source\Modules\Examples\include\ModFaderExampleFract32.h

Unchanged output file:

<DIR >\Source\Modules\Examples\Source\ModFaderExampleFract32.c

...

Generated a total of 8 modules

You'll note that all source files are marked as "Unchanged". Audio Weaver only overwrites generated files if there has been an actual change. This minimizes file changes and makes it easier to work with source code control systems.

Template Substitution

Audio Weaver uses template substitution to generate audio module source and header files. The template files are shown as item 2 in Figure 1, and two files are used

<AWE>\matlab\module_generation\templates\awe_module_template.c

<AWE>\matlab\module_generation\templates\awe_module_template.h

The template files contain boiler plate text together with string substitution variables and special preprocessor directives. Consider a portion of the file awe_module_template.h:

/**

* @file

* @brief $description$

*/

#ifndef _MOD_$classNameUpperCase$_H

#define _MOD_$classNameUpperCase$_H

#include "ModCommon.h"

#include "MathHelper.h"

Each substitution point is shown as $NAME$ in the template file. These substitution points are replaced with the code markers added via awe_addcodemarker.m commands in the module file. For example, when generating the scaler_smoothed_example_module, the string variable $description$ is replaced by "Linear multichannel smoothly varying scaler" and $classNameUpperCase$ is replaced by "ScalerSmoothedExample" to yield:

/**

  • @file

  • @brief Linear multichannel smoothly varying scaler

*/

#ifndef _MOD_SCALERSMOOTHEDEXAMPLE_H

#define _MOD_SCALERSMOOTHEDEXAMPLE_H

#include "ModCommon.h"

#include "MathHelper.h"

By making changes to the template files, you can make wholesale changes to the entire module library!

The template files also contain special forms of preprocessor directives – independent of the standard C preprocessor directives. Further down in awe_module_template.h, you'll find the function declarations:

void $processFunctionName$(void *pInstance);

##if $useCustomSetFunction$

UINT $setFunctionName$(void *pInstance, UINT mask);

##endif

##if $useCustomGetFunction$

UINT $getFunctionName$(void *pInstance);

##endif

##if $useCustomBypassFunction$

void $bypassFunctionName$(void *pInstance);

##endif

The symbol ## identifies a preprocessor directive reserved for the code generator. The directives are evaluated during code generation based on the values of the variables, for example the value of $useCustomSetFunction$ determines if code will be eliminated or exist in the generated file. The scaler smoothed example module has

$useCustomSetFunction$ defined as 1

$useCustomGetFunction$ defined as 0

$useCustomBypassFunction$ defined as 0.

This yields the generated header code:

void awe_modScalerSmoothedExampleProcess(void *pInstance);

UINT32 awe_modScalerSmoothedExampleSet(void *pInstance, UINT32 mask);

The variables used during template substitution are referred to as "code markers". Many code markers are generated automatically by the awe_generate_module.m function. Some code markers are explicitly defined in scaler_smoothed_example_module.m.

awe_addcodemarker(M, 'processFunction', 'Insert:InnerScalerSmoothed_Process.c');

awe_addcodemarker(M, 'setFunction', 'Insert:InnerScalerSmoothed_Set.c');

awe_addcodemarker(M, 'srcFileInclude', '#include "FilterDesign.h"');

Code markers beginning with the string "Insert:" cause input to be read from a specified file. For example, the processing function template in awe_module_template.c is:

AWE_FAST_CODE

void $processFunctionName$(void *pInstance)

{

##if $usePreProcessFunction$

{

$preProcessFunction$

}

##endif

$processFunction$

##if $usePostProcessFunction$

{

$postProcessFunction$

}

##endif

}

The string $processFunction$ is taken from the file

Inner\InnerScalerSmoothedExample_Process.c

shown in Section 2.9.2. You'll note that this is bare code missing even the function definition (which is in the template file). The other code markers – "preProcessFunction" and "postProcessFunction" are not defined. After template substitution, we end up with the final processing function ModScalerSmoothedExample.c shown in Section 2.9.5.

2.7. Building the Audio Module DLL

At this point, the source code for all of the modules in the Examples library has been generated. Open up and rebuild the VisualStudio solution file

<AWE>\AWEModules\Source\Examples\Examples.sln

with the build configuration set to x86 Release. The solution builds the DLL and then copies it into the

<AWE>\Bin\win32-vc100-rel

directory so that it can be referenced by the Server. Further details on this step can be found in Section 8.1.

2.8. Summary of Steps Involved in Writing an Audio Module

To summarize, the steps required in writing a new audio module are:

  1. Create the MATLAB module m-file described in Section 2.1. It defines

a. Input and output pins

b. Instance structure variables

c. Links to inner C code.

d. Documentation

e. User interface

f. Module browser for AWE Designer

  1. Write the inner C code for the processing function.

  1. Write the inner C code for the other module functions, Constructor(), Set(), Get(), and Bypass(), if needed.

  1. Pick a unique integer ID (any number in the range 32768 to 63487) for the new module class ID. Add this information to the file classids.csv associated with the module library.

  1. Add the module function to the specific module pack library generation script, for example make_examples.m. Run the script file to generate the source code and create the schema file.

  1. Add the generated .c and .h files to the project for building the audio module pack library (e.g., ExamplesLib.vcproj). And build the library.

  1. Build the audio module DLL so that the new modules are visible by the Server.

2.9. Scaler Smoothed Example Source Files

2.9.1. scaler_smoothed_example_module.m

function M=scaler_smoothed_example_module(NAME)

% M=scaler_smoothed_example_module(NAME)

% Creates a smoothly varying scaler module with a single input

% and single output pin. This module operates on floating-point

% signals. Arguments:

% NAME - name of the module.

% Copyright 2007-2016. DSP Concepts, Inc. All Rights Reserved.

% ----------------------------------------------------------------------

% Create the high-level object with interface variables only.

% ----------------------------------------------------------------------

M=awe_module('ScalerSmoothedExample', 'Linear multichannel smoothly varying scaler');

% Version is auto-updated by SVN:

M.moduleVersion = generate_version('$Revision: 30333 $');

if (nargin == 0)

return;

end

M.name=NAME;

M.preBuildFunc=@scaler_smoothed_example_prebuild;

M.processFunc=@scaler_smoothed_example_process;

M.setFunc=@scaler_smoothed_example_set;

PT=new_pin_type;

add_pin(M, 'input', 'in', 'audio input', PT);

add_pin(M, 'output', 'out', 'audio output', PT);

add_variable(M, 'gain', 'float', 0, 'parameter', 'Target gain');

M.gain.range=[-10 10];

M.gain.units='linear';

add_variable(M, 'smoothingTime', 'float', 10, 'parameter', 'Time constant of the smoothing process');

M.smoothingTime.range=[0 1000];

M.smoothingTime.units='msec';

add_variable(M, 'currentGain', 'float', M.gain, 'state', 'Instantaneous gain applied by the module. This is also the starting gain of the module.', 1);

M.currentGain.range=M.gain.range;

M.currentGain.units='linear';

add_variable(M, 'smoothingCoeff', 'float', NaN, 'derived', 'Smoothing coefficient', 1);

awe_addcodemarker(M, 'processFunction', 'Insert:InnerScalerSmoothedExample_Process.c');

awe_addcodemarker(M, 'setFunction', 'Insert:InnerScalerSmoothedExample_Set.c');

awe_addcodemarker(M, 'srcFileInclude', '#include "FilterDesign.h"');

M.wireAllocation='across';

% ----------------------------------------------------------------------

% Documentation

% ----------------------------------------------------------------------

M.docInfo.discussion={'Scales all input channels by a single gain value. ', ...

'Changes to the gain parameter are exponentially smoothed (first order IIR) at the sample rate, with the time constant determined by the smoothingTime parameter. ', ...

'This module is controlled by varying the gain variable. Internally, currentGain represents the instantaneous smoothed gain that is applied. ', ...

'currentGain exponentially approaches gain with a time constant equal to smoothingTime. ', ...

'', ...

'The module''s prebuild function initializes the currentGain equal to the gain. Thus, the module begins in a converged state.'};

% ----------------------------------------------------------------------

% Add the inspector information

% ----------------------------------------------------------------------

M.guiInfo.isExpanded=0;

M.gain.guiInfo.controlType='slider';

add_control(M, '.gain');

add_control(M, '.moduleStatus', 'right', 1);

add_control(M, '.smoothingTime', 'below', 1);

% ----------------------------------------------------------------------

% Module browser information

% ----------------------------------------------------------------------

M.moduleBrowser.path = 'Examples';

M.moduleBrowser.image = '../images/ExamplesIcon.bmp';

M.moduleBrowser.searchTags = 'scaler volume';

M.shapeInfo.basicShape = 'triangle';

M.shapeInfo.legend = ' ';

return;

% ----------------------------------------------------------------------

% Prebuild function. Behavior is based on the data type of the

% input pin

% ----------------------------------------------------------------------

function M=scaler_smoothed_example_prebuild(M)

M.currentGain=M.gain;

M.currentGain.range=M.gain.range;

% Propagate the type of the input pin to the output

M.outputPin{1}.type=M.inputPin{1}.type;

return;

% ----------------------------------------------------------------------

% Set function. Computes the smoothing coefficient

% ----------------------------------------------------------------------

function M=scaler_smoothed_example_set(M)

% Compute the smoothing coefficient based on the smoothing time

SR=M.inputPin{1}.type.sampleRate;

M.smoothingCoeff = design_smoother(M.smoothingTime, SR, 1);

return;

2.9.2. InnerScalerSmoothedExample_Process.c

awe_modScalerSmoothedExampleInstance *S = (awe_modScalerSmoothedExampleInstance *)pInstance;

WireInstance **pWires = ClassModule_GetWires(S);

FLOAT32 targetGain = S->gain;

FLOAT32 smoothingCoeff = S->smoothingCoeff;

FLOAT32 *src = (FLOAT32 *)pWires[0]->buffer;

FLOAT32 *dst = (FLOAT32 *)pWires[1]->buffer;

UINT32 channels = ClassWire_GetChannelCount(pWires[0]);

UINT32 blockSize = ClassWire_GetBlockSize(pWires[0]);

FLOAT32 currentGain;

UINT32 i;

FLOAT32 *inPtr;

FLOAT32 *outPtr;

FLOAT32 oneMinusRate = 1.0f - smoothingCoeff;

INT32 sample;

for (i = 0; i < channels; i++)

{

/* The same currentGain is used for each channel. Then we store the result

from the final channel back into the state. */

currentGain = S->currentGain;

/*awe_vecScaleSmooth(src + i, channels, dst + i, channels, &currentGain, targetGain,

smoothingCoeff, blockSize);*/

inPtr = src + i;

outPtr = dst + i;

for(sample = 0; sample < (INT32)blockSize; sample++)

{

currentGain = currentGain * oneMinusRate + targetGain * smoothingCoeff;

*outPtr = *inPtr * currentGain;

inPtr += channels;

outPtr += channels;

}

}

S->currentGain = currentGain;

2.9.3. InnerScalerSmoothedExample_Set.c

awe_modScalerSmoothedExampleInstance *S = (awe_modScalerSmoothedExampleInstance *) pInstance;

WireInstance **pWires = ClassModule_GetWires(S);

FLOAT32 SR;

if (mask & MASK_ScalerSmoothedExample_smoothingTime)

{

SR = (float) ClassWire_GetSampleRate(pWires[0]);

S->smoothingCoeff = design_smoother(S->smoothingTime, SR, 1);

}

return(0);

2.9.4. ModScalerSmoothedExample.h

/****************************************************************************

*

  • Audio Framework

  • ---------------

*

****************************************************************************

  • ModScalerSmoothedExample.h

****************************************************************************

*

  • Description: Linear multichannel smoothly varying scaler

*

  • Copyright: 2019 DSP Concepts, Inc. All rights reserved.

  • 3235 Kifer Road

  • Santa Clara, CA 95054

*

***************************************************************************/

/**

  • @addtogroup Modules

  • @{

*/

/**

  • @file

  • @brief Linear multichannel smoothly varying scaler

*/

#ifndef _MOD_SCALERSMOOTHEDEXAMPLE_H

#define _MOD_SCALERSMOOTHEDEXAMPLE_H

#include "ModCommon.h"

#include "MathHelper.h"

#define MASK_ScalerSmoothedExample_gain 0x00000100

#define MASK_ScalerSmoothedExample_smoothingTime 0x00000200

#define MASK_ScalerSmoothedExample_currentGain 0x00000400

#define MASK_ScalerSmoothedExample_smoothingCoeff 0x00000800

#define OFFSET_ScalerSmoothedExample_gain 0x00000008

#define OFFSET_ScalerSmoothedExample_smoothingTime 0x00000009

#define OFFSET_ScalerSmoothedExample_currentGain 0x0000000A

#define OFFSET_ScalerSmoothedExample_smoothingCoeff 0x0000000B

#define CLASSID_SCALERSMOOTHEDEXAMPLE (CLASS_ID_MODBASE + 32768)

#ifdef __cplusplus

extern "C" {

#endif

// ----------------------------------------------------------------------

// Overall instance class

// ----------------------------------------------------------------------

typedef struct _awe_modScalerSmoothedExampleInstance

{

ModuleInstanceDescriptor instance;

FLOAT32 gain; // Target gain

FLOAT32 smoothingTime; // Time constant of the smoothing process

FLOAT32 currentGain; // Instantaneous gain applied by the module. This is also the starting gain of the module.

FLOAT32 smoothingCoeff; // Smoothing coefficient

} awe_modScalerSmoothedExampleInstance;

#if !defined(NOREDEF)

extern const ModClassModule awe_modScalerSmoothedExampleClass;

#endif // #if !defined(NOREDEF)

/* Dynamic instantiation is used by default. When building for static

** code, define AWE_STATIC_CODE to eliminate the constructor function. */

#ifndef AWE_STATIC_CODE

// This points the constructor for this class to the base constructor

#define awe_modScalerSmoothedExampleConstructor(ARG1, ARG2, ARG3, ARG4, ARG5) ClassModule_Constructor(CLASSID_SCALERSMOOTHEDEXAMPLE, ARG1, ARG2, ARG3, ARG4, ARG5)

#endif // #ifndef AWE_STATIC_CODE

void awe_modScalerSmoothedExampleProcess(void *pInstance);

UINT32 awe_modScalerSmoothedExampleSet(void *pInstance, UINT32 mask);

#ifdef __cplusplus

}

#endif

#endif // _MOD_SCALERSMOOTHEDEXAMPLE_H

/**

  • @}

*

  • End of file.

*/

2.9.5. ModScalerSmoothedExample.c

/****************************************************************************

*

  • Audio Framework

  • ---------------

*

****************************************************************************

  • ModScalerSmoothedExample.c

****************************************************************************

*

  • Description: Linear multichannel smoothly varying scaler

*

  • Copyright: 2019 DSP Concepts, Inc. All rights reserved.

  • 3235 Kifer Road

  • Santa Clara, CA 95054

*

***************************************************************************/

/**

  • @addtogroup Modules

  • @{

*/

/**

  • @file

  • @brief Linear multichannel smoothly varying scaler

*/

#define NOREDEF

#include "Framework.h"

#include "Errors.h"

#include "ModScalerSmoothedExample.h"

#include "FilterDesign.h"

#ifdef __cplusplus

extern "C" {

#endif

/* ----------------------------------------------------------------------

** Audio module class object. This describes the audio module to the

** framework. It contains pointers to functions and number of

** variables.

** ------------------------------------------------------------------- */

CREATE_MODULE_CLASS(Class_awe_modScalerSmoothedExample, (4 + 0))

AWE_MOD_SLOW_ANY_CONST

const Class_awe_modScalerSmoothedExample awe_modScalerSmoothedExampleClass =

{

{

{ NULL, CLASSID_SCALERSMOOTHEDEXAMPLE, },

awe_modScalerSmoothedExampleProcess, // Processing function

IOMatchUpModule_Bypass, // Bypass function

awe_modScalerSmoothedExampleSet, // Set function

0, // Get function

0x00000007, // Module version info

ClassModule_PackArgCounts(4, 0), // (Public words, private words)

{0x0000000F, 0x00000000}, // Specifies which variables are floating-point

},

#ifdef BUILD64

{

offsetof(awe_modScalerSmoothedExampleInstance, gain),

offsetof(awe_modScalerSmoothedExampleInstance, smoothingTime),

offsetof(awe_modScalerSmoothedExampleInstance, currentGain),

offsetof(awe_modScalerSmoothedExampleInstance, smoothingCoeff),

}

#endif

};

/* ----------------------------------------------------------------------

** Memory allocation function. This is required because the module

** requires additional memory outside of its instance structure.

** ------------------------------------------------------------------- */

/* ----------------------------------------------------------------------

** Real-time Processing function.

** ------------------------------------------------------------------- */

AWE_MOD_FAST_CODE

void awe_modScalerSmoothedExampleProcess(void *pInstance)

{

awe_modScalerSmoothedExampleInstance *S = (awe_modScalerSmoothedExampleInstance *)pInstance;

WireInstance **pWires = ClassModule_GetWires(S);

FLOAT32 targetGain = S->gain;

FLOAT32 smoothingCoeff = S->smoothingCoeff;

FLOAT32 *src = (FLOAT32 *)pWires[0]->buffer;

FLOAT32 *dst = (FLOAT32 *)pWires[1]->buffer;

UINT32 channels = ClassWire_GetChannelCount(pWires[0]);

UINT32 blockSize = ClassWire_GetBlockSize(pWires[0]);

FLOAT32 currentGain;

UINT32 i;

FLOAT32 *inPtr;

FLOAT32 *outPtr;

FLOAT32 oneMinusRate = 1.0f - smoothingCoeff;

INT32 sample;

for (i = 0; i < channels; i++)

{

/* The same currentGain is used for each channel. Then we store the result

from the final channel back into the state. */

currentGain = S->currentGain;

/*awe_vecScaleSmooth(src + i, channels, dst + i, channels, &currentGain, targetGain,

smoothingCoeff, blockSize);*/

inPtr = src + i;

outPtr = dst + i;

for(sample = 0; sample < (INT32)blockSize; sample++)

{

currentGain = currentGain * oneMinusRate + targetGain * smoothingCoeff;

*outPtr = *inPtr * currentGain;

inPtr += channels;

outPtr += channels;

}

}

S->currentGain = currentGain;

}

/* ----------------------------------------------------------------------

** Set function which updates derived parameters based on the

** module's interface variables.

** ------------------------------------------------------------------- */

AWE_MOD_SLOW_CODE

UINT32 awe_modScalerSmoothedExampleSet(void *pInstance, UINT32 mask)

{

awe_modScalerSmoothedExampleInstance *S = (awe_modScalerSmoothedExampleInstance *) pInstance;

WireInstance **pWires = ClassModule_GetWires(S);

FLOAT32 SR;

if (mask & MASK_ScalerSmoothedExample_smoothingTime)

{

SR = (float) ClassWire_GetSampleRate(pWires[0]);

S->smoothingCoeff = design_smoother(S->smoothingTime, SR, 1);

}

return(0);

}

#ifdef __cplusplus

}

#endif

/**

  • @}

*

  • End of file.

*/

2.9.6. classids.csv

% Class ID list for the examples that are included in the Audio Weaver

% documentation.

IDOFFSET=32768

ScalerSmoothedExample,0

ScalerExample,1

FaderExample,2

FaderExampleFract32,3

PeakHoldExample,4

DownsamplerExample,5

LAHLimiterExample,6

PeakHoldExampleFract32,7

FeedbackExample,8

2.9.7. ExamplesSchema.sch

ModuleDownsamplerExample 0xBEEF8805, BaseModule

{

D int // Decimation factor. 1 out of every D samples is output

}

ModuleFaderExampleFract32 0xBEEF8803, BaseModule

{

scaleFval float // Scaler Front

scaleBval float // Scaler Back

smoothingTimeF float // Time constant of the smoothing process

smoothingTimeB float // Time constant of the smoothing process

scalerF *ModuleScalerSmoothedFract32 // Linear multichannel smoothly varying scaler

scalerB *ModuleScalerSmoothedFract32 // Linear multichannel smoothly varying scaler

inter *ModuleInterleave // Interleaves multiple audio signals

}

ModuleFaderExample 0xBEEF8802, BaseModule

{

fade float // Front/back Balance. +1 = front only. -1 = rear only.

smoothingTime float // Time constant of the smoothing process

scalerF *ModuleScalerSmoothed // Gain control with linear units and smoothing

scalerB *ModuleScalerSmoothed // Gain control with linear units and smoothing

inter *ModuleInterleave // Interleaves multiple audio signals

}

ModuleLAHLimiterExample 0xBEEF8806, BaseModule

{

maxDelayTime float // Maximum delay time

max_abs *ModuleMaxAbs // Computes the maximum absolute value of all input channels on a sample-by-sample basis

core *ModuleAGCLimiterCore // Gain computer used to realize soft-knee peak limiters

delay *ModuleDelayMsec // Time delay in which the delay is specified in milliseconds

mult *ModuleAGCMultiplier // Mono x N-channel multiplier

}

ModulePeakHoldExampleFract32 0xBEEF8807, BaseModule

{

Reset int // reset the current peak values

attackTime float // Envelope detector attack time constant

decayTime float // Envelope detector decay time constant

decayCoef fract32 // Computed coefficient used for decay

attackCoef fract32 // Computed coefficient used for attack

peakHold *fract32 // Array of peak values

peakDecay *fract32 // Array of decaying peak values

}

ModulePeakHoldExample 0xBEEF8804, BaseModule

{

Reset int // reset the current peak values

attackTime float // Envelope detector attack time constant

decayTime float // Envelope detector decay time constant

decayCoef float // Computed coefficient used for decay

attackCoef float // Computed coefficient used for attack

peakHold *float // Array of peak values

peakDecay *float // Array of decaying peak values

}

ModuleScalerExample 0xBEEF8801, BaseModule

{

gain float // Linear gain

}

ModuleScalerSmoothedExample 0xBEEF8800, BaseModule

{

gain float // Target gain

smoothingTime float // Time constant of the smoothing process

currentGain float // Instantaneous gain applied by the module. This is also the starting gain of the module.

smoothingCoeff float // Smoothing coefficient

}

2.9.8. ExamplesSchema.cpp

Not shown. This is a C file with initialized binary arrays.

2.9.9. Examples.h

extern const ModClassModule awe_modDownsamplerExampleClass;

extern const ModClassModule awe_modFaderExampleFract32Class;

extern const ModClassModule awe_modFaderExampleClass;

extern const ModClassModule awe_modLAHLimiterExampleClass;

extern const ModClassModule awe_modPeakHoldExampleFract32Class;

extern const ModClassModule awe_modPeakHoldExampleClass;

extern const ModClassModule awe_modScalerExampleClass;

extern const ModClassModule awe_modScalerSmoothedExampleClass;

#define LISTOFCLASSOBJECTS \

&awe_modDownsamplerExampleClass, \

&awe_modFaderExampleFract32Class, \

&awe_modFaderExampleClass, \

&awe_modLAHLimiterExampleClass, \

&awe_modPeakHoldExampleFract32Class, \

&awe_modPeakHoldExampleClass, \

&awe_modScalerExampleClass, \

&awe_modScalerSmoothedExampleClass

#define USESDLLS "ModulePackAweDeprecatedDLL.dll”

  • No labels