Custom Signals

To treat new custom objects as signals, you must support the signal interface. Such an object must return an appropriate SignalOperators.IsSignal object when calling SignalOperators.SignalTrait.

IsSignal is an emptry struct that has three type parameters, indicating the sampletype the type of framerate and the type used to represent the length returned by nframes. For example, for an array SignalTrait is implemented as follows.

SignalTrait(x::Type{<:Array{T}}) where T = IsSignal{T,Missing,Int}

All signals should implement the appropriate methods from SignalBase. What additional methods you should implement depends on what kind of signal you have.

AbstractArray objects

If your signal is an array of some kind you should implement SignalOperators.timeslice, which should return a requested range of frames from the signal.

You should also consider defining your array type to be a custom sink.

Other objects

Any other type of signal should implement SignalOperators.nextblock, which is used to sequentially retrieve blocks from a signal.

Analogous to Base.iterate, SignalOperators.nextblock will return nothing when there are no more blocks to produce.

If the returned blocks will be represetend by an array of numbers, then SignalOperators.ArrayBlock should be used.

In other cases, such as when you want to compute individual frames of the block on-the-fly, you should return an object that implements the following two methods.

  • nframes Like a signal, each block has some number of frames. Unlike signals, this cannot be an infinite or missing value. The implementation should be a fast, type-stable function.
  • SignalOperators.frame Individual frames of the block can be accessed by their index within the block (falling in the range of 1:nframes(block)). This should be a fast, type-stable function. The method is guaranteed to only be called at most once for each index in the block.

Optional Methods

There are several optional methods you can define for signals as well.