<html>
<h2>Audio effect interface for ProSound</h2>
ProSound can be extended by adding plug-in effects.<br>
The effects are stored in the directory <tt>&lt;ProSound$Dir&gt;.FX</tt>.<br>
Each effect is a directory holding some or all of these files:
<dl>
<dt>FX
<dd>the effect code (must be present).
<dt>Templates
<dd>templatefile, this can be loaded by ProSound. To support internationalisation, this file may be substituted by a directory (with the same name) holding subdirectories with the names of the territories supported. Each of these subdirectories should then hold a file called Templates, eg. <tt>'...FX.Templates.UK.Templates'</tt>
<dt>!Sprites
<dd>spritefile, *IconSprited by ProSound.
<dt>Sprites
<dd>spritefile, used for the icons in the Templates file.
<dt>!Run
<dd>obeyfile, *Run by ProSound.
<dt>Icons
<dd>spritefile containing two sprites ('0' and '1', mode 27, 28x28 pixels) which are used if bit 10 in the flags is set.
</dl>
        

The !Run file is *Run by ProSound before the effect is loaded. !Sprites is *IconSprited by ProSound before the effect is loaded. FX is loaded by ProSound when the program is started.

<h4>FX</h4>
The FX file has a 14 or 32 words header. If bit 10 in the flags (word 13) is set, the header is extended format and used 32 words.

<pre>
 Word
  0     Offset to init code or 0
  1     Offset to kill code or 0
  2     Offset to start code or 0
  3     Offset to effect code or 0
  4     Offset to mouse handling code or 0
  5     Offset to redraw code or 0
  6     Offset to key handling code or 0
  7     Offset to menu string (max 20 chars, 0-terminated)
  8     Offset to playtime code or 0
  9     Offset to savetime code or 0
 10     Offset to service code or 0
 11     Window handle or 0 or -1
 12     Required size of workspace
 13     Effect group and flags
</pre>
Extended header:
<pre>
 14     Offset to icon handle code or 0
        (ignored if bit 10 in the flags is clear)
 15     Offset to pre-start code or 0
 16-31  Reserved, must be 0 (ignored if bit 10 in the flags is clear)
</pre>

<h4>Templates</h4>
If word 11 (window handle) in the FX header is 0, ProSound will open the templates file, load and create the window called 'FX' and store the handle of this in word 11 in the header.</br>
When designing the window, please try to keep it in the same style as the windows used by other effects.</br>
The total size of the indirect data used by the window should be less than 1024 bytes.


<h4>Init code</h4>
This is called immediately after ProSound has loaded the FX code to the RMA - before loading/creating the window.

<pre>
On entry
        R0  =>  Base of ProSound core
        R1  =>  ProSound workspace
        R2  =>  File descriptor passed to MessageTrans_OpenFile
        R5  =>  Intro screen definition block or 0 (if no intro screen)
                This block allows the fx to print information during
                loading. The block contains:
                +0      Bottom left X (OS units)
                +4      Bottom left Y
                +8      Top right X
                +12     Top right Y
                The background of the box will have been cleared to grey1;
                the fx may plot whatever it likes inside the box.

 On exit
        R0  =   INITIALISED_OK
   or   R0  =>  Error block (V flag clear)
</pre>

When the init code returns, ProSound builds a menu item from the menu string, using the contents of word 11 of the header as the submenu pointer/window handle. If this is <>-1, the menu will have the 'generate message' bit set.


<h4>Kill code</h4>
This is called when ProSound quits, or when the effect is killed for other reasons.

<pre>
 On entry
        -
 On exit
        -
</pre>


<h4>Start code</h4>
This is called when the user selects the menu entry for the effect, or when a Message_MenuWarning is generated from the menu for this effect.</br>
If the effect doesn't supply a windowhandle in 11th word of the header, then this entry should apply the effect.</br>
If the effect DOES supply a window handle in word 11, then the effect should initialise the window at this point (eg. reset icons to their default state)
as the window will be opened (by SYS "Wimp_CreateMenu" or SYS "Wimp_CreateSubMenu") when the call returns. It should NOT apply the effect at this point.

<pre>
On entry
        R0  =>  Track
        R2  =   First sample
        R3  =   Last sample
        R4  =   Project
        R5  =   0

On exit
        R0  =   IGNORE_LINKING to prevent the fx from being applied to the
                other tracks (if bit 9 in the flags is set and there is no
                window in word 11)
    or  R0  =   OPEN_WINDOW (open the window using SYS Wimp_OpenWindow)
    or  R0  =   any other value (open the window using SYS Wimp_CreateMenu)
</pre>


<h4>Effect code</h4>
This applies the effect. 

<pre>
On entry
        R0  =>  Track
        R2  =   First sample
        R3  =   Last sample
        R4  =   Project
        R5  =   0

On exit
        R0  =   IGNORE_LINKING to prevent the fx to be applied to the
                other tracks (if bit 9 in the flags is set)
   or   R0  =   any other value
</pre>


<h4>Mouse handling code</h4>
This is called whenever the user clicks the mouse in the window whose handle is stored in word 11 in the header.

<pre>
On entry
        R1  =>  Wimp block as returned by SYS "Wimp_Poll"

On exit
        R0  =   APPLY_EFFECT to make ProSound call the effect code
                immediately and redraw the track after that
   or   R0  =   DONE_MOUSE to do nothing
</pre>




<h4>Redraw code</h4>
This entry is called whenever the window whose handle is stored in word 11 in the header, needs to be redrawn.

<pre>
On entry
        R1  =>  Wimp block as returned by SYS "Wimp_Poll"

On exit
        -
</pre>

The redraw code is called from within the Wimp_GetRectangle loop.



<h4>Key handling code</h4>
This entry is called whenever a key is pressed while the input focus belongs to the window whose handle is stored in word 11 in the header.

<pre>
On entry
        R1  =>  Wimp block as returned by SYS "Wimp_Poll"

On exit
        R0  =   APPLY_EFFECT to make ProSound call the effect code
                immediately and redraw the track after that
   or   R0  =   DONE_KEY to do nothing
</pre>


<h4>Playtime code</h4>
This entry is called whenever ProSound plays a project.<br>
It allows the effect to apply realtime effects.

<pre>
On entry
        R0  =>  Sample data buffer
        R1  =   Number of samples in the buffer (L+R if stereo)
        R2  =   Index of first sample in the buffer
        R3  =   Project
    or  R3  =   -1 (when playing a file from the library)
        R4  =>  Track (when playing a track)
    or  R4  =   -1 (when playing a project or a file from the library)
        R5  =   Flags
                Bit 0 set => stereo (samples are interleaved LRLRLR...)

On exit
        -
</pre>

The effect may alter the contents of the buffer in R0.<br>
Service_StartPlaying will have been issued immediately before this call is made.


<h4>Savetime code</h4>
This entry is called whenever ProSound saves a project.

<pre>
On entry
        R0  =>  Sample data buffer
        R1  =   Number of samples in the buffer (L+R if stereo)
        R2  =   Position in project of first sample in the buffer
        R3  =   Project
        R4  =>  Track (when saving a track)
    or  R4  =   -1 (when saving a project)
        R5  =   Flags
                Bit 0 set   => R1 holds interleaved stereo samples
                Bit 1 clear => left (if saving a project in 2 mono blocks)
                Bit 1 set   => right (if saving a project in 2 mono blocks)


On exit
        -
</pre>

The effect may alter the contents of the buffer in R0.<br>
The buffer will hold interleaved samples (LRLRLRL...) when saving a project in stereo.<br>
 The savetime code may be called twice when saving a project; once for the right channel and once for the left channel.



<h4>Service code</h4>
This entry is called at various points to inform the effects of changes of various kinds.

<pre>
On entry
        R0  =>  Service code
        R1 - R5 Depends on R0

        R0  =   0       Service_FileAddedToLibrary
                        File added to the library
                        R1  =>  Library
                        R2  =   Library entry number (0-255)
                        This is only called if the file isn't a ProSound
                        track.

        R0  =   1       Service_FileRemovedFromLibrary
                        File removed from the library
                        R1  =>  Library
                        R2  =   Library entry number (0-64)

        R0  =   2       Service_TrackCreated
                        Track created
                        R1  =   Project
                        R2  =>  Track
                        This is only called if the track is added after
                        the project has been created.

        R0  =   3       Service_TrackRemoved
                        Track removed
                        R1  =   Project
                        R2  =>  Track

        R0  =   4       Service_ProjectCreated
                        Project created
                        R1  =   Project

        R0  =   5       Service_ProjectRemoved
                        Project removed
                        R1  =   Project

        R0  =   6       Service_ProjectAltered
                        Project altered (eg. new duration or frequency)
                        R1  =   Project

        R0  =   7       Service_SaveChoices
                        Saving choices
                        R1  =   File handle
                        The fx may save any number of chunks; the format
                        of a chunk is described in the file 'Choices?'.

        R0  =   8       Service_LoadChoices
                        Loading choices
                        R1  =   File handle
                        R2  =   ID of next chunk
                        R3  =   Size of next chunk
                        On entry, the file pointer is set to the first
                        byte after the chunk header; if the fx loads the
                        data it should return with the file pointer set
                        to the first byte after the chunk.
                        The fx should not assume that this service call
                        will ever be issued - the user may choose not
                        to save the choices so there might not be any
                        choices to load.
                        The fx should ignore this call if the ID (in R2)
                        isn't recognised.

        R0  =   9       Service_MenuWarning
                        Menu warning
                        R1  =   Project
                        This service call is issued whenever ProSound
                        receives a Message_MenuWarning for the fx-menu.
                        The fx may use the call ProSound_FXToMenu to find
                        the address of its own menuentry.

        R0  =   10      Service_KeyPressed
                        Unclaimed key press
                        R1  =   Project
                        R2  =>  Track
                        R3  =   Key
                        This service call is issued when the user presses
                        a key and ProSound doesn't act upon it
                        It is provided to allow fxs to be activated thru
                        hotkeys - hotkeys are allocated by Oregan.

        R0  =   11      Service_Initialised
                        All effects have been loaded.

        R0  =   12      Service_Message
                        ProSound receives a User_Messages poll reason code
                        R1  =>  Wimp message block
                        R2  =   Project

        R0  =   13      Service_MouseButtonChanged
                        This service call is issued whenever the mouse
                        button state changes while the mouse is over
                        a sample window.
                        R1  =>  Wimp message block
                        R2  =   Project

        R0  =  14       Service_CurrentProjectIs
                        R1  =   Project
                        This service call is issued whenever the current
                        project changes. It may also be issued even though
                        the project in R1 is the same as the current
                        project before the service call; check for this by
                        reading the unique ID of the projects.

        R0  =  15       Service_StartPlaying
                        ProSound is about to start playing a project or
                        track or file from the library
                        When playing a track
                        R1  =   Project
                        R2  =>  Track
                        or when playing a project
                        R1  =   Project
                        R2  =   0
                        or when playing a file from the library
                        R1  =   -1
                        R2  =>  Library entry
                        This service call is issued immediately before
                        ProSound starts playing.

        R0  =  16       Service_StopPlaying
                        This service call is issued when playback is
                        stopped.

        R0  =  17       Service_Error
                        An error has been generated or has occured
                        R1  =   Error number
                        This service call is issued whenever ProSound
                        reports an error. If this happens during playback,
                        playback is aborted.

        R0  =  18       Service_Playing
                        This service call is issued every now and then
                        while ProSound is playing a track or a project
                        It shouldn't be claimed.

        R0  =  19       Service_Polled
                        This service call is issued whenever ProSound
                        receives a poll.
                        R1  =  Wimp block
                        R2  =  Poll reason code

        R0  =  20       Service_SamplesEdited
                        This service call informs the fxs that part of
                        a track has been edited/changed
                        R1  =  Project
                        R2  =  Track
                        R3  =  First sample
                        R4  =  Last sample
                        There is no guarentee that this call always will
                        be issued when samples are edited, eg. an fx may
                        chose not to issue it. ProSound itself will issue
                        this service call if an fx returns from the mouse or
                        key code with R0 = -1.

        R0  =  253      Service_PlayAndRecordFlags
                        This service call may or may not be broadcasted by
                        ProSound BEFORE Service_Initialised. If it is not
                        broadcasted, the playback/sample-drivers should
                        assume that the flags that would otherwise be set
                        by the call are 0.
                        R1  =  Play-and-record flags
                               Bit 0 set => play-and-record disabled
                               Bit 1 set => play-and-record uses stereo
                                            playback driver (otherwise mono)

        R0  =  254      Service_SetSampleGain
                        This service call allows ProSound to set the input-
                        gain for hardware which supports this.
                        R1  =  Gain in dB (-20 to 20)
                        Only the current driver (ie. the driver whose SDB
                        was passed in R1 in the latest Service_SamplerChange)
                        should respond to the call. If it claims the call,
                        ProSound will assume that the gain will be applied
                        in hardware and will not apply the gain in software.
                        If the sampledriver responds to this call, it should
                        reset itself to 0dB whenever sampling stops; this is
                        necessary as this call is only issued if the user
                        specifies a gain.

        R0  =  255      Service_SampleDriverSetup
                        This service call is issued when the user clicks on
                        the 'Driver...' icon in the Record window. Only the
                        current driver (ie. the driver whose SDB was passed
                        in R1 in the latest Service_SamplerChange) should
                        respond to the call, usually by opening the setup
                        window as a transient window.

        R0  =  256      Service_ClaimSampler
                        This service call may be issued by an fx to inform
                        other fxs that it will start sampling soon.
                        If no other fxs claims the call, the caller may
                        assume that it is safe to go on sampling, otherwise
                        it should abort.
                        This call should only be used if the fx doesn't
                        start sampling immediately after the user have
                        asked the fx to start sampling - ie. if the
                        sampledriver ignores the sampledriver-interface.
                        *** consider this service call obsolete ***

        R0  =  257      Service_SimpleEcho
                        Use by the echo-fx (obsolete)

        R0  =  258      Service_SamplerChanged
                        This service call is issued by the sampledriver-
                        interface when the user selects a sampledriver
                        in the 'Record' window, and when ProSound picks
                        a sampledriver at start-up.
                        R1  => SDB (sampledriver block)

        R0  =  259      Service_AttemptToReinitialise
                        This service call is issued when the user wants the
                        sampledrivers to attempt to reinitialise. Only
                        drivers which aren't available to the user (the
                        disabled bit is set or the driver isn't installed
                        at all) should respond to this call.
                        This service call is currently never issued, but
                        may be used in the future to enable sampledrivers
                        to initialise themselves when eg. support modules
                        are RMLoaded etc. etc.

        R0  =  260      Service_LarkIsPlaybackDriver
                        R1  =   1 (mono) or 2 (stereo)
                        This service call is issued by the Lark playback-
                        driver when it is installed. You should never claim
                        the call.
                        When the Lark sampledriver receives this call, it
                        sets a flag in its flagword indicating that playback
                        is not allowed at the same time as recording.

        R0  =  261      Service_LarkIsNoLongerPlaybackDriver
                        R1  =   1 (mono) or 2 (stereo)
                        See service 260.

        R0  =  262      Service_EagleIsPlaybackDriver
                        R1  =   1 (mono) or 2 (stereo)
                        This service call is issued by the Eagle playback-
                        driver when it is installed. You should never claim
                        the call.
                        When the Eagle sampledriver receives this call, it
                        sets a flag in its flagword indicating that playback
                        is not allowed at the same time as recording.

        R0  =  263      Service_EagleIsNoLongerPlaybackDriver
                        R1  =   1 (mono) or 2 (stereo)
                        See service 262.

        R0  =  264      Service_AudioDynamicsIsPlaybackDriver
                        R1  =   1 (mono) or 2 (stereo)
                        This service call is issued by the AD playbackdriver
                        when it is installed. You should never claim the
                        call.

        R0  =  265      Service_AudioDynamicsIsNoLongerPlaybackDriver
                        R1  =   1 (mono) or 2 (stereo)
                        See service 264.

        R0  =  266      Service_IrlamIsPlaybackDriver
                        R1  =   1 (mono) or 2 (stereo)
                        This service call is issued by the Irlam
                        playbackdriver when it is installed. You should
                        never claim the call.

        R0  =  267      Service_IrlamIsNoLongerPlaybackDriver
                        R1  =   1 (mono) or 2 (stereo)
                        See service 266.

 On exit

        R0  =   CLAIM_SERVICE to claim the service call
    or  R0  &gt;&lt;  CLAIM_SERVICE to pass the call to the rest of the fx
</pre>


<h4>Workspace</h4>
The workspace is allocated (from the RMA) before the init code is called and this word is replaced with a pointer to the workspace.



<h4>Flags and effect group</h4>
<pre>
        Bit 0-3        Group number
        Bit 4 set =>   The fx only supports 1-8 tracks
        Bit 5 set =>   The menustring is followed by a menustring for use
                       when the fx is placed in a fx-group sub-menu; the
                       two strings are seperated by an ASCII 0
        Bit 7 set      The fx uses LOADs of CPU time (ignored)
        Bit 8 set      Do not use the windowhandle in word 11 as submenu
                       pointer
        Bit 9 set      Cannot be applied to linked tracks
        Bit 10 set     Words 14-31 is extended header
        Bit 11 set     Disable undo when calling start/effect code
                        (always assumed for groups 7, 8 and 10)
        Bit 12-30      Must be 0
        Bit 31 set     Do not display in the fx-menu
</pre>

The effects can be group in different groups. The bottom 4 bits of this word gives the group number to place the fx into.

<pre>
 Group  Name

 0      &lt;outside any group&gt;
 1      Filter
 2      Effect
 3      Modulation
 4      Generate
 5      Logical
 6      Capture
 7      Analysis
 8      Save
 9      Envelope
 10     Editing
 11     Enhance
 12     Group 12
 13     Group 13
 14     Group 14
 15     Extensions
</pre>
The grouping is ignored if the total number of effects is less than 12.<br>
The maximum number of effects in a group is 24 - the rest will be placed in the main menu.<br>
Please notice: The groups may be enumerated differently in the Messages file.


<h4>Icon handle code</h4>
This is called when the user clicks on the icon for this fx.<br>
The icon is created from the sprites in the spritefile !Icon in the fx directory. If the file doesn't exist, no icon will be created; if the spritefile exists, it must contain two sprites: '0' and '1'. These must be the same size/mode/design as the sprites in !ProSound.XSprites22, ie. mode 27, 28x28 pixels.

<pre>
 On entry
        R0  =>  Track
        R2  =   First sample
        R3  =   Last sample
        R4  =   Project

 On exit
        R0  =   0  (to do nothing)
        R0  =   ICON_OPEN (to open the window)
        R0  =   ICON_APPLY (to called the effect code immediately)
</pre>

The fx need not necessarily apply the effect at this point - it may eg. open a menu or do whatever it want. Actually, if it wants to apply the effect at this point, it should return with R0 = ICON_APPLY.


<h4>Pre-effect code</h4>
This is called immediately before the start or effect code is called.

<pre>
On entry
        R0  =>  Track
        R2  =   First sample
        R3  =   Last sample
        R4  =   Project
        R5  =   0

On exit
        R0  =   Flags
                Bit 0 set       the fx will affect track 0
                Bit 1 set       the fx will affect track 1
                ...
                Bit 7 set       the fx will affect track 7
</pre>

Bits 0 - 7 need only be set for track other than the track in R0 on entry. This allow ProSound to save undo information for all tracks that will be affected by the fx.<br>
If this entry point doesn't exist, ProSound will assume that only the track in R0 on entry will be affected.


<h4>Notes</h4>

<h6>Special values:</h6>

INITIALISED_OK         = 0<br>
IGNORE_LINKING         = &4B4E494C ("LINK")<br>
APPLY_EFFECT           = -1<br>
DONE_MOUSE             = 0<br>
DONE_KEY               = 0<br>
CLAIM_SERVICE          = -1<br>
OPEN_WINDOW            = &4E45504F ("OPEN")<br>
ICON_OPEN              = -1<br>
ICON_APPLY             = -2<br>


<h6>Undo:</h6>
Before calling the effects code or start code, ProSound will (if undo is enabled) make an copy of the sampels that will be affected - for undoing. This is disabled for fx-groups save, editing and analysis, and can be disabled for any other fx by setting bit 11 in the flags.


<h6>Tracks:</h6>
The effect may - if it wants - use other tracks for input/output than is specified in R0 on entry to the start/effect code. This should be done by opening a window which allows the user to specify which tracks to use for input and which tracks to use for output.


<h6>Linked track:</h6>
The user may want to apply the fx to all linked tracks in one operation. This is handled automatically by ProSound (by calling the start code or effect code for each track) but may be disabled by the fx by returning the word &4B4E494C (="LINK") in R0 on exit from the start code or by having bit 9 set in the flag word (word 13 in the header). This is automatically assumed for fxs in the fxgroups 6, 8 and 10.


<h6>Disabling:</h6>
If an fx cannot initialise correctly, it should either:
<ul>
<li>shade/disable its own menuentry whenever it received a Service_MenuWarning, or
<li> return with an error (and thus kill itself)
</ul>

<h6>Hourglass:</h6>
The hourglass is turned on by ProSound before calling the mouse/key/start/effects code, and is turned off afterwards.<br>
<tt>SWI ProSound_CustomEffects</tt> also turns the hourglass on/off and increments the hourglass-counter at regular intervals.


<h6>Projects:</h6>
Reading from the project workspace is not allowed. Instead, all reading should be done through the call ProSound_ProjectInfo.


<h6>Reading and writing:</h6>
All reading and writing of samples should be done through the calls <tt>SWI ProSound_WriteToDisc</tt> and <tt>SWI ProSound_ReadFromDisc</tt> or through <tt>SWI ProSound_CustomEffect</tt>.
