-- Copyright 2019 Evan Laforge
-- This program is distributed under the terms of the GNU General Public
-- License 3.0, see COPYING or http://www.gnu.org/licenses/gpl-3.0.txt

-- | Per-patch calls.
module Synth.Faust.Code where
import qualified Derive.Call.Module as Module
import qualified Derive.Call.Post as Post
import qualified Derive.Call.Tags as Tags
import qualified Derive.Derive as Derive
import qualified Derive.Score as Score
import qualified Derive.ScoreT as ScoreT
import qualified Derive.Sig as Sig

import qualified Perform.Signal as Signal

import Types


note_terminate :: ScoreT.Control -> RealTime -> Derive.Transformer Derive.Note
note_terminate :: Control -> RealTime -> Transformer Note
note_terminate Control
control RealTime
decay = forall d.
Module
-> CallName
-> Tags
-> Doc
-> WithArgDoc (TransformerF d)
-> Transformer d
Derive.transformer Module
Module.instrument
    CallName
"note-terminate" (Tags
Tags.postproc forall a. Semigroup a => a -> a -> a
<> Tags
Tags.inst)
    Doc
"Terminate a note with a control change."
    forall a b. (a -> b) -> a -> b
$ forall y a d.
Taggable y =>
Parser a -> (a -> Transformer y d) -> WithArgDoc (Transformer y d)
Sig.callt (
    forall a deflt.
(Typecheck a, ToVal deflt) =>
ArgName -> deflt -> Doc -> Parser a
Sig.defaulted ArgName
"value" (Y
0.1 :: Double) Doc
"Move to this value."
    ) forall a b. (a -> b) -> a -> b
$ \Y
value PassedArgs Note
_args -> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. (a -> b) -> Stream a -> Stream b
Post.emap1_ (RealTime -> Y -> Note -> Note
apply RealTime
decay Y
value))
    where
    apply :: RealTime -> Y -> Note -> Note
apply RealTime
decay Y
value Note
event = Control -> (Control -> Control) -> Note -> Note
Score.modify_signal Control
control
        (RealTime -> Y -> RealTime -> Control -> Control
modify RealTime
decay Y
value (Note -> RealTime
Score.event_end Note
event)) Note
event
    modify :: RealTime -> Y -> RealTime -> Control -> Control
modify RealTime
decay Y
value RealTime
end = Control -> Control -> Control
Signal.sig_multiply
        (forall {k} (kind :: k). [(RealTime, Y)] -> Signal kind
Signal.from_pairs
            [(RealTime
Signal.beginning, Y
1), (RealTime
end, Y
1), (RealTime
end forall a. Num a => a -> a -> a
+ RealTime
decay, Y
value)])