Writing SoundEffects effect modules
---------------------------------------------------------------------------------
1994 Alberto Ricci <ricci@pmn.it> <fricci@polito.it>


MODULE STRUCTURE

Your effect module file must be of type 'Eff' and creator 'SFx'. The  symbol
is obtained by typing option-v.

SoundEffects calls your module by passing it four parameters:
- a message (OSType) specifying which action to perform.
- information on the sound (ModParamsPtr).
- pointers to 68000 callback routines (GluePtr).
- pointers to PowerPC callback routines (GluePtr).

To simplify things, a file called Glue.c is included in the SoundEffects
Developers Kit. You should add this file to your project, so you dont need
to handle all the messages yourself: just write your own effect(), settings()
and about() routines, as explained below.

To make your life even easier, two empty effect projects (Symantec C 7.0 and
Metrowerks CodeWarrior 1.1) are included. Just make a copy of, rename it, and
insert your code where needed.


BUILDING THE MODULE

If your module doesnt need a custom About dialog, and uses the standard
resources (as described below under About Window resources), add the file
ModNoAbout.c to your project.

If your module doesnt have any parameters or doesnt need to save any settings,
add the file ModNoSettings.c to your project.

Definitions of the structures and constants used in this document can be found
in the header file Glue.h distributed with the SoundEffects Developers Kit.
This file also contains all the prototypes youll need.

The header file Glue.h is commented, so take a look at it for specific
information.

If you use the supplied Glue.c file, you can also use global variables
throughout your code.


RESOURCES

	effect code resources are of type 'EFCT'.
	put any error messages (which are reported with (*glue->ModShowError)() or by
	returning a value  noErr and  kModCancel to the application) into a
	'STR#' resource, ID = 1000.
	always put one 'mInf' resource, any ID. A template for this resource type is
	included with the SoundEffects Developers Kit.
	In this resource, specify the minimum amount of RAM you want available before
	running and the oldest header version your effect supports (see below,
	Header Versions).


OPTIONAL RESOURCES

	if you add a resource of type 'EFCF' to a module, and an FPU is present, that
	code resource will be called instead of the 'EFCT' one, with the same parameters.
	if you add a resource of type 'EFCP' to a module, and SoundEffects is running
	on a Power Mac, that code resource will be called instead of the 'EFCT' one,
	with the same parameters.
	put any picture and/or text (shareware notices, author info, etc.) you want
	to be displayed in the Progress window when the module is running into a
	PICT and/or TEXT resource, ID = 1001.
	If you want your effect to appear in a submenu of the Effects menu in
	SoundEffects, add a resource of type 'Grup', any ID, containing the name
	of the submenu. The format of this resource is identical to that of a 'STR '
	resource, and a template is included with the Developers Kit.


ABOUT WINDOW RESOURCES

	put any copyright info into a 'STR ' resource, ID = 1000, and it will be
	displayed in the effects about dialog (shown when choosing the effect with
	the shift key down).
	put a description of the effect into a 'TEXT' resource, ID = 1000, which will be
	displayed in the effects about dialog.
	put any version info into a 'vers' resource, ID = 1, and it will be displayed in
	the effects about dialog.
	if you want a custom window size for the about dialog, add a 'nrct' resource,
	ID = 1000, containing the rect of the window in the first rectangle field.
	if you want to add a picture to the window, add it as a 'PICT' resource,
	ID = 1000, and put the rect in which it should appear in the second rectangle
	field in the 'nrct' resource, ID = 1000.
	If you dont add this rectangle to the 'nrct' resource, the pictures rectangle
	will be used.
	If you add the rectangle to the 'nrct' resource, but it is empty (top = bottom
	and left = right), the pictures rectangle will be used, and the top left corner
	will be positioned at the top left corner of the empty rectangle.


HEADER VERSIONS

SoundEffects determines whether an effect module is compatible with it by looking
at two version numbers the module supplies:
- the version number of the header file the module was compiled with, and
- the oldest version number of the header file the module requires.

For example, suppose the version of the headers you are using is version 10.
In the headers file, it is specified which callbacks were introduced in which
version.
Lets suppose in your module you dont use any callbacks that were introduced in
versions 8 or higher: all the callbacks you use are labeled as Version 1...7
Callbacks in the header file. In this case, youd specify 7 as the oldest supported
headers version. This way, you tell SoundEffects that your module cannot run on
versions of SoundEffects which do not support all the callbacks you use (in this
case versions of SoundEffects that correspond to header versions 1 to 6).

You must specify the oldest version number of the header file in a 'mInf' resource,
as described above in Resources.


CALLBACKS

The pointers to the callback routines are passed to your module by SoundEffects in
two parameters: glue68k and gluePPC. These two structures contain pointers to the
same routines, but you will have to use glue68k if your code resource contains
680x0 code, and gluePPC if it contains native PowerPC code.
If you use the file Glue.c supplied with the SoundEffects Developers Kit, this
will be handled for you and your settings() and effect() routines will only receive
the pointer to the one appropriate GlueRec structure.

In any case, you will always call the callbacks the same way:
theResult = (*glue->TheCallback)(theParameters);

All the callbacks may move memory.

	GetBytesToProcess		returns the number of selected bytes, taking into account
							every selected channel and its length.
	ModMaxChSize			returns the length (in bytes) of the longest channel.
	ModMaxRelChSize			takes the number of selected bytes in each channel
							and returns the greatest one.
	ModDoSettingsDialog		handles all the settings dialog automatically.
							Pass true in withSetups if you want to have a pop-up
							menu with common used settings in the dialog. Everything
							will be handled by this single callback.
							Pass an ItemInfoHandle containing a description of each
							dialog item to the callback.
							See the sample module Settings Test for details.
	ModGetSampleValueLimits	returns the maximum and minimum value allowed for a sample
							with the current bps value.


PROGRESS BAR

 Call (*glue->ModSetupProgress)() early in your module to specify which string you
want to display in the progress bar and to start animating the watch cursor.
 pass it a pointer to a short variable. This variable MUST be either a global
variable or one that wont be disposed of before ModCloseProgress will be called.
Whenever you have time in your loop, check the value of this variable: if it is not
zero, you should call (*glue->ModShowProgress)().
 Pass ModShowProgress two parameters to indicate at what point you are in process.
For example, pass percentageDone and 100, or processedSamples and
totalSamplesToProcess. Pass 0xFFFFFFFF in the first parameter if you cant tell
in which point you are of the effect process. In this case, a striped bar will
be shown.
Also pass it a pointer to the timeToCallProgress short variable. It will reset
it to zero.
 ModShowProgress returns a OSErr value. If the user clicks the Stop button, this
value will be kModCancel, and the module should clean up and exit. If possible, it
should restore the original data. If this cant be done or is too much work, pass
false in the canCancel parameter, otherwise pass true.
 ALWAYS call (*glue->ModCloseProgress)() before exiting.

 If you dont want to show a progress window, you can still call ModSetupProgress
and then ModCloseProgress to show the spinning watch cursor.

 You can pass 0L to ModSetupProgress in the textStr or in the modInfo parameters,
but not in the timeToCallProgress parameter.


RECORDS, PARAMETERS AND VARIABLES

	All selection bounds and sound sizes are passed in bytes, not samples.
	If modInfo->selSt is 0L and modInfo->selEnd is 5000L, it means the first byte
	you are allowed to touch is the one at (*myChannelHandle + 0L), and the last one
	if (*myChannelHandle + 4999L), not the 5000th.
	The number of selected bytes is, of course, modInfo->selEnd - modInfo->selSt, in
	this case 5000.
	You can obtain the size of one sample, in bytes, with:
	sampleSize = modInfo->bps/8 + (modInfo->bps%8 != 0);
	modInfo->firstSelCh and modInfo->lastSelCh values range from 1 to
	modInfo->numChans.
	An SEChanHandle is passed to your module inside the ModParamsRec record. This
	handle contains the handles to the documents channels and their sizes.
	The handle to channel number ch is, for example:
	myChannelHandle = (*modInfo->hands)[channelNumber].chan;
	and the size of that channel, in bytes, is:
	myChannelSize = (*modInfo->hands)[channelNumber].size;
	The ModParamsRec should contain everything you need to know about the sound:
	a pointer to the window (parentWind), the selection bounds (selSt, selEnd,
	firstSelCh, lastSelCh), the number of channels (numChans), the sample size
	(bps), the sampling rate (rate), the loop bounds (loopSt, loopEnd), the
	currently selected units (units - see the file ModUnits.h).
	The doExtend field of the ModParamsRec record contains 1 if the user wants
	you to enlarge the sound as necessary when your effect needs to do that;
	0 if the user wants the selection to have the same length as before applying
	the effect, or 2 if he wants to decide each time. So, if youre going to
	modify the length of the selection or if you may change the sound outside
	the selection, and modInfo->doExtend is 2, call (*glue->AskDoExtend)().
	This callback will return either true (extend) or false (dont extend the
	selection).
	The short integers returned by (*glue->ModGetChannelPan)() are formatted as
	volumes in the new SoundManager 3.0. They are fixed-point values, where the
	high byte is the integer part and the low byte is the fractional part.
	0x0100 (kFullVolume)	is full volume (you can overdrive the channel by setting
							the value to more than 1.0),
	0x0080					is half volume, and
	0x0000					is silent.
	All negative values are silent.
	The reference number for the module file is contained in the refNum field of
	the ModParamsRec record, modInfo->refNum.


RESULT CODES

When the module is called, it should perform only the requested action and then
exit, returning a OSErr value. This value should be:
- kModNoError			if the effect ran succesfully and some data was modified.
- kModCancel			if the effect left everything untouched.
- any positive value	if an error occurred and some data was modified.
						SoundEffects will take care of alerting the user about
						this, and it will use the corresponding string in the
						modules 'STR#' resource, ID = 1000, as an error message.
- any negative value	if an error occurred and nothing was changed.
						SoundEffects will use the corresponding positive string
						in the modules 'STR#' resource, ID = 1000, as an error
						message.
