Introduction
This document describes Audio Weaver’s MATLAB automation API. It allows you to leverage the power of MATLAB to configure and control Audio Weaver. The API can be used for parameter calculation, visualization, general automation, regression tests, and even full system building. The API is an advanced feature and assumes that the user is familiar with MATLAB.
The most straightforward use of the API allows MATLAB to interact with the Audio Weaver Designer GUI. This is documented in Interacting with Audio Weaver Designer and is sufficient for most users. More advanced scripting features are described in later sections.
MATLAB is an interpreted scripting language and all of the commands shown in this section can be typed in directly into MATLAB, or copy and pasted directly from this User's Guide.
Requirements
The API is compatible with MATLAB version 2017b or later. You’ll need a standard MATLAB license and the Signal Processing Toolbox. 32-bit and 64-bit versions of MATLAB are supported.
The MATLAB API is included with the “Pro” versions of Audio Weaver; it is not part of the Standard version.
Setup
After installing Audio Weaver Developer or Pro, update MATLAB's search path to include the directory:
...
Code Block |
---|
>> awe_version Audioweaver Version Number: awe server: 32568 awe_module: 32465 awe_subsystem: 32465 awe_variable: 31481 pin: 32555 pin_type: 32495 feedback_pin_type: 31604 connection: 30792 |
Online Help
Anchor | ||
---|---|---|
|
All of the Audio Weaver MATLAB functions have usage instructions within the function header. To get help on a particular function, type
...
The help documentation is provided in HTML format.
Interacting with Audio Weaver Designer
The most basic way of using the MATLAB API is to get and set parameters in a system that is loaded in Audio Weaver Designer.
Manipulating Parameters
Assume that you have the system “Example1.awd” open in Designer.
...
is issued. The system in Designer doesn’t have the new gain value but the target processor does. You have to keep this in mind. Changes made by MATLAB update the target processor directly when in tuning mode but don’t update the system in Designer until you issue set_gsys.m.
Commonly Used Commands
This section describes commonly used MATLAB commands. More details can be found in subsequent sections.
Showing Hidden Variables
By default, the MATLAB API does not show hidden variables (e.g., filter state variables). If you would like to make these visible, type
...
You’ll now see derived variables and state variables which are normally hidden from view.
Building Systems
If the system in Audio Weaver Designer is in Design mode, you can build the system using
...
and then you can start real-time audio playback with
test_start_audio;
Loading and Saving Designs
Instead of loading the GSYS structure from Designer, you can load it directly from disk
...
save_awd('Example1.awd', GSYS);
Variable Ranges
Audio Weaver variables can have range information associated with them. To view a variables range information, you can type
...
GSYS.SYS.Scaler1.gain.range = [-50 0];
The Basics of the MATLAB API
This tutorial walks you through the process of creating modules and subsystems within the Audio Weaver environment. Many of the features of the tool are presented with an emphasis on using existing audio modules. Writing new low-level modules is outside the scope of this tutorial and is described separately in the Audio Weaver Module Developers Guide. The tutorial assumes some familiarity with MATLAB.
Simple Scaler System
This example walks you through the process of creating a simple system containing a gain control. It takes you from instantiation in MATLAB through building the system using dynamic instantiation and finally real-time tuning.
Creating an Audio Module Instance
We begin by creating a single instance of a smoothly varying scaler module. This module scales a signal by a specified gain. The module is “smoothly varying” which means that the gain can be updated discontinuously and that the module performs internal sample-by-sample smoothing to prevent audio clicks. At the MATLAB command line type:
...
Code Block |
---|
gain: 0.5 [linear] // Gain in linear units. smoothingTime: 20 [msec] // Time constant of the smoothing process. |
Creating a Subsystem
Our next step will be to create a subsystem containing the ScalerSmoothed module. A subsystem is one or more audio modules together with I/O pins and a set of connections.
...
This looks similar to an audio module except that it is missing variables and instance names.
Adding I/O Pins
A subsystem also has “pins” that pass signals in and out of the subsystem. Let’s add an input pin to the system:
...
This is a valid statement within the Audio Weaver environment, but for the sake of simplicity, certain functions update variables directly in the calling environment. For example, the add_pin() function updates the argument SYS and thus the return argument may be omitted.
Adding Modules
Now add an instance of the ScalerSmoothed module to the subsystem:
...
The second argument to the type_conversion_module.m specifies the data type. 0 = floating-point, and 1 = fract32.
Connecting Modules
Three modules exist in the subsystem but they have not been wired up yet. We can specify the connections separately:
...
The arguments to the connect command are the source and destination modules, respectively. The subsystem itself is specified by the empty string. Thus, the first statement connects the subsystem’s input pin to the input of the ‘toFloat’ type conversion module. Similarly, the last statement connects the output of the ‘toFract” module to the output of the subsystem. In this example, the subsystem and modules only have one pin each on the input and output, so it is clear as to what connections are specified. For modules and subsystems with multiple input or output pins, we use a slightly different syntax described in Making Connections.
We can also reduce the 4 connect commands to a single command:
...
The input and output of the subsystem are represented by the narrow filled rectangles at the left and right edges of the figure. The modules are drawn as green rectangles and connections are represented by the lines with arrows. The draw command is useful for checking to make sure that the wiring of a subsystem is correct, especially complicated subsystems containing multiple modules.
Building and Running the System
The subsystem is now fully defined and ready to be run on the target. In this tutorial, we will run the subsystem natively on the PC. Issue the MATLAB command:
...
The process of determining the sizes of the pins and wires in the system is referred to as pin propogation. Essentially, the dimensions and sample rates of the input and output pins of the overall system are fixed by the target hardware. The pin information then flows from the input pins through the wires to the output of the system. At this point, we verify that the propagated output pin information matches the actual sizes of the output pins.
Real-time Tuning
At this point, the system is running in real-time on your PC. The audio source is either a file or the line input on your sound card, depending upon the audio_pump command. The scaler is configured with a gain of 0.5 and a smoothing time of 20 milliseconds.
...
Changing the module status is useful for debugging and making simple changes to the processing at run-time.
MIPS and Memory Profiling
Several other useful features are available after a system is built. You can determine the MIPs and memory load of the algorithm by the command:
...
The profile indicates that the wire buffers require a total of 344 32-bit words and that the scaler module itself requires 14 32-bit words. The real-time processing load is about 0.07% of the CPU. The profile isn't that interesting for a such a small system but becomes important for complex systems.
Automatic Gain Control
In this example an automatic gain control (AGC) normalizes the output playback level independent of the level of the input audio. In addition to the AGC, the system has a volume control and input and output meters.
...
The inspector panel created is.
...
Bass and Treble Tone Controls
This example demonstrates how to use the second_order_filter_module.m to create bass and treble tone controls. The steps should start looking familiar. We create the overall system and then add input and output pins that match the target in terms of sample rate:
...
Code Block |
---|
build(SYS); awe_inspect('position', [0 0]) inspect(SYS); test_start_audio; |
Bass Tone Control Module
We now present a more complicated example. A bass tone control is created as a subsystem together with MATLAB design equations. The design equations translate high-level parameters (frequency and gain) into lower level parameters which tune the subsystem. The code in this section is contained in the file bass_tone_control_float_subsystem.m.
Notes:
A related but more complicated example, bass_tone_control_module.m, is also provided with Audio Weaver. This other version supports both floating-point and fract32 signals.
The bass tone control presented here is only to illustrate certain Audio Weaver concepts. If you need a bass tone control in your system, see the example in Bass and Treble Tone Controls.
The design equations are written in MATLAB and allow you to control the module using MATLAB scripts. However, since the control code does not exist on the target, you will be unable to draw an inspector. To take it one step further and write the control code in C requires writing a custom audio module. This is beyond the scope of this User's Guide but points you towards the benefits of writing custom audio modules.
...
You'll see that the bass tone control subsystem is gone and that its 3 internal modules have been promoted to the top level.
Key System Concepts
This section goes into further detail regarding key concepts in Audio Weaver. These were touched upon in the tutorial in Interacting with Audio Weaver Designer and The Basics of the MATLAB API, and are given full coverage here. The concepts explain how Audio Weaver operates behind the scenes and clarifies the relationship between pins, wires, modules, and subsystems.
...
It is important to understand how to use and manipulate the @awe_module class in order to properly use all of the features of Audio Weaver. Variables are also represented in Audio Weaver as objects and in early versions of Audio Weaver we used a separate awe_variable class. Recently, variables were converted to standard MATLAB structures for speed of execution. Although no longer strictly classes in MATLAB they have associated functions and methods.
@awe_module
This class represents a single primitive audio processing module or a hierarchical system. A module consists of the following components: a set of names, input and output pins, variables, and functions. All of these items exist in MATLAB and many of them have duals on the target itself.
Class Object
To create an audio module object, call the function
...
isPreset – Boolean that indicates whether a module will be included in generated presets. By default, this is set to 1 and the module becomes part of the preset. User editable.
Input, Output, and Scratch Pins
Anchor | ||||
---|---|---|---|---|
|
Pins are added to a module by the add_pin.m function. Each pin has an associated Pin Type as described in Pins. After creating the Pin Type, call the function
...
Memory that needs to be persisted by a module between calls to the processing function appears in the instance structure and has usage "state". However, some processing functions require temporary memory storage. This memory is only needed while processing is active and does not need to be persisted between calls. The mechanism for allocating this temporary memory and sharing it between modules is accomplished by scratch pins. Scratch pins are added to a module via add_pin.m with the USAGE argument set to 'scratch'. Scratch pins are not typically used by audio modules, but are often required by subsystems. For subsystems, the routing algorithm automatically determines scratch pins at build time.
Variables
Anchor | ||||
---|---|---|---|---|
|
Every audio module has an associated set of variables. These variables are shown in MATLAB and also appear on the target as well. All of a module’s variables exist in both MATLAB and on the target processor.
...
where the 2nd and subsequent arguments are passed to the awe_variable.m function. See @awe_module for a description of these parameters.
...
Code Block | ||
---|---|---|
| ||
add_variable(M, 'numTaps', 'int', L, 'const', 'Length of the filter'); M.numTaps.range=[1 5000 1]; M.numTaps.units='samples'; add_array(M, 'coeffs', 'float', [1; zeros(L-1,1)], 'parameter', 'Coefficient array'); M.coeffs.arrayHeap='AE_HEAP_FAST2SLOW'; M.coeffs.arraySizeConstructor='S->numTaps * sizeof(float)'; add_variable(M, 'stateIndex', 'int', 0, 'state', 'Index of the oldest state variable in the array of state variables'); M.stateIndex.isHidden=1; % Set to default value here. This is later updated by the pin function add_array(M, 'state', 'float', zeros(L, 1), 'state', 'State variable array'); M.state.arrayHeap='AE_HEAP_FASTB2SLOW'; M.state.arraySizeConstructor='ClassWire_GetChannelCount(pWires[0]) * S->numTaps * sizeof(float)'; M.state.isHidden=1; |
Subsystem Constructor Function
The call to create a new empty subsystem is similar to the call to create a new module described in @awe_module
SYS=awe_subsystem(CLASSNAME, DESCRIPTION);
...
At this point, we have an empty subsystem; no modules, pins, variables, or connections. Pins and variables are added using add_pin.m and add_variable.m just as for @awe_module objects.
Adding Modules
Modules are added to subsystems one at a time using the function
...
Code Block |
---|
for i=1:length(SYS.module) fprintf(1, '%s\n', SYS.module{i}.name); end |
Adding Pins
The syntax for adding input and output pins to subsystems mirrors the syntax for adding these items to modules. Refer to Input, Output, and Scratch Pins for the details. Scratch pins are frequently used by subsystems to hold intermediate wire buffers between modules. Fortunately, allocating these temporary connections between modules is handled automatically by the routing algorithm. There is no need to add scratch pins to subsystems.
...
Code Block |
---|
add_module(SYS, biquad_module('bq11')); pinType=SYS.bq11.inputPin{1}.type; add_pin(SYS, 'input', 'in', 'Audio Input', pinType); add_pin(SYS, 'output', 'out', 'Audio output', pinType); |
Adding Variables
Variables are added to subsystems in the same manner as they are added to modules. Refer to Variables for the details.
Making Connections
Connections between modules are specified using the connect.m command. The general form is:
...
The module names "sine1" and "mult" are obvious because they were specified when the modules were created. The pins names may not be obvious since they appear within the module's constructor function. To determine the names of a module's pins, you can either utilize the detailed help function awe_help described in Online Help (recommended)
awe_help multiplexor_smoothed_module
...
Note: This is required since each output of the subsystem is stored in a separate buffer.
Top-Level Systems
Thus far, we have been using the terms system and subsystem interchangeably. There is a slight difference, though, that you need to be aware of. The highest level system object that is passed to the build command must be a top-level system created by the function:
...
The top-level system is still an @awe_subsystem object but it is treated differently by the build process. The main difference is how the output pin properties are handled. In a top-level system, the output pins properties are explicitly specified and not derived from pin propagation. As an added check, the pin propagation algorithm verifies that the wires attached to a top-level system's output pins match the properties of each output pin of the target. The top-level system functions are described in more detail in target_system.m and matlab_target_system.m.
In contrast, internal subsystems are created by calls to
SYS=awe_subsystem(CLASSNAME, DESCRIPTION)
.awe_variable objects
A variable in Audio Weaver represents a single scalar or array variable on the target processor. Variables are added to modules or subsystems using the add_variable.m command described in the Audio Weaver Module Developers Guide. Even if you are not developing modules, it is good to understand the awe_variable object so that you can fully utilize variables.
...
Code Block |
---|
filter = Biquad // 2nd order IIR filter b0: 1 // First numerator coefficient b1: 0 // Second numerator coefficient b2: 0 // Third numerator coefficient a1: 0 // Second denominator coefficient a2: 0 // Third denominator coefficient state: 0 0] |
See AWE_INFO for a description of all user settable fields in the AWE_INFO structure.
Advanced Variables: add_argument()
There are certain cases where runtime tunable parameters do not contain enough information for correctly sizing memory blocks within a system. Arguments are created from information passed in at module creation. An example for using an argument is usually to set an upper bound for runtime memory such as to set a maxDelay parameter on a delay module. This can allow the user to set a max delay at construction time, and then use a runtime delay setting bounded by maxDelay. Guidelines for module arguments are as follows:
...
More detailed information for add_argument() is in Developing Custom Modules: Guide.
Pins
The function new_pin_type.m was introduced in Adding I/O Pins and returns a data structure representing a pin. The internal structure of a pin can be seen by examining the pin data structure. At the MATLAB command prompt type:
...
Consider the bass tone control subsystem introduced in Bass Tone Control Module. The subsystem was connected to stereo input and output pins and thus all of the internal wires hold two channels of information. If the bass tone control were connected to a mono input, then all of the internal wires would be mono and the module would operate as expected. This generality allows you to design algorithms which operate on an arbitrary number of channels with little added complexity.
...
Code Block |
---|
>> PT=new_pin_type([], [], [], '*32') PT = numChannels: 1 blockSize: 32 sampleRate: 48000 dataType: 'float' isComplex: 0 numChannelsRange: [] blockSizeRange: [] sampleRateRange: [] dataTypeRange: {'float' 'int' 'fract32'} isComplexRange: 0 guiInfo: [1x1 struct] initialValueReal: [] initialValueImag: [] classVersion: 29350 |
Automatic Assignment in the Calling Environment
The standard MATLAB programming model is to pass parameters by value. If a function updates one of its input arguments, then it must be returned as an output argument for the change to occur in the calling environment. For example, the add_module.m function takes an audio module as an argument and adds it to an existing subsystem. The syntax is:
...
The most common time that users stumble with this concept is when they use the awe_setstatus.m command described in awe_getstatus.m and awe_setstatus.m. When you are changing the status of a module within a subsystem you must reassign the output argument as in:
SYS.mod=awe_setstatus(SYS.mod, 'bypassed');
General Audio Weaver Commands
The section describes general commands used to configure and control Audio Weaver.
awe_init.m
HOME=awe_init;
Configures MATLAB for use with Audio Weaver and launches the Server application. The MATLAB path is updated and the global variable AWE_INFO is set. When called, the function returns the home directory for Audio Weaver.
...
You must call awe_init.m prior to building a system, or using any commands which interact with the Server. In addition, you have to call this function whenever the Server is shutdown and relaunched outside of Audio Weaver.
awe_help.m
awe_help
By itself, the function lists out all audio modules which are available in Audio Weaver. Clicking on an item in the list pulls up detailed help for the selected module. You can also get detailed help on a module by passing the module's .m file as a second argument. For example,
...
The function identifies suitable module files by opening all .m files on the Audio Weaver module path and searching for the string 'AudioWeaverModule' somewhere in the file. If the string exists, then the .m file is assumed to contain an audio module.
awe_server_launch.m
This function manually launches the Audio Weaver Server and is called automatically by awe_init.m.
...
Note that any time you manually launch the Audio Weaver Server, you have to rerun awe_init.m to reestablish communication with the Server.
awe_diary.m
Saves commands sent from MATLAB to the Audio Weaver Server to a text file. The function can be called several different ways.
...
In addition to logging text script files, the Audio Weaver diary can also create compiled script files. Refer to Creating and Compiling Files.
awe_getini.m and awe_setini.m
Code Block |
---|
STR=awe_getini(SECTION, KEY); awe_setini(SECTION, KEY, VALUE) |
...
checks the value of the "UseRS232Target" key. If set to 1, it issues the "audio_pump" command to begin real-time execution on the embedded target. Otherwise, if set to 0 (on the PC), it issues the "audio_pump,../../Audio/Bach Piano.mp3" and begins playback of an MP3 file.
awe_home.m
Returns the current home directory of Audio Weaver as a string. Internally, the function queries MATLAB to determine the location of the file awe_home.m and bases the home directory off the location of this file. The function has several variants that return different internal Audio Weaver directories:
Code Block |
---|
awe_home('bin') – returns the directory containing the Audio Weaver binaries. awe_home('audio') – returns the directory containing default audio files. awe_home('examples') – returns the base directory of where the examples are stored. awe_home('doc') – returns the directory containing Audio Weaver documentation. awe_home('home') – returns the Audio Weaver home directory. This is the default behavior if no argument is specified to the function. awe_home('modules') – returns the location of the Audio Weaver public module files. |
awe_server_command.m
OUT=awe_server_command(IN)
...
executes all of the Server commands contained in file.aws. Files paths are relative to the AWE_Server.exe executable. Absolute paths are also permitted. This command is equivalent to the Server's File > Execute Script… menu command.
awe_version.m
Returns the current version of Audio Weaver as a data structure. For example, this release returns:
...
Each field represent the SVN revision number for that particular module.
AWE_INFO
This global variable was first introduced in @awe_module and controls some aspects of Audio Weaver. AWE_INFO is a structure with the following fields:
AWE_INFO.displayControl – determines whether hidden variables are displayed in module and subsystem structures. Refer to @awe_module.
AWE_INFO.testControl – Used internally by DSP Concepts for automated regression tests.
...
.profileMemory – specifies if memory heap information is monitored during the build process. Refer to build.m.
.echoCommands – specifies if all of the Server commands and responses are echoed to the MATLAB output window. This is primarily used when debugging and you want to monitor the communication between MATLAB and the audio Server.
...
AWE_INFO.windowsVersion – a string indicating the currently used version of Windows. This string is returned by the DOS command "ver". The string has the form "X.Y.Z" where X is the major build version and Y and Z are minor build versions. Version 5 indicates that Windows XP is in use. Version 6 indicates that Windows Vista is in use. (Audio Weaver uses the Windows version information to determine how closely inspectors can be spaced.)
Building and Run-Time Commands
The commands in the section relate to building the target system and getting real-time MIPs and memory usage information.
target_system.m
SYS=target_system(CLASSNAME, DESCRIPTION, RT)
...
The argument RT affects only pin propagation. If RT=0, then the properties of the system's output pins are derived from pin propagation. That is, the pin properties are derived from the modules connected to the output pins. In contrast, if RT=1, the properties of the system's output pins are specified by the add_pin.m call. Pin propagation verifies that the propagated pin information matches the properties of the output pins.
matlab_target_system.m
SYS=matlab_target_system(CLASSNAME, DESCRIPTION)
...
Note: MATLAB target systems do not have an RT argument. That is because the MATLAB target only simulates the processing and is not restricted by the properties of physical output pins.
prebuild.m
SYS=prebuild(SYS);
This function prepares an Audio Weaver system for execution. The function is called automatically by build.m, but there may be times when it needs to be manually executed. The function performs the following operations:
...
Step 5 ensures that all variable sizes are cleared up before you start setting them.
build.m
SYS=build(SYS);
Builds an audio system and gets it ready for real-time execution in Audio Weaver. The function calls prebuild.m in order to propagate pin information through the system, determine run-time order, and to allocate scratch buffers. Next, each module is instantiated on the target and the overall system created.
...
Info |
---|
Automatic matching of data types and number of channels is a new feature introduced in Audio Weaver 2.0. Along with this change, all target platforms were standardized to have a common fract32 data type. Automatic matching simplifies the overall process of building systems, especially on a floating-point target since the required type conversion modules are automatically inserted. |
target_profile.m
target_profile(SYS, FORMAT)
...
Code Block |
---|
>> SYS.agc.targetInfo ans = heapSize: [3x1 double] heapName: {3x1 cell} mangledName: 'agc' objectAddr: [] objectID: [] profileTime: 5.0664 profilePercent: 0.0739 isSIMD: 0 MIPS: 0.0038 allocationOrder: [] |
target_get_heap_info.m
This call returns the names and sizes of all memory heaps on the target. By default, the function returns the current sizes of the heaps
...
When memory profiling is enabled in Audio Weaver, this call is made before and after each audio module is instantiated on the target. By comparing the memory sizes before and after instantiation, the memory requirements of each module can be determined.
target_get_classlist.m
Queries the Server to determine which audio module classes are available. When called with no return argument, the function lists out the available classes to the MATLAB output window. A partial example is shown below:
...
Code Block |
---|
>> L(3) ans = className: 'ModuleDelay' dllName: 'FrameDLL.dll' addr: 269748316 classID: 3 numPublic: 3 numPrivate: 1 |
target_get_info.m
Queries the Server to determine properties of the target. The function returns a data structure with the fields shown below:
...
isSIMD – boolean specifying whether the target supports SIMD or not.
Commands Related to Audio Modules and Subsystems
add_control.m
Anchor | ||||
---|---|---|---|---|
|
Adds a single variable to a module's inspector. This command is described in Creating User Interfaces.
add_module.m
SYS=add_module(SYS, MOD)
Adds a module to an @awe_subsystem object. Arguments:
...
Code Block |
---|
??? Error using ==> add_module A module with that name already exists in the system |
add_pin.m
M=add_pin(M, USAGE, NAME, DESCRIPTION, TYPE)
...
Examples of how to use this function are provided in Adding Modules. Note that the set of input pin names must be unique, as well as the set of output pin names. The add_pin function checks for this and reports the following error if this condition is violated:
...
An input pin named 'in' already exists. Choose another name
awe_getstatus.m and awe_setstatus.m
These functions apply to audio modules and to subsystems that have been compiled, and exist natively on the target. In contrast, flattened subsystems do not support these calls. These functions query and change the run-time status of an audio module. Each audio module has an associated status that affects its run-time behavior:
...
allows you to control whether the "Inactive" option is available on the inspector. By default, the variable is equal to 1 and "Inactive" is shown. If you set this to zero, then the inspector only contains the first 3 options:
...
check_connections.m
STATUS=check_connections(SYS)
...
Note |
---|
Be aware that this heuristic can often lead to mismatches in pin dimensions and sample rates. It is good practice to never have unconnected pins. |
connect.m
SYS=connect(SYS, SRC, DST)
...
By default, ISFEEDBACK=0 and a standard feedforward connection is made. Set ISFEEDBACK=1 to indicate feedback. See Feedback for a detailed discussion of using feedback within Audio Weaver systems.
...
When CHECK=1, the function calls check_connections.m to verify the integrity of the wiring. By default, CHECK=0.
delete_connection.m
SYS=delete_connection(SYS, MOD1, PIN1, MOD2, PIN2)
...
The function returns the updated subsystem object. This call is typically never used in practice, but is used internally by Audio Weaver when preparing a subsystem for real-time execution.
delete_module.m
SYS=delete_module(SYS, MOD)
...
If no output argument is accepted, then the function updates the object SYS in the calling environment.
draw.m
Code Block |
---|
draw(SYS) draw(MODULE) |
...
If you make a change to the module status using either an inspector or programmatically from MATLAB using the awe_setstatus.m command, then the drawing in a figure window will not be automatically updated. Instead, you need to manually refresh the window using the toolbar button or right-clicking on an empty part of the figure window and selecting Redraw.
findconnection.m
C=findconnection(SYS, MOD1, PIN1, MOD2, PIN2)
...
There are no connections from the input of the system directly to the output of the system. The result is an empty cell array.
findconnectiondst.m
[MODINDEX, PININDEX]=findconnectiondst(SYS, MOD, PINNAME)
...
Code Block |
---|
>> SYS.module{3} lim = LookAheadLimiter // Multi-channel soft knee limiter with look ahead max_abs: [MaxAbs] core: [AGCLimiterCore] delay: [DelayMsec] mult: [AGCMultiplier] >> SYS.module{3}.inputPin{1} ans = type: [1x1 struct] usage: 'input' name: 'in' description: 'Audio Input' referenceCount: 0 isFeedback: 0 coord: [NaN NaN] wireIndex: 3 |
findconnectionsrc.m
[MODINDEX, PININDEX]=findconnectionsrc(SYS, MOD, PINNAME)
...
Code Block |
---|
>> SYS.module{2}.outputPin{1} ans = type: [1x1 struct] usage: 'output' name: 'out' description: 'audio output' referenceCount: 0 isFeedback: 0 coord: [NaN NaN] wireIndex: 3 |
findmodule.m
MODINDEX=findmodule(SYS, MOD)
...
Code Block |
---|
>> SYS.module{index} secondMeter = Meter // Peak and RMS meter module meterType: 0 // Operating module of the meter value: [1.0018 1.00951] |
findpin.m
INDEX=findpin(M, IO, PIN)
...
Code Block |
---|
>> index=findpin(SYS.lim.mult, 'input', 'in') index = 2 |
flatten.m
SYS=flatten(SYS)
This function operates on subsystems and promotes all internal modules to the upper level. It ends up eliminating hierarchy and returning a “flattened” subsystem. Arguments:
...
Code Block |
---|
>> SYS.lim.core.targetInfo.mangledName ans = lim_core |
get_variable.m and set_variable.m
Extract and assign individual awe_variable objects. These functions apply to audio modules and subsystems. These functions are needed at times, because of the object oriented nature of the Audio Weaver MATLAB functions. When accessing a variable "var" within a module "M", as in:
...
The get_variable.m and set_variable.m functions are typically not used in practice. You can always access the internal fields of a awe_variable object even when it is part of an audio module. For example, to access the "range" field of the variable "gain", use:
range=M.gain.range;
4.5.17. isfield.m
This function is similar to the standard isfield function within MATLAB applied to @awe_module and @awe_subsystem objects. The function determines if a module or subsystem has a specified variable. The syntax is:
...
The function returns 1 if the module M has a field named FIELDNAME. Otherwise, the function returns 0. Note, the function only queries variables that are part of the audio module or subsystem and not any of the private object fields.
module_count.m
COUNT=module_count(SYS)
Returns the number of modules at the top level of a subsystem.
...
Code Block |
---|
>> module_count(SYS, 1) ans = 10 |
new_pin_type.m
Creates a structure that represents a pin on an audio module or subsystem. A pin contains information about the current number of channels, block size, sample rate, data type, and complexity, as well as the allowable range for each of these items. Refer to the discussion in Section 4.1.3.
process.m
[SYS, WIRE_OUT]=process(SYS, WIRE_IN, NUMBLOCKS)
...
The resulting figure is shown below. The top subfigure shows the input to the system. Note that it has an amplitude of +/-1dB. The bottom subfigure shows the output of the system. Note that it has a peak gain of 4, which equals 12 dB, at 2kHz:
...
readd_module.m
SYS=readd_module(SYS, HNAME, OLDNAME, NEWNAME, ARGS)
...
ARGS - cell array of input arguments. These are passed to the module instantiation function following NEWNAME.
update.m
Explicitly calls the update (or set) function associated with a module. This function is used only in a few instances; typically all updates happen automatically. For example, if you instantiate a scaler_smoothed_module.m, and then change the smoothing time:
...
Code Block |
---|
>> M.setFunc ans = @scaler_smoothed_set |
Displaying Module Documentation
Audio Weaver modules include on-line help in HTML format. For example, to see the generated help for the Hilbert transform module, type
...
The process of documenting modules is detailed in the Audio Weaver Module Developers Guide.
Advanced System Design Features
This section discusses advanced system design features including multirate processing and feedback.
Multirate Processing
Audio Weaver supports multirate processing through the use of decimator and interpolator modules. There are two restrictions that must be observed:
...
downsampler_module.m (the same module supports float and fract32 data types).
fir_decimator_fract32_module.m
upsampler_module.m (the same module supports float and fract32 data types).
fir_interpolator_fract32_module.m
Multiple Audio Processing Threads
In the previous section on multirate processing all of the blocks have the same time duration and modules execute sequentially in the same thread. In some cases, you would like the audio processing to have multiple block sizes and each block size operates in a different thread. For example, the main audio processing may occur with a 32-sample block size while a separate measurement thread operates at a 128-sample block size. If the same rate is 32 kHz, then the main audio processing occurs every 1 msec while the measurement process occurs every 4 msec. The large block processing occurs in a separate lower priority interrupt and is periodically interrupted by the higher priority 32-sample block processing. This is illustrated in the figure below:
...
A related module is the rebuffer_module.m which buffers up data into overlapping blocks.
Feedback
Feedback is a key building block for audio algorithms and is frequently used in reverberation and dynamics processors. There are a number of issues to keep in mind when using feedback in Audio Weaver. This section describes how to add feedback to a system and gives a complete example of a subsystem incorporating feedback.
Feedback and Feedfoward Connections
Most connections in Audio Weaver are feedforward. That is, the output of a module (or the input of the subsystem) serves as input for subsequent modules. Audio data flows from left to right in the signal flow diagram.
...
Point-to-point connections in Audio Weaver are specified via the connect.m function described in connect.m The connect.m command has an optional fourth argument which is used to indicate feedback.
...
When you make a feedback connection, you explicitly identify the location at which the feedback and the associated delay occur. Recall that connections between modules correspond to buffers of data. The routing algorithm allocates buffers as needed and attempts to reuse buffers whenever possible in order to conserve memory. When feedback occurs, a new wire buffer is allocated and never reused. This wire buffer holds the delayed data and implements the delay of 1 block.
Behavior Depends on the Feedback Location
The location of the feedback connection affects the behavior of the system. For example, suppose that the feedback connection in the previous diagram occurs between modules 4 and 2. Then the delay will be inserted at that location:
...
Feedback connections cannot be made to the input or output of a subsystem; they must be internal to a subsystem. This is a logical problem with these types of connections. What does it mean for system input or output to be feedback? The connect.m function checks for this.
Explicitly Specifying Feedback Pin Information
There is one final complexity associated with using feedback. Recall that the routing algorithm propagates pin information throughout the system. The algorithm starts at the input pins and then propagates the pin type (numChannels, blockSize, sampleRate, and dataType) from module to module. If feedback occurs in a system, you must explicitly set the pinType at the source of the feedback wire; it is impossible for Audio Weaver to ascertain this information conclusively simply by examining the wiring diagram. If you are developing a subsystem that has feedback, the pinType of the feedback must be specified within the subsystem function. The pinType must be based upon the input pins to the subsystem and not on any intermediate connections. After writing the connect command
...
Code Block |
---|
numChannels = -round(SYS.inputPin{1}.type.numChannels * numChannels); blockSize = -round(SYS.inputPin{1}.type.numChannels * blockSize); sampleRate = -round(SYS.inputPin{1}.type.numChannels * sampleRate); |
Examples
If we specify -1 to
feedbackPinType.blockSize
Then the block size calculated from the formula is equal toSYS.inputPin{1}.type.blocksize
.If we specify -2 to
feedbackPinType.blockSize
Then the block size calculated from the formula is equal to2*(SYS.inputPin{1}.type.blocksize)
.If we specify –(1/2) to
feedbackPinType.blockSize
Then block size calculated from the formula is equal to(1/2)*(SYS.inputPin{1}.type.blocksize)
.If we specify the values using negative factors then the feedback pin type will be automated for any input pin type. We can also specify the direct values to the feedback pin type.
Code Block feedbackPinType.blockSize = 64; feedbackPinType.numChannels = 2; feedbackPinType.sampleRate = 48000; feedbackPinType.dataType = 'fract32'; feedbackPinType.isComplex = 0;
The above specification will hardcode the system to work only for the input pin with the above type. If we change the block size or number of channels at the input then the system fails.
Feedback Delay System
An example of how feedback is used in practice is contained in the file feedback_delay_subsystem.m. This subsystem realizes the system shown below:
...
Code Block |
---|
function SYS=feedback_delay_subsystem(NAME, MAXDELAY) % ---------------------------------------------------------------------- % Set default input arguments % ---------------------------------------------------------------------- if (nargin < 2) MAXDELAY=1024; end % ---------------------------------------------------------------------- % Creates the subsystem % ---------------------------------------------------------------------- SYS=awe_subsystem('FeedbackDelaySubsystem', 'Recursive system implementing a feedback delay module'); SYS.name=NAME; % Add the modules add_module(SYS, adder_module('add', 2)); add_module(SYS, delay_module('delay', MAXDELAY)); add_module(SYS, scaler_module('scale')); % Add input and output pins pinType=new_pin_type; add_pin(SYS, 'input', 'in', 'Audio Input', pinType); add_pin(SYS, 'output', 'out', 'Audio output', pinType); % Connect the modules together connect(SYS, '', 'add.in1'); connect(SYS, 'add', ''); connect(SYS, 'add', 'delay'); connect(SYS, 'delay', 'scale', 1); feedbackPinType.blockSize = -1; feedbackPinType.numChannels = -1; feedbackPinType.sampleRate = -1; feedbackPinType.dataType = 'Inherit'; feedbackPinType.isComplex = -1; SYS=set_feedback_pinType(SYS, SYS.connection{end}, feedbackPinType); connect(SYS, 'scale', 'add.in2'); SYS.delay.currentDelay=MAXDELAY; SYS.scale.gain=0.8; % Add the GUI add_control(SYS, '.scale.gain'); add_control(SYS, '.delay.currentDelay'); return; |
Creating User Interfaces
Audio Weaver allows you to design custom user interfaces for audio modules and subsystems. The user interfaces are designed by MATLAB commands and translated into Audio Weaver script. The user interfaces created are drawn by the Audio Weaver Server and exist outside of the MATLAB environment. This section begins with a brief tutorial that demonstrates how to use existing user interfaces and to create interfaces for a custom subsystem.
Quick Tutorial
Run the example system agc_example.m. The script instantiates the system shown below and begins real-time execution.
...
Double-clicking on the title bar returns the inspector to its "normal" size.
Using Controls
This section contains a few tips for using the inspector controls.
Clicking on a slider advances the control part way.
Grabbing and moving a slider updates the variable continuously.
An edit box directly above a slider or knob shows the current value. Clicking on an edit box allows you to type in a value.
Left clicking on a knob instantly turns the knob so that it is positioned over the click location.
Turn a knob by left clicking, and holding, a point on the knob. While you are actively turning a knob, you can increase the turn radius to more precisely adjust the value.
Knobs can wrap around from the minimum to the maximum value. Beware!
6.3. Creating Subsystem Control Panels
Now let us go a step further and draw a single control panel containing the individual inspectors for all 4 modules. Add the following lines prior to the "build" command within the agc_example.m script:
...
Code Block |
---|
add_control(SYS, '.scale.gainDB'); add_control(SYS, '.agc.core.targetLevel'); |
...
Ganging Controls Together
In certain applications, it is useful to have a single inspector control affect multiple variables on the target. For example, your audio system may have separate gains for left and right signals and instead of having two different inspector controls, you want a single control that affects both gain parameters. Tying a single control to multiple variables is referred to as ganging in Audio Weaver.
...
There are a few things to keep in mind when ganging together controls. First, the same inspector value is written to all of the variables. If you need finer control, such as a balance control that uses different gains for different scalers, you'll need to develop a custom audio module with its own set function. Second, the variable updates are not truly simultaneous. Instead, they'll be separated by a few milliseconds in time. If you need truly simultaneous updates, then develop a custom inspector.
Overriding Default GUI Settings
Anchor | ||||
---|---|---|---|---|
|
Compare the combined inspector panel with the ones shown in the 4 inspector panels. All of the controls are there, but some of the (quite useful) labels shown in the window title bars are gone. For example, what do the first two level meters graphs correspond to? We can improve the combined inspector by overriding some of the variable names. By default, Audio Weaver utilizes the variable name as a label shown on the inspector. Override this default behavior by adding the command
...
As before, the units information could also have been incorporated into the awe_variable object itself (which would have been a better idea!)
Changing Control Sizes
Audio Weaver uses a set of normalized coordinates when drawing controls. The coordinates are chosen such that a knob has a size of exactly 1 X-unit by 1 Y-unit:
...
Code Block |
---|
SYS.scale.gainDB.guiInfo.size=[1 3]; SYS.inputMeter.value.guiInfo.size=[1 3]; SYS.outputMeter.value.guiInfo.size=[1 3]; |
Changing the Inspector Layout
The inspector panel shown in the combined inspector panel consists of 4 separate "sub-inspectors", one for each internal module. By default, Audio Weaver draws sub-inspectors and individual controls from left to right. Subsequent controls are added to the right of the last control.
...
"bottomRight" adds a new row at the bottom and and to the right.
...
Inspector Control Types
We have so far seen several different types of controls: knobs, sliders, meters, and checkboxes. There are several other types of controls and the default control type is assigned based on the following logic. The following steps are evaluated from start to finish and terminate when a suitable match is found.
...
SYS.agc.core.recoveryRate.guiInfo.controlType='slider';
...
Module Status Control
An audio module can be in one of four run-time states: Active, Muted, Bypassed, and Inactive, as described in Real-Time Tuning. The module status is set using a group of radio buttons. To add a module status control, use the syntax:
...
Note that the variable "moduleStatus" does not exist within the module. Instead, special case code is used to instantiate this control.
Drawing Arrays of Controls
The default controlType assigned to an array variable is a grid control. The grid control displays a 2-dimensional matrix of values and is similar to an Excel spreadsheet. There are times when an array of controls (knobs, sliders, meters, etc.) is more convenient than a grid control. For example, consider a 4-input 2-output mixer_module.m The mixer gains are stored in a 4 x 2 matrix .gain of cofficients and the default inspector interface would appear as:
...
Certain other modules use arrays of controls when drawing themselves. For example, the meter_module.m is designed to operate on multichannel signals and uses a separate meter control for each audio channel. The meter_module.m script overrides the default grid control with a 'meter' module. The interfaces shown in 4 inspector panels and the Overall inspector panel have two controls shown for both the meter1 and meter2 modules. That is because these modules are displaying stereo information and thus a pair of meters is shown.
Base and Extended Controls
We saw in the Quick Tutorial that some inspectors could toggle between showing and hiding an "extended" panel by double-clicking on the title bar. (Note that this only works for inspectors drawn by the Server; not by inspectors drawn by the Designer GUI.) Typically, the frequently used controls appear on the base panel while the less frequently used items, such as the module status, appear on the extended panel.
...
Code Block |
---|
add_control(SYS, '.agc.core', 'topRight', 0); add_control(SYS, '.agc.core', 'topRight', 1); |
Further Control Attributes
An "attribute string" specifies additional details regarding how a control is drawn. The attribute string provides fine grained control over, for example, the number of tick marks displayed or the numeric values at which tick marks are displayed. The attribute string information is control-specific and consists of a set of key/value pairs: "key1=value1 key2=value3". Note that there is a space between key value pairs and not a comma. The attribute string is contained within the .guiInfo.attribStr field.
...
Logarithmic knob or slider. In audio, it is useful to have a knob that acts on a logarithmic scale for controlling frequency. To enable this, set:
module.variable.guiInfo.attribStr='mapping=log';
You can see an example of this within the sine_gen_module.mRestricting knobs and sliders to even values:
module.variable.guiInfo.attribStr='stepSize=2';
Converting a linear value to dB for meter display. Often an audio module performs calculations in linear space whereas the preferred display is in dB. Instead of performing the linear to dB conversion on the target, you can perform it in the meter itself. Use:
module.variable.guiInfo.attribStr='mapping=db20';
Grid Control Attributes
format=format_specifier – a printf style format to use when formatting values, default %g
...
sidewidth – default 30, value must be >= 30, width of first column in pixels
Edit and Constant Control Attributes
format=format_specifier – a printf style format to use when formatting values, default %.2f
...
readonly – 0 or 1, default 0; when set prevents the user editing the value
Checkbox Control Attributes
readonly=val – 0 or 1, default 0; when set prevents the user changing the selection
Drop List Control Attributes
readonly=val – 0 or 1, default 0; when set prevents the user changing the selection
Knob and Slider Control Attributes
min=val – default 0, the minimum value of the slider
...
muteonmin=[0|1] – default 0, when 1, the underlying variable is set to 0 when the slider/knob is turned to its minimum value. This is useful for dB controls which should mute when turned all the way down.
LED Control Attributes
There are no attributes associated with the LED control.
Meter Control Attributes
format=format_specifier – a printf style format to use when formatting values, default %.2f
...
height=val – default is natural control height, values larger than default stretch the control vertically downwards. Do not set this value. The height is automatically calculated based on guiInfo.size.
Module Level .guiInfo
We've seen how a variable's .guiInfo field can be used to customize the control attached to it. Modules and subsystems also have a .guiInfo field that can be used to modify the appearance of their inspector panel. Two characteristics of the inspector panel can be customized:
M.guiInfo.showMore – a Boolean value that specifies whether the normal inspector (=0) or the extended inspector (=1) should be initially shown. By default, showMore=0 and the normal inspector appears.
M.guiInfo.caption – specifies the string that should appear in the inspector's title bar. By default, this is empty and the dialog title bar contains the string:
moduleName [className]
Flash File System
Some hardware targets provide on-board flash memory configured to work with Audio Weaver. The flash memory stores files, usually compiled Audio Weaver Scripts, that execute upon boot up. This feature allows the hardware target to operate in standalone mode, that is, without having a PC attached.
When the Server connects to a hardware target, the target reports back its capabilities and features to the Server. This information is displayed within the Server's Output Window. One of the lines shown indicates whether the target provides a Flash File System:
Is FLASH supported: Yes
Accessing the Flash File System Using MATLAB
This section describes how to access the Flash File System using MATLAB commands.
Flash Memory Directory
To obtain a directory of files residing in flash memory, use the command
...
Code Block |
---|
.isStartup .isCompiled .isAWS .isPreset |
Adding Files
Files are added one at a time using the command
...
FILENAME must be at most 24 characters in length, for example “agc_example.awb”; this is checked by the function. The function also checks that FILENAME does not already exist in the Flash File System.
Deleting Files
To delete individual files use
...
This command takes several seconds to execute. The command executes without prompting you to confirm the erasure.
Creating and Compiling Files
The MATLAB command awe_diary.m is the primary method for creating Audio Weaver Script (.aws) files. This command is discussed in awe_diary.m and essentially captures all of the commands sent from MATLAB to the Server and logs them to a specified file. Typically, you wrap the building of a system in pairs of awe_diary commands as shown below:
...
MAXMESSAGELENGTH – maximum message length in the generated .awb file, in words. When building a system and you are connected to an embedded target then the message buffer size of the embedded target is used and this argument is ignored. Only use when you are generating the .awb file on the PC and want to limit the message buffer size. MAXMESSAGESIZE must be in the range of 16 to 264.
Flash Manager Example
This section concludes with an example of how to utilize the flash memory manager in practice. We store one of the Audio Weaver example systems in flash and configure the board to execute the script upon boot up. Both compiled and text commands are stored. The compiled files are executed when the DSP boots; the text script files are executed when the Server connects. We will use the automatic gain control system and build the system and create a preset using MATLAB.
...