Safe Haskell | Safe-Inferred |
---|
Derive.DeriveT
Description
This module defines basic tracklang types.
The Derive.PSignal section is re-exported from Derive.PSignal. I'd rather move it to PSignal, but it needs to be here to avoid circular imports.
Here are the names for various aspects of signals:
numbers pitches both scalar Signal.Y PSignal.Y name ScoreT.Control ScoreT.PControl signal Signal.Control PSignal.PSignal ref DeriveT.ControlRef DeriveT.PControlRef Ref
Synopsis
- newtype PSignal = PSignal (Segment.Boxed Pitch)
- _signal :: PSignal -> Segment.Boxed Pitch
- interpolate :: Segment.Interpolate Pitch
- type Pitch = RawPitch Untransposed_
- type Transposed = RawPitch Transposed_
- data Transposed_
- data Untransposed_
- data RawPitch a = Pitch {}
- pitch :: Scale -> (PitchConfig -> Either PitchError Pitch.NoteNumber) -> (PitchConfig -> Either PitchError Pitch.Note) -> PitchConfig -> Pitch
- coerce :: RawPitch a -> RawPitch b
- pitch_nn :: Transposed -> Either PitchError Pitch.NoteNumber
- pitch_note :: Transposed -> Either PitchError Pitch.Note
- annotate_out_of_range :: RawPitch a -> Maybe Pitch.NoteNumber -> PitchError -> PitchError
- data PitchConfig = PitchConfig !Environ !ScoreT.ControlValMap
- data Scale = Scale {}
- data PitchError
- data OutOfRange = OutOfRange {
- oor_nn :: !(Maybe Pitch.NoteNumber)
- oor_semi :: !(Maybe Pitch.FSemi)
- oor_valid :: !(Maybe (Int, Int))
- oor_transposers :: !ScoreT.ControlValMap
- out_of_range :: OutOfRange
- modify_out_of_range :: (OutOfRange -> OutOfRange) -> PitchError -> PitchError
- out_of_range_error :: Real a => a -> (Int, Int) -> PitchError
- pitches_equal :: RawPitch a -> RawPitch a -> Bool
- data Duration
- multiply_duration :: Duration -> Double -> Duration
- newtype Environ = Environ (Map EnvKey.Key Val)
- insert :: EnvKey.Key -> Val -> Environ -> Environ
- lookup :: EnvKey.Key -> Environ -> Maybe Val
- environ_attributes :: Environ -> Attrs.Attributes
- data Val
- vals_equal :: Val -> Val -> Maybe Bool
- lists_equal :: (a -> a -> Maybe Bool) -> [a] -> [a] -> Maybe Bool
- val_to_mini :: Val -> Maybe Expr.MiniVal
- newtype Quoted = Quoted Expr
- show_call_val :: Val -> Text
- num :: Double -> Val
- str :: Text -> Val
- score_time :: ScoreTime.ScoreTime -> Val
- real_time :: RealTime.RealTime -> Val
- transposition :: Pitch.Transpose -> Val
- to_scale_id :: Val -> Maybe Pitch.ScaleId
- quoted :: Expr.Symbol -> [Val] -> Quoted
- quoted0 :: Expr.Symbol -> Quoted
- data Ref control val
- = ControlSignal val
- | DefaultedControl control val
- | LiteralControl control
- type ControlRef = Ref ScoreT.Control (ScoreT.Typed Signal.Control)
- type PControlRef = Ref ScoreT.PControl PSignal
- show_control :: ShowVal.ShowVal control => (sig -> Text) -> Ref control sig -> Text
- real_control :: ScoreT.Control -> RealTime.RealTime -> ControlRef
- constant_control :: Signal.Y -> ControlRef
- type Expr = Expr.Expr Val
- type Call = Expr.Call Val
- type Term = Expr.Term Val
- calls_equal :: Call -> Call -> Maybe Bool
- terms_equal :: Term -> Term -> Maybe Bool
- type PitchCall = Call
- map_str :: (Expr.Str -> Expr.Str) -> Call -> Call
- type ControlMap = Map ScoreT.Control (ScoreT.Typed Signal.Control)
- type ControlFunctionMap = Map ScoreT.Control ControlFunction
- type PitchMap = Map ScoreT.PControl PSignal
- data ControlFunction = ControlFunction !Text !(ScoreT.Control -> Dynamic -> RealTime.RealTime -> ScoreT.Typed Signal.Y)
- call_control_function :: ControlFunction -> ScoreT.Control -> Dynamic -> RealTime.RealTime -> ScoreT.Typed Signal.Y
- modify_control_function :: ((RealTime.RealTime -> ScoreT.Typed Signal.Y) -> RealTime.RealTime -> ScoreT.Typed Signal.Y) -> ControlFunction -> ControlFunction
- data Dynamic = Dynamic {}
- empty_dynamic :: Dynamic
Derive.PSignal
A pitch signal is similar to a Signal.Control
, except that its values
are Pitch
es instead of plain floating point values.
Constructors
PSignal (Segment.Boxed Pitch) |
Instances
interpolate :: Segment.Interpolate Pitch Source #
A pitch interpolated a certain distance between two other pitches.
type Pitch = RawPitch Untransposed_ Source #
This is an untransposed pitch. All pitches have transposition signals from the dynamic state applied when they are converted to MIDI or whatever backend. So if I want the final concrete pitch, I have to apply the transposition signals. But if I want to emit a note with this pitch, I want the untransposed one, or the transposition will be applied twice. I use a phantom type parameter to keep them straight.
type Transposed = RawPitch Transposed_ Source #
The transposed version of Pitch
.
data Transposed_ Source #
data Untransposed_ Source #
A pitch is an abstract value that can generate a Pitch.NoteNumber
or
symbolic Pitch.Note
.
Constructors
Pitch | |
Fields
|
Instances
ToVal Pitch Source # | |
Typecheck Pitch Source # | |
Show (RawPitch a) Source # | |
DeepSeq.NFData (RawPitch a) Source # | It can't be reduced since it has lambdas, but at least this way you can easily rnf things that contain it. |
Defined in Derive.DeriveT | |
ShowVal.ShowVal (RawPitch a) Source # | Pitches have no literal syntax, but I have to print something. |
Pretty.Pretty (RawPitch a) Source # | Will look like: 62.95nn,4i(*wayang) |
pitch :: Scale -> (PitchConfig -> Either PitchError Pitch.NoteNumber) -> (PitchConfig -> Either PitchError Pitch.Note) -> PitchConfig -> Pitch Source #
Make an abstract Pitch.
pitch_nn :: Transposed -> Either PitchError Pitch.NoteNumber Source #
Usually I only want to evaluate a fully transposed pitch. Exceptions
are documented by applying coerce
.
pitch_note :: Transposed -> Either PitchError Pitch.Note Source #
Usually I only want to evaluate a fully transposed pitch. Exceptions
are documented by applying coerce
.
annotate_out_of_range :: RawPitch a -> Maybe Pitch.NoteNumber -> PitchError -> PitchError Source #
data PitchConfig Source #
A PitchConfig is the data that can continue to influence the pitch's frequency.
Pitches are configured by controls and by an environ. The controls
are for values that change over time, such as transposition or tuning.
They're combined additively, which is really only appropriate for
transposition. Controls are mostly applied only on conversion to the
performer. TODO I don't entirely remember why. However, this leads to
some trickiness because if I want to compare a pitch to an absolute
NoteNumber, I need the final transposed value, but if I put it in an event
it must be untransposed, or transposition will be applied twice.
To avoid double. To avoid this, there's a phantom type parameter to
distinguish an untransposed Pitch
from a Transposed
one.
The Environ is for symbolic configuration, such as key or tuning mode. Unlike controls, though, it's taken from the environ in scope when the pith is created. Otherwise, you can't evaluate a pitch with a different key by setting the environ.
Constructors
PitchConfig !Environ !ScoreT.ControlValMap |
Instances
Monoid PitchConfig Source # | |
Defined in Derive.DeriveT Methods mempty :: PitchConfig # mappend :: PitchConfig -> PitchConfig -> PitchConfig # mconcat :: [PitchConfig] -> PitchConfig # | |
Semigroup PitchConfig Source # | |
Defined in Derive.DeriveT Methods (<>) :: PitchConfig -> PitchConfig -> PitchConfig # sconcat :: NonEmpty PitchConfig -> PitchConfig # stimes :: Integral b => b -> PitchConfig -> PitchConfig # | |
Show PitchConfig Source # | |
Defined in Derive.DeriveT Methods showsPrec :: Int -> PitchConfig -> ShowS # show :: PitchConfig -> String # showList :: [PitchConfig] -> ShowS # | |
Pretty.Pretty PitchConfig Source # | |
Defined in Derive.DeriveT Methods pretty :: PitchConfig -> Text Source # format :: PitchConfig -> Doc Source # formatList :: [PitchConfig] -> Doc Source # |
PSignal can't take a Scale because that would be a circular import. Fortunately it only needs a few fields. However, because of the circularity, the Scale.Scale -> PSignal.Scale constructor is in Derive.Derive.
Constructors
Scale | |
Fields
|
data PitchError Source #
Things that can go wrong evaluating a pitch.
Constructors
UnparseableNote !Pitch.Note | |
OutOfRangeError !OutOfRange | Note out of the scale's range. The values are transpositions from the environment, in case it was out of range because of a transposition. Some scales have a restricted range, in which case they should throw
|
InvalidInput | Input note doesn't map to a scale note. |
EnvironError !EnvKey.Key !(Maybe Text) | A required environ value was missing or had the wrong type or value. Nothing if the value is missing, otherwise a Text description. |
ControlError !ScoreT.Control !Text | Same as EnvironError, but for control vals. |
NotImplemented | The scale doesn't implement that operation. |
PitchError !Text | Other kind of error. |
Instances
Show PitchError Source # | |
Defined in Derive.DeriveT Methods showsPrec :: Int -> PitchError -> ShowS # show :: PitchError -> String # showList :: [PitchError] -> ShowS # | |
Eq PitchError Source # | |
Defined in Derive.DeriveT | |
Ord PitchError Source # | |
Defined in Derive.DeriveT Methods compare :: PitchError -> PitchError -> Ordering # (<) :: PitchError -> PitchError -> Bool # (<=) :: PitchError -> PitchError -> Bool # (>) :: PitchError -> PitchError -> Bool # (>=) :: PitchError -> PitchError -> Bool # max :: PitchError -> PitchError -> PitchError # min :: PitchError -> PitchError -> PitchError # | |
Pretty.Pretty PitchError Source # | |
Defined in Derive.DeriveT Methods pretty :: PitchError -> Text Source # format :: PitchError -> Doc Source # formatList :: [PitchError] -> Doc Source # |
data OutOfRange Source #
Constructors
OutOfRange | |
Fields
|
Instances
Show OutOfRange Source # | |
Defined in Derive.DeriveT Methods showsPrec :: Int -> OutOfRange -> ShowS # show :: OutOfRange -> String # showList :: [OutOfRange] -> ShowS # | |
Eq OutOfRange Source # | |
Defined in Derive.DeriveT | |
Ord OutOfRange Source # | |
Defined in Derive.DeriveT Methods compare :: OutOfRange -> OutOfRange -> Ordering # (<) :: OutOfRange -> OutOfRange -> Bool # (<=) :: OutOfRange -> OutOfRange -> Bool # (>) :: OutOfRange -> OutOfRange -> Bool # (>=) :: OutOfRange -> OutOfRange -> Bool # max :: OutOfRange -> OutOfRange -> OutOfRange # min :: OutOfRange -> OutOfRange -> OutOfRange # | |
Pretty.Pretty OutOfRange Source # | |
Defined in Derive.DeriveT Methods pretty :: OutOfRange -> Text Source # format :: OutOfRange -> Doc Source # formatList :: [OutOfRange] -> Doc Source # |
modify_out_of_range :: (OutOfRange -> OutOfRange) -> PitchError -> PitchError Source #
out_of_range_error :: Real a => a -> (Int, Int) -> PitchError Source #
Duration
Some calls can operate in either RealTime or ScoreTime.
multiply_duration :: Duration -> Double -> Duration Source #
Duration can't be in Fractional since you can't multiple a RealDuration by a ScoreDuration, but scaling operations are still useful.
Environ
Constructors
Environ (Map EnvKey.Key Val) |
insert :: EnvKey.Key -> Val -> Environ -> Environ Source #
Insert a val directly, with no typechecking.
Val
This is the type of first class values in the tracklang. It's main purpose is the type for arguments to tracklang calls, and val calls' return type.
Constructors
VNum !(ScoreT.Typed Signal.Y) | A number with an optional type suffix. It also has a ratio style literal, though the output is still a floating point value, not a true ratio. Literal: |
VAttributes !Attrs.Attributes | A set of Attributes for an instrument. Literal: |
VControlRef !ControlRef | A control name. An optional value gives a default if the control isn't present. Literal: |
VPControlRef !PControlRef | A pitch control name. The scale is taken from the environ. Unlike
a control signal, the empty string is a valid signal name and means the
default pitch signal. The Literal: |
VPitch !Pitch | No literal, but is returned from val calls, notably scale calls. |
VNotePitch !Pitch.Pitch | A parsed Literal: |
VStr !Expr.Str | A string. There is an unquoted and a quoted form, parsed at
Literal: |
VQuoted !Quoted | A quoted expression. Quoted calls are resolved by Derive.Sig when it typechecks arguments. This way you can set an argument default to an expression that will be evaluated every time the call occurs. Derive.Sig expects that the expression is a valid val call, which means no pipes. Literal: |
VControlFunction !ControlFunction | |
VNotGiven | An explicit not-given arg for functions so you can use positional args with defaults. Literal: |
VSeparator | A token used as a separator when calls want to parse their argument lists via their own complicated means. TODO only used by old gamakam, get rid of this Literal: |
VList ![Val] | List of values. Literal: |
Instances
Show Val Source # | |
DeepSeq.NFData Val Source # | |
Defined in Derive.DeriveT | |
ShowVal.ShowVal Val Source # | This instance is actually invalid due to showing VPitch, which has no
literal, and for |
ToVal Val Source # | |
Typecheck Val Source # | |
Pretty.Pretty Val Source # | |
ShowVal.ShowVal (Expr.Call Val) Source # | |
ShowVal.ShowVal (Expr.Expr Val) Source # | |
ShowVal.ShowVal (Expr.Term Val) Source # | |
Pretty.Pretty (Expr.Call Val) Source # | |
Pretty.Pretty (Expr.Term Val) Source # | |
vals_equal :: Val -> Val -> Maybe Bool Source #
Return Nothing if the Vals can't be compared, and whether or not they're equal otherwise.
val_to_mini :: Val -> Maybe Expr.MiniVal Source #
Instances
Show Quoted Source # | |
ShowVal.ShowVal Quoted Source # | Unlike Exprs in general, a Quoted Expr should be representable with show_val. This is because a Quoted has only been parsed, not evaluated, so it shouldn't have anything unshowable, like pitches. |
ToVal Quoted Source # | |
Typecheck Quoted Source # | Anything except a pitch can be coerced to a quoted, using ShowVal. This means you can write a lot of things without quotes. Pitches have to be quoted because they explicitly have an invalid ShowVal. |
Pretty.Pretty Quoted Source # | |
show_call_val :: Val -> Text Source #
Show a str intended for call position. Call position is special in that it can contain any character except space and equals without quoting.
val utils
score_time :: ScoreTime.ScoreTime -> Val Source #
real_time :: RealTime.RealTime -> Val Source #
transposition :: Pitch.Transpose -> Val Source #
to_scale_id :: Val -> Maybe Pitch.ScaleId Source #
quoted0 :: Expr.Symbol -> Quoted Source #
Ref
Constructors
ControlSignal val | A signal literal. |
DefaultedControl control val | If the control isn't present, use the given default. |
LiteralControl control | Throw an exception if the control isn't present. |
Instances
type ControlRef = Ref ScoreT.Control (ScoreT.Typed Signal.Control) Source #
type PControlRef = Ref ScoreT.PControl PSignal Source #
show_control :: ShowVal.ShowVal control => (sig -> Text) -> Ref control sig -> Text Source #
real_control :: ScoreT.Control -> RealTime.RealTime -> ControlRef Source #
Defaulted control from a RealTime.
Expr
call utils
Derive.Score
ControlMap
type ControlMap = Map ScoreT.Control (ScoreT.Typed Signal.Control) Source #
ControlFunction
data ControlFunction Source #
Another representation of a signal, complementary to Signal.Control
.
It's more powerful because it has access to a subset of the Dynamic state,
as well as the Control
is was originally bound to. However, it's also
less powerful because you can't inspect it to see if it's constant, or emit
exactly the samples present without resorting to sampling, or draw it on
the UI. This is the ubiquitous code vs. data tradeoff.
In addition, the main motivation to add control functions was to randomize values, which means that, unlike signals, they're not actually functions at all, and thus couldn't be rendered as a continuous signal. This means that functions are only suitable for sampling at points, not for slicing over time ranges.
Having both signals and functions is awkward because then some calls may ignore a control function if they require a signal, which is inconsistent and confusing. This is the case for all control generators since the signal usually is on a control track and will wind up being rendered on the UI. So the convention is that control functions are generally just modifications of an underlying signal, rather than synthesizing a signal.
Another awkward thing about ControlFunction is that it really wants to be in Deriver, but can't, due to circular imports. The alternative is a giant hs-boot file, or lumping thousands of lines into Derive.Deriver.Monad. Currently it's a plain function but if I want logging and exceptions I could use Derive.Deriver.DeriveM. It still wouldn't solve the main problem, which is that I can't reuse the Deriver functions, and instead have to rewrite them.
See NOTE [control-function].
Constructors
ControlFunction !Text !(ScoreT.Control -> Dynamic -> RealTime.RealTime -> ScoreT.Typed Signal.Y) | Control is the control name this function was bound to, if it was bound to one. Dynamic is a stripped down Derive State. For ControlFunctions that represent a control signal, the RealTime is the desired X value, otherwise it's just some number. |
Instances
Show ControlFunction Source # | |
Defined in Derive.DeriveT Methods showsPrec :: Int -> ControlFunction -> ShowS # show :: ControlFunction -> String # showList :: [ControlFunction] -> ShowS # | |
DeepSeq.NFData ControlFunction Source # | |
Defined in Derive.DeriveT Methods rnf :: ControlFunction -> () # | |
ShowVal.ShowVal ControlFunction Source # | Not parseable. |
Defined in Derive.DeriveT Methods show_val :: ControlFunction -> Text Source # | |
ToVal ControlFunction Source # | |
Defined in Derive.Typecheck Methods to_val :: ControlFunction -> Val Source # | |
Typecheck ControlFunction Source # | |
Defined in Derive.Typecheck | |
Pretty.Pretty ControlFunction Source # | |
Defined in Derive.DeriveT Methods pretty :: ControlFunction -> Text Source # format :: ControlFunction -> Doc Source # formatList :: [ControlFunction] -> Doc Source # |
call_control_function :: ControlFunction -> ScoreT.Control -> Dynamic -> RealTime.RealTime -> ScoreT.Typed Signal.Y Source #
modify_control_function :: ((RealTime.RealTime -> ScoreT.Typed Signal.Y) -> RealTime.RealTime -> ScoreT.Typed Signal.Y) -> ControlFunction -> ControlFunction Source #
Modify the underlying function, presumably to compose something onto the input or output.
A stripped down Derive.Deriver.Monad.Dynamic for ControlFunctions
to use. The duplication is unfortunate, see ControlFunction
.
Constructors
Dynamic | |
Fields
|