Skip to content
Igor Zinken edited this page Jan 2, 2016 · 6 revisions

For the use case of the Sequencer, please read "Understanding MWEngine's core actors" first.

NOTE 1: if you are interested in controlling the playback position / tempo / loop range, etc. of a sequence, you're looking for the article on Controlling the Sequencer.

NOTE 2 : it is unlikely your application requires you to manually interact with the Sequencer, the base methods inside BaseInstrument should suffice to enqueue AudioEvents for playback by the AudioEngine. It is however, always good to understand its inner workings :)

constructor

Non existant. Sequencer is a namespace that provides static methods and properties.

public methods

int Sequencer::registerInstrument( BaseInstrument* instrument )

Registers an instrument inside the Sequencer. This implies that the instruments events are eligible for playback. This method is invoked automatically by instruments during their construction. Method returns an integer value stating the instruments index inside the Sequencers instrument vector.

bool Sequencer::unregisterInstrument( BaseInstrument* instrument )

Unregisters an instrument from the Sequencer. This implies that the instruments events are not eligible for playback. This method is invoked automatically by instruments during their destruction. Method returns a boolean value stating whether the instrument has been removed (when false, instrument wasn't registered inside the Sequencer).

bool Sequencer::getAudioEvents( std::vector<AudioChannel*>* channels,
                                int bufferPosition, int bufferSize,
                                bool addLiveInstruments, bool flushChannels )

Queried by the AudioEngine during playback. channels is a vector of AudioChannels provided by the AudioEngine, this vector will be cleared at the invocation of this method, and will only return AudioChannels with audible content (i.e. only unmuted channels as even channels that have no events to play back should be returned so the engine can apply their ProcessingChain (for instance because a Delay-Processor has been applied and should continue working). bufferPosition is the position of the "playback head" (relative to the beginning of the sequence range), while bufferSize describes the amount of samples we'd like to retrieve for from the requested bufferPosition onwards. addLiveInstruments indicates whether live events should also be collected (for instant playback) and flushChannels ensures the returned AudioChannels have flushed the contents that have been retrieved in a previous query.

This method returns a boolean indicating whether the requested range implies the loop should be started. This occurs when the requested end position of the range (being ( bufferPosition + bufferSize - 1 )) exceeds the max_buffer_position of the AudioEngine (as defined by SequencerControllers methods). The AudioEngine will then make another request from the beginning of the loop range (_min_buffer_position) for the remaining samples left in bufferSize. The engine will ensure flushChannels is false so the events can be merged into the existing channels event contents.

A practical usage example as used by AudioEngine :

AudioEngine provides a pointer to a temporary AudioChannel-vector, it invokes getAudioEvents() on the Sequencer to get all the AudioEvents that are audible from given bufferPosition up to (bufferPosition + bufferSize - 1). The engine can then render the audio contents of each of these events. bufferPosition is the current offset in the loop range of the sequencer. The engine invokes this method upon each iteration of its render cycle, as such the bufferPosition is incremented by the BUFFER_SIZE (see global.h) on each iteration and wrapped back to the start of the sequence range once it exceeds the maximum buffer position.

void Sequencer::updateEvents()

This method will recursively invoke the updateEvents()-method of all registered instruments. This is invoked by the AudioEngine when a change occurs that affects time, for instance when the tempo or the time signature is changed.

void Sequencer::clearEvents()

This method will recursively invoke the clearEvents()-method of all registered instruments. This ensures that no AudioEvents are present in the application.

std::vector<BaseCacheableAudioEvent*>* Sequencer::collectCacheableSequencerEvents( int bufferPosition,
                                                                                   int bufferEnd )

This method will returns all cacheable events (BaseCacheableAudioEvents) that are present in the given bufferPosition to bufferEnd-range.

A practical usage example :

In your application you have a lot of SynthEvents that are very expensive in their render() routines to be executed repeatedly (or simultaneously). You can cache these events contents as SynthEvents extend BaseCacheableAudioEvent and have a caching mechanism.

Let's say your application is running in a loop of 8 measures at 120 BPM 4/4 time and rendered at 44.1 kHz. Each measure will have a length of 88200 samples. We would like to precache all events of the next measure. At the start of each measure you can request all events for the next measure like so :

int startPos = ( currentMeasureNum + 1 ) * AudioEngine::bytes_per_bar;
int endPos   = startPos + AudioEngine::bytes_per_bar;
collectCacheableSequencerEvents( startPos, endPos );

These events can then be fed into the BulkCacher so their cache()-methods can be invoked sequentially, and all the events have their buffers cached and ready when it is their time to play.

"internal" methods

These methods are all handled internally by the getAudioEvents()-method:

void Sequencer::collectSequencedEvents( BaseInstrument* instrument,
                                        int bufferPosition, int bufferEnd )

This method will fill given instrument 's AudioChannel with all sequenced AudioEvents that are audible between given bufferPosition and bufferEnd.

void Sequencer::collectLiveEvents( BaseInstrument* instrument )

This method will fill given instrument 's AudioChannel with all live AudioEvents that should be audible instantly.

public properties

std::vector<BaseInstrument*> Sequencer::instruments

The Vector containing all instantiated instruments that are registered for playback.

BulkCacher* Sequencer::bulkCacher

An instance of the BulkCacher-utility that can be used to precache eligible events prior to their playback.

Clone this wiki locally