Page 1 of 1

Tutorials

Posted: Fri Oct 26, 2007 9:32 am
by reflex
This thread will contain some additional explanation and tutorials regarding the FL plugin sdk.

Posted: Fri Oct 26, 2007 9:35 am
by reflex
Voice velocity and volume

1. Velocity vs. volume
In FL, velocity is mapped to volume internally, and plugins are encouraged not to have their own velocity-to-volume scaling, for better consistency with other FL plugins.

That said, plugins are still free to map velocity to other parameters, and for this FL provides:

- FPV_GetVelocity, which returns the trigger-velocity of a voice, unaffected by the channel's volume. This value is to map velocity to something else (filter, etc)

- FPV_SetLinkVelocity, to tell FL to really stop mapping velocity to volume, so that you can use your own (or no velocity-to-volume at all). This is strongly discouraged, and should only be used by lazy programmers porting their VSTi not really caring about FL/FL plugins, as the result is less bad than having both the plugin's internal vel-to-volume AND FL's own, at the same time (resulting in a very wrong vel-to-vol curve), as if too often happened in the past (for almost every plugin ported to FL format).


2. Retrieve velocity of a voice
To get the velocity for a voice, use the FPV_GetVelocity opcode with PlugHost.Voice_ProcessEvent. This is the velocity (MIDI-like, but in 0..1 range) for the note as set in the pianoroll (or played by the user on a keyboard), not affected by any other level.
(in the past, this velocity could be computed from InitLevels.Volume, using some formula, but FPV_GetVelocity was later added to make things easier).


3. Retrieve volume of a voice
For volume, use the value in FinalLevels.Volume (from the VoiceParams structure passed to TriggerVoice). Multiply this value with your own levels, but never ever add anything to this.
Levels in FinalLevels change during a voice's lifetime, as FL performs slides & other effects on voices.


4. Panning
The same way, plugins are strongly encouraged to use ComputeLRVol, to compute a left & right volume from volume & panning (or from 1 & panning), again for better consistency with other FL plugins (to use the same panning law).

Posted: Fri Oct 26, 2007 9:41 am
by reflex
Internal Controllers

Follow these steps to create a plugin that publishes internal controllers to FL.

Let FL know your plugin is an internal controller
- Add FPF_WantNewTick to to Flags field of the TFruityPlugInfo struct. This will let FL know that it has to call NewTick() (see below).
- Set the NumOutCtrls field of the TFruityPlugInfoStruct to the (maximum) number of internal controllers your plugin exports.

GetName()
Implement the FPN_OutCtrl case to return the name of the internal controller specified by the Index parameter.
Set the name to an empty string if the controller is not in use. FL will then ignore it.

Adding an internal controller
I'm not sure. Dashboard doesn't seem to do anything specific to let FL know that the internal controllers have changed, and FL calls GetName() when the user starts to link a control. So nothing to do here, I guess.

Removing an internal controller
Call PlugHost->Dispatcher with FHD_KillIntCtrl to tell FL that a range of internal controllers has been deactivated. This will delete all automation associated with it.

Sending controller value changes
Override the NewTick() method.
In it, call PlugHost->OnControllerChanged() for all internal controllers whose value has changed.

ProcessParam()
Pay attention to the REC_InternalCtrl flag in RECFlags in the code that responds to REC_UpdateValue.

Posted: Thu Sep 18, 2008 9:45 am
by reflex
Making a plugin thread safe

- Call the host's dispatcher with the code FHD_SetThreadSafe and Value set to 1 (usually when the plugin is created)
- Don't call PlugHost LockMix and UnlockMix during processing
- Use LockMix_Shared and UnlockMix_Shared around any access to the output buffer(s):

Code: Select all

PlugHost->LockMix_Shared();
<write to output buffer>
PlugHost->UnlockMix_Shared();
- Where possible, write to the output buffer(s) near the end of your processing
- If the plugin accesses tracks at random (GetMixBuffer and GetSendBuffer), use LockMix_Shared and UnlockMix_Shared there too