Skip to content
Igor Zinken edited this page Apr 27, 2022 · 7 revisions

BaseSynthEvent

A BaseSynthEvent describes an AudioEvent that synthesizes its contents, i.e. it doesn't reference a buffer containing audio sampled from a recording, but it is self contained in providing its _buffer with audio. As such, your subclass of BaseSynthEvent (see the provided SynthEvent in the repository as an example) should provide your own custom methods of synthesizing content.

A BaseSynthEvent is a subclass of BaseCacheableAudioEvent, meaning it is provided with the interface methods for caching its content. In order to use caching with a BaseSynthEvent, ensure EVENT_CACHING (see global.h) is set to true. If caching is enabled, the events _buffer-channels will be of eventLength in size. However, if caching is disabled, the _buffer-channels size will be equal to the BUFFER_SIZE of the engine to omit unnecessary memory allocation. Note that caching is disabled for "live SynthEvents" as the user can adjust the instrument properties while holding during the events lifetime (e.g. the duration the "key" is held down on the "keyboard");

The Instrument associated with a (Base)SynthEvent is the SynthInstrument. The actual sound generation is handled by an instance of Synthesizer which is held by the SynthInstrument.

constructors / destructor

BaseSynthEvent( float aFrequency, SynthInstrument *aInstrument )

Initializes a SynthEvent to render at given aFrequency (in Hertz) on given aInstrument. By invoking play()/stop() note on/off is triggered to make the Event audible. By setting its playback range and invoking addToSequencer() the Event will have sequenced playback.

BaseSynthEvent( float aFrequency, int aPosition, float aLength,
                SynthInstrument *aInstrument, bool aAutoCache )

Used to initialize a SynthEvent for use in a sequenced context (via this constructor it is immediately added to the Sequencer for timed playback). aFrequency describes the pitch (in Hertz) of the note that the event will synthesize. aPosition is the position (in BAR_SUBDIVISIONS) of the event relative to the Sequencer (for instance a value between 0 - 15 per measure when BAR_SUBDIVISIONS is set to 16 to operate in a 16-step sequenced context). aLength is the duration of the event (in BAR_SUBDIVISIONS, note it is floating point). aInstrument is the SynthInstrument the SynthEvent instance should correspond to. aAutoCache describes whether the event should automatically cache its contents (see BaseCacheableAudioEvent)

~BaseSynthEvent()

Removes the event from the Sequencer and deletes the ADSR envelopes. The base destructors are also invoked recursively.

public methods

float getFrequency()

Returns the frequency (in Hz) of the note the SynthEvent instance should render.

setFrequency( float value )

Set the frequency (in Hz) of the note the SynthEvent instance should render to value.

ADSR* getADSR()

Returns a pointer to the ADSR instance that will apply the envelopes onto the events contents.

void invalidateProperties()

Re-initializes properties of the event related to its synthesis mode (for instance to generate ring buffers for Karplus Strong synthesized events). This method is deferred to be invoked after a render to ensure memory can be freed outside of a read cycle.

override

void mixBuffer( AudioBuffer* outputBuffer )
void mixBuffer( AudioBuffer* outputBuffer, int bufferPos,
                int minBufferPosition, int maxBufferPosition,
                bool loopStarted, int loopOffset, bool useChannelRange )

Override from BaseAudioEvent. Invoked by the Sequencer for sequenced SynthEvents. If caching is enabled, the base method is invoked. If caching was disabled, this method will invoke a render-request for the length of given _outputBuffer_s bufferSize.

override

AudioBuffer* getBuffer()

Override from BaseAudioEvent. If caching is enabled, this will invoke a cache-request (subsequently invoking a render) if the events cache hadn't been built yet, prior to returning the buffer pointer.

override

unlock()

Override from BaseAudioEvent. Will invoke calculateBuffers() if an _updateAfterUnlock-request was pending.

override

cache( bool doCallback )

Override from BaseCacheableAudioEvent. This will invoke a render-request on the event instances _buffer for the full eventLength of the event.

protected methods

updateProperties()

Will perform all operations necessary to update the properties after a previous invalidateProperties()-request. This will adjust the properties of the ADSR-instance of the SynthEvent to match the associated SynthInstrument envelopes and invoke calculateBuffers() as it is now safe to mutate the SynthEvents _buffer. After this invocation both _update and _cancel are set to false so rendering can continue / cache can be re-built.

render( AudioBuffer* aOutputBuffer )

This will render the SynthEvents contents into given aOutputBuffer. Depending on the invocation, aOutputBuffer is either the event instances _buffer (when caching), or a temporary buffer (for output) provided by the associated AudioChannel.

The body of this method should be extended by your inheriting class as a BaseSynthEvent has no logic to render audio! Keep the base class wrapping code intact to facilitate :

  • calculate the renders read / write offsets (as this method should be able to render snippets of the full event, instead of only being able to render the audio in one go from eventStart to eventEnd, it should be able to render at any offset within that range for any fraction of the total eventLength !!).
  • be able to invoke updateProperties() if the events properties have been invalidated during a render
  • apply the ADSR envelopes onto the rendered output

and in case caching is enabled:

  • be able to cancel rendering if the event was caching
  • be able to set caching as completed when the cached buffer has been filled completely

note this function is in essence what your custom SynthEvent is all about : here the characteristic of the event (i.e. its unique audio content) is generated. In other words : another place to write your awesome mathematics skills!

init( SynthInstrument *aInstrument, float aFrequency, int aPosition,
      int aLength, bool aIsSequenced )

Invoked by the constructors to set initial properties.

int position
float length

The position and duration of the event (in BAR_SUBDIVISIONS)

protected properties

SynthInstrument* _instrument

Pointer to the SynthInstrument this event corresponds to.

float _frequency

Hold the values referenced by the public getters / setters defined above.

ADSR* _adsr

An ADSR instance that is used to apply the instruments envelope properties onto the rendered content.

bool _rendering

Whether the event is executing a rendering operation.

bool _update

Whether the event is requesting an invocation of updateProperties to adjust to changes.

Clone this wiki locally