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
DeveloperÕs Kit. You should add this file to your project, so you donÕt 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 doesnÕt 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 doesnÕt have any parameters or doesnÕt 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 DeveloperÕs Kit.
This file also contains all the prototypes youÕll 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 DeveloperÕs 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 DeveloperÕs Kit.


ABOUT WINDOW RESOURCES

¥	put any copyright info into a 'STR ' resource, ID = 1000, and it will be
	displayed in the effectÕs 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 effectÕs about dialog.
¥	put any version info into a 'vers' resource, ID = 1, and it will be displayed in
	the effectÕs 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 donÕt add this rectangle to the 'nrct' resource, the pictureÕs rectangle
	will be used.
	If you add the rectangle to the 'nrct' resource, but it is empty (top = bottom
	and left = right), the pictureÕs 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.
LetÕs suppose in your module you donÕt 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, youÕd 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 DeveloperÕs 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 wonÕt 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 canÕt 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 canÕt be done or is too much work, pass
false in the canCancel parameter, otherwise pass true.
¥ ALWAYS call (*glue->ModCloseProgress)() before exiting.

¥ If you donÕt 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 documentÕs 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 youÕre 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 (donÕt 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
						moduleÕs '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 moduleÕs 'STR#' resource, ID = 1000, as an error
						message.
