Processor
The base class for all HISE modules in the signal path.
Every object within HISE that processes audio or MIDI is derived from this base class to share the following features:
- handling of child processors (and special treatment for child processors which are Chains)
- bypassing & parameter management (using the 'float' type for compatibility with audio processing & plugin parameters): setAttribute()
/ getAttribute()
- set input / output values for metering and visualization (setInputValue()
, setOutputValue()
)
- access to the global MainController
object (see ControlledObject
)
- import / export via ValueTree (see RestorableObject)
- methods for identification (getId()
, getType()
, getName()
, getSymbol()
, getColour()
)
- access to the console
The general architecture of a HISE patch is a tree of Processor objects, all residing in a main container of the type ModulatorSynthChain (which can be obtained using getMainController()
->getMainSynthChain()). There is a small helper class ProcessorHelpers, which contains some static methods for searching & checking the type of the Processor.
Normally, you would not derive from this class directly, but use some of its less generic subclasses (MidiProcessor
, Modulator
, EffectProcessor
or ModulatorSynth
). There are also some additional interface classes to extend the Processor class with specific features: Processor Interface Classes
Class Hierarchy
Base Classes
hise::SafeChangeBroadcaster
hise::RestorableObject
- hise::ControlledObject
hise::Dispatchable
Derived Classes
- hise::EffectProcessor
hise::EffectProcessorChain
- hise::MidiProcessor
- hise::Modulator
- hise::ModulatorSynth
Class methods
Processor
Processor(MainController *m, const String &id_, int numVoices)
Creates a new Processor with the given Identifier.
~Processor
~Processor()
Overwrite this if you need custom destruction behaviour.
createEditor
ProcessorEditorBody * createEditor(ProcessorEditor *parentEditor)=0
Creates a ProcessorEditor for this Processor and returns the pointer.
If you subclass this, just allocate a ProcessorEditor of the desired type on the heap and return it. Remember to pass the Processor as parameter to allow asynchronous GUI notification. The concept between Processor and ProcessorEditor is the same as AudioProcessor and AudioProcessorEditor.
exportAsValueTree
ValueTree exportAsValueTree() const override
This saves the Processor.
It saves the ID, the bypassed state and the fold state. It also saves all child processors. You can overwrite this function and add more properties and their child processors but make sure you call the base class method.
For primitive values, you can use the macro saveAttribute(name, nameAsString):
You don't need to save the editor states, as the first 32 bits of EditorState is saved.
ValueTree exportAsValueTree() const override
{
// must be named 'v' for the macros
ValueTree v = BaseClass::exportAsValueTree();
saveAttribute(attributeName, "AttributeName");
// ...
if(useTable) saveTable(tableVariableName, "TableVariableNameData");
return v;
};
restoreFromValueTree
void restoreFromValueTree(const ValueTree &previouslyExportedProcessorState) override
Restores a previously saved ValueTree.
The value tree must be created with exportAsValueTree or it will be unpredictable. The child processors are created automatically (both for chains and processors with fixed internal chains, but you should overwrite this method if your Processor uses parameters.
There is a handy macro saveAttribute(name, nameAsString) for this purpose.
restoreFromValueTree(const ValueTree &v) override // parameter must be named 'v' for the macros
{
// replace BaseClass with the class name of the immediate base class
BaseClass::restoreFromValueTree(v);
loadAttribute(attributeName, "AttributeName");
// ...
// If your Processor uses tables:
if(useTable) loadTable(tableVariableName, "TableVariableData");
}
getType
const Identifier getType() const =0
Overwrite this method to specify the name.
Use non-whitespace Strings (best practice is CamelCase). In most cases, this will be enough: cppconst String getType() const { return "ProcessorName";};
getSymbol
const Path getSymbol() const
Returns the symbol of the Processor.
It either checks if a special symbol is set for this particular Processor, or returns the default one defined in getSpecialSymbol()
setSymbol
void setSymbol(Path newSymbol)
Sets a special symbol for the Processor.
If this method is used, the getSymbol()
method will return this Path instead of the default one defined in getSpecialSymbol()
;
setAttribute
void setAttribute(int parameterIndex, float newValue, juce::NotificationType notifyEditor)
Changes a Processor parameter.
This can be used in the audio thread eg. by other Processors. Overwrite the method setInternalAttribute()
to store the parameters in private member variables. If the Processor is polyphonic, the attributes must stay the same for different voices. In this case store a multiplicator for the attribute in a ProcessorState.
parameterIndexthe parameter index (use a enum from the derived class)
newValuethe new value between 0.0 and 1.0
notifyEditorif sendNotification, then a asynchronous message is sent.
getAttribute
float getAttribute(int parameterIndex) const =0
returns the attribute with the specified index (use a enum in the derived class).
getDefaultValue
float getDefaultValue(int) const
Overwrite this and return the default value.
getChildProcessor
Processor * getChildProcessor(int processorIndex)=0
This must be overriden by every Processor and return the Chain
with the Chain
index.
You can either:- return nullptr, if the Processor uses no internal chains
- one of the internal chains (it's recommended to use the InternalChains enum for this case)
- return the Processor at the index if the Processor is a Chain
. You can use it's handler's getProcessor() method.
getNumChildProcessors
int getNumChildProcessors() const =0
This must return the number of Child processors.
If this Processor is a Chain
, you can use it's getHandler()->getNumProcessor() method.
getDescription
String getDescription() const =0
Return a one-line description of the processor.
getNumInternalChains
int getNumInternalChains() const
If your processor uses internal chains, you can return the number here.
This is used by the ProcessorEditor to make the chain button bar.
enableConsoleOutput
void enableConsoleOutput(bool shouldBeEnabled)
Enables the Processor to output messages to the Console.
This method itself does nothing, but you can use this to make a button or something else.
getColour
Colour getColour() const
Overwrite this method if you want a special colour.
This colour will be used in the debug console and in the editor.
getVoiceAmount
int getVoiceAmount() const noexcept
getNumVoices() is occupied by the Synthesiser class, d'oh!
getId
const String & getId() const
Returns the unique id of the Processor instance (!= the Processor name).
It must be a valid Identifier (so no whitespace and weird characters).
getName
const String getName() const
Overwrite this and return a pretty name. If you don't overwrite it, the getType()
method is used.
setBypassed
void setBypassed(bool shouldBeBypassed, NotificationType notifyChangeHandler=dontSendNotification) noexcept
This bypasses the processor. You don't have to check in the processors logic itself, normally the chain should do that for you.
isBypassed
bool isBypassed() const noexcept
Returns true if the processor is bypassed. For checking the bypass state of ModulatorSynths, better use isSoftBypassed().
prepareToPlay
void prepareToPlay(double sampleRate_, int samplesPerBlock_)
Sets the sample rate and the block size.
getSampleRate
double getSampleRate() const
Returns the sample rate.
getLargestBlockSize
int getLargestBlockSize() const
Returns the block size.
getOutputValue
float getOutputValue() const
This can be used to display the Processors output value.
getInputValue
float getInputValue() const
This can be used to display the Processors input value.
setEditorState
void setEditorState(int state, bool isOn, NotificationType notifyView=sendNotification)
Saves the state of the Processor's editor. It must be saved within the Processor, because the Editor can be deleted.
You can add more states in your subclass (they should be expressable as bool). Best use a enum: cppenum EditorState{
newState = Processor::numEditorStates,};
getEditorState
bool getEditorState(int state) const
Restores the state of the Processor's editor. It must be saved within the Processor, because the Editor can be deleted.
restoreCompleteEditorState
void restoreCompleteEditorState(const XmlElement *storedState)
Restores the EditorState from a BigInteger that was retrieved using getCompleteEditorState.
getIdentifierForParameterIndex
Identifier getIdentifierForParameterIndex(int parameterIndex) const
This returns a Identifier with the name of the parameter.
If you want to use this feature (this lets you access Parameters with the script, you should add the parameter name for each parameter in your subtype constructor.
getNumParameters
int getNumParameters() const
This returns the number of (named) parameters.
setIsOnAir
void setIsOnAir(bool isBeingProcessedInAudioThread)
Call this method after inserting the processor in the signal chain.
If you call prepareToPlay before calling this method, it won't lock which makes inserting new processors nicer.