-
Notifications
You must be signed in to change notification settings - Fork 46
AudioChannel
For the use case of an AudioChannel, please read "Understanding MWEngine's core actors" first.
An AudioChannel describes a unique track ("strip" on a mixer) that holds content separated from other tracks. For instance : you can have an AudioChannel for a synthesizer, and another one for a drum machine, etc. The benefit is that the synthesized audio doesn't interfere with the drum machine's output in the way that it can be processed separately.
For instance : an AudioChannel has its own pan and volume, so you can balance certain instruments at a different level to others, as well as spread them across the stereo field. An AudioChannel also has its own ProcessingChain, meaning you can apply effects and manipulate the channels audio separately from other channels.
Additionally, AudioChannels can hold a cached reference to their events contents in case some very expensive processing is going on. If the AudioChannels ProcessingChain-output is fixed (i.e. doesn't change upon repeated invocations on the same source buffers), the AudioChannel can safely cache its contents and repeatedly return this to the Sequencer.
If an AudioChannel shouldn't be cacheable, it will contain no AudioBuffer of its own, the AudioEngine will supply it with a temporary buffer to render its contents into.
AudioChannel( float aVolume )
Constructs an AudioChannel. Given aVolume should be a floating point value between 0 - 1 to describe the volume level at which the channel will be mixed into the output / master strip.
AudioChannel( float aVolume, int aMaxBufferPosition )
Overload of the original constructor. aMaxBufferPosition will however describe the max buffer offset the channel holds. In the original constructor this value is 0 to indicate that the AudioChannels allowed range is equal to that of the Sequencer.
Should you desire your AudioChannel to play a loop (for instance: the AudioChannel holds a sequenced drumloops events) over the total Sequence length, you specify the max buffer position. See description of public property maxBufferPosition below.
~AudioChannel()
Will invoke public method reset and delete the ProcessingChain.
void addEvent( BaseAudioEvent* aEvent );
This will add an AudioEvent to this AudioChannel instances queue. Whenever the Sequencer queries the AudioChannel for returning it events (so they can be synthesized / processed by the engine), it will return this event (when its eligible for playing).
void addLiveEvent( BaseAudioEvent* aLiveEvent );
Same as addEvent, only the given aLiveEvent will be pushed into a different queue for easier separation.
void createOutputBuffer();
An AudioChannel has its own output buffer which will contain all (temporary) contents that are rendered upon each iteration of the AudioEngine's render cycle. This method creates the buffer at the buffer size and channel amount corresponding to the current engine properties defined in AudioEngineProps. If the existing buffer matches these properties, no action is taken.
AudioBuffer* getOutputBuffer();
Retrieves the temporary output buffer. This is invoked either by the AudioEngine during the render cycle to overwrite the existing buffer contents or by the LevelUtility to calculate the average level of the AudioChannels output.
void readCachedBuffer( AudioBuffer* aOutputBuffer, int aReadOffset );
If the AudioChannel instance has its owns cached buffer, this method can merge the buffer (from the given aReadOffset) into the given aOutputBuffer.
bool canCache();
Whether the AudioChannel instance can cache its contents in an internal buffer.
void canCache( bool value, int aBufferSize, int aCacheStartOffset, int aCacheEndOffset );
Toggle the cacheable state of the AudioChannel using boolean value value. When true, the AudioChannel instance will create an internal AudioBuffer equal in length to given aBufferSize with an equal amount of output channels as defined in global.h (e.g. the amount of outputs that the engine is rendering).
Values aCacheStartOffset and aCacheEndOffset describe the range (relative to the Sequencer) in which the AudioChannel can cache its contents.
void writeCache( AudioBuffer* aBuffer, int aReadOffset );
Mixes in the contents of given aBuffer (starting at given aReadOffset) into the cached buffer (note that that write offset is handled internally and thus not present in the argument list).
If the cache is full (i.e. a invocation of this method has written at the end of the cached buffer, the value of the instances public properties isCaching is set to false, and hasCache to true.
void clearCachedBuffer();
Flushes the content of this AudioChannels internal cached buffer (if it existed). Will also set the instance's public property hasCache to false.
void reset();
Will clear the contents of the event queues (but will not delete the associated AudioEvents!).
void setPan( float value );
Set the channel pan offset in the -1 to +1 range. -1 is fully left, 0 is panned centrally and +1 is fully right. 0 does not imply mono (unless the channels contents is mono material). If pan is for instance +0.5 then the right channels contents will remain at full volume, but the left channel will mix at 50% volume into its own channel and will mix 50% into the right channel.
float getPan();
Returns the current pan value.
ProcessingChain* processingChain
The ProcessingChain that holds the collection of Processors that should be applied to the output of this AudioChannel instance.
By having ProcessingChains available across AudioChannels it is possible to for instance add a delay to one AudioChannel, and add a distortion effect to another AudioChannel, without having the processors work on each others signals.
bool hasLiveEvents
Whether the AudioChannel instance also holds a queue of live synthesized events.
bool isMono
Whether the AudioChannel actually holds single channel content (note its amount of output buffers is equal to the output channels described in global.h).
bool muted
When true, the AudioChannel will not be mixed in into the master output (nor will its contents be processed to save CPU overhead).
bool hasCache
Whether the AudioChannel has an internal cache to read from. When true, its events are not synthesized, nor processed, but instead the internal cache is mixed into the master output (by the engine). This property should only be mutated using canCache()-method.
bool isCaching
Whether the AudioChannel is currently caching its contents. This will instruct the engine that all processed events output should be appended to the cached buffer of the AudioChannel instance. This property is mutated internally by the caching methods.
float volume
Floating point value between 0 - 1. The volume at which the channel will be mixed into the master output.
int maxBufferPosition
Specifies the maximum buffer position (relative to the Sequencers "playback head") the AudioChannel spans. When 0, this is equal to the entire range of the Sequencer, any other value will indicate that the AudioChannel should loop its contents when reaching the value of subset maxBufferPosition.
Should you desire your AudioChannel to play a loop (for instance: the AudioChannel holds a sequenced drumloops events) over the total Sequence length, you specify a max buffer position other than 0.
An example : the Sequencers tempo is 120 BPM at 4/4 time and the engine is synthesizing at 44.1 kHz. Each measure is 88200 samples in length. The Sequencer is looping for 8 measures, as such its maximum buffer position is at ( 88200 * 8 == ) 705600 samples. The current AudioChannel instance however should endlessly loop its events for a single measure, as such its aMaxBufferPosition should be 88200. This indicates that when the Sequencer starts reading beyond the first measure, it will read from this AudioChannel instances first measure instead.
std::vector<BaseAudioEvent*> audioEvents
std::vector<BaseAudioEvent*> liveEvents
These vectors will temporarily hold all AudioEvents that should be played back for the current render cycle of the AudioEngine. The contents of these vectors are maintained by the add(Live)Event()-methods which are invoked by the Sequencer.