WAGS.Control.Functions
- Package
- purescript-wags
- Repository
- mikesol/purescript-wags
#start Source
start :: forall env audio engine m res. Monad m => AudioInterpret audio engine => InitialFrameT env audio engine m res Unit
The initial Frame
that is needed to begin any Scene
.
piece :: Scene (SceneI Unit Unit) FFIAudio (Effect Unit) Frame0
piece =
WAGS.do
start -- initial frame
{ time } <- env
create (scene time) $> Right unit
@> loop
( const
$ WAGS.do
{ time } <- env
ivoid $ change (scene time)
)
#modifyRes Source
modifyRes :: forall env audio engine proof m res i. Monad m => AudioInterpret audio engine => (res -> res) -> FrameT env audio engine proof m res i i res
Modifies the residual for a frame and returns the result.
If a frame never modifies its residual, the value of mempty
for res
is returned to the scene.
#makeScene Source
makeScene :: forall env audio engine proofA m res i currentIdx graph changeBit skolems a. Monad m => Monoid res => AudioInterpret audio engine => GraphIsRenderable graph => FrameT env audio engine proofA m res i (UniverseC currentIdx graph changeBit skolems) (Either (SceneT env audio engine proofA m res) a) -> (forall proofB. FrameT env audio engine proofB m res i (UniverseC currentIdx graph changeBit skolems) a -> SceneT env audio engine proofB m res) -> SceneT env audio engine proofA m res
Make a scene. The infix operator for this operation is @>
.
This function uses the GraphIsRenderable
typeclass to assert that an audio graph is renderable by the web audio engine. This means, amongst other things, that it has a unique output device (ie speaker), that it does not have any dangling units not connected to a loudspeaker, etc.
It accepts as arguments:
- a frame to render
- a function that accepts a frame from the next moment in time (
proofB
) and returns a scene.
From these arguments, it produces a SceneT
.
piece :: Scene (SceneI Unit Unit) FFIAudio (Effect Unit) Frame0
piece =
WAGS.do
start
{ time } <- env
create (scene time) $> Right unit
@> loop -- here, @> is the infix version of `makeScene`
( const
$ WAGS.do
{ time } <- env
ivoid $ change (scene time)
)
#makeScene' Source
makeScene' :: forall env audio engine proofA m res i currentIdx graph changeBit skolems a. Monad m => Monoid res => AudioInterpret audio engine => GraphIsRenderable graph => FrameT env audio engine proofA m res i (UniverseC currentIdx graph changeBit skolems) a -> (forall proofB. FrameT env audio engine proofB m res i (UniverseC currentIdx graph changeBit skolems) a -> SceneT env audio engine proofB m res) -> SceneT env audio engine proofA m res
Similar to makeScene'
, but without the possibility to branch to a new scene. Aliased as @|>
.
#loop Source
loop :: forall env audio engine proofA i m res currentIdx graph changeBit skolems edge a. Monad m => Monoid res => AudioInterpret audio engine => TerminalIdentityEdge graph edge => GraphIsRenderable graph => (forall proofB j. a -> FrameT env audio engine proofB m res (UniverseC currentIdx graph j skolems) (UniverseC currentIdx graph (Succ j) skolems) a) -> FrameT env audio engine proofA m res i (UniverseC currentIdx graph changeBit skolems) a -> SceneT env audio engine proofA m res
Loops audio.
In WAGS, a "loop" is a universe whose changeBit
increments by 1. That means that the structure of the graph is similar (no units added, none taken away) while some or none of its internal content (ie frequencies, gains, etc) has changed. This is accomplished using the change
family of functions in WAGS.Change
.
piece :: Scene (SceneI Unit Unit) FFIAudio (Effect Unit) Frame0
piece =
WAGS.do
start -- initial frame
{ time } <- env
create (scene time) $> Right unit
@> loop -- we loop by changing the scene based on `time` in the `env`
( const
$ WAGS.do
{ time } <- env
ivoid $ change (scene time)
)
#branch Source
branch :: forall env audio engine proofA i m res currentIdx graph changeBit skolems a. Monad m => Monoid res => AudioInterpret audio engine => GraphIsRenderable graph => (forall proofB j. a -> FrameT env audio engine proofB m res (UniverseC currentIdx graph j skolems) (UniverseC currentIdx graph j skolems) (Either (FrameT env audio engine proofB m res i (UniverseC currentIdx graph j skolems) Unit -> SceneT env audio engine proofB m res) (FrameT env audio engine proofB m res (UniverseC currentIdx graph j skolems) (UniverseC currentIdx graph (Succ j) skolems) a))) -> FrameT env audio engine proofA m res i (UniverseC currentIdx graph changeBit skolems) a -> SceneT env audio engine proofA m res
Accepts a "branch" frame for making a scene, where Left
is a new scene and Right
is the incoming scene with the change bit incremented by 1. Useful for the common pattern where we loop an audio graph until something in the environment changes, at which point we move on to a new graph.
simpleScene =
( WAGS.do
start
e <- env
create (scene0 e) $> Right unit
)
@> ( branch \_ -> WAGS.do
{ time } <- env
pr <- proof
withProof pr
$ if time < 0.3 then
Right
(
WAGS.do
e <- env
ivoid $ change (scene0 e)
)
else
Left
( loop
( const
$ WAGS.do
e <- env
ivoid $ change (scene1 e)
)
)
)
#inSitu Source
inSitu :: forall env audio engine proof m r i x z a. Monad m => (FrameT env audio engine proof m r i z a -> SceneT env audio engine proof m r) -> FrameT env audio engine proof m r x z a -> FrameT env audio engine proof m r i x Unit -> SceneT env audio engine proof m r
Often times, the computation in a frame will need to start from
universe x
and proceed to universe z
before continuing to
produce a scene. inSitu
"thunks" the computation at x
.
#universe Source
universe :: forall env audio engine proof m res i. Monad m => AudioInterpret audio engine => FrameT env audio engine proof m res i i (Proxy i)
Get the current universe as a proxy.
#currentIdx Source
currentIdx :: forall env audio engine proof m res currentIdx graph changeBit skolems. Monad m => AudioInterpret audio engine => FrameT env audio engine proof m res (UniverseC currentIdx graph changeBit skolems) (UniverseC currentIdx graph changeBit skolems) (Proxy currentIdx)
Get the current index as a proxy.
#changeBit Source
changeBit :: forall env audio engine proof m res currentIdx graph changeBit skolems. Monad m => AudioInterpret audio engine => FrameT env audio engine proof m res (UniverseC currentIdx graph changeBit skolems) (UniverseC currentIdx graph changeBit skolems) (Proxy changeBit)
Get the changeBit as a proxy.
#env Source
env :: forall env audio engine proof m res i. Monad m => AudioInterpret audio engine => FrameT env audio engine proof m res i i env
Get the environment from a frame.
piece :: Scene (SceneI Unit Unit) FFIAudio (Effect Unit) Frame0
piece =
WAGS.do
start
{ time } <- env -- get the environment
create (scene time) $> Right unit
@> loop
( const
$ WAGS.do
{ time } <- env
ivoid $ change (scene time)
)
#freeze Source
freeze :: forall env audio engine proof m res i currentIdx graph changeBit skolems x. Monad m => Monoid res => AudioInterpret audio engine => GraphIsRenderable graph => FrameT env audio engine proof m res i (UniverseC currentIdx graph changeBit skolems) x -> SceneT env audio engine proof m res
Freezes the current audio frame.
scene = (start :*> create (speaker (sinOsc 440.0))) @|> freeze
#lift Source
lift :: forall env audio engine proof m res i a. Monad m => AudioInterpret audio engine => m a -> FrameT env audio engine proof m res i i a
Lift a computation from the underlying monad m
into FrameT
.
#proof Source
proof :: forall env audio engine proof m res i. Monad m => AudioInterpret audio engine => FrameT env audio engine proof m res i i proof
Get the proof term from a frame. Useful to construct a new frame using withProof
.
The following snippet is taken from the WTK example where proof
is used to generate a proof term that is then consumed by withProof
in order to make the final Frame
.
piece :: { makeRenderingEnv :: MakeRenderingEnv } -> Scene (SceneI Trigger Unit) FFIAudio (Effect Unit) Frame0
piece { makeRenderingEnv } =
( WAGS.do
start
ivoid $ create $ fullKeyboard klavierIdentity
k0 <- cursor $ cursors.k0
k1 <- cursor $ cursors.k1
k2 <- cursor $ cursors.k2
k3 <- cursor $ cursors.k3
k4 <- cursor $ cursors.k4
k5 <- cursor $ cursors.k5
k6 <- cursor $ cursors.k6
k7 <- cursor $ cursors.k7
k8 <- cursor $ cursors.k8
k9 <- cursor $ cursors.k9
myProof <- proof
withProof myProof
$ Right
{ audioRefs: k0 /\ k1 /\ k2 /\ k3 /\ k4 /\ k5 /\ k6 /\ k7 /\ k8 /\ k9
, currentKeys: (Nil :: (List KeyInfo))
, availableKeys: K0 : K1 : K2 : K3 : K4 : K5 : K6 : K7 : K8 : K9 : Nil
}
)
@> loop
( \{ audioRefs, currentKeys, availableKeys } -> WAGS.do
{ time, trigger, active } <- env
graphProxy <- graph
let
{ notesOff
, onsets
, newCurrentKeys
, newAvailableKeys
, futureCurrentKeys
, futureAvailableKeys
} = makeRenderingEnv active trigger time availableKeys currentKeys
( playKeys
{ graphProxy
, audioRefs
, currentTime: time
, notesOff
}
unit
onsets
newCurrentKeys
)
$> { audioRefs
, currentKeys: futureCurrentKeys
, availableKeys: futureAvailableKeys
}
)
#withProof Source
withProof :: forall env audio engine proof m res i a. Monad m => AudioInterpret audio engine => proof -> a -> FrameT env audio engine proof m res i i a
Consumes a proof
term to construct a FrameT
.
This pattern is used because FrameT
does not implement IxApplicative
. Instead, in order to construct a frame, one needs to provide proof
that one is at the current moment in time. This is to prevent frames from different timestamps from mixing.
- Modules
- FRP.
Event. MIDI - WAGS.
Change - WAGS.
Connect - WAGS.
Control. Functions - WAGS.
Control. MemoizedState - WAGS.
Control. Qualified - WAGS.
Control. Thunkable - WAGS.
Control. Types - WAGS.
Create - WAGS.
Cursor - WAGS.
Debug - WAGS.
Destroy - WAGS.
Disconnect - WAGS.
Graph. Constructors - WAGS.
Graph. Decorators - WAGS.
Graph. Getter - WAGS.
Graph. Optionals - WAGS.
Graph. Parameter - WAGS.
Interpret - WAGS.
Move - WAGS.
MoveNode - WAGS.
Rebase - WAGS.
Rendered - WAGS.
Run - WAGS.
Universe. AudioUnit - WAGS.
Universe. Bin - WAGS.
Universe. BinN - WAGS.
Universe. EdgeProfile - WAGS.
Universe. Graph - WAGS.
Universe. Node - WAGS.
Universe. Skolems - WAGS.
Universe. Universe - WAGS.
Util - WAGS.
Validation