|
Synthesizer.Dimensional.Causal.ControlledProcess | Portability | requires multi-parameter type classes (Flat) | Stability | provisional | Maintainer | synthesizer@henning-thielemann.de |
|
|
|
Description |
Basic definitions for causal signal processors
which are controlled by another signal.
Additionally to Synthesizer.Dimensional.ControlledProcess
you can convert those processes to plain causal processes
in the case of equal audio and control rates (synchronous control).
It is sensible to bundle the functions
computation of internal parameters and
running the main process,
since computation of the internal parameters
depends on the sample rate of the main process
in case of frequency control values
even though the computation of internal parameters happens
at a different sample rate.
ToDo:
- Is it better to provide the conversion method not by a record
but by a type class?
The difficulty with this is,
how to handle global parameters like the filter order?
- Note, that parameters might be computed by different ways.
Thus a type class with functional dependencies
for automatic selection of input types and conversion
will not always be flexible enough.
- Is it possible and reasonable to hide the type parameter
for the internal control parameter
since the user does not need to know it?
- The internal parameters that the converter generate
usually depend on the sample rate of the (target) audio signal.
However, it does not depend on the sample rate of control signal
where it is applied to.
How can we ensure that it is not used somewhere else?
We could discourage access to it at all.
But it might be sensible to define new external parameters
in terms of existing ones.
We could add a phantom s type parameter
to internal control parameters.
Would this do the trick? Is this convenient?
|
|
Synopsis |
|
data T conv proc = Cons {} | | type Converter s ecAmp ec ic = T ecAmp Flat ec (RateDep s ic) | | newtype RateDep s ic = RateDep {} | | makeConverter :: (ecAmp -> ec -> ic) -> Converter s ecAmp ec ic | | causalFromConverter :: Converter s ecAmp ec ic -> T s ecAmp Flat ec (RateDep s ic) | | joinSynchronousPlain :: T (Converter s ecAmp ec ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut) -> T s (ecAmp, ampIn) ampOut (ec, sampIn) sampOut | | joinSynchronous :: T s u t (T (Converter s ecAmp ec ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T s u t (T s (ecAmp, ampIn) ampOut (ec, sampIn) sampOut) | | joinFirstSynchronousPlain :: T (Converter s ecAmp ec ic, a) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut) -> T a (T s (ecAmp, ampIn) ampOut (ec, sampIn) sampOut) | | joinFirstSynchronous :: T s u t (T (Converter s ecAmp ec ic, a) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T s u t (T a (T s (ecAmp, ampIn) ampOut (ec, sampIn) sampOut)) | | runSynchronous1 :: C v => T s u t (T (Converter s (T v ecAmp) ec ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T s u t (R s v ecAmp ec -> T s ampIn ampOut sampIn sampOut) | | runSynchronousPlain2 :: (C v0, C v1) => T (Converter s (T v0 ecAmp0, T v1 ecAmp1) (ec0, ec1) ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut) -> R s v0 ecAmp0 ec0 -> R s v1 ecAmp1 ec1 -> T s ampIn ampOut sampIn sampOut | | runSynchronous2 :: (C v0, C v1) => T s u t (T (Converter s (T v0 ecAmp0, T v1 ecAmp1) (ec0, ec1) ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T s u t (R s v0 ecAmp0 ec0 -> R s v1 ecAmp1 ec1 -> T s ampIn ampOut sampIn sampOut) | | runAsynchronous :: (C u, C t) => T t (RateDep s ic) -> T s u t (T (Converter s ecAmp ec ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T r u t -> R r (RateDep s ic) -> T s u t (T s ampIn ampOut sampIn sampOut) | | runAsynchronousBuffered :: (C u, C t) => T t (RateDep s ic) -> T s u t (T (Converter s ecAmp ec ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T r u t -> R r (RateDep s ic) -> T s u t (T s ampIn ampOut sampIn sampOut) | | applyConverter1 :: C v => Converter s (T v ecAmp) ec ic -> R s v ecAmp ec -> R s (RateDep s ic) | | runAsynchronous1 :: (C u, C v, C t) => T t (RateDep s ic) -> T s u t (T (Converter s (T v ecAmp) ec ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T u t (S v ecAmp) ec -> T s u t (T s ampIn ampOut sampIn sampOut) | | processAsynchronous1 :: (C u, C v, C t) => T t (RateDep s ic) -> T s u t (T (Converter s (T v ecAmp) ec ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T (Recip u) t -> (forall r. T r u t (R r v ecAmp ec)) -> T s u t (T s ampIn ampOut sampIn sampOut) | | applyConverter2 :: (C v0, C v1) => Converter s (T v0 ecAmp0, T v1 ecAmp1) (ec0, ec1) ic -> R s v0 ecAmp0 ec0 -> R s v1 ecAmp1 ec1 -> R s (RateDep s ic) | | runAsynchronous2 :: (C u, C v0, C v1, C t) => T t (RateDep s ic) -> T s u t (T (Converter s (T v0 ecAmp0, T v1 ecAmp1) (ec0, ec1) ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T u t (S v0 ecAmp0) ec0 -> T u t (S v1 ecAmp1) ec1 -> T s u t (T s ampIn ampOut sampIn sampOut) | | processAsynchronous2 :: (C u, C v0, C v1, C t) => T t (RateDep s ic) -> T s u t (T (Converter s (T v0 ecAmp0, T v1 ecAmp1) (ec0, ec1) ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T (Recip u) t -> (forall r. T r u t (R r v0 ecAmp0 ec0)) -> (forall r. T r u t (R r v1 ecAmp1 ec1)) -> T s u t (T s ampIn ampOut sampIn sampOut) | | processAsynchronousNaive2 :: (C u, C v0, C v1, C t) => T t (RateDep s ic) -> T s u t (T (Converter s (T v0 ecAmp0, T v1 ecAmp1) (ec0, ec1) ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T (Recip u) t -> (forall r. T r u t (R r v0 ecAmp0 ec0)) -> (forall r. T r u t (R r v1 ecAmp1 ec1)) -> T s u t (T s ampIn ampOut sampIn sampOut) | | processAsynchronousBuffered2 :: (C u, C v0, C v1, C t) => T t (RateDep s ic) -> T s u t (T (Converter s (T v0 ecAmp0, T v1 ecAmp1) (ec0, ec1) ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T (Recip u) t -> (forall r. T r u t (R r v0 ecAmp0 ec0)) -> (forall r. T r u t (R r v1 ecAmp1 ec1)) -> T s u t (T s ampIn ampOut sampIn sampOut) |
|
|
Documentation |
|
|
This is quite analogous to Dimensional.Causal.Process
but adds the conv parameter for conversion
from intuitive external parameters to internal parameters.
| Constructors | Cons | | converter :: conv | | processor :: proc | |
|
| Instances | |
|
|
|
ecAmp is a set of physical units for the external control parameters,
ec is the type for the external control parameters,
ic for internal control parameters.
|
|
|
Constructors | | Instances | |
|
|
|
This function is intended for implementing high-level dimensional processors
from low-level processors.
It introduces the sample rate tag s.
|
|
|
|
joinSynchronousPlain :: T (Converter s ecAmp ec ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut) -> T s (ecAmp, ampIn) ampOut (ec, sampIn) sampOut | Source |
|
|
joinSynchronous :: T s u t (T (Converter s ecAmp ec ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T s u t (T s (ecAmp, ampIn) ampOut (ec, sampIn) sampOut) | Source |
|
|
joinFirstSynchronousPlain :: T (Converter s ecAmp ec ic, a) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut) -> T a (T s (ecAmp, ampIn) ampOut (ec, sampIn) sampOut) | Source |
|
|
joinFirstSynchronous :: T s u t (T (Converter s ecAmp ec ic, a) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T s u t (T a (T s (ecAmp, ampIn) ampOut (ec, sampIn) sampOut)) | Source |
|
|
runSynchronous1 :: C v => T s u t (T (Converter s (T v ecAmp) ec ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T s u t (R s v ecAmp ec -> T s ampIn ampOut sampIn sampOut) | Source |
|
|
runSynchronousPlain2 :: (C v0, C v1) => T (Converter s (T v0 ecAmp0, T v1 ecAmp1) (ec0, ec1) ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut) -> R s v0 ecAmp0 ec0 -> R s v1 ecAmp1 ec1 -> T s ampIn ampOut sampIn sampOut | Source |
|
|
runSynchronous2 :: (C v0, C v1) => T s u t (T (Converter s (T v0 ecAmp0, T v1 ecAmp1) (ec0, ec1) ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T s u t (R s v0 ecAmp0 ec0 -> R s v1 ecAmp1 ec1 -> T s ampIn ampOut sampIn sampOut) | Source |
|
|
|
|
|
|
|
|
runAsynchronous1 :: (C u, C v, C t) => T t (RateDep s ic) -> T s u t (T (Converter s (T v ecAmp) ec ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T u t (S v ecAmp) ec -> T s u t (T s ampIn ampOut sampIn sampOut) | Source |
|
|
processAsynchronous1 :: (C u, C v, C t) => T t (RateDep s ic) -> T s u t (T (Converter s (T v ecAmp) ec ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T (Recip u) t -> (forall r. T r u t (R r v ecAmp ec)) -> T s u t (T s ampIn ampOut sampIn sampOut) | Source |
|
|
applyConverter2 :: (C v0, C v1) => Converter s (T v0 ecAmp0, T v1 ecAmp1) (ec0, ec1) ic -> R s v0 ecAmp0 ec0 -> R s v1 ecAmp1 ec1 -> R s (RateDep s ic) | Source |
|
|
runAsynchronous2 :: (C u, C v0, C v1, C t) => T t (RateDep s ic) -> T s u t (T (Converter s (T v0 ecAmp0, T v1 ecAmp1) (ec0, ec1) ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T u t (S v0 ecAmp0) ec0 -> T u t (S v1 ecAmp1) ec1 -> T s u t (T s ampIn ampOut sampIn sampOut) | Source |
|
Using two SigP.T's as input has the disadvantage
that their rates must be compared dynamically.
It is not possible with our data structures
to use one rate for multiple signals.
We could also allow the input of a Rate.T and two Proc.T's,
since this is the form we get from the computation routines.
But this way we lose sharing.
|
|
processAsynchronous2 :: (C u, C v0, C v1, C t) => T t (RateDep s ic) -> T s u t (T (Converter s (T v0 ecAmp0, T v1 ecAmp1) (ec0, ec1) ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T (Recip u) t -> (forall r. T r u t (R r v0 ecAmp0 ec0)) -> (forall r. T r u t (R r v1 ecAmp1 ec1)) -> T s u t (T s ampIn ampOut sampIn sampOut) | Source |
|
This function will be more commonly used than runAsynchronous2,
but it disallows sharing of control signals.
It can be easily defined in terms of runAsynchronous2 and runProcess,
but the implementation here does not need the check for equal sample rates.
|
|
processAsynchronousNaive2 :: (C u, C v0, C v1, C t) => T t (RateDep s ic) -> T s u t (T (Converter s (T v0 ecAmp0, T v1 ecAmp1) (ec0, ec1) ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T (Recip u) t -> (forall r. T r u t (R r v0 ecAmp0 ec0)) -> (forall r. T r u t (R r v1 ecAmp1 ec1)) -> T s u t (T s ampIn ampOut sampIn sampOut) | Source |
|
|
processAsynchronousBuffered2 :: (C u, C v0, C v1, C t) => T t (RateDep s ic) -> T s u t (T (Converter s (T v0 ecAmp0, T v1 ecAmp1) (ec0, ec1) ic) (T s (ampIn, Flat) ampOut (sampIn, RateDep s ic) sampOut)) -> T (Recip u) t -> (forall r. T r u t (R r v0 ecAmp0 ec0)) -> (forall r. T r u t (R r v1 ecAmp1 ec1)) -> T s u t (T s ampIn ampOut sampIn sampOut) | Source |
|
This buffers internal control parameters before interpolation.
This should be faster, since interpolation needs frequent look-ahead,
and this is faster on a buffered signal than on a plain stateful signal generator.
Since the look-ahead is constant,
it is interesting whether interpolation can be made more efficient
without the inefficient intermediate list structure.
|
|
Produced by Haddock version 2.4.2 |