synthesizer-llvm-0.8.2: Efficient signal processing using runtime compilation

Safe HaskellNone




data T a Source

This type is very similar to T but differs in several details:

  • It stores values in time order, whereas T stores in opposite order.
  • Since it stores future values it is not causal and can only track signal generators.
  • There is no need for an initial value.
  • It stores one value less than T since it is meant to provide infixes of the signal rather than providing the basis for a delay line.

Those differences in detail would not justify a new type, you could achieve the same by a combination of track and skip. The fundamental problem of this combination is that it requires to keep the ring buffer alive longer than the providing signal exists. This is not possible with the current design. That's why we provide the combination of track and skip in a way that does not suffer from that problem. This functionality is critical for dynamic.

track :: C a => T p Int -> T p a -> T p (T a)Source

track time signal bundles time successive values of signal. The values can be accessed using index with indices ranging from 0 to time-1.

The time parameter must be non-negative.

trackSkip :: C a => T p Int -> T p a -> T p (Value Word32) (T a)Source

trackSkip time input $* skips is like Process.skip (track time input) $* skips but this composition would require a Memory constraint for T which we cannot provide.

trackSkipHold :: C a => T p Int -> T p a -> T p (Value Word32) ((Value Bool, Value Word32), T a)Source

Like trackSkip but repeats the last buffer content when the end of the input signal is reached. The returned Bool flag is True if a skip could be performed completely and it is False if the skip exceeds the end of the input. That is, once a False is returned all following values are tagged with False. The returned Word32 value is the number of actually skipped values. This lags one step behind the input of skip values. The number of an actual number of skips is at most the number of requested skips. If the flag is False, then the number of actual skips is zero. The converse does not apply.

If the input signal is too short, the output is undefined. (Before the available data the buffer will be filled with arbitrary values.) We could fill the buffer with zeros, but this would require an Arithmetic constraint and the generated signal would not be very meaningful. We could also return an empty signal if the input is too short. However this would require a permanent check.

index :: C a => Value Word32 -> T a -> CodeGenFunction r aSource

This function does not check for range violations. If the ring buffer was generated by track time, then the minimum index is zero and the maximum index is time-1. Index zero refers to the current sample and index time-1 refers to the one that is farthermost in the future.