XPlot

From STX Wiki
Jump to navigationJump to search


XPlot : CObjEx

A general class for plotting multiple graphs.

XPlot Construction

Initialize a new XPlot-instance to display 1 or more graphs. Returns the new object or an empty string. Information and error messages are written to the BSCRIPT CON console.

Usage:

XPlot rows=1 ; columns=1 ; title ; profile ; window ; owner

Parameters:
rows
The number of rows (default=1).
columns
The number of columns for each row (inrow0 inrow1 ...). The default is one column per row.
title
The display window title.
profile
The name of the graphics profile to use. A graphics profile is also known as a colour scheme.
window
The window position and size (in the format 'x y width height').
owner
The id of an existing display item which should own this new window. See NEW DISPLAY for details.
Result:

A new XPlot object if successful or an empty string.

Examples:

The simplest way to create an XPlot instance with one graph is as follows:

#xplot := xplot
if '$#xplot[?]' != 'instance' em -1 ; Failed to create the xplot instance

XPlot Member Functions

The XPLOT class has the following member functions. See CObjEx Member Functions for a list of functions implemented in the parent class.

AddPlot

The XPLOT function AddPlot is identical to the PLOT function, except that it adds to an existing graph (in addition to or on top of the original plot). If no graph exists at the specified adr, then the call is passed to Plot. It supports the following plot types: XYPLOT, FUNCTION and PARAMETER. The parameters are identical to the PLOT function.

Dialog

The function Dialog can be used to show and hide a dialog in the XPlot display.

Usage:

inst Dialog cmd ; args

Parameters:
cmd
The following commands are available: New|Delete|Msg|On|Enabled|Off|Hidden. See below for details.
args
See below for details.
Result:

The ID of the current or new dialog item or an empty string.

New

Creates a new dialog item (deleting the old one first).

Usage:

inst Dialog New ; pos

pos
Sets the position of the dialog within the display. The following values are supported:
ABOVE|BELOW|LEFT|RIGHT
Delete

Removes the dialog from the display and deletes the dialog item.

Usage:

inst Dialog Delete

Msg

Posts a message to the macro message queue. The format of the message is:

MENU dialogItem msgId msgPar

Note that when the display is closed, this function is called to post the message MENU dialogItem CLOSE to the dialog item.

Usage:

inst Dialog Msg ; msgid msgpar

Parameters:
msgid
The message ID.
msgpar
The message parameters.
On|Off|Enabled|Disabled

Show the dialog and set it's position.

Usage:

inst Dialog mode; pos

Parameters:
mode
Turns the dialog on or off and enables or disables it if it is on. The following keywords are supported:
ON|OFF|ENABLED|DISABLED
pos
Sets the position of the dialog within the display. The following values are supported:
ABOVE|BELOW|LEFT|RIGHT

Display

Returns the ID of the display object associated with this XPLOT instance.

Usage:

inst display

Result:

Returns the display object of the XPLOT instance.

End

Enters the message loop, waits until the user closes the plot display and then destroys itself.

Get

Retrieve an attribute from a specific graph.

Usage:

xplot Get adr ; attribute

Parameters:
adr
The address of the display splitter (see member function Graph for detail).
attribute
The id of the requested attribute. The following values are supported:
CURSORPOSITION - Returns the current cursor positions in the following format: i1 x1 y1 i2 x2 y2
Note that x1 <= x2
YDATA - Returns the y data item.
XDATA - Returns the x data item.
RANGE - Returns the x axis and y axis range in the following format: xmin xmax ymin ymax
TYPE - Returns the plot type (see Plot for a list of available plot types).

GetFColors

The GetFColors function returns a blank separated list of the function colors defined in the selected graphics profile.

Usage:

xplot GetFColors

Result:

Returns a blank separated list of color keywords.

Graph

Returns the requested attribute attr of the graph identified by adr.

Usage:

xplot Graph adr [; attr=GRAPH ]

Parameters:
adr
The id of a graph item, an XGRAPH instance or the 'row column' address of a splitter in the display. Note that the row and column indices are zero-based.
attr
The attribute to returned. The following values are allowed:
INSTANCE - Return the id of the XGRAPH instance associated with adr.
GRAPH - Return the id of the graph object associated with adr. This is the default attribute.
ROW - Return the row index of the splitter associated with adr.
COLUMN - Return the column index of the splitter associated with adr.
Result:

Return values are selected by the argument attr. See the description of attr for details. If the address argument adr do not refer to a graph, XGRAPH or splitter of the display, an empty string is returned.

Examples:

Get the graph item id for the top left graph.

#graph := $#xplot graph 0 0

Legend

Display a graph legend. Use $#xplot LEGEND $#graph to clear the legend.

Usage:

xplot Legend graph ; unit ; x ; y ; w ; h ; color ; info ; text1 ; text2 ; textX

Parameters:
graph
The graph address (e.g. row and column index. See PLOT for detail).
unit
The unit for size and position values. The following values are supported:
real - The real x/y values.
% or percent - The percent of the graph's plot area.
x, y
The position of the upper right corner of the first legend line.
w, h
The width and height of one legend line.
color
The legend text color.
info
This flag selects the line attributes to be displayed. The following values are supported:
color - The color.
all - The color, style, width and symbol.
textX
The text for the legend for function X. If no text is supplied, the legend line is removed.This parameter can be either a string, or a simple table.
Result:

void

Plot

The XPlot function Plot can be used to plot a function in a graph. Currently, STx supports waveform , x/y (aka function and more specifically parameter), spectrogram and waterfall plots.

XYPLOT

Plot an x/y function graph.

Usage:

xplot Plot adr ; XYPLOT ; y ; x ; title ; xr ; xu ; xt ; yr ; yu ; yt ; fstyles ; xlabtab ; ylabtab

Parameters:
adr
The address of the display splitter (see the member function GRAPH for details).
y
The y axis data (a vector or an array).
x
The data to be used for the x axis. This can be one of the following:
A data vector with y[!nrow] values and 1 column.
* - An asterisk. This is the default and means that the x axis uses the values 0 through to y[!nrow]-1.
A blank separated list of values ('x1 x2' -> x[i] = x1+(x2-x1)/(y[!nrow]-1), i = 0..y[!nrow]-1).
title
The title to be displayed in this plot.
xr
The x axis display range. This can be one of the following values:
* - An asterisk - an automatic scale is generated.
xmin xmax - Two numerical values - the minimum and maximum values.
xu
The text describing the x axis unit (e.g. seconds). The default is an empty string.
The WAVEFORM plot only allows the following values: SAMPLES|MS|S. The default is S.
xt
The title to be used for the x axis. The default is an empty string.
yr
The y axis display range. This can be one of the following:
* - An asterisk - an automatic scale is generated.
ymin ymax - Two numerical values - the minimum and maximum values.
yu
The text describing the y axis unit (e.g. dB).
yt
The title to be used for the y axis. The default is an empty string.
fstyles
An fstyle argument (see fstyle for details) or a zero-based function line index as specified in a color scheme (see Color Schemes in the User Guide).
xlabtab, ylabtab, zlabtab
Extended tables containing the scale, grid and label definitions. For a description of the table format, please see the scale definition table for details.
Result:

Return 0 if successful.

Examples:

Plot a simple x/y function.

#xplot := XPLOT 1 ; 1 ; XPLOT ; Default ; 0 0 400 400
$#xplot plot 0 ; XYPLOT; $(eval fill(10, 0, 1)) ; * ; xyplot ; * ; ; x-axis ; * ; ; y-axis
FUNCTION

Plot a function graph. Note that this is identical to an XYPLOT.

Usage:

xplot Plot adr ; FUNCTION ; y ; x ; title ; xr ; xu ; xt ; yr ; yu ; yt ; fstyles ; xlabtab ; ylabtab

Parameters:

See XYPLOT for parameter descriptions.

Result:

Return 0 if successful.

PARAMETER

Plot a parameter graph. A parameter graph differs from a function graph because a parameter plot can have missing values - it does not necessarily have values for every point on the x axis.

Usage:

xplot Plot adr ; parameter ; y ; title ; xr ; xu ; xt ; yr ; yu ; yt ; fstyles ; xlabtab ; ylabtab

Parameters:

See the xyplot for parameter details.

Result:

Return 0 if successful.

SPECTROGRAM

Plot a spectrogram graph.

Usage:

xplot plot adr ; spectrogram ; d ; y ; title ; xr ; xu ; xt ; yr ; yu ; yt ; zr ; xlabtab ; ylabtab

Parameters:
d
A data array containing one spectrum or function line per y row. Note that this parameter is specific to the SPECTROGRAM and WATERFALL plots.
y
The y-scale data (frequency). This can be one of the following:
1) vData - A data vector with y[!ncol] values and 1 column.
2) * - An asterisk: y[i] = i, i = 0..d[!ncol]-1. This is the default.
3) y1 y2 - Two blank separated values: y[i] = y1+i*(y2-y1)/(d[!ncol]-1), i = 0..d[!ncol]-1.
zr
The z scale is a color scale. The following values are supported:
* - An asterisk. The range is automatically generated.
zmin zmax - Two numerical values specifying the minimum and maximum z axis values.
zdown - A numerical value. The maximum z value is chosen automatically and the minimum value is calculated as follows: zmax-zdown.

For all other parameters, see xyplot for descriptions.


WATERFALL

Plot a waterfall graph.

Usage:

xplot PLOT adr ; WATERFALL ; d ; x ; title ; xr ; xu ; xt ; yr ; yu ; yt ; zr ; zu ; zt ; xw ; yw ; n ; xlabtab ; ylabtab ; zlabtab

Parameters:
d
The data array (one spectrum or function-line / row).
zr
The z axis display range. The following values are supported:
* - An asterisk. The range is automatically generated.
zmin zmax - Two numerical values specifying the minimum and maximum z axis values.
zu
The text describing the z axis unit (e.g. s).
zt
The title to be used for the z axis. The default is an empty string.
xw
The relative width of the x scale. A value between -1 and 1. The default is 0.8.
yw
The relative width of the y scale. A value between -1 and 1. The default is 0.8.
n
The number of lines to be plotted. The default is 150.

For all other parameters, see XYPLOT for descriptions.

WAVEFORM

Plot a waveform graph. Note that the displayed wave item is automatically attached to the graph. This means, no explicit call to SetWave is necessary.

Usage:

xplot PLOT adr ; WAVEFORM ; wave ; title ; xu ; xt ; ymax ; yr ; yt ; fill

Parameters:
wave
A wave item id or an XWAVE instance
xu
The unit to use on the x axis. The following values: SAMPLES|MS|S. The default is S.
ymax
The maximum waveform amplitude. This can be a value between 0 and ...
yr
The y axis display range. This can be any positive number. The default is 1.
fill
1 if the waveform envelope should be filled or 0.

For all other parameters, see XYPLOT for descriptions.

TEXTBOX

Plot a graph containing text.

Usage:

xplot PLOT adr ; TEXTBOX ; title ; color ; halign ; valign ; text

Parameters:
title
The graph title.
color
The text color. This can be an of the STx color arguments.
halign
The horizontal text alignment. This can be one of the following values: CENTER|LEFT|RIGHT
valign
The vertical text alignment. This can be one of the following values: CENTER|TOP|BOTTOM
text
The text to be displayed. This can be a simple table with an entry per line of text or a semi-colon separated list of text lines.

For all other parameters, see XYPLOT for descriptions.

fstyle

The fstyle argument passed to the XPlot functions Plot and AddPlot has the following syntax and components:

linestyle:linecol:printcol:linewidth:drawstyle:drawsym:ymiss

linestyle
Determines whether the function line is solid (SOLID), dotted (DOT) or dashed (DASH). The default value is taken from the XPLOT color profile.
linecol
The colour to use for the function line on screen. This can be any STx colour keyword or RGB value. The default value is taken from the XPLOT color profile.
printcol
The colour to use for the function line when printing. See linecol for details. The default value is taken from the XPLOT color profile.
linewidth
The width of the function line. Possible values are 0 through to 4 for lines with the SOLID linestyle and 0 or 1 for lines with the DOT or DASH linestyle. The default value is taken from the XPLOT color profile.
drawstyle
The style to use to draw the function. Each function point can be plotted separately (POINTS), a line can be drawn between each function point (LINES), the area below the function can be filled with the linecol (AREA), the function points can be joined by steps (STEPS - note that this is only available for the PARAMETER plot) or no points are plotted (NONE - this is best used when a drawing symbol (drawsym) is defined). The default style is LINES.
drawsym
The symbol to draw at each point. This can be used in conjunction with a drawing style (see drawstyle). The following keywords are supported:
NONE|SQUARE|TRIANGLE|CIRCLE|CROSS|DIAMOND
The default style is NONE.
ymiss
The value to use for missing y values. If ymiss is not specified (empty) all values are displayed, otherwise all points where y=ymiss are not displayed. If ymiss is not empty and is not a number then ymiss is set to 0. If no ymiss is defined, no ymiss is used (this is the default).

Redraw

Redraw the selected graph. This is currently only implemented for the FUNCTION (XYPLOT) and PARAMETER plots.

Usage:

xplot REDRAW adr

Parameters:
adr
The address of the display splitter (see member function Graph for details).
Result:

Return 0 if successful.

ScaleOctave

Generate a logarithmic scale table for use with the Plot or AddPlot functions. This function can also be called statically.

Usage:

xplot ScaleOctave df count ; fmax ; fmin

xplot ScaleOctave df count ; fmax ; fmin

xplot ScaleOctave vector ; fmax ; fmin

xplot ScaleOctave vector ; fmax ; fmin

Parameters:
df
The frequency resolution in Hz.
count
The number of frequency points.
fmax
The maximum frequency to be displayed.
fmin
The minimum frequency to be displayed.
vector
The scale range as a data vector.
Result:

The following string is returned:

xmin xmax xlabTab xdata

Where xmin and xmax are is the minimum and maximum of the logarithmic scale, xlabTab is the scale definition table which you can then pass to a Plot function and xdata is the logarithmic frequency values vector. See the scale definition table description in the Command Reference for details of the table syntax.

Examples:

Create a scale definition table for a logarithmic frequency axis with 2000 points at 10 Hz intervals and a maximum frequency of 10000 Hz.

readstr '$(xplot scaleOctave 10 2000; 10000)' #xmin #xmax #xlab #x
Notes:

See also ScaleSteps.

ScaleLog10

Generate a logarithmic scale table for use with the Plot or AddPlot functions. This function can also be called statically.

Usage:

xplot ScaleLog10 df count ; fmax ; fmin

xplot ScaleLog10 df count ; fmax ; fmin

xplot ScaleLog10 vector ; fmax ; fmin

xplot ScaleLog10 vector ; fmax ; fmin

Parameters:
df
The frequency resolution in Hz.
count
The number of frequency points.
fmax
The maximum frequency to be displayed.
fmin
The minimum frequency to be displayed.
vector
The scale range as a data vector.
Result:

The following string is returned:

xmin xmax xlabTab xdata

Where xmin and xmax are is the minimum and maximum of the logarithmic scale, xlabTab is the scale definition table which you can then pass to a Plot function and xdata is the logarithmic frequency values vector. See the scale definition table description in the Command Reference for details of the table syntax.

Notes:

See also ScaleSteps and ScaleOctave.

ScaleSteps

Generate a linear scale table for use with the Plot or AddPlot functions. This function can also be called statically, e.g. 'xplot ScaleSteps -70 -10 ; 10 ; 5 ; 5 ; 1 ; 1'.

Usage:

inst ScaleSteps min max ; labelDist ; majorGridDist ; majorTickDist ; minorGridDist ; minorTickDist

xplot ScaleSteps min max ; labelDist; majorGridDist; majorTickDist ; minorGridDist ; minorTickDist

inst ScaleSteps vector ; labelDist; majorGridDist; majorTickDist ; minorGridDist ; minorTickDist

xplot ScaleSteps vector ; labelDist; majorGridDist; majorTickDist ; minorGridDist ; minorTickDist

Parameters:
min, max
The scale range.
vector
The scale range as a data vector.
labelDist
The label distance in scale units.
majorGridDist
The distance of the major grid lines in scale units.
majorTickDist
The distance between major ticks in scale units.
minorGridDist
The distance of the minor grid lines in scale units.
minorTickDist
The distance between minor ticks in scale units.
Result:

The following string is returned:

min max labTab

Where min and max are is the computed or corrected scale range and labTab is the scale definition table which you can then pass to a Plot function. See the scale definition table description in the Command Reference for details of the table syntax.

Examples:

Calculate the linear scale, grid and labels for an amplitude axis between -70 and -10 dB with labels every 10 dB, major grid lines and ticks every 5dB and minor grid lines and ticks every dB.

readstr '$($#xplot ScaleSteps -70 -10 ; 10 ; 5 ; 5 ; 1 ; 1)' #ymin #ymax #ylab
Notes:

See also ScaleOctave and ScaleLog10.

Set

The Set function sets the cursor mode and text attributes.

Usage:

xplot Set [ graph|* ; ] attr args

Parameters:
xgraph
An xgraph instance on which to call the Set command. If no graph is specified or an asterisk, then the Set command is carried out on all graphs.
attr
One of the following values:
cursormode - turn cursors on and off and change the way they look.
xunit - the name of the x-axis unit
yunit - the name of the y-axis unit
xtext - the description of the x-axis
ytext - the description of the y-axis
title - the graph's title
args
The value of args depends on attr.
If attr is cursormode, then args is as follows:
mode|* type|* line|*
Where mode is one of the following values:
on - show the cursor
off - hide the cursor
Where type is one of the following values:
cross|crosshair|vbarcross|harmonic
And line is one of the following values:
off |on
If attr is not cursormode, then args is used as the text, unit or title.
Result:

No return value.

SetCallback

The callback function is called by the message handlers to process popup and context menu messages and hotkeys which are not used by XPLOT or XGRAPH. The following commands are used to call the callback function:

If called from an XGRAPH message handler:

cbfunction xgraphinstance irow icol msgid msgpar

If called from the XPLOT message handler:

cbfunction xplotinstance * * msgid msgpar

Usage:

xplot SetCallback [ cbfunction ]

Parameters:
cbfunction
The name of the callback function or an empty string to remove a previous association.
Result:

No return value.

SetWave

Attach a signal to one graph or all graphs (see adr). If a wave item is attached to a graph, it can not be deleted before it is detached or the graph or XPLOT instance is deleted.

Usage:

xplot SetWave [ waveitem ]

xplot SetWave adr ; [ waveitem ]

Parameters:
adr
The address of the display splitter (see member function Graph for details). If this parameter is omitted, then the wave item is set for all graphs.
waveitem
A wave item id or an XWAVE instance (or empty to remove attachment).
Result:

Return 0 if successful.

Note that wave items can only be attached to graphs of type FUNCTION, XYPLOT, PARAMETER, SPECTROGRAM and WAVEFORM.====XPlot Hotkeys====

The following hotkeys are implemented in the XPLOT class:

C Turn the cursors on and off.
S Change to the next cursor style.
B Turn cursor binding on and off.
Ctrl+N Bind the cursor to the next function.
Ctrl+P Bind the cursor to the previous function.
R Turn the cursor rubberline on and off.
T Turn the title on and off.
X Change to the next x-scale mode.
Y Change to the next y-scale mode.
Z Change to the next z-scale mode.
Space Open the setup dialog.
P Play the attached wave (between the cursors).
Q Play the attached wave (the whole signal).
ESC Stop playback.
Ins Show the selected metasegment's settings in a dialog or, if no metasegment is selected, show a dialog to create a new metasegment.
Del Delete the selected metasegments.
Ctrl+Left Click Move the legend to the clicked position.
Shift+Left Click Create a metasegment at the clicked position (show the 'Insert Metasegment' dialog).


XPlot Examples

Simple XPLOT Example

The following example demonstrates simple XPLOT usage.

[macro xplot_example_1]
    //
    // create display (and graph)
    //
    #xplot := xplot 2 ; 1 ; xplot ; default ; 100 100 800 800
    if '$#xplot[?]' != 'instance' em -1 ; xplot creation failed ($emsg)
    //
    // plot graphs (including data generation)
    //
    #nValues := 100
    $#xplot Plot 0 0 ; XYPLOT ; $(eval fill($#nValues,1,1)) ; * ; Graph Title ; * ; x unit ; x title ; * ; y unit ; y title ; solid:green::1
    $#xplot Plot 1 0 ; SPECTROGRAM ; $(eval rand(1,100,100)) ; * ; Graph Title ; * ; x unit ; x title ; * ; y unit ; y title ; solid:green::1
    //
    // clean up
    //
    // the clean up takes place automatically
    // when the plot window is closed
exit
Plot rows of a matrix using XPLOT

The following example demonstrates how to plot the rows of a matrix using the XPLOT class.

//{{3.9 6473}{2009.01.29  16.44.04} - automatically created version information - do not change or delete this line}

[macro xplot_example_2]

//
//      This row demonstrates how to plot each row of a matrix
//
//      C.G. 29.1.2009
//


//
// create display (and graph)
//

#xplot := xplot 1 ; 1 ; xplot ; default ; 100 100 800 800
if '$#xplot[?]' != 'instance' em -1 ; xplot creation failed ($emsg)


//
// create a matrix and fill it with some meaningless data
//

#mat := new table * /Parameter * number:X:100
if '$#mat[?]' != table em -1 ; cannot create table ($emsg)

for #i := 0 to $#i < 10 step #i := int $#i + 1
        $#mat[$#i,*] := eval fill( 100, $#i+1, $#i+1 )
end


//
// plot each row of the matrix
//

for #i := int 0 to $#i < $#mat[!nrow] step #i := int $#i + 1
        #x := eval $#mat[$#i,*]
        $#xplot AddPlot 0 0 ; XYPLOT ; $#x ; * ; row-by-row plot ; * ; x unit ; x title ; * ; y unit ; y title ; solid:green::1
end

exit 1 int 0


Advanced XPLOT Example

This example not only demonstrates the use of the XPLOT class, but also signal processing using the EVAL function.

//=================================================================================================
//      
//      DSP Examples
//      
//      last update:    Nov 17, 2007 (AN)
//      {{STX}} version:    {{STX}} 3.8 Beta
//
//      The examples in this file demonstrates how to ...
//              ...     use the EVAL command for signal processing
//              ...     use the class XWAVE     to read a signal frame by frame
//              ...     display spectrograms, waveforms and functions in XPLOT graphs
//              ...     enable XPLOT to play signals
//              ...     use the XPLOT callback function to implement simple user controls
//              ...     set and get cursor attritbutes and positions of XPLOT graphs
//              ...     add a legend to a XPLOT graph
//              ... use BUTIL MSGBOX for simple dialogs
//              ...     use the CON object (class BScript) to display log. messages
//              ...     use the CON object to save numeric tables to textfiles
//              ...     simulate item messages using the message queue macro MSGQUEUE
//              ...     implement and call local subroutines
//
//=================================================================================================


//-------------------------------------------------------------------------------------------------
//
//      DSPExAvrSpectrum                Create a plot containing the average spectra of all segments selected
//                                                      in the DataSet view.
//
//-------------------------------------------------------------------------------------------------
[Macro DSPExAvrSpectrum #lfrm=100ms';'#sfrm=50%';'#wtyp=hamming';'#ascale=dB';'#fscale=Hz';'#amax=1';'#aref=1';'#]
//      arguments:      #lfrm           frame length,   absolute time expression
//                              #sfrm           frame shift,    relative time expression
//                              #wtyp           window type,    {Hanning, Hamming, ...)
//                              #fscale         spectrogram frequency scale unit (Hz, kHz, Bark, Mel, ERB)
//                              #amax           calibration factor or CALSET to use a calibration set
//                              #aref           reference amplitude, ignored if #amax equals CALSET

//      set mode to macro name (see macro DSPExCallback)
DSPExMode := set '$#mac'

//      get segments selected in the DataSet view
#segments := dspexlib getsegments

//      create the result table (one spectrum per row)
#asp := new table * * num:x:$#segments[] /p

//      segment analysis loop
#nok := 0       //      number of computed average spectra
for #i := 0 to $#i < $#segments[] step #i := int $#i+1

        //      get next segment from segment list
        readtab $#segments $#i #aset';'#aseg';'#ach';'#
        con log process segment "set=$#aset, id=$#aseg, ch=$#ach" ($(int $#i+1) of $#segments[])

        //      create the wave object and initialize frame settings (mode "centered")
        //      usage: XWAVE setref ; segmentid ; channel ; mode ; framelength ; frameshift ; ampmax ; ampref
        if $(#wave := xwave '$#aset;$#aseg;$#ach;1;$#lfrm;$#sfrm;$#amax;$#aref')[?] != instance then
                butil 'msgbox msg; create wave object for segment "$#aset/$#aseg,$#ach" failed; Error!'
                continue
        //      set / check sampling rate
        else if '$#srate' == '' then
                #srate := $($#wave srate)       
        else if $($#wave srate) != $#srate then
                butil 'msgbox msg; segment "$#aset/$#aseg,$#ach" - sampling rate mismatch; Error!'
                $#wave destroy  //      delete wave object
                continue
        end
        
        //      compute the average spectrum
        if $(#tmp := dspexlib averagespectrum $#wave ; $#wtyp ; $#ascale)[?] != table then
                butil 'msgbox msg; compute average spectrum of segment "$#aset/$#aseg,$#ach" failed; Error!'
                $#wave destroy  //      delete wave object
                continue
        end
                
        $#asp[*,$#nok] := $#tmp                                 //      save the spectrum
        delete $#tmp                                                    //      delete temp. buffer
        #legend := '$#legend $($#wave title);'  //      add segment to legend string
        $#wave destroy                                                  //      delete wave object
        #nok := int $#nok+1                                             //      increment result vector counter

end

//      exit if no results are computed
if $#nok < 1 exit 

//      compute frequency scale vector, unit and frequency resolution
readstr '$(dspexlib frequencyscale $#srate ; $#asp[!nrow] ; $#fscale)' #frq #funit #df

//      create and configure the plot object
//      usage: XPLOT rows ; cols0 cols1 .. ; windowtitle ; graphicprofile ; wx wy wwidth wheight
#plot := xplot 1; 1; Average Spectrum; Rainbow; 0 0 1024 800

//      plot all spectra and display the legend
#title := format 'lfrm=%s, sfrm=%s, wtyp=%s, df=%.3fHz' '$#lfrm' '$#sfrm' '$#wtyp' $#df
readstr '$(dspexlib amplitudescale $#ascale)' #ytext #yunit
//      usage: xplot PLOT row col; FUNCTION; ydata; xdata; title; xrange; xunit; xtext; yrange; yunit; yrange
$#plot plot 0; function; $#asp; $#frq; $#title; ; $#funit; frequency; ; $#yunit ; $#ytext
$#plot legend 0; %; 50; 95; 45; 5; black; color; $#legend
$#plot set cursormode on crosshair      //      set cursor mode and style       
$#plot setcallback dspexcallback        //      assign callback function

//      wait until plot window is closed 
$#plot end      //      the xplot object is destroyed automatically when the window is closed
  
//      finished - cleanup and and exit
delete $#asp $#frq $#segments   //      delete data items
showLogOnExit := 0      //      close the bscript log-window automatically 
exit


//-------------------------------------------------------------------------------------------------
//
//      DSPExSpectrogram                Plot a spectrogram of all segments selected in the DataSet view.
//                                                      For each segment one spectrogram window is displayed. The window
//                                                      must be closed before the next segment is analysed.
//
//-------------------------------------------------------------------------------------------------
[Macro DSPExSpectrogram #lfrm=40ms';'#sfrm=10%';'#wtyp=hamming';'#arange=50';'#fscale=Hz';'#amax=1';'#aref=1';'#]
//      arguments:      #lfrm           frame length,   absolute time expression
//                              #sfrm           frame shift,    relative time expression
//                              #wtyp           window type,    {Hanning, Hamming)
//                              #arange         spectrogram display range in dB (max .. max-range)
//                              #fscale         spectrogram frequency scale unit (Hz, kHz, Bark, Mel, ERB)
//                              #amax           calibration factor or CALSET to use a calibration set
//                              #aref           reference amplitude, ignored if #amax equals CALSET

//      set mode variable to macro name (see macro DSPExCallback)
DSPExMode := set '$#mac'

//      get segments selected in the DataSet view
#segments := dspexlib getsegments

//      segment analysis loop
for #i := 0 to $#i < $#segments[] && '$DSPExMode' != '' step #i := int $#i+1

        //      get next segment from segment list
        readtab $#segments $#i #aset';'#aseg';'#ach';'#

        //      create the wave object and initialize frame settings (mode "centered")
        if $(#wave := xwave '$#aset;$#aseg;$#ach;1;$#lfrm;$#sfrm;$#amax;$#aref')[?] != instance then
                butil 'msgbox msg; create wave object for segment "$#aset ; $#aseg ; $#ach" failed; Error!'
                continue
        end 

        //      compute the spectrogram
        if $(#asp := dspexlib spectrogram $#wave ; $#wtyp ; log)[?] != table then
                butil 'msgbox msg; compute spectrogram of segment "$#aset ; $#aseg ; $#ach" failed; Error!'
                $#wave destroy
                continue
        end 

        //      compute frequency scale vector, unit and frequency resolution
        readstr '$(dspexlib frequencyscale $($#wave srate) ; $#asp[!ncol] ; $#fscale)' #frq #funit #df

        //      create and configure the plot object
        #plot := xplot 2; 1 1; $($#wave title)   quit = c-q, next = c-n; Rainbow; 0 0 1024 800
        $($#plot display) height 3 1 /apply             //      set height of graphs

        //      plot spectrogram and waveform
        #title := format 'lfrm=%s, sfrm=%s, wtyp=%s, arange=%s, amax=%.1fdB, df=%.3fHz' '$#lfrm' '$#sfrm' '$#wtyp' '$#arange' $(eval max($#asp)) $#df
        $#plot plot 0; spectrogram; $#asp; $#frq; $#title; $($#wave tbegin) $($#wave tend); s; time; ; $#funit; frequency; $#arange
        $#plot plot 1; waveform; $#wave; ; s; time; $($#wave amax); $($#wave amax); amplitude; 1
        $#plot set cursormode on crosshair      //      set cursor mode and style       
        $#plot setcallback dspexcallback        //      assign callback function

        //      assign wave object to xplot graphs (for playback)
        $#plot setwave $#wave 

        //      wait until plot window is closed 
        $#plot end      //      the xplot object is destroyed automatically when the window is closed
  
        //      cleanup
        delete $#asp $#frq              //      delete data items
        $#wave destroy                  //      delete wave object
end

//      finished - cleanup and exit
delete $#segments       //      delete segment table
showLogOnExit := 0      //      close the bscript log-window automatically 
exit


//-------------------------------------------------------------------------------------------------
//
//      DSPExCallback                   Callback function for XPLOT.
//
//      arguments:
//              if called from xplotobject message handler      ->   'CALLBACK xplotobject * * msgid msgpar'                   
//              if called from xgraphobject message handler     ->   'CALLBACK xgraphobject row col msgid msgpar'
//
//      Note: This macro uses the shell variable DSPEXMODE to check which macro has installed the 
//      callback and to set return values.
//
//-------------------------------------------------------------------------------------------------
[Macro DSPExCallback #obj #row #col #msgid #msgpar]

//      get xplot-object if called from a xgraph-object
if '$#obj[!class]' == xgraph #obj := $#obj get xplot

//      message filter for keystroke messages

//      process Control-Q (QUIT) key
if '$#msgid$#msgpar' == keyCQ then

        if $(butil msgbox yesno; Quit ?; $DSPExMode) == yes then
                //      place the display-close message in the message queue to end the xplot message loop
                msgqueue 'display $($#obj display) close'
                //      set mode variable to empty-string if C-Q key was pressed
                DSPExMode := ''
        end

//      process Control-C (COPY) and Control-S (SAVE) keys
else if $(#i := keyword '$#msgid$#msgpar' keyCC keyCS) >= 0  then

        //      get xgraph-object displayed in row 0 (later used to retrieve data)
        #obj := $#obj graph 0; instance

        //      select the data to be saved and the save format
        #todo := butil msgbox userdefined Amp Frq+Amp Cancel;; $DSPExMode - $(word $#i 'Copy to Clipboard' 'Save to CSV-File') 
        if $#todo == Amp then
                #table := eval $($#obj get ydata)       //      use eval to get a copy of y-data
        else if $#todo == Frq+Amp then
                if '$DSPExMode' == DSPExAvrSpectrum then
                        #table := eval vmcol( $($#obj get xdata) , $($#obj get ydata) ) // merge x- and y-data into one table
                else
                        #table := eval vmcol( $($#obj get xdata) , trn($($#obj get ydata)) ) // merge x- and transposed y-data into one table
                end
        end

        //      copy / save if table exists
        if $#table[?] == table then
                //      select target
                if $#i == 0 then
                        #file := set clipboard  // set target to "clipboard" for all copy_xxx functions
                else
                        #file := butil filedialog save; Select Output File; ; CSV=CSV-File; TXT=Textfile        //      use filedialog to select the output file
                end

                //      use the CON-object to copy/save table
                if '$#file' != '' con savedata text; $#table; $#file; 0; comma; dot
                delete $#table
        end

//      process Control-I (INFO) || Control-M (MAX-MEAN) keys
else if $(#i := keyword '$#msgid$#msgpar' keyCI keyCM) >= 0  then

        //      get xgraph-object displayed in row 0
        #obj := $#obj graph 0;inst

        //      save original graph title
        if '$GraphTitle' == '' GraphTitle := $#obj get title

        if $#i == 0 then
                //      get and display cursor positions
                readstr '$($#obj get cursorposition)' #i1 #x1 #y1 #i2 #x2 #y2 #
                #text := format 'Index = %d .. %d,  X = %g ... %g (%g),  Y = %g ... %g (%g)' $#i1 $#i2 $#x1 $#x2 abs($#x1-$#x2) $#y1 $#y2 abs($#y1-$#y2)
        else
                //      set cursor mode (on), style (crosshair), rubberline (off), bind-mode (off), bind-functionindex (0)
                $#obj set cursormode on crosshair off off 0
                //      get x- and y-data
                #x := $#obj get xdata
                #y := $#obj get ydata
                //      find index of maximum y value 
                #imax := eval imax($#y[*,0])
                //      compute mean of x and y
                #xavr := eval avr($#x)
                #yavr := eval avr($#y)
                //      set cursor 1 to maximum and cursor 2 to mean
                $#obj set cursorpos 1 $#x[$#imax] $#y[$#imax] deselect
                $#obj set cursorpos 2 $#xavr $#yavr deselect
                //      show maximum and mean in xgraph title
                #text := format 'Maximum( %g , %g ), Average( %g , %g )' $#x[$#imax] $#y[$#imax] $#xavr $#yavr
        end
        //      show info in graph title
        $#obj set title $GraphTitle -- $#text

end

//      note: the return value of the callback function is not used by the xplot/xgraph message handler
exit


//-------------------------------------------------------------------------------------------------
//
//      DSPExLib                        Implements a set of signal processing functions which can be called with
//                                              "DSPLIBEXAMPLE functionname functionarguments". This call style is often
//                                              used to reduce the number of macros of a script or application.
//
//      Functions:
//
//              DSPEXLIB GETSEGMENTS
//                      result: a list of all segments selected in the DataSet view stored in a simple
//                                      table (per line: 'setReference ; segmentId ; channelIndex')
//                      note:   this function shows an error message and terminates the caller if no segments
//                                      are selected
//
//              DSPEXLIB AVERAGESPECTRUM wave ; wtyp ; atyp
//                      wave            prepared xwave object
//                      wtyp            type of window function:        HANNING, HAMMING, KAISER, ...
//                      atyp            type of output spectrum:        LOGARITHMIC (=DB), POWER, LINEAR (=AMPLITUDE)
//                      result: an averaged fft spectrum in the selected format
//
//              DSPEXLIB SPECTROGRAM wave ; wtyp ; atyp
//                      wave            prepared xwave object
//                      wtyp            type of window function:        HANNING, HAMMING, KAISER, ...
//                      atyp            type of output spectrum:        LOGARITHMIC (=DB), POWER, LINEAR (=AMPLITUDE)
//                                                                                                      or COMPLEX
//                      result: a matrix of fft spectra in the selected format, one spectrum per line
//
//              DSPEXLIB FREQUENCYSCALE sr ; n ; type
//                      sr                      sampling rate in Hz
//                      n                       number of spectrum bins (equally spaced in the Hz domain)
//                      type            type of frequency scale:        HZ, KHZ, BARK, MEL, ERB
//                      result: 'frq unit df'; frq is the frequency scale vector, unit is the frequency unit
//                                      name and df is the frequency scale step in Hz
//
//              DSPEXLIB AMPLITUDESCALE type
//                      type            type of amplitude scale:        LOGARITHMIC (=DB), POWER, LINEAR (=AMPLITUDE)
//                      result: 'name unit df'; name and unit of amplitude scale
//
//-------------------------------------------------------------------------------------------------
[Macro DSPExLib]

//      function call dispatching
readvar #argv #fun #argv /d
goto fun$#fun noFun

noFun:
//      function not implemented
//      result: empty string

        //      show an error message and exit
        con log '$#mac function "$#fun" not implemented' 
        exit 1 set ''

//-------------------------------------------------------------------------------------------------
funGetSegments: //      in:
                                //      out:    segment_list_table
//-------------------------------------------------------------------------------------------------
        //      retrieve list of selected segments from the DataSet application
        #segments := datasetcmd getselected segments
        if '$#segments[?]' == table && '$#segments[]' > 0 exit 1 set $#segments
        butil msgbox msg ; no segments selected - select and try again; Error!
        if '$#segments[?]' == table delete $#segments
        exit 2 set ''   //      terminate this and the calling macro!

//-------------------------------------------------------------------------------------------------
funAverageSpectrum:     //      in:             xwaveobject ; windowtype ; amplitudescale 
                                        //      out:    averagespectrum_vector
//-------------------------------------------------------------------------------------------------
        //      parse arguments
        readvar #argv #wave';'#wtyp';'#atyp';'#

        //      show init message
        con log $#mac $(upper '$#fun') - initializing

        //      create window
        #w := gosub makewindow $($#wave framelength) $#wtyp

        //      create result table 
        #spg := new table * 

        //      compute averaged amplitude spectrum
        #n := $($#wave framecount)
        $#spg := eval cr2len ( fft ( $($#wave read) ?* $#w ) )
        for #i := 1 to $#i < $#n step #i := int $#i+1
                if $#i%10 == 0 con logext 0; $#mac $(upper '$#fun') - $#i of $#n frames processed
                $#spg := eval cr2len ( fft ( $($#wave read) ?* $#w ) ) + $#spg
        end
        $#spg := eval $#spg / $#n

        //      convert to selected output spectrum type
        if $(#atyp := keyword '$#atyp' dB logarithmic power amplitude linear) < 2 then
                $#spg := eval lin2log($#spg , $($#wave aref), 20)
        else if $#atyp == 2 then 
                $#spg := eval $#spg ?^ 2
        end

        //      show end message
        con logext 0; $#mac $(upper '$#fun') - finished ($#n spectra computed)

        //      return averaged spectrum
        exit 1 set $#spg

//-------------------------------------------------------------------------------------------------
funSpectrogram: //      in:             xwaveobject ; windowtype ; amplitudescale 
                                //      out:    spectrogram_matrix
//-------------------------------------------------------------------------------------------------
        //      parse arguments
        readvar #argv #wave';'#wtyp';'#atyp';'#

        //      show init message
        con log $#mac $(upper '$#fun') - initializing

        //      create window
        #w := gosub makewindow $($#wave framelength) $#wtyp

        //      check selected output spectrum type
        if $(#atyp := keyword '$#wtyp' dB logarithmic power amplitude linear complex) < 5 then
                //      compute amplitude or power spectra
        
                //      create result table (one spectrum per line)
                #spg := new table * * num:x:$(int $($#wave fftlength)/2 + 1) /p
                //      compute amplitude spectra
                #n := $($#wave framecount)
                for #i := 0 to $#i < $#n step #i := int $#i+1
                        if $#i%10 == 0 con logext 0; $#mac $(upper '$#fun') - $#i of $#n frames processed
                        $#spg[$#i,*] := eval cr2len ( fft ( $($#wave read) ?* $#w ) )
                end
                //      convert to selected output spectrum type
                if $(#atyp := keyword '$#atyp' dB logarithmic power amplitude linear) < 2 then
                        $#spg := eval lin2log($#spg , $($#wave aref), 20)
                else if $#atyp == 2 then 
                        $#spg := eval $#spg ?^ 2
                end

        else
                //      compute complex spectra

                //      create result table (one spectrum per line)
                #spg := new table * * num:x:$(int $($#wave fftlength) + 2) /p
                //      compute complex spectra
                for #i := int $($#wave framecount) to $#i > 0 step #i := int $#i-1
                        if $#i%50 == 0 con logext 0; $#mac $(upper '$#fun') - $#i of $#n frames processed
                        $#spg[$#i,*] := eval fft ( $($#wave read) ?* $#w )
                end

        end

        //      show end message
        con logext 0; $#mac $(upper '$#fun') - finished ($#n spectra computed)

        //      return spectrogram matrix
        exit 1 set $#spg

//-------------------------------------------------------------------------------------------------
funFrequencyScale:      //      in:             samplingrate ; spectrumbins ; frequencyscale 
                                        //      out:    frequencyscale_vector frequencyscale_unit frequency_resolution_Hz
//-------------------------------------------------------------------------------------------------
        //      parse arguments
        readvar #argv #sr';'#n';'#unit';'#
        //      generate frequency scale equally spaced in Hz
        #frq := new table * // dummy table to make frq-scale permanent
        $#frq := eval fill($#n, 0, $(#df := eval $#sr / 2 / ($#n - 1)) )
        //      convert to selected scale
        if $(#unit := keyword '$#unit' Hz kHz Bark Mel ERB) < 0 #unit := 0
        if $(#unit := word $#unit Hz kHz Bark Mel ERB) == kHz then
                $#frq := eval $#frq / 1000
        else if $#unit != Hz then
                $#frq := eval hz2$#unit($#frq)
        end
        //      return scale settings
        exit 1 set '$#frq $#unit $#df'

//-------------------------------------------------------------------------------------------------
funAmplitudeScale:      //      in:             amplitudescale 
                                        //      out:    amplitudescale_text amplitudescale_unit
//-------------------------------------------------------------------------------------------------
        //      parse arguments
        readvar #argv #unit';'#
        //      get text and unit of amplitude scale
        if $(#i := keyword '$#unit' dB logarithmic power amplitude linear) < 2 #i := 0
        #unit := word $#i dB dB - - -
        #text := word $#i amplitude amplitude power amplitude amplitude
        exit 1 set '$#text $#unit'

//
//      local subroutines
//

makeWindow:
        //      GOSUB MAKEWINDOW windowlength windowtype -> windowvector
        readvar #argv #wlen #wtyp # 
        #list := hanning hamming blackman kaiser bartlett taprect nuttall flattop gauss
        if $(#wtyp := keyword '$#wtyp' $#list) < 0 #wtyp := 0 
        exit 1 eval window($#wtyp, $#wlen, 1) * 2 / $#wlen

Navigation menu

Personal tools