diff --git a/CHANGELOG.md b/CHANGELOG.md index 775bb6f1..5786e2f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.3.0] - 2021-06-06 + +### Added + +- Simplifies `change` instructions. Now, instead of writing `{ sinOsc: sinOsc_ 440.0 }` it is possible to write `{ sinOsc: 440.0 }`. +- Speeds up rendering by avoiding unnecessary checks. + +### Changed + +- The `Optional` files are now split between `Create` and `Change`. This fixes many bugs where a default parameter in a `Create` accidentally modulated a value during a `Change`. Now, the `Change` default is `Nothing`, meaning nothing changes. Furthermore, the underscore syntax (`sinOsc_`) has been removed. + ## [0.2.4] - 2021-06-05 ### Added diff --git a/examples/atari-speaks/AtariSpeaks.purs b/examples/atari-speaks/AtariSpeaks.purs index 99073493..e5958aa2 100644 --- a/examples/atari-speaks/AtariSpeaks.purs +++ b/examples/atari-speaks/AtariSpeaks.purs @@ -1,6 +1,7 @@ module WAGS.Example.AtariSpeaks where import Prelude + import Control.Comonad.Cofree (Cofree, mkCofree) import Control.Promise (toAffE) import Data.Foldable (for_) @@ -22,10 +23,10 @@ import WAGS.Change (ichange) import WAGS.Control.Functions.Validated (iloop, (@!>)) import WAGS.Control.Types (Frame0, Scene) import WAGS.Create (icreate) +import WAGS.Create.Optionals (CGain, CLoopBuf, CSpeaker, gain, loopBuf, speaker) import WAGS.Graph.AudioUnit (TGain, TLoopBuf, TSpeaker) -import WAGS.Graph.Optionals (CGain, CLoopBuf, CSpeaker, gain, loopBuf, speaker) import WAGS.Interpret (AudioContext, FFIAudio(..), close, context, decodeAudioDataFromUri, defaultFFIAudio, makeUnitCache) -import WAGS.Run (SceneI, run) +import WAGS.Run (RunAudio, SceneI, RunEngine, run) vol = 1.4 :: Number @@ -61,8 +62,8 @@ scene time = { loop1: loopBuf { playbackRate: 1.5 + 0.1 * sin (2.0 * rad) - , start: 0.1 + 0.1 * sin rad - , end: 0.5 + 0.25 * sin (2.0 * rad) + , loopStart: 0.1 + 0.1 * sin rad + , loopEnd: 0.5 + 0.25 * sin (2.0 * rad) } "atar" } @@ -72,7 +73,7 @@ scene time = } } -piece :: Scene (SceneI Unit Unit) FFIAudio (Effect Unit) Frame0 Unit +piece :: Scene (SceneI Unit Unit) RunAudio RunEngine Frame0 Unit piece = (_.time >>> scene >>> icreate) @!> iloop \{ time } _ -> ivoid $ ichange (scene time) easingAlgorithm :: Cofree ((->) Int) Int diff --git a/examples/hello-world/HelloWorld.purs b/examples/hello-world/HelloWorld.purs index fd94c0e3..a0dca608 100644 --- a/examples/hello-world/HelloWorld.purs +++ b/examples/hello-world/HelloWorld.purs @@ -1,6 +1,7 @@ module WAGS.Example.HelloWorld where import Prelude + import Control.Comonad.Cofree (Cofree, mkCofree) import Data.Functor.Indexed (ivoid) import Data.Tuple.Nested (type (/\)) @@ -11,10 +12,10 @@ import WAGS.Change (ichange) import WAGS.Control.Functions.Validated (iloop, (@!>)) import WAGS.Control.Types (Frame0, Scene) import WAGS.Create (icreate) +import WAGS.Create.Optionals (CGain, CSpeaker, CSinOsc, gain, sinOsc, speaker) import WAGS.Graph.AudioUnit (TGain, TSinOsc, TSpeaker) -import WAGS.Graph.Optionals (CGain, CSpeaker, CSinOsc, gain, sinOsc, speaker) import WAGS.Interpret (FFIAudio(..), FFIAudio') -import WAGS.Run (SceneI, run) +import WAGS.Run (RunAudio, SceneI, RunEngine, run) type SceneTemplate = CSpeaker @@ -48,7 +49,7 @@ scene time = , gain3: gain 0.1 { sin3: sinOsc (530.0 + (19.0 * (5.0 * sin rad))) } } -piece :: Scene (SceneI Unit Unit) FFIAudio (Effect Unit) Frame0 Unit +piece :: Scene (SceneI Unit Unit) RunAudio RunEngine Frame0 Unit piece = (_.time >>> scene >>> icreate) @!> iloop \{ time } _ -> ivoid $ ichange (scene time) easingAlgorithm :: Cofree ((->) Int) Int diff --git a/examples/kitchen-sink/KitchenSink.purs b/examples/kitchen-sink/KitchenSink.purs index 9c9fb08d..e97b2dcc 100644 --- a/examples/kitchen-sink/KitchenSink.purs +++ b/examples/kitchen-sink/KitchenSink.purs @@ -120,7 +120,7 @@ handleAction = case _ of unitCache <- H.liftEffect makeUnitCache myWave <- H.liftEffect - $ makePeriodicWave audioCtx (0.3 +> -0.1 +> empty) (-0.25 +> 0.05 +> empty) + $ makePeriodicWave audioCtx (0.0 +> -0.1 +> empty) (0.0 +> 0.05 +> empty) wicked <- H.liftEffect $ makeFloatArray (makeDistortionCurve 400.0) let recorder = diff --git a/examples/kitchen-sink/KitchenSink/Piece.purs b/examples/kitchen-sink/KitchenSink/Piece.purs index 1ce0a903..d3ca82ff 100644 --- a/examples/kitchen-sink/KitchenSink/Piece.purs +++ b/examples/kitchen-sink/KitchenSink/Piece.purs @@ -7,7 +7,7 @@ import WAGS.Create (icreate) import WAGS.Example.KitchenSink.TLP.LoopSig (LoopSig(..), SceneSig) import WAGS.Example.KitchenSink.TLP.SinOsc (doSinOsc) import WAGS.Example.KitchenSink.Types.SinOsc (ksSinOscCreate) -import WAGS.Graph.Optionals (gain, speaker) +import WAGS.Create.Optionals (gain, speaker) piece :: SceneSig Frame0 piece = diff --git a/examples/kitchen-sink/KitchenSink/TLP/Allpass.purs b/examples/kitchen-sink/KitchenSink/TLP/Allpass.purs index 2f85d45d..853f2463 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/Allpass.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/Allpass.purs @@ -1,11 +1,9 @@ module WAGS.Example.KitchenSink.TLP.Allpass where import Prelude - import Control.Applicative.Indexed (ipure) import Control.Monad.Indexed.Qualified as Ix import Data.Either (Either(..)) -import Data.Functor.Indexed (ivoid) import Math ((%)) import Type.Proxy (Proxy(..)) import WAGS.Change (ichange) @@ -20,14 +18,13 @@ import WAGS.Example.KitchenSink.Timing (timing, pieceTime) import WAGS.Example.KitchenSink.Types.Allpass (AllpassGraph, deltaKsAllpass) import WAGS.Example.KitchenSink.Types.Empty (cursorGain) import WAGS.Example.KitchenSink.Types.Lowpass (ksLowpassCreate) -import WAGS.Graph.Optionals (lowpass_, playBuf_) import WAGS.Patch (ipatch) doAllpass :: forall proof. StepSig AllpassGraph proof doAllpass = ibranch \{ time } lsig -> if time % pieceTime < timing.ksAllpass.end then - Right (ichange (deltaKsAllpass time) $> lsig) + Right (deltaKsAllpass time $> lsig) else if lsig.iteration `mod` 2 == 0 then Left $ icont doLowpass Ix.do @@ -46,9 +43,8 @@ doAllpass = Left $ icont doLowpass Ix.do ipatch - ivoid - $ ichange - { lowpass: lowpass_ { freq: 300.0 } - , buf: playBuf_ "my-buffer" - } + ichange + { lowpass: 300.0 + , buf: "my-buffer" + } ipure lsig diff --git a/examples/kitchen-sink/KitchenSink/TLP/Bandpass.purs b/examples/kitchen-sink/KitchenSink/TLP/Bandpass.purs index 5f3e19ac..b2c98cc9 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/Bandpass.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/Bandpass.purs @@ -1,13 +1,11 @@ module WAGS.Example.KitchenSink.TLP.Bandpass where import Prelude - import Control.Applicative.Indexed (ipure) import Control.Monad.Indexed.Qualified as Ix import Data.Either (Either(..)) import Math ((%)) import Type.Proxy (Proxy(..)) -import WAGS.Change (ichange) import WAGS.Connect (iconnect) import WAGS.Control.Functions (ibranch, icont) import WAGS.Create (icreate) @@ -24,7 +22,7 @@ doBandpass :: forall proof. StepSig BandpassGraph proof doBandpass = ibranch \{ time } lsig -> if time % pieceTime < timing.ksBandpass.end then - Right (ichange (deltaKsBandpass time) $> lsig) + Right (deltaKsBandpass time $> lsig) else Left $ icont doNotch Ix.do diff --git a/examples/kitchen-sink/KitchenSink/TLP/Constant.purs b/examples/kitchen-sink/KitchenSink/TLP/Constant.purs index 502d1166..95b9a17a 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/Constant.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/Constant.purs @@ -7,7 +7,6 @@ import Control.Monad.Indexed.Qualified as Ix import Data.Either (Either(..)) import Math ((%)) import Type.Proxy (Proxy(..)) -import WAGS.Change (ichange) import WAGS.Connect (iconnect) import WAGS.Control.Functions (ibranch, icont) import WAGS.Create (icreate) @@ -24,7 +23,7 @@ doConstant :: forall proof. StepSig ConstantGraph proof doConstant = ibranch \{ time } lsig -> if time % pieceTime < timing.ksConstant.end then - Right (ichange (deltaKsConstant time) $> lsig) + Right (deltaKsConstant time $> lsig) else Left $ icont doDynamicsCompressor Ix.do diff --git a/examples/kitchen-sink/KitchenSink/TLP/Delay.purs b/examples/kitchen-sink/KitchenSink/TLP/Delay.purs index b7f77fef..c0bff99d 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/Delay.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/Delay.purs @@ -1,13 +1,11 @@ module WAGS.Example.KitchenSink.TLP.Delay where import Prelude - import Control.Applicative.Indexed (ipure) import Control.Monad.Indexed.Qualified as Ix import Data.Either (Either(..)) import Math ((%)) import Type.Proxy (Proxy(..)) -import WAGS.Change (ichange) import WAGS.Connect (iconnect) import WAGS.Control.Functions (ibranch, icont) import WAGS.Create (icreate) @@ -24,7 +22,7 @@ doDelay :: forall proof. StepSig DelayGraph proof doDelay = ibranch \{ time } lsig -> if time % pieceTime < timing.ksDelay.end then - Right (ichange (deltaKsDelay time) $> lsig) + Right (deltaKsDelay time $> lsig) else Left $ icont doFeedback Ix.do diff --git a/examples/kitchen-sink/KitchenSink/TLP/DynamicsCompressor.purs b/examples/kitchen-sink/KitchenSink/TLP/DynamicsCompressor.purs index d8275e9e..e55e8030 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/DynamicsCompressor.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/DynamicsCompressor.purs @@ -6,7 +6,6 @@ import Control.Monad.Indexed.Qualified as Ix import Data.Either (Either(..)) import Math ((%)) import Type.Proxy (Proxy(..)) -import WAGS.Change (ichange) import WAGS.Connect (iconnect) import WAGS.Control.Functions (ibranch, icont) import WAGS.Create (icreate) @@ -36,4 +35,4 @@ doDynamicsCompressor = iconnect { source: Proxy :: _ "sinOsc", dest: cursorGain } ipure $ l { iteration = iteration + 1 } else - Right (ichange (deltaKsDynamicsCompressor time) $> l) + Right (deltaKsDynamicsCompressor time $> l) diff --git a/examples/kitchen-sink/KitchenSink/TLP/Feedback.purs b/examples/kitchen-sink/KitchenSink/TLP/Feedback.purs index 1069dea9..d602a144 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/Feedback.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/Feedback.purs @@ -5,7 +5,6 @@ import Prelude import Control.Applicative.Indexed (ipure) import Control.Monad.Indexed.Qualified as Ix import Data.Either (Either(..)) -import Data.Functor.Indexed (ivoid) import Math ((%)) import Type.Proxy (Proxy(..)) import WAGS.Change (ichange) @@ -20,13 +19,12 @@ import WAGS.Example.KitchenSink.Timing (pieceTime, timing) import WAGS.Example.KitchenSink.Types.Empty (cursorGain) import WAGS.Example.KitchenSink.Types.Feedback (FeedbackGraph, deltaKsFeedback) import WAGS.Example.KitchenSink.Types.LoopBuf (ksLoopBufCreate) -import WAGS.Graph.Optionals (gain_) doFeedback :: forall proof. StepSig FeedbackGraph proof doFeedback = ibranch \{ time } lsig -> if time % pieceTime < timing.ksFeedback.end then - Right (ichange (deltaKsFeedback time) $> lsig) + Right (deltaKsFeedback time $> lsig) else Left $ icont doLoopBuf Ix.do @@ -49,5 +47,5 @@ doFeedback = idestroy cursorHighpass icreate ksLoopBufCreate iconnect { source: Proxy :: _ "loopBuf", dest: cursorGain } - ivoid $ ichange { mix: gain_ 1.0 } + ichange { mix: 1.0 } ipure lsig diff --git a/examples/kitchen-sink/KitchenSink/TLP/Highpass.purs b/examples/kitchen-sink/KitchenSink/TLP/Highpass.purs index 6d68b7f9..8a45b395 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/Highpass.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/Highpass.purs @@ -1,13 +1,11 @@ module WAGS.Example.KitchenSink.TLP.Highpass where import Prelude - import Control.Applicative.Indexed (ipure) import Control.Monad.Indexed.Qualified as Ix import Data.Either (Either(..)) import Math ((%)) import Type.Proxy (Proxy(..)) -import WAGS.Change (ichange) import WAGS.Connect (iconnect) import WAGS.Control.Functions (ibranch, icont) import WAGS.Create (icreate) @@ -24,7 +22,7 @@ doHighpass :: forall proof. StepSig HighpassGraph proof doHighpass = ibranch \{ time } lsig -> if time % pieceTime < timing.ksHighpass.end then - Right (ichange (deltaKsHighpass time) $> lsig) + Right (deltaKsHighpass time $> lsig) else Left $ icont doMicrophone Ix.do diff --git a/examples/kitchen-sink/KitchenSink/TLP/Highshelf.purs b/examples/kitchen-sink/KitchenSink/TLP/Highshelf.purs index fd1934e9..e759a119 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/Highshelf.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/Highshelf.purs @@ -1,13 +1,11 @@ module WAGS.Example.KitchenSink.TLP.Highshelf where import Prelude - import Control.Applicative.Indexed (ipure) import Control.Monad.Indexed.Qualified as Ix import Data.Either (Either(..)) import Math ((%)) import Type.Proxy (Proxy(..)) -import WAGS.Change (ichange) import WAGS.Connect (iconnect) import WAGS.Control.Functions (ibranch, icont) import WAGS.Create (icreate) @@ -24,7 +22,7 @@ doHighshelf :: forall proof. StepSig HighshelfGraph proof doHighshelf = ibranch \{ time } lsig -> if time % pieceTime < timing.ksHighshelf.end then - Right (ichange (deltaKsHighshelf time) $> lsig) + Right (deltaKsHighshelf time $> lsig) else Left $ icont doLowshelf Ix.do diff --git a/examples/kitchen-sink/KitchenSink/TLP/LoopBuf.purs b/examples/kitchen-sink/KitchenSink/TLP/LoopBuf.purs index 132dd3ae..bcc51fca 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/LoopBuf.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/LoopBuf.purs @@ -6,7 +6,6 @@ import Control.Monad.Indexed.Qualified as Ix import Data.Either (Either(..)) import Math ((%)) import Type.Proxy (Proxy(..)) -import WAGS.Change (ichange) import WAGS.Connect (iconnect) import WAGS.Control.Functions (ibranch, icont) import WAGS.Create (icreate) @@ -23,7 +22,7 @@ doLoopBuf :: forall proof. StepSig LoopBufGraph proof doLoopBuf = ibranch \{ time } lsig -> if time % pieceTime < timing.ksLoopBuf.end then - Right (ichange (deltaKsLoopBuf time) $> lsig) + Right (deltaKsLoopBuf time $> lsig) else Left $ icont doStereoPanner Ix.do diff --git a/examples/kitchen-sink/KitchenSink/TLP/LoopSig.purs b/examples/kitchen-sink/KitchenSink/TLP/LoopSig.purs index 79225781..6df7a4fc 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/LoopSig.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/LoopSig.purs @@ -1,34 +1,33 @@ module WAGS.Example.KitchenSink.TLP.LoopSig where import Prelude -import Effect (Effect) + import WAGS.Control.Indexed (IxWAG) import WAGS.Control.Types (Frame, Scene, WAG) -import WAGS.Example.KitchenSink.Types.SinOsc (SinOscGraph) -import WAGS.Interpret (FFIAudio) -import WAGS.Run (SceneI) +import WAGS.Example.KitchenSink.Types.StartGraph (StartGraph) +import WAGS.Run (RunEngine, SceneI, RunAudio) type Res = String type SceneSig :: forall k. k -> Type type SceneSig proof - = Scene (SceneI Unit Unit) FFIAudio (Effect Unit) proof Res + = Scene (SceneI Unit Unit) RunAudio RunEngine proof Res type FrameSig' step proof a - = Frame (SceneI Unit Unit) FFIAudio (Effect Unit) proof Res step a + = Frame (SceneI Unit Unit) RunAudio RunEngine proof Res step a type FrameSig step proof = FrameSig' step proof { loop :: LoopSig, iteration :: Int } type WAGSig' step proof a - = WAG FFIAudio (Effect Unit) proof Res step a + = WAG RunAudio RunEngine proof Res step a type WAGSig step proof = WAGSig' step proof { loop :: LoopSig, iteration :: Int } type IxWAGSig' stepA stepB proof a - = IxWAG FFIAudio (Effect Unit) proof Res stepA stepB a + = IxWAG RunAudio RunEngine proof Res stepA stepB a type IxWAGSig stepA stepB proof = IxWAGSig' stepA stepB proof { loop :: LoopSig, iteration :: Int } @@ -38,4 +37,4 @@ type StepSig step proof SceneSig proof newtype LoopSig - = LoopSig (forall proof. StepSig SinOscGraph proof) + = LoopSig (forall proof. StepSig StartGraph proof) diff --git a/examples/kitchen-sink/KitchenSink/TLP/Lowpass.purs b/examples/kitchen-sink/KitchenSink/TLP/Lowpass.purs index fd199e69..b8fda3c1 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/Lowpass.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/Lowpass.purs @@ -1,13 +1,11 @@ module WAGS.Example.KitchenSink.TLP.Lowpass where import Prelude - import Control.Applicative.Indexed (ipure) import Control.Monad.Indexed.Qualified as Ix import Data.Either (Either(..)) import Math ((%)) import Type.Proxy (Proxy(..)) -import WAGS.Change (ichange) import WAGS.Connect (iconnect) import WAGS.Control.Functions (ibranch, icont) import WAGS.Create (icreate) @@ -24,7 +22,7 @@ doLowpass :: forall proof. StepSig LowpassGraph proof doLowpass = ibranch \{ time } lsig -> if time % pieceTime < timing.ksLowpass.end then - Right (ichange (deltaKsLowpass time) $> lsig) + Right (deltaKsLowpass time $> lsig) else Left $ icont doHighshelf Ix.do diff --git a/examples/kitchen-sink/KitchenSink/TLP/Lowshelf.purs b/examples/kitchen-sink/KitchenSink/TLP/Lowshelf.purs index 35532291..d52bded3 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/Lowshelf.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/Lowshelf.purs @@ -1,13 +1,11 @@ module WAGS.Example.KitchenSink.TLP.Lowshelf where import Prelude - import Control.Applicative.Indexed (ipure) import Control.Monad.Indexed.Qualified as Ix import Data.Either (Either(..)) import Math ((%)) import Type.Proxy (Proxy(..)) -import WAGS.Change (ichange) import WAGS.Connect (iconnect) import WAGS.Control.Functions (ibranch, icont) import WAGS.Create (icreate) @@ -24,7 +22,7 @@ doLowshelf :: forall proof. StepSig LowshelfGraph proof doLowshelf = ibranch \{ time } lsig -> if time % pieceTime < timing.ksLowshelf.end then - Right (ichange (deltaKsLowshelf time) $> lsig) + Right (deltaKsLowshelf time $> lsig) else Left $ icont doBandpass Ix.do diff --git a/examples/kitchen-sink/KitchenSink/TLP/Microphone.purs b/examples/kitchen-sink/KitchenSink/TLP/Microphone.purs index 85f8149d..017d7bd2 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/Microphone.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/Microphone.purs @@ -1,13 +1,11 @@ module WAGS.Example.KitchenSink.TLP.Microphone where import Prelude - import Control.Applicative.Indexed (ipure) import Control.Monad.Indexed.Qualified as Ix import Data.Either (Either(..)) import Math ((%)) import Type.Proxy (Proxy(..)) -import WAGS.Change (ichange) import WAGS.Connect (iconnect) import WAGS.Control.Functions (ibranch, icont) import WAGS.Create (icreate) @@ -24,7 +22,7 @@ doMicrophone :: forall proof. StepSig MicrophoneGraph proof doMicrophone = ibranch \{ time } lsig -> if time % pieceTime < timing.ksMicrophone.end then - Right (ichange (deltaKsMicrophone time) $> lsig) + Right (deltaKsMicrophone time $> lsig) else Left $ icont doWaveShaper Ix.do diff --git a/examples/kitchen-sink/KitchenSink/TLP/Notch.purs b/examples/kitchen-sink/KitchenSink/TLP/Notch.purs index d6ce1469..bf4a7379 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/Notch.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/Notch.purs @@ -1,13 +1,11 @@ module WAGS.Example.KitchenSink.TLP.Notch where import Prelude - import Control.Applicative.Indexed (ipure) import Control.Monad.Indexed.Qualified as Ix import Data.Either (Either(..)) import Math ((%)) import Type.Proxy (Proxy(..)) -import WAGS.Change (ichange) import WAGS.Connect (iconnect) import WAGS.Control.Functions (ibranch, icont) import WAGS.Create (icreate) @@ -24,7 +22,7 @@ doNotch :: forall proof. StepSig NotchGraph proof doNotch = ibranch \{ time } lsig -> if time % pieceTime < timing.ksNotch.end then - Right (ichange (deltaKsNotch time) $> lsig) + Right (deltaKsNotch time $> lsig) else Left $ icont doPeaking Ix.do diff --git a/examples/kitchen-sink/KitchenSink/TLP/Peaking.purs b/examples/kitchen-sink/KitchenSink/TLP/Peaking.purs index e9d15f37..202902a6 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/Peaking.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/Peaking.purs @@ -1,13 +1,11 @@ module WAGS.Example.KitchenSink.TLP.Peaking where import Prelude - import Control.Monad.Indexed (ipure, (:*>)) import Control.Monad.Indexed.Qualified as Ix import Data.Either (Either(..)) import Math ((%)) import Type.Proxy (Proxy(..)) -import WAGS.Change (ichange) import WAGS.Connect (iconnect) import WAGS.Control.Functions (ibranch, imodifyRes, icont) import WAGS.Create (icreate) @@ -26,7 +24,7 @@ doPeaking = if time % pieceTime < timing.ksPeaking.end then Right $ imodifyRes (const $ "Using a peaking filter") - :*> ichange (deltaKsPeaking time) + :*> deltaKsPeaking time $> lsig else Left diff --git a/examples/kitchen-sink/KitchenSink/TLP/SawtoothOsc.purs b/examples/kitchen-sink/KitchenSink/TLP/SawtoothOsc.purs index fdebf1f0..2eceff8d 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/SawtoothOsc.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/SawtoothOsc.purs @@ -1,12 +1,10 @@ module WAGS.Example.KitchenSink.TLP.SawtoothOsc where import Prelude - import Control.Applicative.Indexed (ipure) import Control.Monad.Indexed.Qualified as Ix +import Control.Plus (empty) import Data.Either (Either(..)) -import Data.Functor.Indexed (ivoid) -import Data.Maybe (Maybe(..)) import Math ((%)) import Type.Proxy (Proxy(..)) import WAGS.Change (ichange) @@ -21,8 +19,7 @@ import WAGS.Example.KitchenSink.Timing (timing, pieceTime) import WAGS.Example.KitchenSink.Types.Allpass (ksAllpassCreate) import WAGS.Example.KitchenSink.Types.Empty (cursorGain) import WAGS.Example.KitchenSink.Types.SawtoothOsc (SawtoothOscGraph) -import WAGS.Graph.Optionals (sawtoothOsc) -import WAGS.Graph.Parameter (AudioParameter_(..), defaultParam) +import WAGS.Graph.Parameter (AudioParameter_) doSawtoothOsc :: forall proof. StepSig SawtoothOscGraph proof doSawtoothOsc = @@ -31,17 +28,7 @@ doSawtoothOsc = Right Ix.do -- tests cancel when (time % pieceTime > timing.ksSawtoothOsc.begin + 2.0) - ( ivoid - $ ichange - { sawtoothOsc: - sawtoothOsc - $ AudioParameter - ( defaultParam - { param = Nothing :: Maybe Number - } - ) - } - ) + (ichange { sawtoothOsc: empty :: AudioParameter_ Number }) ipure lsig else Left diff --git a/examples/kitchen-sink/KitchenSink/TLP/SinOsc.purs b/examples/kitchen-sink/KitchenSink/TLP/SinOsc.purs index 28be4e42..2447c6ca 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/SinOsc.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/SinOsc.purs @@ -1,13 +1,11 @@ module WAGS.Example.KitchenSink.TLP.SinOsc where import Prelude - import Control.Applicative.Indexed (ipure) import Control.Monad.Indexed.Qualified as Ix import Data.Either (Either(..)) import Math ((%)) import Type.Proxy (Proxy(..)) -import WAGS.Change (ichange) import WAGS.Connect (iconnect) import WAGS.Control.Functions (ibranch, icont) import WAGS.Create (icreate) @@ -24,7 +22,7 @@ doSinOsc :: forall proof. StepSig SinOscGraph proof doSinOsc = ibranch \{ time } lsig -> if time % pieceTime < timing.ksSinOsc.end then - Right (ichange (deltaKsSinOsc time) $> lsig) + Right (deltaKsSinOsc time $> lsig) else Left $ icont doTriangleOsc Ix.do diff --git a/examples/kitchen-sink/KitchenSink/TLP/SquareOsc.purs b/examples/kitchen-sink/KitchenSink/TLP/SquareOsc.purs index fa504e69..701ca32e 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/SquareOsc.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/SquareOsc.purs @@ -1,13 +1,11 @@ module WAGS.Example.KitchenSink.TLP.SquareOsc where import Prelude - import Control.Monad.Indexed (ipure, (:*>)) import Control.Monad.Indexed.Qualified as Ix import Data.Either (Either(..)) import Math ((%)) import Type.Proxy (Proxy(..)) -import WAGS.Change (ichange) import WAGS.Connect (iconnect) import WAGS.Control.Functions (ibranch, icont, imodifyRes) import WAGS.Create (icreate) @@ -26,7 +24,7 @@ doSquareOsc = if time % pieceTime < timing.ksSquareOsc.end then Right ( imodifyRes (const "Playing a square osc") - :*> ichange (deltaKsSquareOsc time) + :*> deltaKsSquareOsc time $> lsig ) else diff --git a/examples/kitchen-sink/KitchenSink/TLP/StereoPanner.purs b/examples/kitchen-sink/KitchenSink/TLP/StereoPanner.purs index ea0291e1..c3c9f7c3 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/StereoPanner.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/StereoPanner.purs @@ -7,7 +7,6 @@ import Control.Monad.Indexed.Qualified as Ix import Data.Either (Either(..)) import Math ((%)) import Type.Proxy (Proxy(..)) -import WAGS.Change (ichange) import WAGS.Connect (iconnect) import WAGS.Control.Functions (ibranch, icont) import WAGS.Create (icreate) @@ -24,7 +23,7 @@ doStereoPanner :: forall proof. StepSig StereoPannerGraph proof doStereoPanner = ibranch \{ time } lsig -> if time % pieceTime < timing.ksStereoPanner.end then - Right (ichange (deltaKsStereoPanner time) $> lsig) + Right (deltaKsStereoPanner time $> lsig) else Left $ icont doConstant Ix.do diff --git a/examples/kitchen-sink/KitchenSink/TLP/TriangleOsc.purs b/examples/kitchen-sink/KitchenSink/TLP/TriangleOsc.purs index 9f2d36ba..48eb8d0a 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/TriangleOsc.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/TriangleOsc.purs @@ -4,7 +4,6 @@ import Prelude import Control.Applicative.Indexed (ipure) import Control.Monad.Indexed.Qualified as Ix import Data.Either (Either(..)) -import Data.Functor.Indexed (ivoid) import Math ((%)) import Type.Proxy (Proxy(..)) import WAGS.Change (ichange) @@ -19,20 +18,19 @@ import WAGS.Example.KitchenSink.Timing (timing, pieceTime) import WAGS.Example.KitchenSink.Types.Empty (cursorGain) import WAGS.Example.KitchenSink.Types.SquareOsc (ksSquareOscCreate) import WAGS.Example.KitchenSink.Types.TriangleOsc (TriangleOscGraph, deltaKsTriangleOsc) -import WAGS.Graph.Optionals (squareOsc_) import WAGS.Patch (ipatch) doTriangleOsc :: forall proof. StepSig TriangleOscGraph proof doTriangleOsc = ibranch \{ time } lsig -> if time % pieceTime < timing.ksTriangleOsc.end then - Right (ichange (deltaKsTriangleOsc time) $> lsig) + Right (deltaKsTriangleOsc time $> lsig) else Left $ icont doSquareOsc if lsig.iteration `mod` 2 == 0 then Ix.do ipatch - ivoid $ ichange { squareOsc: squareOsc_ 220.0 } + ichange { squareOsc: 220.0 } ipure lsig else Ix.do let diff --git a/examples/kitchen-sink/KitchenSink/TLP/WaveShaper.purs b/examples/kitchen-sink/KitchenSink/TLP/WaveShaper.purs index 0220380a..767f0f16 100644 --- a/examples/kitchen-sink/KitchenSink/TLP/WaveShaper.purs +++ b/examples/kitchen-sink/KitchenSink/TLP/WaveShaper.purs @@ -1,13 +1,11 @@ module WAGS.Example.KitchenSink.TLP.WaveShaper where import Prelude - import Control.Applicative.Indexed (ipure) import Control.Monad.Indexed.Qualified as Ix import Data.Either (Either(..)) import Math ((%)) import Type.Proxy (Proxy(..)) -import WAGS.Change (ichange) import WAGS.Connect (iconnect) import WAGS.Control.Functions (ibranch, icont) import WAGS.Create (icreate) @@ -24,7 +22,7 @@ doWaveShaper :: forall proof. StepSig WaveShaperGraph proof doWaveShaper = ibranch \{ time } lsig -> if time % pieceTime < timing.ksWaveShaper.end then - Right (ichange (deltaKsWaveShaper time) $> lsig) + Right (deltaKsWaveShaper time $> lsig) else Left $ icont doDelay Ix.do diff --git a/examples/kitchen-sink/KitchenSink/Types/Allpass.purs b/examples/kitchen-sink/KitchenSink/Types/Allpass.purs index 2e68a86a..e1b29c62 100644 --- a/examples/kitchen-sink/KitchenSink/Types/Allpass.purs +++ b/examples/kitchen-sink/KitchenSink/Types/Allpass.purs @@ -3,11 +3,13 @@ module WAGS.Example.KitchenSink.Types.Allpass where import Prelude import Data.Tuple.Nested (type (/\)) import Math ((%)) -import WAGS.Math (calcSlope) +import WAGS.Change (ichange) +import WAGS.Create.Optionals (CAllpass, CPlayBuf, allpass, playBuf) +import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Timing (timing, pieceTime) import WAGS.Example.KitchenSink.Types.Empty (TopWith) import WAGS.Graph.AudioUnit (OnOff(..), TAllpass, TPlayBuf) -import WAGS.Graph.Optionals (CAllpass, CPlayBuf, DAllpass, DGain, DPlayBuf, allpass, allpass_, gain_, playBuf, playBuf_) +import WAGS.Math (calcSlope) type AllpassGraph = TopWith { allpass :: Unit } @@ -18,7 +20,7 @@ type AllpassGraph ksAllpassCreate :: { allpass :: CAllpass { buf :: CPlayBuf } } ksAllpassCreate = { allpass: allpass { freq: 300.0 } { buf: playBuf "my-buffer" } } -deltaKsAllpass :: Number -> { mix :: DGain, allpass :: DAllpass, buf :: DPlayBuf } +deltaKsAllpass :: forall proof. Number -> IxWAGSig' AllpassGraph AllpassGraph proof Unit deltaKsAllpass = (_ % pieceTime) >>> (_ - timing.ksAllpass.begin) @@ -29,10 +31,8 @@ deltaKsAllpass = switchW = time % 4.0 < 2.0 in - { mix: gain_ (if time > (timing.ksAllpass.dur - 1.0) then 0.0 else 1.0) - , allpass: allpass_ { freq: calcSlope 0.0 300.0 timing.ksAllpass.dur 2000.0 time } - , buf: - playBuf_ - { onOff: if switchOO then On else Off } - (if switchW then "my-buffer" else "shruti") - } + ichange + { mix: if time > (timing.ksAllpass.dur - 1.0) then 0.0 else 1.0 + , allpass: calcSlope 0.0 300.0 timing.ksAllpass.dur 2000.0 time + , buf: { onOff: if switchOO then On else Off, buffer: if switchW then "my-buffer" else "shruti" } + } diff --git a/examples/kitchen-sink/KitchenSink/Types/Bandpass.purs b/examples/kitchen-sink/KitchenSink/Types/Bandpass.purs index 55dcc307..04fd637f 100644 --- a/examples/kitchen-sink/KitchenSink/Types/Bandpass.purs +++ b/examples/kitchen-sink/KitchenSink/Types/Bandpass.purs @@ -3,11 +3,13 @@ module WAGS.Example.KitchenSink.Types.Bandpass where import Prelude import Data.Tuple.Nested (type (/\)) import Math ((%)) -import WAGS.Math (calcSlope) +import WAGS.Change (ichange) +import WAGS.Create.Optionals (CBandpass, CPlayBuf, bandpass, playBuf) +import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Timing (timing, pieceTime) import WAGS.Example.KitchenSink.Types.Empty (TopWith) import WAGS.Graph.AudioUnit (OnOff(..), TBandpass, TPlayBuf) -import WAGS.Graph.Optionals (CBandpass, CPlayBuf, DGain, DPlayBuf, DBandpass, bandpass, bandpass_, gain_, playBuf, playBuf_) +import WAGS.Math (calcSlope) type BandpassGraph = TopWith { bandpass :: Unit } @@ -18,7 +20,7 @@ type BandpassGraph ksBandpassCreate :: { bandpass :: CBandpass { buf :: CPlayBuf } } ksBandpassCreate = { bandpass: bandpass { freq: 300.0 } { buf: playBuf "my-buffer" } } -deltaKsBandpass :: Number -> { mix :: DGain, bandpass :: DBandpass, buf :: DPlayBuf } +deltaKsBandpass :: forall proof. Number -> IxWAGSig' BandpassGraph BandpassGraph proof Unit deltaKsBandpass = (_ % pieceTime) >>> (_ - timing.ksBandpass.begin) @@ -29,10 +31,8 @@ deltaKsBandpass = switchW = time % 4.0 < 2.0 in - { mix: gain_ (if time > (timing.ksBandpass.dur - 1.0) then 0.0 else 1.0) - , bandpass: bandpass_ { freq: calcSlope 0.0 300.0 timing.ksBandpass.dur 2000.0 time } - , buf: - playBuf_ - { onOff: if switchOO then On else Off } - (if switchW then "my-buffer" else "shruti") - } + ichange + { mix: if time > (timing.ksBandpass.dur - 1.0) then 0.0 else 1.0 + , bandpass: calcSlope 0.0 300.0 timing.ksBandpass.dur 2000.0 time + , buf: { onOff: if switchOO then On else Off, buffer: if switchW then "my-buffer" else "shruti" } + } diff --git a/examples/kitchen-sink/KitchenSink/Types/Constant.purs b/examples/kitchen-sink/KitchenSink/Types/Constant.purs index 0b18fdfb..d61b29f2 100644 --- a/examples/kitchen-sink/KitchenSink/Types/Constant.purs +++ b/examples/kitchen-sink/KitchenSink/Types/Constant.purs @@ -2,9 +2,11 @@ module WAGS.Example.KitchenSink.Types.Constant where import Prelude import Data.Tuple.Nested (type (/\)) +import WAGS.Change (ichange) +import WAGS.Create.Optionals (CConstant, constant) +import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Types.Empty (TopWith) import WAGS.Graph.AudioUnit (TConstant) -import WAGS.Graph.Optionals (CConstant, DGain, DConstant, constant, constant_, gain_) type ConstantGraph = TopWith { constant :: Unit } @@ -14,9 +16,10 @@ type ConstantGraph ksConstantCreate :: { constant :: CConstant } ksConstantCreate = { constant: constant 0.0 } -deltaKsConstant :: Number -> { mix :: DGain, constant :: DConstant } +deltaKsConstant :: forall proof. Number -> IxWAGSig' ConstantGraph ConstantGraph proof Unit deltaKsConstant = const - { mix: gain_ 1.0 - , constant: constant_ 0.0 - } + $ ichange + { mix: 1.0 + , constant: 0.0 + } diff --git a/examples/kitchen-sink/KitchenSink/Types/Delay.purs b/examples/kitchen-sink/KitchenSink/Types/Delay.purs index d524c51c..7c857924 100644 --- a/examples/kitchen-sink/KitchenSink/Types/Delay.purs +++ b/examples/kitchen-sink/KitchenSink/Types/Delay.purs @@ -3,11 +3,13 @@ module WAGS.Example.KitchenSink.Types.Delay where import Prelude import Data.Tuple.Nested (type (/\)) import Math ((%)) -import WAGS.Math (calcSlope) +import WAGS.Change (ichange) +import WAGS.Create.Optionals (CDelay, CGain, CPlayBuf, Ref, delay, gain, playBuf, ref) +import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Timing (timing, pieceTime) import WAGS.Example.KitchenSink.Types.Empty (TopWith) import WAGS.Graph.AudioUnit (OnOff(..), TDelay, TGain, TPlayBuf) -import WAGS.Graph.Optionals (CDelay, CGain, CPlayBuf, DDelay, DGain, DPlayBuf, Ref, delay, delay_, gain, gain_, playBuf, playBuf_, ref) +import WAGS.Math (calcSlope) type DelayGraph = TopWith { dmix :: Unit } @@ -25,7 +27,7 @@ ksDelayCreate = } } -deltaKsDelay :: Number -> { mix :: DGain, delay :: DDelay, buf :: DPlayBuf } +deltaKsDelay :: forall proof. Number -> IxWAGSig' DelayGraph DelayGraph proof Unit deltaKsDelay = (_ % pieceTime) >>> (_ - timing.ksDelay.begin) @@ -36,10 +38,8 @@ deltaKsDelay = switchW = time % 4.0 < 2.0 in - { mix: gain_ (if time > (timing.ksDelay.dur - 1.0) then 0.0 else 1.0) - , delay: delay_ $ calcSlope 0.0 0.3 timing.ksDelay.dur 0.6 time - , buf: - playBuf_ - { onOff: if switchOO then On else Off } - (if switchW then "my-buffer" else "shruti") - } + ichange + { mix: if time > (timing.ksDelay.dur - 1.0) then 0.0 else 1.0 + , delay: calcSlope 0.0 0.3 timing.ksDelay.dur 0.6 time + , buf: { onOff: if switchOO then On else Off, buffer: if switchW then "my-buffer" else "shruti" } + } diff --git a/examples/kitchen-sink/KitchenSink/Types/DynamicsCompressor.purs b/examples/kitchen-sink/KitchenSink/Types/DynamicsCompressor.purs index 21597d58..a76bfe18 100644 --- a/examples/kitchen-sink/KitchenSink/Types/DynamicsCompressor.purs +++ b/examples/kitchen-sink/KitchenSink/Types/DynamicsCompressor.purs @@ -3,10 +3,12 @@ module WAGS.Example.KitchenSink.Types.DynamicsCompressor where import Prelude import Data.Tuple.Nested (type (/\)) import Math ((%)) +import WAGS.Change (ichange) +import WAGS.Create.Optionals (CDynamicsCompressor, CPlayBuf, compressor, playBuf) +import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Timing (timing, pieceTime) import WAGS.Example.KitchenSink.Types.Empty (TopWith) import WAGS.Graph.AudioUnit (OnOff(..), TDynamicsCompressor, TPlayBuf) -import WAGS.Graph.Optionals (CDynamicsCompressor, CPlayBuf, DGain, DPlayBuf, DDynamicsCompressor, compressor, compressor_, gain_, playBuf, playBuf_) type DynamicsCompressorGraph = TopWith { compressor :: Unit } @@ -17,7 +19,7 @@ type DynamicsCompressorGraph ksDynamicsCompressorCreate :: { compressor :: CDynamicsCompressor { buf :: CPlayBuf } } ksDynamicsCompressorCreate = { compressor: compressor {} { buf: playBuf "my-buffer" } } -deltaKsDynamicsCompressor :: Number -> { mix :: DGain, compressor :: DDynamicsCompressor, buf :: DPlayBuf } +deltaKsDynamicsCompressor :: forall proof. Number -> IxWAGSig' DynamicsCompressorGraph DynamicsCompressorGraph proof Unit deltaKsDynamicsCompressor = (_ % pieceTime) >>> (_ - timing.ksDynamicsCompressor.begin) @@ -28,19 +30,16 @@ deltaKsDynamicsCompressor = switchW = time % 4.0 < 2.0 in - { mix: gain_ (if time > (timing.ksDynamicsCompressor.dur - 1.0) then 0.0 else 1.0) - , compressor: - compressor_ + ichange + { mix: if time > (timing.ksDynamicsCompressor.dur - 1.0) then 0.0 else 1.0 + , compressor: { threshold: if time > (dur / 2.0) then -50.0 else -40.0 , knee: if time > (dur / 3.0) then 20.0 else 40.0 , ratio: if time > (dur / 4.0) then 2.0 else 5.0 , attack: if time > (dur / 5.0) then 0.003 else 0.005 , release: if time > (dur / 6.0) then 0.25 else 0.5 } - , buf: - playBuf_ - { onOff: if switchOO then On else Off } - (if switchW then "my-buffer" else "shruti") - } + , buf: { onOff: if switchOO then On else Off, buffer: if switchW then "my-buffer" else "shruti" } + } where dur = timing.ksDynamicsCompressor.dur diff --git a/examples/kitchen-sink/KitchenSink/Types/Feedback.purs b/examples/kitchen-sink/KitchenSink/Types/Feedback.purs index 6700a783..a93c0d81 100644 --- a/examples/kitchen-sink/KitchenSink/Types/Feedback.purs +++ b/examples/kitchen-sink/KitchenSink/Types/Feedback.purs @@ -3,11 +3,13 @@ module WAGS.Example.KitchenSink.Types.Feedback where import Prelude import Data.Tuple.Nested (type (/\)) import Math ((%)) -import WAGS.Math (calcSlope) +import WAGS.Change (ichange) +import WAGS.Create.Optionals (CDelay, CGain, CPlayBuf, Ref, CHighpass, delay, gain, highpass, playBuf, ref) +import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Timing (timing, pieceTime) import WAGS.Example.KitchenSink.Types.Empty (TopWith) import WAGS.Graph.AudioUnit (OnOff(..), TDelay, TGain, THighpass, TPlayBuf) -import WAGS.Graph.Optionals (CDelay, CGain, CPlayBuf, DDelay, DGain, DPlayBuf, Ref, CHighpass, delay, delay_, gain, gain_, highpass, playBuf, playBuf_, ref) +import WAGS.Math (calcSlope) type FeedbackGraph = TopWith { dmix :: Unit } @@ -32,7 +34,7 @@ ksFeedbackCreate = } } -deltaKsFeedback :: Number -> { mix :: DGain, delay :: DDelay, buf :: DPlayBuf } +deltaKsFeedback :: forall proof. Number -> IxWAGSig' FeedbackGraph FeedbackGraph proof Unit deltaKsFeedback = (_ % pieceTime) >>> (_ - timing.ksFeedback.begin) @@ -43,10 +45,8 @@ deltaKsFeedback = switchW = time % 4.0 < 2.0 in - { mix: gain_ (if time > (timing.ksFeedback.dur - 1.0) then 0.0 else 1.0) - , delay: delay_ $ calcSlope 0.0 0.3 timing.ksFeedback.dur 0.6 time - , buf: - playBuf_ - { onOff: if switchOO then On else Off } - (if switchW then "my-buffer" else "shruti") - } + ichange + { mix: if time > (timing.ksFeedback.dur - 1.0) then 0.0 else 1.0 + , delay: calcSlope 0.0 0.3 timing.ksFeedback.dur 0.6 time + , buf: { onOff: if switchOO then On else Off, buffer: if switchW then "my-buffer" else "shruti" } + } diff --git a/examples/kitchen-sink/KitchenSink/Types/Highpass.purs b/examples/kitchen-sink/KitchenSink/Types/Highpass.purs index 5a2f11db..90a1b210 100644 --- a/examples/kitchen-sink/KitchenSink/Types/Highpass.purs +++ b/examples/kitchen-sink/KitchenSink/Types/Highpass.purs @@ -3,11 +3,13 @@ module WAGS.Example.KitchenSink.Types.Highpass where import Prelude import Data.Tuple.Nested (type (/\)) import Math ((%)) -import WAGS.Math (calcSlope) +import WAGS.Change (ichange) +import WAGS.Create.Optionals (CHighpass, CPlayBuf, highpass, playBuf) +import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Timing (timing, pieceTime) import WAGS.Example.KitchenSink.Types.Empty (TopWith) import WAGS.Graph.AudioUnit (OnOff(..), THighpass, TPlayBuf) -import WAGS.Graph.Optionals (CHighpass, CPlayBuf, DGain, DPlayBuf, DHighpass, highpass, highpass_, gain_, playBuf, playBuf_) +import WAGS.Math (calcSlope) type HighpassGraph = TopWith { highpass :: Unit } @@ -18,7 +20,7 @@ type HighpassGraph ksHighpassCreate :: { highpass :: CHighpass { buf :: CPlayBuf } } ksHighpassCreate = { highpass: highpass { freq: 300.0 } { buf: playBuf "my-buffer" } } -deltaKsHighpass :: Number -> { mix :: DGain, highpass :: DHighpass, buf :: DPlayBuf } +deltaKsHighpass :: forall proof. Number -> IxWAGSig' HighpassGraph HighpassGraph proof Unit deltaKsHighpass = (_ % pieceTime) >>> (_ - timing.ksHighpass.begin) @@ -29,10 +31,8 @@ deltaKsHighpass = switchW = time % 4.0 < 2.0 in - { mix: gain_ (if time > (timing.ksHighpass.dur - 1.0) then 0.0 else 1.0) - , highpass: highpass_ { freq: calcSlope 0.0 300.0 timing.ksHighpass.dur 2000.0 time } - , buf: - playBuf_ - { onOff: if switchOO then On else Off } - (if switchW then "my-buffer" else "shruti") - } + ichange + { mix: if time > (timing.ksHighpass.dur - 1.0) then 0.0 else 1.0 + , highpass: calcSlope 0.0 300.0 timing.ksHighpass.dur 2000.0 time + , buf: { onOff: if switchOO then On else Off, buffer: if switchW then "my-buffer" else "shruti" } + } diff --git a/examples/kitchen-sink/KitchenSink/Types/Highshelf.purs b/examples/kitchen-sink/KitchenSink/Types/Highshelf.purs index 83d5a5c5..3043416c 100644 --- a/examples/kitchen-sink/KitchenSink/Types/Highshelf.purs +++ b/examples/kitchen-sink/KitchenSink/Types/Highshelf.purs @@ -1,13 +1,16 @@ module WAGS.Example.KitchenSink.Types.Highshelf where import Prelude + import Data.Tuple.Nested (type (/\)) import Math ((%)) -import WAGS.Math (calcSlope) +import WAGS.Change (ichange) +import WAGS.Create.Optionals (CHighshelf, CPlayBuf, highshelf, playBuf) +import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Timing (timing, pieceTime) import WAGS.Example.KitchenSink.Types.Empty (TopWith) import WAGS.Graph.AudioUnit (OnOff(..), THighshelf, TPlayBuf) -import WAGS.Graph.Optionals (CHighshelf, CPlayBuf, DGain, DPlayBuf, DHighshelf, highshelf, highshelf_, gain_, playBuf, playBuf_) +import WAGS.Math (calcSlope) type HighshelfGraph = TopWith { highshelf :: Unit } @@ -18,7 +21,7 @@ type HighshelfGraph ksHighshelfCreate :: { highshelf :: CHighshelf { buf :: CPlayBuf } } ksHighshelfCreate = { highshelf: highshelf { freq: 300.0 } { buf: playBuf "my-buffer" } } -deltaKsHighshelf :: Number -> { mix :: DGain, highshelf :: DHighshelf, buf :: DPlayBuf } +deltaKsHighshelf :: forall proof. Number -> IxWAGSig' HighshelfGraph HighshelfGraph proof Unit deltaKsHighshelf = (_ % pieceTime) >>> (_ - timing.ksHighshelf.begin) @@ -29,10 +32,8 @@ deltaKsHighshelf = switchW = time % 4.0 < 2.0 in - { mix: gain_ (if time > (timing.ksHighshelf.dur - 1.0) then 0.0 else 1.0) - , highshelf: highshelf_ { freq: calcSlope 0.0 300.0 timing.ksHighshelf.dur 2000.0 time } - , buf: - playBuf_ - { onOff: if switchOO then On else Off } - (if switchW then "my-buffer" else "shruti") - } + ichange + { mix: if time > timing.ksHighshelf.dur - 1.0 then 0.0 else 1.0 + , highshelf: calcSlope 0.0 300.0 timing.ksHighshelf.dur 2000.0 time + , buf: { onOff: if switchOO then On else Off, buffer: if switchW then "my-buffer" else "shruti" } + } diff --git a/examples/kitchen-sink/KitchenSink/Types/LoopBuf.purs b/examples/kitchen-sink/KitchenSink/Types/LoopBuf.purs index 33b603ce..fe683189 100644 --- a/examples/kitchen-sink/KitchenSink/Types/LoopBuf.purs +++ b/examples/kitchen-sink/KitchenSink/Types/LoopBuf.purs @@ -1,13 +1,14 @@ module WAGS.Example.KitchenSink.Types.LoopBuf where import Prelude - import Data.Tuple.Nested (type (/\)) import Math (pi, sin, (%)) +import WAGS.Change (ichange) +import WAGS.Create.Optionals (CLoopBuf, loopBuf) +import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Timing (pieceTime, timing) import WAGS.Example.KitchenSink.Types.Empty (TopWith) import WAGS.Graph.AudioUnit (OnOff(..), TLoopBuf) -import WAGS.Graph.Optionals (CLoopBuf, DLoopBuf, loopBuf, loopBuf_) type LoopBufGraph = TopWith { loopBuf :: Unit } @@ -15,9 +16,9 @@ type LoopBufGraph ) ksLoopBufCreate :: { loopBuf :: CLoopBuf } -ksLoopBufCreate = { loopBuf: loopBuf { playbackRate: 1.0, start: 1.0, end: 2.5 } "my-buffer" } +ksLoopBufCreate = { loopBuf: loopBuf { playbackRate: 1.0, loopStart: 1.0, loopEnd: 2.5 } "my-buffer" } -deltaKsLoopBuf :: Number -> { loopBuf :: DLoopBuf } +deltaKsLoopBuf :: forall proof. Number -> IxWAGSig' LoopBufGraph LoopBufGraph proof Unit deltaKsLoopBuf = (_ % pieceTime) >>> (_ - timing.ksLoopBuf.begin) @@ -30,12 +31,12 @@ deltaKsLoopBuf = switchW = time % 4.0 < 2.0 in - { loopBuf: - loopBuf_ + ichange + { loopBuf: { onOff: if switchOO then On else Off , playbackRate: 1.0 + (0.1 * sin rad) - , start: 1.0 - , end: 1.4 + 0.2 * (sin rad) + , loopStart: 1.0 + , loopEnd: 1.4 + 0.2 * (sin rad) + , buffer: if switchW then "my-buffer" else "shruti" } - (if switchW then "my-buffer" else "shruti") - } + } diff --git a/examples/kitchen-sink/KitchenSink/Types/Lowpass.purs b/examples/kitchen-sink/KitchenSink/Types/Lowpass.purs index 2fd85492..f58f0b7b 100644 --- a/examples/kitchen-sink/KitchenSink/Types/Lowpass.purs +++ b/examples/kitchen-sink/KitchenSink/Types/Lowpass.purs @@ -3,11 +3,13 @@ module WAGS.Example.KitchenSink.Types.Lowpass where import Prelude import Data.Tuple.Nested (type (/\)) import Math ((%)) -import WAGS.Math (calcSlope) +import WAGS.Change (ichange) +import WAGS.Create.Optionals (CLowpass, CPlayBuf, lowpass, playBuf) +import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Timing (timing, pieceTime) import WAGS.Example.KitchenSink.Types.Empty (TopWith) import WAGS.Graph.AudioUnit (OnOff(..), TLowpass, TPlayBuf) -import WAGS.Graph.Optionals (CLowpass, CPlayBuf, DGain, DPlayBuf, DLowpass, lowpass, lowpass_, gain_, playBuf, playBuf_) +import WAGS.Math (calcSlope) type LowpassGraph = TopWith { lowpass :: Unit } @@ -18,7 +20,7 @@ type LowpassGraph ksLowpassCreate :: { lowpass :: CLowpass { buf :: CPlayBuf } } ksLowpassCreate = { lowpass: lowpass { freq: 300.0 } { buf: playBuf "my-buffer" } } -deltaKsLowpass :: Number -> { mix :: DGain, lowpass :: DLowpass, buf :: DPlayBuf } +deltaKsLowpass :: forall proof. Number -> IxWAGSig' LowpassGraph LowpassGraph proof Unit deltaKsLowpass = (_ % pieceTime) >>> (_ - timing.ksLowpass.begin) @@ -29,10 +31,8 @@ deltaKsLowpass = switchW = time % 4.0 < 2.0 in - { mix: gain_ (if time > (timing.ksLowpass.dur - 1.0) then 0.0 else 1.0) - , lowpass: lowpass_ { freq: calcSlope 0.0 300.0 timing.ksLowpass.dur 2000.0 time } - , buf: - playBuf_ - { onOff: if switchOO then On else Off } - (if switchW then "my-buffer" else "shruti") - } + ichange + { mix: if time > (timing.ksLowpass.dur - 1.0) then 0.0 else 1.0 + , lowpass: calcSlope 0.0 300.0 timing.ksLowpass.dur 2000.0 time + , buf: { onOff: if switchOO then On else Off, buffer: if switchW then "my-buffer" else "shruti" } + } diff --git a/examples/kitchen-sink/KitchenSink/Types/Lowshelf.purs b/examples/kitchen-sink/KitchenSink/Types/Lowshelf.purs index 7bbe2360..f534396e 100644 --- a/examples/kitchen-sink/KitchenSink/Types/Lowshelf.purs +++ b/examples/kitchen-sink/KitchenSink/Types/Lowshelf.purs @@ -3,11 +3,13 @@ module WAGS.Example.KitchenSink.Types.Lowshelf where import Prelude import Data.Tuple.Nested (type (/\)) import Math ((%)) -import WAGS.Math (calcSlope) +import WAGS.Change (ichange) +import WAGS.Create.Optionals (CLowshelf, CPlayBuf, lowshelf, playBuf) +import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Timing (timing, pieceTime) import WAGS.Example.KitchenSink.Types.Empty (TopWith) import WAGS.Graph.AudioUnit (OnOff(..), TLowshelf, TPlayBuf) -import WAGS.Graph.Optionals (CLowshelf, CPlayBuf, DGain, DPlayBuf, DLowshelf, lowshelf, lowshelf_, gain_, playBuf, playBuf_) +import WAGS.Math (calcSlope) type LowshelfGraph = TopWith { lowshelf :: Unit } @@ -18,7 +20,7 @@ type LowshelfGraph ksLowshelfCreate :: { lowshelf :: CLowshelf { buf :: CPlayBuf } } ksLowshelfCreate = { lowshelf: lowshelf { freq: 300.0 } { buf: playBuf "my-buffer" } } -deltaKsLowshelf :: Number -> { mix :: DGain, lowshelf :: DLowshelf, buf :: DPlayBuf } +deltaKsLowshelf :: forall proof. Number -> IxWAGSig' LowshelfGraph LowshelfGraph proof Unit deltaKsLowshelf = (_ % pieceTime) >>> (_ - timing.ksLowshelf.begin) @@ -29,10 +31,8 @@ deltaKsLowshelf = switchW = time % 4.0 < 2.0 in - { mix: gain_ (if time > (timing.ksLowshelf.dur - 1.0) then 0.0 else 1.0) - , lowshelf: lowshelf_ { freq: calcSlope 0.0 300.0 timing.ksLowshelf.dur 2000.0 time } - , buf: - playBuf_ - { onOff: if switchOO then On else Off } - (if switchW then "my-buffer" else "shruti") - } + ichange + { mix: if time > (timing.ksLowshelf.dur - 1.0) then 0.0 else 1.0 + , lowshelf: calcSlope 0.0 300.0 timing.ksLowshelf.dur 2000.0 time + , buf: { onOff: if switchOO then On else Off, buffer: if switchW then "my-buffer" else "shruti" } + } diff --git a/examples/kitchen-sink/KitchenSink/Types/Microphone.purs b/examples/kitchen-sink/KitchenSink/Types/Microphone.purs index ca31e231..bf922a20 100644 --- a/examples/kitchen-sink/KitchenSink/Types/Microphone.purs +++ b/examples/kitchen-sink/KitchenSink/Types/Microphone.purs @@ -1,13 +1,14 @@ module WAGS.Example.KitchenSink.Types.Microphone where import Prelude - import Data.Tuple.Nested (type (/\)) import Math ((%), cos, pi) +import WAGS.Change (ichange) +import WAGS.Create.Optionals (CMicrophone, microphone) +import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Timing (pieceTime, timing) import WAGS.Example.KitchenSink.Types.Empty (TopWith) import WAGS.Graph.AudioUnit (TMicrophone) -import WAGS.Graph.Optionals (CMicrophone, DGain, gain_, microphone) type MicrophoneGraph = TopWith { microphone :: Unit } @@ -17,7 +18,7 @@ type MicrophoneGraph ksMicrophoneCreate :: { microphone :: CMicrophone } ksMicrophoneCreate = { microphone: microphone } -deltaKsMicrophone :: Number -> { mix :: DGain } +deltaKsMicrophone :: forall proof. Number -> IxWAGSig' MicrophoneGraph MicrophoneGraph proof Unit deltaKsMicrophone = (_ % pieceTime) >>> (_ - timing.ksMicrophone.begin) @@ -26,4 +27,4 @@ deltaKsMicrophone = let rad = pi * time in - { mix: gain_ (0.1 - 0.1 * (cos time)) } + ichange { mix: 0.1 - 0.1 * (cos time) } diff --git a/examples/kitchen-sink/KitchenSink/Types/Notch.purs b/examples/kitchen-sink/KitchenSink/Types/Notch.purs index 776f9e75..0193ab82 100644 --- a/examples/kitchen-sink/KitchenSink/Types/Notch.purs +++ b/examples/kitchen-sink/KitchenSink/Types/Notch.purs @@ -3,11 +3,13 @@ module WAGS.Example.KitchenSink.Types.Notch where import Prelude import Data.Tuple.Nested (type (/\)) import Math ((%)) -import WAGS.Math (calcSlope) +import WAGS.Change (ichange) +import WAGS.Create.Optionals (CNotch, CPlayBuf, notch, playBuf) +import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Timing (timing, pieceTime) import WAGS.Example.KitchenSink.Types.Empty (TopWith) import WAGS.Graph.AudioUnit (OnOff(..), TNotch, TPlayBuf) -import WAGS.Graph.Optionals (CNotch, CPlayBuf, DGain, DPlayBuf, DNotch, notch, notch_, gain_, playBuf, playBuf_) +import WAGS.Math (calcSlope) type NotchGraph = TopWith { notch :: Unit } @@ -18,7 +20,7 @@ type NotchGraph ksNotchCreate :: { notch :: CNotch { buf :: CPlayBuf } } ksNotchCreate = { notch: notch { freq: 300.0 } { buf: playBuf "my-buffer" } } -deltaKsNotch :: Number -> { mix :: DGain, notch :: DNotch, buf :: DPlayBuf } +deltaKsNotch :: forall proof. Number -> IxWAGSig' NotchGraph NotchGraph proof Unit deltaKsNotch = (_ % pieceTime) >>> (_ - timing.ksNotch.begin) @@ -29,10 +31,8 @@ deltaKsNotch = switchW = time % 4.0 < 2.0 in - { mix: gain_ (if time > (timing.ksNotch.dur - 1.0) then 0.0 else 1.0) - , notch: notch_ { freq: calcSlope 0.0 300.0 timing.ksNotch.dur 2000.0 time } - , buf: - playBuf_ - { onOff: if switchOO then On else Off } - (if switchW then "my-buffer" else "shruti") - } + ichange + { mix: if time > (timing.ksNotch.dur - 1.0) then 0.0 else 1.0 + , notch: calcSlope 0.0 300.0 timing.ksNotch.dur 2000.0 time + , buf: { onOff: if switchOO then On else Off, buffer: if switchW then "my-buffer" else "shruti" } + } diff --git a/examples/kitchen-sink/KitchenSink/Types/Peaking.purs b/examples/kitchen-sink/KitchenSink/Types/Peaking.purs index 57e2cf17..aafd4823 100644 --- a/examples/kitchen-sink/KitchenSink/Types/Peaking.purs +++ b/examples/kitchen-sink/KitchenSink/Types/Peaking.purs @@ -3,11 +3,13 @@ module WAGS.Example.KitchenSink.Types.Peaking where import Prelude import Data.Tuple.Nested (type (/\)) import Math ((%)) -import WAGS.Math (calcSlope) +import WAGS.Change (ichange) +import WAGS.Create.Optionals (CPeaking, CPlayBuf, peaking, playBuf) +import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Timing (timing, pieceTime) import WAGS.Example.KitchenSink.Types.Empty (TopWith) import WAGS.Graph.AudioUnit (OnOff(..), TPeaking, TPlayBuf) -import WAGS.Graph.Optionals (CPeaking, CPlayBuf, DGain, DPlayBuf, DPeaking, peaking, peaking_, gain_, playBuf, playBuf_) +import WAGS.Math (calcSlope) type PeakingGraph = TopWith { peaking :: Unit } @@ -18,7 +20,7 @@ type PeakingGraph ksPeakingCreate :: { peaking :: CPeaking { buf :: CPlayBuf } } ksPeakingCreate = { peaking: peaking { freq: 300.0 } { buf: playBuf "my-buffer" } } -deltaKsPeaking :: Number -> { mix :: DGain, peaking :: DPeaking, buf :: DPlayBuf } +deltaKsPeaking :: forall proof. Number -> IxWAGSig' PeakingGraph PeakingGraph proof Unit deltaKsPeaking = (_ % pieceTime) >>> (_ - timing.ksPeaking.begin) @@ -29,10 +31,8 @@ deltaKsPeaking = switchW = time % 4.0 < 2.0 in - { mix: gain_ (if time > (timing.ksPeaking.dur - 1.0) then 0.0 else 1.0) - , peaking: peaking_ { freq: calcSlope 0.0 300.0 timing.ksPeaking.dur 2000.0 time } - , buf: - playBuf_ - { onOff: if switchOO then On else Off } - (if switchW then "my-buffer" else "shruti") - } + ichange + { mix: if time > (timing.ksPeaking.dur - 1.0) then 0.0 else 1.0 + , peaking: calcSlope 0.0 300.0 timing.ksPeaking.dur 2000.0 time + , buf: { onOff: if switchOO then On else Off, buffer: if switchW then "my-buffer" else "shruti" } + } diff --git a/examples/kitchen-sink/KitchenSink/Types/PeriodicOsc.purs b/examples/kitchen-sink/KitchenSink/Types/PeriodicOsc.purs index d6e48e71..ea7a5b6e 100644 --- a/examples/kitchen-sink/KitchenSink/Types/PeriodicOsc.purs +++ b/examples/kitchen-sink/KitchenSink/Types/PeriodicOsc.purs @@ -1,7 +1,6 @@ module WAGS.Example.KitchenSink.Types.PeriodicOsc where import Prelude -import Data.Functor.Indexed (ivoid) import Data.Tuple.Nested (type (/\), (/\)) import Data.Vec as V import Data.Vec ((+>)) @@ -11,7 +10,7 @@ import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Timing (pieceTime, timing) import WAGS.Example.KitchenSink.Types.Empty (TopWith) import WAGS.Graph.AudioUnit (OnOff(..), TPeriodicOsc) -import WAGS.Graph.Optionals (CPeriodicOsc, gain_, periodicOsc, periodicOsc_) +import WAGS.Create.Optionals (CPeriodicOsc, periodicOsc) type PeriodicOscGraph = TopWith { periodicOsc :: Unit } @@ -35,18 +34,20 @@ deltaKsPeriodicOsc = switchW = time % 4.0 < 2.0 in if switchW then - ivoid - $ ichange - { mix: gain_ (0.1 - 0.1 * (cos time)) - , periodicOsc: - periodicOsc_ (if switchOO then On else Off) "my-wave" - (440.0 + 50.0 * ((sin (rad * 1.5)) `pow` 2.0)) + ichange + { mix: 0.1 - 0.1 * (cos time) + , periodicOsc: + { waveform: "my-wave" + , onOff: if switchOO then On else Off + , freq: 440.0 + 50.0 * ((sin (rad * 1.5)) `pow` 2.0) } + } else - ivoid - $ ichange - { mix: gain_ (0.1 - 0.1 * (cos time)) - , periodicOsc: - periodicOsc_ (if switchOO then On else Off) ((0.1 +> -0.3 +> -0.5 +> 0.05 +> 0.2 +> V.empty) /\ (-0.05 +> 0.25 +> 0.4 +> -0.2 +> 0.05 +> V.empty)) - (440.0 + 50.0 * ((sin (rad * 1.5)) `pow` 2.0)) + ichange + { mix: 0.1 - 0.1 * (cos time) + , periodicOsc: + { onOff: if switchOO then On else Off + , waveform: (0.1 +> -0.3 +> -0.5 +> 0.05 +> 0.2 +> V.empty) /\ (-0.05 +> 0.25 +> 0.4 +> -0.2 +> 0.05 +> V.empty) + , freq: 440.0 + 50.0 * ((sin (rad * 1.5)) `pow` 2.0) } + } diff --git a/examples/kitchen-sink/KitchenSink/Types/SawtoothOsc.purs b/examples/kitchen-sink/KitchenSink/Types/SawtoothOsc.purs index eba3083b..48edecc7 100644 --- a/examples/kitchen-sink/KitchenSink/Types/SawtoothOsc.purs +++ b/examples/kitchen-sink/KitchenSink/Types/SawtoothOsc.purs @@ -3,18 +3,17 @@ module WAGS.Example.KitchenSink.Types.SawtoothOsc where import Prelude import Control.Applicative.Indexed (ipure) import Control.Monad.Indexed.Qualified as Ix -import Data.Functor.Indexed (ivoid) import Data.Int (toNumber) import Data.List ((..)) import Data.List as L import Data.Tuple.Nested (type (/\)) import Math (cos, pi, pow, sin) import WAGS.Change (ichange) +import WAGS.Create.Optionals (CSawtoothOsc, sawtoothOsc) import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Types.Empty (TopWith) -import WAGS.Graph.AudioUnit (OnOff(..), TSawtoothOsc) -import WAGS.Graph.Optionals (CSawtoothOsc, DGain, DSawtoothOsc, gain_, sawtoothOsc, sawtoothOsc_) -import WAGS.Graph.Parameter (AudioParameterTransition(..), AudioParameter_(..)) +import WAGS.Graph.AudioUnit (TSawtoothOsc) +import WAGS.Graph.Parameter (modTime) type SawtoothOscGraph = TopWith { sawtoothOsc :: Unit } @@ -34,16 +33,15 @@ frontloadSawtoothOsc = go stSpan go L.Nil = ipure unit go (L.Cons a b) = Ix.do - ivoid $ ichange (deltaKsSawtoothOsc a) + deltaKsSawtoothOsc a go b -deltaKsSawtoothOsc :: Number -> { mix :: DGain, sawtoothOsc :: DSawtoothOsc } +deltaKsSawtoothOsc :: forall proof. Number -> IxWAGSig' SawtoothOscGraph SawtoothOscGraph proof Unit deltaKsSawtoothOsc time = let rad = pi * time in - { mix: gain_ (0.1 - 0.1 * (cos time)) - , sawtoothOsc: - sawtoothOsc_ On - $ AudioParameter { param: pure $ 440.0 + 50.0 * ((sin (rad * 1.5)) `pow` 2.0), timeOffset: time, transition: LinearRamp, forceSet: false } - } + ichange + { mix: 0.1 - 0.1 * (cos time) + , sawtoothOsc: modTime (const time) $ pure (440.0 + 50.0 * ((sin (rad * 1.5)) `pow` 2.0)) + } diff --git a/examples/kitchen-sink/KitchenSink/Types/SinOsc.purs b/examples/kitchen-sink/KitchenSink/Types/SinOsc.purs index 11b17e95..029555a3 100644 --- a/examples/kitchen-sink/KitchenSink/Types/SinOsc.purs +++ b/examples/kitchen-sink/KitchenSink/Types/SinOsc.purs @@ -1,23 +1,21 @@ module WAGS.Example.KitchenSink.Types.SinOsc where import Prelude - -import Data.Tuple.Nested (type (/\)) import Math (cos, pi, pow, sin, (%)) +import WAGS.Change (ichange) +import WAGS.Create.Optionals (CSinOsc, sinOsc) +import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Timing (pieceTime, timing) -import WAGS.Example.KitchenSink.Types.Empty (TopWith) -import WAGS.Graph.AudioUnit (OnOff(..), TSinOsc) -import WAGS.Graph.Optionals (CSinOsc, DSinOsc, DGain, gain_, sinOsc, sinOsc_) +import WAGS.Example.KitchenSink.Types.StartGraph (StartGraph) +import WAGS.Graph.AudioUnit (OnOff(..)) type SinOscGraph - = TopWith { sinOsc :: Unit } - ( sinOsc :: TSinOsc /\ {} - ) + = StartGraph ksSinOscCreate :: { sinOsc :: CSinOsc } -ksSinOscCreate = { sinOsc: sinOsc 440.0 } +ksSinOscCreate = { sinOsc: sinOsc 440.0 } -deltaKsSinOsc :: Number -> { mix :: DGain, sinOsc :: DSinOsc } +deltaKsSinOsc :: forall proof. Number -> IxWAGSig' SinOscGraph SinOscGraph proof Unit deltaKsSinOsc = (_ % pieceTime) >>> (_ - timing.ksSinOsc.begin) @@ -30,8 +28,7 @@ deltaKsSinOsc = switchW = time % 4.0 < 2.0 in - { mix: gain_ (0.1 - 0.1 * (cos time)) - , sinOsc: - sinOsc_ (if switchOO then On else Off) - (440.0 + 50.0 * ((sin (rad * 1.5)) `pow` 2.0)) - } + ichange + { mix: 0.1 - 0.1 * (cos time) + , sinOsc: { onOff: if switchOO then On else Off, freq: 440.0 + 50.0 * ((sin (rad * 1.5)) `pow` 2.0) } + } diff --git a/examples/kitchen-sink/KitchenSink/Types/SquareOsc.purs b/examples/kitchen-sink/KitchenSink/Types/SquareOsc.purs index 6869db93..533df3d2 100644 --- a/examples/kitchen-sink/KitchenSink/Types/SquareOsc.purs +++ b/examples/kitchen-sink/KitchenSink/Types/SquareOsc.purs @@ -1,13 +1,14 @@ module WAGS.Example.KitchenSink.Types.SquareOsc where import Prelude - import Data.Tuple.Nested (type (/\)) import Math (cos, pi, pow, sin, (%)) +import WAGS.Change (ichange) +import WAGS.Create.Optionals (CSquareOsc, squareOsc) +import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Timing (pieceTime, timing) import WAGS.Example.KitchenSink.Types.Empty (TopWith) import WAGS.Graph.AudioUnit (OnOff(..), TSquareOsc) -import WAGS.Graph.Optionals (CSquareOsc, DSquareOsc, DGain, gain_, squareOsc, squareOsc_) type SquareOscGraph = TopWith { squareOsc :: Unit } @@ -17,7 +18,7 @@ type SquareOscGraph ksSquareOscCreate :: { squareOsc :: CSquareOsc } ksSquareOscCreate = { squareOsc: squareOsc 220.0 } -deltaKsSquareOsc :: Number -> { mix :: DGain, squareOsc :: DSquareOsc } +deltaKsSquareOsc :: forall proof. Number -> IxWAGSig' SquareOscGraph SquareOscGraph proof Unit deltaKsSquareOsc = (_ % pieceTime) >>> (_ - timing.ksSquareOsc.begin) @@ -30,8 +31,10 @@ deltaKsSquareOsc = switchW = time % 4.0 < 2.0 in - { mix: gain_ (0.1 - 0.1 * (cos time)) - , squareOsc: - squareOsc_ (if switchOO then On else Off) - (220.0 + 50.0 * ((sin (rad * 1.5)) `pow` 2.0)) - } + ichange + { mix: 0.1 - 0.1 * (cos time) + , squareOsc: + { onOff: if switchOO then On else Off + , freq: 220.0 + 50.0 * ((sin (rad * 1.5)) `pow` 2.0) + } + } diff --git a/examples/kitchen-sink/KitchenSink/Types/StartGraph.purs b/examples/kitchen-sink/KitchenSink/Types/StartGraph.purs new file mode 100644 index 00000000..abe21444 --- /dev/null +++ b/examples/kitchen-sink/KitchenSink/Types/StartGraph.purs @@ -0,0 +1,9 @@ +module WAGS.Example.KitchenSink.Types.StartGraph where + +import Prelude +import Data.Tuple.Nested (type (/\)) +import WAGS.Example.KitchenSink.Types.Empty (TopWith) +import WAGS.Graph.AudioUnit (TSinOsc) + +type StartGraph + = TopWith { sinOsc :: Unit } ( sinOsc :: TSinOsc /\ {} ) diff --git a/examples/kitchen-sink/KitchenSink/Types/StereoPanner.purs b/examples/kitchen-sink/KitchenSink/Types/StereoPanner.purs index 2a1db86a..8c775c60 100644 --- a/examples/kitchen-sink/KitchenSink/Types/StereoPanner.purs +++ b/examples/kitchen-sink/KitchenSink/Types/StereoPanner.purs @@ -1,13 +1,14 @@ module WAGS.Example.KitchenSink.Types.StereoPanner where import Prelude - import Data.Tuple.Nested (type (/\)) import Math (sin, (%), pi) +import WAGS.Change (ichange) +import WAGS.Create.Optionals (CStereoPanner, CPlayBuf, pan, playBuf) +import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Timing (timing, pieceTime) import WAGS.Example.KitchenSink.Types.Empty (TopWith) import WAGS.Graph.AudioUnit (OnOff(..), TStereoPanner, TPlayBuf) -import WAGS.Graph.Optionals (CStereoPanner, CPlayBuf, DGain, DPlayBuf, DStereoPanner, pan, pan_, gain_, playBuf, playBuf_) type StereoPannerGraph = TopWith { pan :: Unit } @@ -18,7 +19,7 @@ type StereoPannerGraph ksStereoPannerCreate :: { pan :: CStereoPanner { buf :: CPlayBuf } } ksStereoPannerCreate = { pan: pan 0.0 { buf: playBuf "my-buffer" } } -deltaKsStereoPanner :: Number -> { mix :: DGain, pan :: DStereoPanner, buf :: DPlayBuf } +deltaKsStereoPanner :: forall proof. Number -> IxWAGSig' StereoPannerGraph StereoPannerGraph proof Unit deltaKsStereoPanner = (_ % pieceTime) >>> (_ - timing.ksStereoPanner.begin) @@ -29,10 +30,8 @@ deltaKsStereoPanner = switchW = time % 4.0 < 2.0 in - { mix: gain_ (if time > (timing.ksStereoPanner.dur - 1.0) then 0.0 else 1.0) - , pan: pan_ (sin (time * pi)) - , buf: - playBuf_ - { onOff: if switchOO then On else Off } - (if switchW then "my-buffer" else "shruti") - } + ichange + { mix: if time > (timing.ksStereoPanner.dur - 1.0) then 0.0 else 1.0 + , pan: sin (time * pi) + , buf: { onOff: if switchOO then On else Off, buffer: if switchW then "my-buffer" else "shruti" } + } diff --git a/examples/kitchen-sink/KitchenSink/Types/TriangleOsc.purs b/examples/kitchen-sink/KitchenSink/Types/TriangleOsc.purs index c47b541d..a30514b9 100644 --- a/examples/kitchen-sink/KitchenSink/Types/TriangleOsc.purs +++ b/examples/kitchen-sink/KitchenSink/Types/TriangleOsc.purs @@ -4,10 +4,12 @@ import Prelude import Data.Tuple.Nested (type (/\)) import Math (cos, pi, pow, sin, (%)) import Type.Proxy (Proxy(..)) +import WAGS.Change (ichange) +import WAGS.Create.Optionals (CRecorder, CTriangleOsc, recorder, triangleOsc) +import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Timing (pieceTime, timing) import WAGS.Example.KitchenSink.Types.Empty (TopWith) import WAGS.Graph.AudioUnit (OnOff(..), TRecorder, TTriangleOsc) -import WAGS.Graph.Optionals (CRecorder, CTriangleOsc, DGain, DTriangleOsc, gain_, recorder, triangleOsc, triangleOsc_) type TriangleOscGraph = TopWith { recorder :: Unit } @@ -18,7 +20,7 @@ type TriangleOscGraph ksTriangleOscCreate :: { recorder :: CRecorder "my-recorder" { triangleOsc :: CTriangleOsc } } ksTriangleOscCreate = { recorder: recorder Proxy { triangleOsc: triangleOsc 440.0 } } -deltaKsTriangleOsc :: Number -> { mix :: DGain, triangleOsc :: DTriangleOsc } +deltaKsTriangleOsc :: forall proof. Number -> IxWAGSig' TriangleOscGraph TriangleOscGraph proof Unit deltaKsTriangleOsc = (_ % pieceTime) >>> (_ - timing.ksTriangleOsc.begin) @@ -31,8 +33,10 @@ deltaKsTriangleOsc = switchW = time % 4.0 < 2.0 in - { mix: gain_ (0.1 - 0.1 * (cos time)) - , triangleOsc: - triangleOsc_ (if switchOO then On else Off) - (440.0 + 50.0 * ((sin (rad * 1.5)) `pow` 2.0)) - } + ichange + { mix: 0.1 - 0.1 * (cos time) + , triangleOsc: + { onOff: if switchOO then On else Off + , freq: 440.0 + 50.0 * ((sin (rad * 1.5)) `pow` 2.0) + } + } diff --git a/examples/kitchen-sink/KitchenSink/Types/WaveShaper.purs b/examples/kitchen-sink/KitchenSink/Types/WaveShaper.purs index 8bed08f0..07850060 100644 --- a/examples/kitchen-sink/KitchenSink/Types/WaveShaper.purs +++ b/examples/kitchen-sink/KitchenSink/Types/WaveShaper.purs @@ -4,10 +4,12 @@ import Prelude import Data.Tuple.Nested (type (/\)) import Math ((%)) import Type.Proxy (Proxy(..)) +import WAGS.Change (ichange) +import WAGS.Create.Optionals (CPlayBuf, CWaveShaper, playBuf, waveShaper) +import WAGS.Example.KitchenSink.TLP.LoopSig (IxWAGSig') import WAGS.Example.KitchenSink.Timing (timing, pieceTime) import WAGS.Example.KitchenSink.Types.Empty (TopWith) import WAGS.Graph.AudioUnit (OnOff(..), OversampleTwoX(..), TPlayBuf, TWaveShaper) -import WAGS.Graph.Optionals (CPlayBuf, CWaveShaper, DGain, DPlayBuf, gain_, playBuf, playBuf_, waveShaper) type WaveShaperGraph = TopWith { waveShaper :: Unit } @@ -23,7 +25,7 @@ ksWaveShaperCreate = { buf: playBuf "my-buffer" } } -deltaKsWaveShaper :: Number -> { mix :: DGain, buf :: DPlayBuf } +deltaKsWaveShaper :: forall proof. Number -> IxWAGSig' WaveShaperGraph WaveShaperGraph proof Unit deltaKsWaveShaper = (_ % pieceTime) >>> (_ - timing.ksWaveShaper.begin) @@ -34,9 +36,7 @@ deltaKsWaveShaper = switchW = time % 4.0 < 2.0 in - { mix: gain_ (if time > (timing.ksWaveShaper.dur - 1.0) then 0.0 else 1.0) - , buf: - playBuf_ - { onOff: if switchOO then On else Off } - (if switchW then "my-buffer" else "shruti") - } + ichange + { mix: if time > (timing.ksWaveShaper.dur - 1.0) then 0.0 else 1.0 + , buf: { onOff: if switchOO then On else Off, buffer: if switchW then "my-buffer" else "shruti" } + } diff --git a/examples/makenna/Makenna.purs b/examples/makenna/Makenna.purs index 713d4162..e58a917f 100644 --- a/examples/makenna/Makenna.purs +++ b/examples/makenna/Makenna.purs @@ -30,14 +30,14 @@ import Math (pow) import WAGS.Change (ichange) import WAGS.Control.Functions.Validated (iloop, (@!>)) import WAGS.Control.Indexed (IxFrame) -import WAGS.Math (calcSlope) import WAGS.Control.Types (Frame0, Scene) import WAGS.Create (icreate) +import WAGS.Create.Optionals (CPeriodicOsc, CSpeaker, CGain, gain, periodicOsc, speaker) import WAGS.Graph.AudioUnit (TGain, TPeriodicOsc, TSpeaker) -import WAGS.Graph.Optionals (CPeriodicOsc, CSpeaker, CGain, gain, periodicOsc, speaker) -import WAGS.Graph.Parameter (ff, param) +import WAGS.Graph.Parameter (ff) import WAGS.Interpret (AudioContext, FFIAudio(..), close, context, defaultFFIAudio, makePeriodicWave, makeUnitCache) -import WAGS.Run (SceneI, run) +import WAGS.Math (calcSlope) +import WAGS.Run (RunAudio, SceneI, RunEngine, run) type Note = Number /\ Maybe Number @@ -143,15 +143,14 @@ scene time ({ start, dur } /\ pitch) to = speaker { gain: gain - (ff to $ param (maybe 0.0 (const $ asdr (time - start) dur) pitch)) - { osc: periodicOsc "bday" (ff to $ param (midiToCps (fromMaybe 60.0 pitch))) - } + (ff to $ pure (maybe 0.0 (const $ asdr (time - start) dur) pitch)) + { osc: periodicOsc "bday" (ff to $ pure (midiToCps (fromMaybe 60.0 pitch))) } } -createFrame :: IxFrame (SceneI Unit Unit) FFIAudio (Effect Unit) Frame0 Unit {} SceneType (List EnrichedNote) +createFrame :: IxFrame (SceneI Unit Unit) RunAudio RunEngine Frame0 Unit {} SceneType (List EnrichedNote) createFrame { time } = icreate (scene time (inTempo rest0) 0.0) $> L.fromFoldable score'' -piece :: Scene (SceneI Unit Unit) FFIAudio (Effect Unit) Frame0 Unit +piece :: Scene (SceneI Unit Unit) RunAudio RunEngine Frame0 Unit piece = createFrame @!> iloop \{ time } l -> diff --git a/examples/wtk/WTK/RenderingEnv.purs b/examples/wtk/WTK/RenderingEnv.purs index b1e60377..9a59a5f1 100644 --- a/examples/wtk/WTK/RenderingEnv.purs +++ b/examples/wtk/WTK/RenderingEnv.purs @@ -10,7 +10,6 @@ import Math (pow) import WAGS.Math (calcSlope) import WAGS.Example.WTK.Types (KeyUnit, MakeRenderingEnv) import WAGS.Graph.AudioUnit (OnOff(..)) -import WAGS.Graph.Optionals (defaultGetSetAP) keyDur :: Number keyDur = 1.6 @@ -33,21 +32,21 @@ asdr n | otherwise = 0.0 keyStart :: Number -> KeyUnit -keyStart cps = { gain: defaultGetSetAP 0.0, onOff: On, freq: defaultGetSetAP cps } +keyStart cps = { gain: 0.0, onOff: On, freq: cps } keySustain :: Number -> Number -> Number -> KeyUnit keySustain initialTime cps currentTime = { gain: - defaultGetSetAP (asdr (currentTime - initialTime)) + (asdr (currentTime - initialTime)) , onOff: On - , freq: defaultGetSetAP cps + , freq: cps } keySustainOff :: Number -> Number -> Number -> Number -> KeyUnit -keySustainOff initialTime cps offTime currentTime = { gain: defaultGetSetAP (asdr (currentTime - initialTime) * dampen currentTime offTime), onOff: On, freq: defaultGetSetAP cps } +keySustainOff initialTime cps offTime currentTime = { gain: (asdr (currentTime - initialTime) * dampen currentTime offTime), onOff: On, freq: cps } keyEnd :: Number -> KeyUnit -keyEnd cps = { gain: defaultGetSetAP 0.0, onOff: Off, freq: defaultGetSetAP cps } +keyEnd cps = { gain: 0.0, onOff: Off, freq: cps } midiEventsToOnsets :: List MIDIEvent -> (List Int /\ List Int) midiEventsToOnsets = go Nil Nil diff --git a/examples/wtk/WTK/TLP.purs b/examples/wtk/WTK/TLP.purs index 1292ce07..9db2b973 100644 --- a/examples/wtk/WTK/TLP.purs +++ b/examples/wtk/WTK/TLP.purs @@ -1,21 +1,19 @@ module WAGS.Example.WTK.TLP where import Prelude + import Control.Applicative.Indexed (ipure) import Control.Monad.Indexed.Qualified as Ix -import Data.Functor.Indexed (ivoid) import Data.List (List(..), (:)) import Data.Set as S -import Effect (Effect) import WAGS.Change (ichange) import WAGS.Control.Functions.Validated ((@!>), iloop) import WAGS.Control.Indexed (IxWAG, IxFrame) import WAGS.Control.Types (Frame0, Scene) import WAGS.Create (icreate) import WAGS.Example.WTK.Types (Key(..), KeyInfo, MakeRenderingEnv, Trigger, KlavierType, fullKeyboard) -import WAGS.Graph.Optionals (gain_, sinOsc_) -import WAGS.Interpret (class AudioInterpret, FFIAudio) -import WAGS.Run (SceneI) +import WAGS.Interpret (class AudioInterpret) +import WAGS.Run (RunAudio, SceneI, RunEngine) playKeys :: forall audio engine proof res. @@ -33,104 +31,104 @@ playKeys rec@{ currentTime, notesOff } Nil (a : b) = case a.k of K0 -> Ix.do let { gain, freq, onOff } = if currentTime - a.startT > a.keyDuration then a.endU else a.sustainU currentTime - ivoid $ ichange { k0: gain_ gain, osc0: sinOsc_ onOff freq } + ichange { k0: gain, osc0: { onOff, freq } } playKeys rec Nil b K1 -> Ix.do let { gain, freq, onOff } = if currentTime - a.startT > a.keyDuration then a.endU else a.sustainU currentTime - ivoid $ ichange { k1: gain_ gain, osc1: sinOsc_ onOff freq } + ichange { k1: gain, osc1: { onOff, freq } } playKeys rec Nil b K2 -> Ix.do let { gain, freq, onOff } = if currentTime - a.startT > a.keyDuration then a.endU else a.sustainU currentTime - ivoid $ ichange { k2: gain_ gain, osc2: sinOsc_ onOff freq } + ichange { k2: gain, osc2: { onOff, freq } } playKeys rec Nil b K3 -> Ix.do let { gain, freq, onOff } = if currentTime - a.startT > a.keyDuration then a.endU else a.sustainU currentTime - ivoid $ ichange { k3: gain_ gain, osc3: sinOsc_ onOff freq } + ichange { k3: gain, osc3: { onOff, freq } } playKeys rec Nil b K4 -> Ix.do let { gain, freq, onOff } = if currentTime - a.startT > a.keyDuration then a.endU else a.sustainU currentTime - ivoid $ ichange { k4: gain_ gain, osc4: sinOsc_ onOff freq } + ichange { k4: gain, osc4: { onOff, freq } } playKeys rec Nil b K5 -> Ix.do let { gain, freq, onOff } = if currentTime - a.startT > a.keyDuration then a.endU else a.sustainU currentTime - ivoid $ ichange { k5: gain_ gain, osc5: sinOsc_ onOff freq } + ichange { k5: gain, osc5: { onOff, freq } } playKeys rec Nil b K6 -> Ix.do let { gain, freq, onOff } = if currentTime - a.startT > a.keyDuration then a.endU else a.sustainU currentTime - ivoid $ ichange { k6: gain_ gain, osc6: sinOsc_ onOff freq } + ichange { k6: gain, osc6: { onOff, freq } } playKeys rec Nil b K7 -> Ix.do let { gain, freq, onOff } = if currentTime - a.startT > a.keyDuration then a.endU else a.sustainU currentTime - ivoid $ ichange { k7: gain_ gain, osc7: sinOsc_ onOff freq } + ichange { k7: gain, osc7: { onOff, freq } } playKeys rec Nil b K8 -> Ix.do let { gain, freq, onOff } = if currentTime - a.startT > a.keyDuration then a.endU else a.sustainU currentTime - ivoid $ ichange { k8: gain_ gain, osc8: sinOsc_ onOff freq } + ichange { k8: gain, osc8: { onOff, freq } } playKeys rec Nil b K9 -> Ix.do let { gain, freq, onOff } = if currentTime - a.startT > a.keyDuration then a.endU else a.sustainU currentTime - ivoid $ ichange { k9: gain_ gain, osc9: sinOsc_ onOff freq } + ichange { k9: gain, osc9: { onOff, freq } } playKeys rec Nil b playKeys rec (a : b) currentPlaying = case a.k of K0 -> Ix.do let { gain, freq, onOff } = a.startU - ivoid $ ichange { k0: gain_ gain, osc0: sinOsc_ onOff freq } + ichange { k0: gain, osc0: { onOff, freq } } playKeys rec b currentPlaying K1 -> Ix.do let { gain, freq, onOff } = a.startU - ivoid $ ichange { k1: gain_ gain, osc1: sinOsc_ onOff freq } + ichange { k1: gain, osc1: { onOff, freq } } playKeys rec b currentPlaying K2 -> Ix.do let { gain, freq, onOff } = a.startU - ivoid $ ichange { k2: gain_ gain, osc2: sinOsc_ onOff freq } + ichange { k2: gain, osc2: { onOff, freq } } playKeys rec b currentPlaying K3 -> Ix.do let { gain, freq, onOff } = a.startU - ivoid $ ichange { k3: gain_ gain, osc3: sinOsc_ onOff freq } + ichange { k3: gain, osc3: { onOff, freq } } playKeys rec b currentPlaying K4 -> Ix.do let { gain, freq, onOff } = a.startU - ivoid $ ichange { k4: gain_ gain, osc4: sinOsc_ onOff freq } + ichange { k4: gain, osc4: { onOff, freq } } playKeys rec b currentPlaying K5 -> Ix.do let { gain, freq, onOff } = a.startU - ivoid $ ichange { k5: gain_ gain, osc5: sinOsc_ onOff freq } + ichange { k5: gain, osc5: { onOff, freq } } playKeys rec b currentPlaying K6 -> Ix.do let { gain, freq, onOff } = a.startU - ivoid $ ichange { k6: gain_ gain, osc6: sinOsc_ onOff freq } + ichange { k6: gain, osc6: { onOff, freq } } playKeys rec b currentPlaying K7 -> Ix.do let { gain, freq, onOff } = a.startU - ivoid $ ichange { k7: gain_ gain, osc7: sinOsc_ onOff freq } + ichange { k7: gain, osc7: { onOff, freq } } playKeys rec b currentPlaying K8 -> Ix.do let { gain, freq, onOff } = a.startU - ivoid $ ichange { k8: gain_ gain, osc8: sinOsc_ onOff freq } + ichange { k8: gain, osc8: { onOff, freq } } playKeys rec b currentPlaying K9 -> Ix.do let { gain, freq, onOff } = a.startU - ivoid $ ichange { k9: gain_ gain, osc9: sinOsc_ onOff freq } + ichange { k9: gain, osc9: { onOff, freq } } playKeys rec b currentPlaying type Accumulator @@ -138,14 +136,14 @@ type Accumulator , availableKeys :: List Key } -createFrame :: IxFrame (SceneI Trigger Unit) FFIAudio (Effect Unit) Frame0 Unit {} KlavierType Accumulator +createFrame :: IxFrame (SceneI Trigger Unit) RunAudio RunEngine Frame0 Unit {} KlavierType Accumulator createFrame _ = icreate fullKeyboard $> { currentKeys: Nil , availableKeys: K0 : K1 : K2 : K3 : K4 : K5 : K6 : K7 : K8 : K9 : Nil } -piece :: { makeRenderingEnv :: MakeRenderingEnv } -> Scene (SceneI Trigger Unit) FFIAudio (Effect Unit) Frame0 Unit +piece :: { makeRenderingEnv :: MakeRenderingEnv } -> Scene (SceneI Trigger Unit) RunAudio RunEngine Frame0 Unit piece { makeRenderingEnv } = createFrame @!> iloop \{ time, trigger, active } { currentKeys, availableKeys } -> Ix.do diff --git a/examples/wtk/WTK/Types.purs b/examples/wtk/WTK/Types.purs index 350f99a9..f1a4c684 100644 --- a/examples/wtk/WTK/Types.purs +++ b/examples/wtk/WTK/Types.purs @@ -7,7 +7,7 @@ import Data.Set as S import Data.Tuple.Nested (type (/\)) import FRP.Event.MIDI (MIDIEventInTime) import WAGS.Graph.AudioUnit (OnOff(..), TGain, TSinOsc, TSpeaker) -import WAGS.Graph.Optionals (CGain, CSinOsc, CSpeaker, GetSetAP, gain, sinOsc, speaker) +import WAGS.Create.Optionals (CGain, CSinOsc, CSpeaker, gain, sinOsc, speaker) data Key = K0 @@ -68,16 +68,16 @@ fullKeyboard = speaker { mix: gain 1.0 - { k0: gain 0.0 { osc0: sinOsc Off 440.0 } - , k1: gain 0.0 { osc1: sinOsc Off 440.0 } - , k2: gain 0.0 { osc2: sinOsc Off 440.0 } - , k3: gain 0.0 { osc3: sinOsc Off 440.0 } - , k4: gain 0.0 { osc4: sinOsc Off 440.0 } - , k5: gain 0.0 { osc5: sinOsc Off 440.0 } - , k6: gain 0.0 { osc6: sinOsc Off 440.0 } - , k7: gain 0.0 { osc7: sinOsc Off 440.0 } - , k8: gain 0.0 { osc8: sinOsc Off 440.0 } - , k9: gain 0.0 { osc9: sinOsc Off 440.0 } + { k0: gain 0.0 { osc0: sinOsc { onOff: Off, freq: 440.0 } } + , k1: gain 0.0 { osc1: sinOsc { onOff: Off, freq: 440.0 } } + , k2: gain 0.0 { osc2: sinOsc { onOff: Off, freq: 440.0 } } + , k3: gain 0.0 { osc3: sinOsc { onOff: Off, freq: 440.0 } } + , k4: gain 0.0 { osc4: sinOsc { onOff: Off, freq: 440.0 } } + , k5: gain 0.0 { osc5: sinOsc { onOff: Off, freq: 440.0 } } + , k6: gain 0.0 { osc6: sinOsc { onOff: Off, freq: 440.0 } } + , k7: gain 0.0 { osc7: sinOsc { onOff: Off, freq: 440.0 } } + , k8: gain 0.0 { osc8: sinOsc { onOff: Off, freq: 440.0 } } + , k9: gain 0.0 { osc9: sinOsc { onOff: Off, freq: 440.0 } } } } @@ -85,7 +85,7 @@ type Trigger = List { time :: Instant, value :: MIDIEventInTime } type KeyUnit - = { gain :: GetSetAP, freq :: GetSetAP, onOff :: OnOff } + = { gain :: Number, freq :: Number, onOff :: OnOff } type KeyInfo = { startU :: KeyUnit diff --git a/gen/opt_filt.py b/gen/opt_filt.py index 8b49e367..b22739c7 100644 --- a/gen/opt_filt.py +++ b/gen/opt_filt.py @@ -18,7 +18,7 @@ def ofilt(s,opt): ) default{s} :: {{ | {s}Optional }} -default{s} = {{ {opt}: defaultGetSetAP 1.0 }} +default{s} = {{ {opt}: 1.0 }} class {s}Ctor i {l} | i -> {l} where {l} :: i -> {l} diff --git a/package.json b/package.json index eab72788..49ed043b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "purescript-wags", - "version": "0.2.3", + "version": "0.3.0", "description": "Web Audio Graphs as a Stream", "scripts": { "build": "spago build", diff --git a/src/WAGS/Change.purs b/src/WAGS/Change.purs index 90b876f0..affa24f8 100644 --- a/src/WAGS/Change.purs +++ b/src/WAGS/Change.purs @@ -1,20 +1,16 @@ module WAGS.Change where import Prelude - import Control.Comonad (extract) -import Data.Either (Either(..)) -import Data.Functor (voidRight) -import Data.Map as M -import Data.Maybe (Maybe(..)) +import Data.Maybe (Maybe(..), maybe) import Data.Symbol (class IsSymbol, reflectSymbol) -import Data.Tuple (Tuple, snd) import Data.Tuple.Nested ((/\), type (/\)) import Data.Vec as V import Heterogeneous.Folding (class FoldingWithIndex, class HFoldlWithIndex, hfoldlWithIndex) -import Partial.Unsafe (unsafePartial) import Prim.Row as R +import Prim.RowList as RL import Record as Record +import Type.Proxy (Proxy(..)) import WAGS.Control.Indexed (IxWAG(..)) import WAGS.Control.Types (WAG, unsafeUnWAG, unsafeWAG) import WAGS.Edgeable (class Edgeable, withEdge) @@ -22,59 +18,82 @@ import WAGS.Graph.AudioUnit (OnOff(..)) import WAGS.Graph.AudioUnit as CTOR import WAGS.Graph.Graph (Graph) import WAGS.Graph.Node (NodeC) -import WAGS.Graph.Parameter (AudioParameter_(..), AudioParameter, defaultParam, param) +import WAGS.Graph.Parameter (class MM, class Paramable, AudioParameter, AudioParameter_, mm, paramize) import WAGS.Interpret (class AudioInterpret, setAttack, setBuffer, setBufferOffset, setDelay, setFrequency, setGain, setKnee, setLoopEnd, setLoopStart, setOff, setOffset, setOn, setPan, setPeriodicOsc, setPeriodicOscV, setPlaybackRate, setQ, setRatio, setRelease, setThreshold) -import WAGS.Rendered (AnAudioUnit(..)) -import WAGS.Util (tmap) -type ChangeType (ptr :: Symbol) (a :: Type) (graph :: Graph) (b :: Type) +apure = pure :: forall a. a -> AudioParameter_ a + +type Change'Type (ptr :: Symbol) (a :: Type) (graph :: Graph) = forall proxy audio engine proof res. AudioInterpret audio engine => proxy ptr -> WAG audio engine proof res { | graph } a -> - WAG audio engine proof res { | graph } b + WAG audio engine proof res { | graph } Unit -- | Change an audio unit `node` in `igraph` with index `ptr`, outputting the changed node. -class Change' (ptr :: Symbol) (a :: Type) (graph :: Graph) (b :: Type) | ptr a graph -> b where - change' :: ChangeType ptr a graph b - -ichange' :: - forall proxy ptr a audio engine proof res i b. - AudioInterpret audio engine => - Change' ptr a i b => - proxy ptr -> - a -> - IxWAG audio engine proof res { | i } { | i } b -ichange' ptr a = IxWAG (change' ptr <<< voidRight a) +class Change' (ptr :: Symbol) (a :: Type) (graph :: Graph) where + change' :: Change'Type ptr a graph --- | A term that can be coerced to an setter for a control-rate audio parameter. -class SetterVal a where - setterVal :: a -> AudioParameter -> AudioParameter +type CanBeChangedType (sym :: Symbol) (val :: Type) (ptr :: Symbol) (graph :: Graph) + = forall proxy audio engine proof res. + AudioInterpret audio engine => + proxy sym -> + val -> + proxy ptr -> + WAG audio engine proof res { | graph } Unit -> + WAG audio engine proof res { | graph } Unit -instance setterValNumber :: SetterVal Number where - setterVal = const <<< AudioParameter <<< defaultParam { param = _ } <<< Just +class CanBeChanged (sym :: Symbol) (val :: Type) (ptr :: Symbol) (graph :: Graph) where + canBeChanged :: CanBeChangedType sym val ptr graph -instance setterValAudioParameter :: SetterVal AudioParameter where - setterVal = const +type Change''Type (rl :: RL.RowList Type) (ptr :: Symbol) (a :: Row Type) (graph :: Graph) + = forall proxyA proxyB audio engine proof res. + AudioInterpret audio engine => + proxyA rl -> + proxyB ptr -> + WAG audio engine proof res { | graph } { | a } -> + WAG audio engine proof res { | graph } Unit -instance setterValTuple :: SetterVal (Tuple a (AudioParameter -> AudioParameter)) where - setterVal = snd +-- | Change an audio unit `node` in `igraph` with index `ptr`, outputting the changed node. +class Change'' (rl :: RL.RowList Type) (ptr :: Symbol) (a :: Row Type) (graph :: Graph) where + change'' :: Change''Type rl ptr a graph + +instance change''Nil :: Change'' RL.Nil ptr a graph where + change'' _ _ = (<$) unit + +instance change''Cons :: + ( IsSymbol sym + , IsSymbol ptr + , R.Cons sym val ignore a + , CanBeChanged sym val ptr graph + , Change'' rest ptr a graph + ) => + Change'' (RL.Cons sym val rest) ptr a graph where + change'' px a w = + let + psym = Proxy :: _ sym -instance setterValTupleN :: SetterVal (Tuple a (AudioParameter -> Number)) where - setterVal = map param <<< snd + ew = extract w -instance setterValFunction :: SetterVal (AudioParameter -> AudioParameter) where - setterVal = identity + res = canBeChanged psym (Record.get psym ew) (Proxy :: _ ptr) (w $> unit) + in + change'' (Proxy :: _ rest) a (res $> ew) -instance setterValFunctionN :: SetterVal (AudioParameter -> Number) where - setterVal = map param +ichange' :: + forall proxy ptr a audio engine proof res i. + AudioInterpret audio engine => + Change' ptr a i => + proxy ptr -> + a -> + IxWAG audio engine proof res { | i } { | i } Unit +ichange' ptr a = IxWAG (change' ptr <<< (<$) a) data ChangeFoldingWithIndex = ChangeFoldingWithIndex instance changeFoldingWithIndexUnit :: ( AudioInterpret audio engine - , Change' sym Unit inGraph Unit + , Change' sym Unit inGraph ) => FoldingWithIndex ChangeFoldingWithIndex @@ -94,16 +113,13 @@ instance changeFoldingWithIndexUnit :: proof res { | inGraph } - { | inRecord } + Unit ) where - foldingWithIndex ChangeFoldingWithIndex _ ifr node = ifr + foldingWithIndex ChangeFoldingWithIndex _ ifr node = ifr $> unit else instance changeFoldingWithIndex :: ( AudioInterpret audio engine - , Edgeable node' (Tuple node edges) - , Change' sym node inGraph outNode - , IsSymbol sym - , R.Lacks sym inRecord - , R.Cons sym outNode inRecord midRecord + , Edgeable node' (node /\ edges) + , Change' sym node inGraph , HFoldlWithIndex ChangeFoldingWithIndex ( WAG @@ -112,7 +128,7 @@ else instance changeFoldingWithIndex :: proof res { | inGraph } - { | midRecord } + Unit ) edges ( WAG @@ -121,7 +137,7 @@ else instance changeFoldingWithIndex :: proof res { | inGraph } - { | outRecord } + Unit ) ) => FoldingWithIndex @@ -133,7 +149,7 @@ else instance changeFoldingWithIndex :: proof res { | inGraph } - { | inRecord } + Unit ) node' ( WAG @@ -142,7 +158,7 @@ else instance changeFoldingWithIndex :: proof res { | inGraph } - { | outRecord } + Unit ) where foldingWithIndex ChangeFoldingWithIndex prop ifr node' = let @@ -152,12 +168,12 @@ else instance changeFoldingWithIndex :: in hfoldlWithIndex ChangeFoldingWithIndex - (res $> (Record.insert prop (extract res) (extract ifr))) + (res $> unit) edges -- | Similar to `change'`, but accepts a record with multiple units to change. change :: - forall r rr audio engine proof res inGraph. + forall r audio engine proof res inGraph. AudioInterpret audio engine => HFoldlWithIndex ChangeFoldingWithIndex @@ -167,7 +183,7 @@ change :: proof res { | inGraph } - {} + Unit ) { | r } ( WAG @@ -176,7 +192,7 @@ change :: proof res { | inGraph } - rr + Unit ) => WAG audio @@ -191,15 +207,15 @@ change :: proof res { | inGraph } - rr + Unit change r = hfoldlWithIndex ChangeFoldingWithIndex - (r $> {}) + (r $> unit) (extract r) ichange :: - forall r rr audio engine proof res inGraph. + forall r audio engine proof res inGraph. AudioInterpret audio engine => HFoldlWithIndex ChangeFoldingWithIndex @@ -209,7 +225,7 @@ ichange :: proof res { | inGraph } - {} + Unit ) { | r } ( WAG @@ -218,7 +234,7 @@ ichange :: proof res { | inGraph } - rr + Unit ) => { | r } -> IxWAG @@ -228,913 +244,1470 @@ ichange :: res { | inGraph } { | inGraph } - rr -ichange r = IxWAG (change <<< voidRight r) + Unit +ichange r = IxWAG (change <<< (<$) r) + +class PushOnOffToEnd (i :: RL.RowList Type) (o :: RL.RowList Type) | i -> o + +instance pushOnOffToEndNil :: PushOnOffToEnd RL.Nil RL.Nil +else instance pushOnOffToEndOO :: PushOnOffToEnd (RL.Cons "onOff" a RL.Nil) (RL.Cons "onOff" a RL.Nil) +else instance pushOnOffToEndOOC :: PushOnOffToEnd (RL.Cons x y (RL.Cons "onOff" a z)) o => PushOnOffToEnd (RL.Cons "onOff" a (RL.Cons x y z)) o +else instance pushOnOffToEndRest :: PushOnOffToEnd c o => PushOnOffToEnd (RL.Cons a b c) (RL.Cons a b o) + +class Detup (a :: Type) (b :: Type) | a -> b + +instance detupT :: Detup (a /\ b) a +else instance detupOther :: Detup a a + +class + Monoid tau <= OneShotChange tau p au | tau p -> au where + oneShotChange :: tau -> p -> au + +instance changeNumber :: + (Change' ptr AudioParameter graph) => + Change' + ptr + Number + graph where + change' px w = change' px (map apure w) + +instance changeAudioParameter :: + ( R.Cons ptr tau' ignore graph + , Detup tau' tau + , Monoid tau + , OneShotChange tau AudioParameter au + , Change' ptr au graph + ) => + Change' + ptr + AudioParameter + graph where + change' px w = change' px (oneShotChange (mempty :: tau) <$> w) + +instance changeOO :: + ( R.Cons ptr tau' ignore graph + , Detup tau' tau + , Monoid tau + , OneShotChange tau OnOff au + , Change' ptr au graph + ) => + Change' + ptr + OnOff + graph where + change' px w = change' px (oneShotChange (mempty :: tau) <$> w) + +instance changeString :: + ( R.Cons ptr tau' ignore graph + , Detup tau' tau + , Monoid tau + , OneShotChange tau String au + , Change' ptr au graph + ) => + Change' + ptr + String + graph where + change' px w = change' px (oneShotChange (mempty :: tau) <$> w) + +instance changeVec :: + ( R.Cons ptr tau' ignore graph + , Detup tau' tau + , Monoid tau + , OneShotChange tau (V.Vec size Number /\ V.Vec size Number) au + , Change' ptr au graph + ) => + Change' + ptr + (V.Vec size Number /\ V.Vec size Number) + graph where + change' px w = change' px (oneShotChange (mempty :: tau) <$> w) + +instance changeRec :: + (RL.RowToList r rl', PushOnOffToEnd rl' rl, Change'' rl ptr r graph) => + Change' + ptr + { | r } + graph where + change' px w = change'' (Proxy :: _ rl) px w instance changeUnit :: Change' ptr Unit - graphi - Unit where + graph where change' _ w = w $> unit -instance changeAllpass :: +class Freqable (tau :: Type) + +instance freqableAllpass :: Freqable CTOR.TAllpass + +instance freqableBandpass :: Freqable CTOR.TBandpass + +instance freqableNotch :: Freqable CTOR.TNotch + +instance freqablePeaking :: Freqable CTOR.TPeaking + +instance freqableHighshelf :: Freqable CTOR.THighshelf + +instance freqableLowshelf :: Freqable CTOR.TLowshelf + +instance freqableHighpass :: Freqable CTOR.THighpass + +instance freqableLowpass :: Freqable CTOR.TLowpass + +instance freqableSinOsc :: Freqable CTOR.TSinOsc + +instance freqableSawtoothOsc :: Freqable CTOR.TSawtoothOsc + +instance freqableSquareOsc :: Freqable CTOR.TSquareOsc + +instance freqablePeriodicOsc :: Freqable CTOR.TPeriodicOsc + +instance freqableTriangleOsc :: Freqable CTOR.TTriangleOsc + +instance canBeChangedFreqN :: + (CanBeChanged "freq" AudioParameter ptr graph) => + CanBeChanged "freq" Number ptr graph where + canBeChanged sym val ptr w = canBeChanged sym (apure val) ptr w + +instance canBeChangedFreq :: ( IsSymbol ptr - , SetterVal argA - , SetterVal argB - , R.Cons ptr (NodeC CTOR.TAllpass edges) ignore graphi + , R.Cons ptr tau' ignore graph + , Detup tau' tau + , Freqable tau ) => - Change' ptr (CTOR.Allpass argA argB) graphi (CTOR.Allpass AudioParameter AudioParameter) where - change' ptr w = o + CanBeChanged "freq" AudioParameter ptr graph where + canBeChanged sym val ptr w = o where - { context: i, value: (CTOR.Allpass argA argB) } = unsafeUnWAG w + { context: i } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes + argA_Changes = [ setFrequency nn val ] + + o = + unsafeWAG + { context: + i + { instructions = i.instructions <> argA_Changes + } + , value: unit + } + +class OnOffable (tau :: Type) - partial :: Partial => Maybe AnAudioUnit -> Tuple AudioParameter AudioParameter - partial (Just (AAllpass a b)) = a /\ b +instance onOffableConstant :: OnOffable CTOR.TConstant - v_argA@(AudioParameter v_argA') /\ v_argB@(AudioParameter v_argB') = unsafePartial $ partial lookup +instance onOffablePlayBuf :: OnOffable CTOR.TPlayBuf - s_argA = setterVal argA +instance onOffableLoopBuf :: OnOffable CTOR.TLoopBuf - argA_iv' = s_argA v_argA +instance onOffableSinOsc :: OnOffable CTOR.TSinOsc - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet then [] else [ setFrequency nn argA_iv' ] +instance onOffableSawtoothOsc :: OnOffable CTOR.TSawtoothOsc - s_argB = setterVal argB +instance onOffableSquareOsc :: OnOffable CTOR.TSquareOsc + +instance onOffablePeriodicOsc :: OnOffable CTOR.TPeriodicOsc + +instance onOffableTriangleOsc :: OnOffable CTOR.TTriangleOsc + +instance canBeChangedOnOff :: + ( IsSymbol ptr + , R.Cons ptr tau' ignore graph + , Detup tau' tau + , OnOffable tau + ) => + CanBeChanged "onOff" OnOff ptr graph where + canBeChanged sym val ptr w = o + where + { context: i } = unsafeUnWAG w - argB_iv' = s_argB v_argB + nn = reflectSymbol ptr - argB_Changes = let AudioParameter argB_iv = argB_iv' in if argB_iv.param == v_argB'.param && not argB_iv.forceSet then [] else [ setQ nn argB_iv' ] + argA_Changes = [ (if val == On then setOn else setOff) nn ] o = unsafeWAG { context: i - { internalNodes = (M.insert nn (AAllpass argA_iv' argB_iv') i.internalNodes) - , instructions = i.instructions <> (argA_Changes <> argB_Changes) + { instructions = i.instructions <> argA_Changes } - , value: CTOR.Allpass argA_iv' argB_iv' + , value: unit } -instance changeBandpass :: +class Qable (tau :: Type) + +instance qableAllpass :: Qable CTOR.TAllpass + +instance qableBandpass :: Qable CTOR.TBandpass + +instance qableNotch :: Qable CTOR.TNotch + +instance qablePeaking :: Qable CTOR.TPeaking + +instance qableHighpass :: Qable CTOR.THighpass + +instance qableLowpass :: Qable CTOR.TLowpass + +instance canBeChangedQN :: + (CanBeChanged "q" AudioParameter ptr graph) => + CanBeChanged "q" Number ptr graph where + canBeChanged sym val ptr w = canBeChanged sym (apure val) ptr w + +instance canBeChangedQ :: ( IsSymbol ptr - , SetterVal argA - , SetterVal argB - , R.Cons ptr (NodeC CTOR.TBandpass edges) ignore graphi + , R.Cons ptr tau' ignore graph + , Detup tau' tau + , Qable tau ) => - Change' ptr (CTOR.Bandpass argA argB) graphi (CTOR.Bandpass AudioParameter AudioParameter) where - change' ptr w = o + CanBeChanged "q" AudioParameter ptr graph where + canBeChanged sym val ptr w = o where - { context: i, value: (CTOR.Bandpass argA argB) } = unsafeUnWAG w + { context: i } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes + argA_Changes = [ setQ nn val ] + + o = + unsafeWAG + { context: + i + { instructions = i.instructions <> argA_Changes + } + , value: unit + } - partial :: Partial => Maybe AnAudioUnit -> Tuple AudioParameter AudioParameter - partial (Just (ABandpass a b)) = a /\ b +class Gainable (tau :: Type) - v_argA@(AudioParameter v_argA') /\ v_argB@(AudioParameter v_argB') = unsafePartial $ partial lookup +instance gainablePeaking :: Gainable CTOR.TPeaking - s_argA = setterVal argA +instance gainableHighshelf :: Gainable CTOR.THighshelf - argA_iv' = s_argA v_argA +instance gainableLowshelf :: Gainable CTOR.TLowshelf - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet then [] else [ setFrequency nn argA_iv' ] +instance canBeChangedGainN :: + (CanBeChanged "gain" AudioParameter ptr graph) => + CanBeChanged "gain" Number ptr graph where + canBeChanged sym val ptr w = canBeChanged sym (apure val) ptr w - s_argB = setterVal argB +instance canBeChangedGain :: + ( IsSymbol ptr + , R.Cons ptr tau' ignore graph + , Detup tau' tau + , Gainable tau + ) => + CanBeChanged "gain" AudioParameter ptr graph where + canBeChanged sym val ptr w = o + where + { context: i } = unsafeUnWAG w - argB_iv' = s_argB v_argB + nn = reflectSymbol ptr - argB_Changes = let AudioParameter argB_iv = argB_iv' in if argB_iv.param == v_argB'.param && not argB_iv.forceSet then [] else [ setQ nn argB_iv' ] + argA_Changes = [ setGain nn val ] o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ABandpass argA_iv' argB_iv') i.internalNodes) - , instructions = i.instructions <> (argA_Changes <> argB_Changes) + { instructions = i.instructions <> argA_Changes } - , value: CTOR.Bandpass argA_iv' argB_iv' + , value: unit } -instance changeConstant :: +class Offsetable (tau :: Type) + +instance offsetableConstant :: Offsetable CTOR.TConstant + +instance canBeChangedOffsetN :: + (CanBeChanged "offset" AudioParameter ptr graph) => + CanBeChanged "offset" Number ptr graph where + canBeChanged sym val ptr w = canBeChanged sym (apure val) ptr w + +instance canBeChangedOffset :: ( IsSymbol ptr - , SetterVal argA - , R.Cons ptr (NodeC CTOR.TConstant edges) ignore graphi + , R.Cons ptr tau' ignore graph + , Detup tau' tau + , Offsetable tau ) => - Change' ptr (CTOR.Constant argA) graphi (CTOR.Constant AudioParameter) where - change' ptr w = o + CanBeChanged "offset" AudioParameter ptr graph where + canBeChanged sym val ptr w = o where - { context: i, value: (CTOR.Constant onOff argA) } = unsafeUnWAG w + { context: i } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes + argA_Changes = [ setOffset nn val ] - partial :: Partial => Maybe AnAudioUnit -> Tuple OnOff AudioParameter - partial (Just (AConstant a b)) = a /\ b + o = + unsafeWAG + { context: + i + { instructions = i.instructions <> argA_Changes + } + , value: unit + } - oldOnOff /\ v_argA@(AudioParameter v_argA') = unsafePartial $ partial lookup +class LoopStartable (tau :: Type) - onOffDiff = oldOnOff /= onOff +instance loopStartableLoopBuf :: LoopStartable CTOR.TLoopBuf - s_argA = setterVal argA +instance canBeChangedLoopStart :: + ( IsSymbol ptr + , R.Cons ptr tau' ignore graph + , Detup tau' tau + , LoopStartable tau + ) => + CanBeChanged "loopStart" Number ptr graph where + canBeChanged sym val ptr w = o + where + { context: i } = unsafeUnWAG w - argA_iv' = s_argA v_argA + nn = reflectSymbol ptr - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet then [] else [ setOffset nn argA_iv' ] + argA_Changes = [ setLoopStart nn val ] o = unsafeWAG { context: i - { internalNodes = (M.insert nn (AConstant onOff argA_iv') i.internalNodes) - , instructions = i.instructions <> (argA_Changes <> (if onOffDiff then [ (if onOff == On then setOn else setOff) nn ] else [])) + { instructions = i.instructions <> argA_Changes } - , value: CTOR.Constant onOff argA_iv' + , value: unit } -instance changeDelay :: +class LoopEndable (tau :: Type) + +instance loopEndableLoopBuf :: LoopEndable CTOR.TLoopBuf + +instance canBeChangedLoopEnd :: ( IsSymbol ptr - , SetterVal argA - , R.Cons ptr (NodeC CTOR.TDelay edges) ignore graphi + , R.Cons ptr tau' ignore graph + , Detup tau' tau + , LoopEndable tau ) => - Change' ptr (CTOR.Delay argA) graphi (CTOR.Delay AudioParameter) where - change' ptr w = o + CanBeChanged "loopEnd" Number ptr graph where + canBeChanged sym val ptr w = o where - { context: i, value: (CTOR.Delay argA) } = unsafeUnWAG w + { context: i } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes + argA_Changes = [ setLoopEnd nn val ] - partial :: Partial => Maybe AnAudioUnit -> AudioParameter - partial (Just (ADelay a)) = a + o = + unsafeWAG + { context: + i + { instructions = i.instructions <> argA_Changes + } + , value: unit + } + +class BufferOffsetable (tau :: Type) - v_argA@(AudioParameter v_argA') = unsafePartial $ partial lookup +instance bufferOffsetableLoopBuf :: BufferOffsetable CTOR.TLoopBuf - s_argA = setterVal argA +instance canBeChangedBufferOffset :: + ( IsSymbol ptr + , R.Cons ptr tau' ignore graph + , Detup tau' tau + , BufferOffsetable tau + ) => + CanBeChanged "bufferOffset" Number ptr graph where + canBeChanged sym val ptr w = o + where + { context: i } = unsafeUnWAG w - argA_iv' = s_argA v_argA + nn = reflectSymbol ptr - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet then [] else [ setDelay nn argA_iv' ] + argA_Changes = [ setBufferOffset nn val ] o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ADelay argA_iv') i.internalNodes) - , instructions = i.instructions <> argA_Changes + { instructions = i.instructions <> argA_Changes } - , value: CTOR.Delay argA_iv' + , value: unit } -instance changeDynamicsCompressor :: +class PlaybackRateable (tau :: Type) + +instance playbackRateableLoopBuf :: PlaybackRateable CTOR.TLoopBuf + +instance playbackRateablePlayBuf :: PlaybackRateable CTOR.TPlayBuf + +instance canBeChangedPlaybackRateN :: + (CanBeChanged "playbackRate" AudioParameter ptr graph) => + CanBeChanged "playbackRate" Number ptr graph where + canBeChanged sym val ptr w = canBeChanged sym ((pure :: forall a. a -> AudioParameter_ a) val) ptr w + +instance canBeChangedPlaybackRate :: ( IsSymbol ptr - , SetterVal argA - , SetterVal argB - , SetterVal argC - , SetterVal argD - , SetterVal argE - , R.Cons ptr (NodeC CTOR.TDynamicsCompressor edges) ignore graphi + , R.Cons ptr tau' ignore graph + , Detup tau' tau + , PlaybackRateable tau ) => - Change' ptr (CTOR.DynamicsCompressor argA argB argC argD argE) graphi (CTOR.DynamicsCompressor AudioParameter AudioParameter AudioParameter AudioParameter AudioParameter) where - change' ptr w = o + CanBeChanged "playbackRate" AudioParameter ptr graph where + canBeChanged sym val ptr w = o where - { context: i, value: (CTOR.DynamicsCompressor argA argB argC argD argE) } = unsafeUnWAG w + { context: i } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes + argA_Changes = [ setPlaybackRate nn val ] - partial :: Partial => Maybe AnAudioUnit -> AudioParameter /\ AudioParameter /\ AudioParameter /\ AudioParameter /\ AudioParameter - partial (Just (ADynamicsCompressor a b c d e)) = a /\ b /\ c /\ d /\ e + o = + unsafeWAG + { context: + i + { instructions = i.instructions <> argA_Changes + } + , value: unit + } - v_argA@(AudioParameter v_argA') /\ v_argB@(AudioParameter v_argB') /\ v_argC@(AudioParameter v_argC') /\ v_argD@(AudioParameter v_argD') /\ v_argE@(AudioParameter v_argE') = unsafePartial $ partial lookup +class Bufferable (tau :: Type) - s_argA = setterVal argA +instance bufferableLoopBuf :: Bufferable CTOR.TLoopBuf - argA_iv' = s_argA v_argA +instance bufferablePlayBuf :: Bufferable CTOR.TPlayBuf - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet then [] else [ setThreshold nn argA_iv' ] +instance canBeChangedBuffer :: + ( IsSymbol ptr + , R.Cons ptr tau' ignore graph + , Detup tau' tau + , Bufferable tau + ) => + CanBeChanged "buffer" String ptr graph where + canBeChanged sym val ptr w = o + where + { context: i } = unsafeUnWAG w - s_argB = setterVal argB + nn = reflectSymbol ptr - argB_iv' = s_argB v_argB + argA_Changes = [ setBuffer nn val ] - argB_Changes = let AudioParameter argB_iv = argB_iv' in if argB_iv.param == v_argB'.param && not argB_iv.forceSet then [] else [ setKnee nn argB_iv' ] + o = + unsafeWAG + { context: + i + { instructions = i.instructions <> argA_Changes + } + , value: unit + } - s_argC = setterVal argC +class Waveformable (tau :: Type) - argC_iv' = s_argC v_argC +instance waveformablePeriodicOsc :: Waveformable CTOR.TPeriodicOsc - argC_Changes = let AudioParameter argC_iv = argC_iv' in if argC_iv.param == v_argC'.param && not argC_iv.forceSet then [] else [ setRatio nn argC_iv' ] +instance canBeChangedWaveform :: + ( IsSymbol ptr + , R.Cons ptr tau' ignore graph + , Detup tau' tau + , Waveformable tau + ) => + CanBeChanged "waveform" String ptr graph where + canBeChanged sym val ptr w = o + where + { context: i } = unsafeUnWAG w - s_argD = setterVal argD + nn = reflectSymbol ptr - argD_iv' = s_argD v_argD + argA_Changes = [ setPeriodicOsc nn val ] - argD_Changes = let AudioParameter argD_iv = argD_iv' in if argD_iv.param == v_argD'.param && not argD_iv.forceSet then [] else [ setAttack nn argD_iv' ] + o = + unsafeWAG + { context: + i + { instructions = i.instructions <> argA_Changes + } + , value: unit + } - s_argE = setterVal argE +instance canBeChangedWaveformV :: + ( IsSymbol ptr + , R.Cons ptr tau' ignore graph + , Detup tau' tau + , Waveformable tau + ) => + CanBeChanged "waveform" (V.Vec size Number /\ V.Vec size Number) ptr graph where + canBeChanged sym val ptr w = o + where + { context: i } = unsafeUnWAG w - argE_iv' = s_argE v_argE + nn = reflectSymbol ptr - argE_Changes = let AudioParameter argE_iv = argE_iv' in if argE_iv.param == v_argE'.param && not argE_iv.forceSet then [] else [ setRelease nn argE_iv' ] + argA_Changes = [ setPeriodicOscV nn val ] o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ADynamicsCompressor argA_iv' argB_iv' argC_iv' argD_iv' argE_iv') i.internalNodes) - , instructions = i.instructions <> (argA_Changes <> argB_Changes <> argC_Changes <> argD_Changes <> argE_Changes) + { instructions = i.instructions <> argA_Changes } - , value: - CTOR.DynamicsCompressor argA_iv' argB_iv' argC_iv' argD_iv' argE_iv' + , value: unit } -instance changeGain :: +class Thresholdable (tau :: Type) + +instance thresholdableDynamicsCompressor :: Thresholdable CTOR.TDynamicsCompressor + +instance canBeChangedThresholdN :: + (CanBeChanged "threshold" AudioParameter ptr graph) => + CanBeChanged "threshold" Number ptr graph where + canBeChanged sym val ptr w = canBeChanged sym (apure val) ptr w + +instance canBeChangedThreshold :: ( IsSymbol ptr - , SetterVal argA - , R.Cons ptr (NodeC CTOR.TGain edges) ignore graphi + , R.Cons ptr tau' ignore graph + , Detup tau' tau + , Thresholdable tau ) => - Change' ptr (CTOR.Gain argA) graphi (CTOR.Gain AudioParameter) where - change' ptr w = o + CanBeChanged "threshold" AudioParameter ptr graph where + canBeChanged sym val ptr w = o where - { context: i, value: (CTOR.Gain argA) } = unsafeUnWAG w + { context: i } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes + argA_Changes = [ setThreshold nn val ] + + o = + unsafeWAG + { context: + i + { instructions = i.instructions <> argA_Changes + } + , value: unit + } + +class Ratioable (tau :: Type) - partial :: Partial => Maybe AnAudioUnit -> AudioParameter - partial (Just (AGain a)) = a +instance ratioableDynamicsCompressor :: Ratioable CTOR.TDynamicsCompressor - v_argA@(AudioParameter v_argA') = unsafePartial $ partial lookup +instance canBeChangedRatioN :: + (CanBeChanged "ratio" AudioParameter ptr graph) => + CanBeChanged "ratio" Number ptr graph where + canBeChanged sym val ptr w = canBeChanged sym (apure val) ptr w - s_argA = setterVal argA +instance canBeChangedRatio :: + ( IsSymbol ptr + , R.Cons ptr tau' ignore graph + , Detup tau' tau + , Ratioable tau + ) => + CanBeChanged "ratio" AudioParameter ptr graph where + canBeChanged sym val ptr w = o + where + { context: i } = unsafeUnWAG w - argA_iv' = s_argA v_argA + nn = reflectSymbol ptr - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet then [] else [ setGain nn argA_iv' ] + argA_Changes = [ setRatio nn val ] o = unsafeWAG { context: i - { internalNodes = (M.insert nn (AGain argA_iv') i.internalNodes) - , instructions = i.instructions <> argA_Changes + { instructions = i.instructions <> argA_Changes } - , value: CTOR.Gain argA_iv' + , value: unit } -instance changeHighpass :: +class Kneeable (tau :: Type) + +instance kneeableDynamicsCompressor :: Kneeable CTOR.TDynamicsCompressor + +instance canBeChangedKneeN :: + (CanBeChanged "knee" AudioParameter ptr graph) => + CanBeChanged "knee" Number ptr graph where + canBeChanged sym val ptr w = canBeChanged sym (apure val) ptr w + +instance canBeChangedKnee :: ( IsSymbol ptr - , SetterVal argA - , SetterVal argB - , R.Cons ptr (NodeC CTOR.THighpass edges) ignore graphi + , R.Cons ptr tau' ignore graph + , Detup tau' tau + , Kneeable tau ) => - Change' ptr (CTOR.Highpass argA argB) graphi (CTOR.Highpass AudioParameter AudioParameter) where - change' ptr w = o + CanBeChanged "knee" AudioParameter ptr graph where + canBeChanged sym val ptr w = o where - { context: i, value: (CTOR.Highpass argA argB) } = unsafeUnWAG w + { context: i } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes + argA_Changes = [ setKnee nn val ] + + o = + unsafeWAG + { context: + i + { instructions = i.instructions <> argA_Changes + } + , value: unit + } + +class Attackable (tau :: Type) + +instance attackableDynamicsCompressor :: Attackable CTOR.TDynamicsCompressor + +instance canBeChangedAttackN :: + (CanBeChanged "attack" AudioParameter ptr graph) => + CanBeChanged "attack" Number ptr graph where + canBeChanged sym val ptr w = canBeChanged sym (apure val) ptr w + +instance canBeChangedAttack :: + ( IsSymbol ptr + , R.Cons ptr tau' ignore graph + , Detup tau' tau + , Attackable tau + ) => + CanBeChanged "attack" AudioParameter ptr graph where + canBeChanged sym val ptr w = o + where + { context: i } = unsafeUnWAG w + + nn = reflectSymbol ptr - partial :: Partial => Maybe AnAudioUnit -> Tuple AudioParameter AudioParameter - partial (Just (AHighpass a b)) = a /\ b + argA_Changes = [ setAttack nn val ] - v_argA@(AudioParameter v_argA') /\ v_argB@(AudioParameter v_argB') = unsafePartial $ partial lookup + o = + unsafeWAG + { context: + i + { instructions = i.instructions <> argA_Changes + } + , value: unit + } - s_argA = setterVal argA +class Releaseable (tau :: Type) - argA_iv' = s_argA v_argA +instance releaseableDynamicsCompressor :: Releaseable CTOR.TDynamicsCompressor - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet then [] else [ setFrequency nn argA_iv' ] +instance canBeChangedReleaseN :: + (CanBeChanged "release" AudioParameter ptr graph) => + CanBeChanged "release" Number ptr graph where + canBeChanged sym val ptr w = canBeChanged sym (apure val) ptr w - s_argB = setterVal argB +instance canBeChangedRelease :: + ( IsSymbol ptr + , R.Cons ptr tau' ignore graph + , Detup tau' tau + , Releaseable tau + ) => + CanBeChanged "release" AudioParameter ptr graph where + canBeChanged sym val ptr w = o + where + { context: i } = unsafeUnWAG w - argB_iv' = s_argB v_argB + nn = reflectSymbol ptr - argB_Changes = let AudioParameter argB_iv = argB_iv' in if argB_iv.param == v_argB'.param && not argB_iv.forceSet then [] else [ setQ nn argB_iv' ] + argA_Changes = [ setRelease nn val ] o = unsafeWAG { context: i - { internalNodes = (M.insert nn (AHighpass argA_iv' argB_iv') i.internalNodes) - , instructions = i.instructions <> (argA_Changes <> argB_Changes) + { instructions = i.instructions <> argA_Changes } - , value: CTOR.Highpass argA_iv' argB_iv' + , value: unit } -instance changeHighshelf :: +instance oneShotChangeAllpass :: OneShotChange CTOR.TAllpass AudioParameter (CTOR.Allpass (Maybe AudioParameter) (Maybe AudioParameter)) where + oneShotChange _ freq = CTOR.Allpass (Just freq) Nothing + +instance changeAllpass :: ( IsSymbol ptr - , SetterVal argA - , SetterVal argB - , R.Cons ptr (NodeC CTOR.THighshelf edges) ignore graphi + , MM mArgA (Maybe argA) + , Paramable argA + , MM mArgB (Maybe argB) + , Paramable argB + , R.Cons ptr (NodeC CTOR.TAllpass edges) ignore graph ) => - Change' ptr (CTOR.Highshelf argA argB) graphi (CTOR.Highshelf AudioParameter AudioParameter) where + Change' ptr (CTOR.Allpass mArgA mArgB) graph where change' ptr w = o where - { context: i, value: (CTOR.Highshelf argA argB) } = unsafeUnWAG w + { context: i, value: (CTOR.Allpass argA argB) } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes + argA_iv' = paramize <$> (mm argA) - partial :: Partial => Maybe AnAudioUnit -> Tuple AudioParameter AudioParameter - partial (Just (AHighshelf a b)) = a /\ b + argA_Changes = maybe [] (\argA_iv'' -> [ setFrequency nn argA_iv'' ]) argA_iv' - v_argA@(AudioParameter v_argA') /\ v_argB@(AudioParameter v_argB') = unsafePartial $ partial lookup + argB_iv' = paramize <$> (mm argB) - s_argA = setterVal argA + argB_Changes = maybe [] (\argB_iv'' -> [ setQ nn argB_iv'' ]) argB_iv' - argA_iv' = s_argA v_argA + o = + unsafeWAG + { context: + i + { instructions = i.instructions <> argA_Changes <> argB_Changes + } + , value: unit + } - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet then [] else [ setFrequency nn argA_iv' ] +instance oneShotChangeBandpass :: OneShotChange CTOR.TBandpass AudioParameter (CTOR.Bandpass (Maybe AudioParameter) (Maybe AudioParameter)) where + oneShotChange _ freq = CTOR.Bandpass (Just freq) Nothing - s_argB = setterVal argB +instance changeBandpass :: + ( IsSymbol ptr + , MM mArgA (Maybe argA) + , Paramable argA + , MM mArgB (Maybe argB) + , Paramable argB + , R.Cons ptr (NodeC CTOR.TBandpass edges) ignore graph + ) => + Change' ptr (CTOR.Bandpass mArgA mArgB) graph where + change' ptr w = o + where + { context: i, value: (CTOR.Bandpass argA argB) } = unsafeUnWAG w + + nn = reflectSymbol ptr - argB_iv' = s_argB v_argB + argA_iv' = paramize <$> (mm argA) - argB_Changes = let AudioParameter argB_iv = argB_iv' in if argB_iv.param == v_argB'.param && not argB_iv.forceSet then [] else [ setGain nn argB_iv' ] + argA_Changes = maybe [] (\argA_iv'' -> [ setFrequency nn argA_iv'' ]) argA_iv' + + argB_iv' = paramize <$> (mm argB) + + argB_Changes = maybe [] (\argB_iv'' -> [ setQ nn argB_iv'' ]) argB_iv' o = unsafeWAG { context: i - { internalNodes = (M.insert nn (AHighshelf argA_iv' argB_iv') i.internalNodes) - , instructions = i.instructions <> (argA_Changes <> argB_Changes) + { instructions = i.instructions <> argA_Changes <> argB_Changes } - , value: CTOR.Highshelf argA_iv' argB_iv' + , value: unit } -instance changeLoopBuf :: +instance oneShotChangeConstant :: OneShotChange CTOR.TConstant AudioParameter (CTOR.Constant (Maybe OnOff) (Maybe AudioParameter)) where + oneShotChange _ offset = CTOR.Constant Nothing (Just offset) + +instance oneShotChangeConstantOO :: OneShotChange CTOR.TConstant OnOff (CTOR.Constant (Maybe OnOff) (Maybe AudioParameter)) where + oneShotChange _ oo = CTOR.Constant (Just oo) Nothing + +instance changeConstant :: ( IsSymbol ptr - , SetterVal argA - , R.Cons ptr (NodeC CTOR.TLoopBuf edges) ignore graphi + , MM mOnOff (Maybe OnOff) + , MM mArgA (Maybe argA) + , Paramable argA + , R.Cons ptr (NodeC CTOR.TConstant edges) ignore graph ) => - Change' ptr (CTOR.LoopBuf argA) graphi (CTOR.LoopBuf AudioParameter) where + Change' ptr (CTOR.Constant mOnOff mArgA) graph where change' ptr w = o where - { context: i, value: (CTOR.LoopBuf buffer onOff argA loopStart loopEnd) } = unsafeUnWAG w + { context: i, value: (CTOR.Constant onOff argA) } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes + oo_Changes = maybe [] (\onOff' -> [ (if onOff' == On then setOn else setOff) nn ]) (mm onOff) + + argA_iv' = paramize <$> (mm argA) - partial :: Partial => Maybe AnAudioUnit -> String /\ OnOff /\ AudioParameter /\ Number /\ Number - partial (Just (ALoopBuf a b c d e)) = a /\ b /\ c /\ d /\ e + argA_Changes = maybe [] (\argA_iv'' -> [ setOffset nn argA_iv'' ]) argA_iv' - oldBuffer /\ oldOnOff /\ v_argA@(AudioParameter v_argA') /\ oldLoopStart /\ oldLoopEnd = unsafePartial $ partial lookup + o = + unsafeWAG + { context: + i + { instructions = i.instructions <> (argA_Changes <> oo_Changes) + } + , value: unit + } - onOffDiff = oldOnOff /= onOff +instance oneShotChangeDelay :: OneShotChange CTOR.TDelay AudioParameter (CTOR.Delay (Maybe AudioParameter)) where + oneShotChange _ delay = CTOR.Delay (Just delay) - s_argA = setterVal argA +instance changeDelay :: + ( IsSymbol ptr + , MM mArgA (Maybe argA) + , Paramable argA + , R.Cons ptr (NodeC CTOR.TDelay edges) ignore graph + ) => + Change' ptr (CTOR.Delay mArgA) graph where + change' ptr w = o + where + { context: i, value: (CTOR.Delay argA) } = unsafeUnWAG w - argA_iv' = s_argA v_argA + nn = reflectSymbol ptr - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet && not (onOffDiff && onOff == On) then [] else [ setPlaybackRate nn argA_iv' ] + argA_iv' = paramize <$> (mm argA) + + argA_Changes = maybe [] (\argA_iv'' -> [ setDelay nn argA_iv'' ]) argA_iv' o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ALoopBuf buffer onOff argA_iv' loopStart loopEnd) i.internalNodes) - , instructions = - i.instructions - <> ( (if buffer /= oldBuffer then [ setBuffer nn buffer ] else []) - <> argA_Changes - <> (if (oldLoopStart /= loopStart) || (onOffDiff && onOff == On) then [ setLoopStart nn loopStart ] else []) - <> (if (oldLoopEnd /= loopEnd) || (onOffDiff && onOff == On) then [ setLoopEnd nn loopEnd ] else []) - <> (if onOffDiff then [ (if onOff == On then setOn else setOff) nn ] else []) - ) + { instructions = i.instructions <> argA_Changes } - , value: CTOR.LoopBuf buffer onOff argA_iv' loopStart loopEnd + , value: unit } -instance changeLowpass :: +instance changeDynamicsCompressor :: ( IsSymbol ptr - , SetterVal argA - , SetterVal argB - , R.Cons ptr (NodeC CTOR.TLowpass edges) ignore graphi + , MM mArgA (Maybe argA) + , Paramable argA + , MM mArgB (Maybe argB) + , Paramable argB + , MM mArgC (Maybe argC) + , Paramable argC + , MM mArgD (Maybe argD) + , Paramable argD + , MM mArgE (Maybe argE) + , Paramable argE + , R.Cons ptr (NodeC CTOR.TDynamicsCompressor edges) ignore graph ) => - Change' ptr (CTOR.Lowpass argA argB) graphi (CTOR.Lowpass AudioParameter AudioParameter) where + Change' ptr (CTOR.DynamicsCompressor mArgA mArgB mArgC mArgD mArgE) graph where change' ptr w = o where - { context: i, value: (CTOR.Lowpass argA argB) } = unsafeUnWAG w + { context: i, value: (CTOR.DynamicsCompressor argA argB argC argD argE) } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes + argA_iv' = paramize <$> (mm argA) + + argA_Changes = maybe [] (\argA_iv'' -> [ setThreshold nn argA_iv'' ]) argA_iv' - partial :: Partial => Maybe AnAudioUnit -> Tuple AudioParameter AudioParameter - partial (Just (ALowpass a b)) = a /\ b + argB_iv' = paramize <$> (mm argB) - v_argA@(AudioParameter v_argA') /\ v_argB@(AudioParameter v_argB') = unsafePartial $ partial lookup + argB_Changes = maybe [] (\argB_iv'' -> [ setKnee nn argB_iv'' ]) argB_iv' - s_argA = setterVal argA + argC_iv' = paramize <$> (mm argC) - argA_iv' = s_argA v_argA + argC_Changes = maybe [] (\argC_iv'' -> [ setRatio nn argC_iv'' ]) argC_iv' - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet then [] else [ setFrequency nn argA_iv' ] + argD_iv' = paramize <$> (mm argD) - s_argB = setterVal argB + argD_Changes = maybe [] (\argD_iv'' -> [ setAttack nn argD_iv'' ]) argD_iv' - argB_iv' = s_argB v_argB + argE_iv' = paramize <$> (mm argE) - argB_Changes = let AudioParameter argB_iv = argB_iv' in if argB_iv.param == v_argB'.param && not argB_iv.forceSet then [] else [ setQ nn argB_iv' ] + argE_Changes = maybe [] (\argE_iv'' -> [ setRelease nn argE_iv'' ]) argE_iv' o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ALowpass argA_iv' argB_iv') i.internalNodes) - , instructions = i.instructions <> (argA_Changes <> argB_Changes) + { instructions = + i.instructions + <> argA_Changes + <> argB_Changes + <> argC_Changes + <> argD_Changes + <> argE_Changes } - , value: CTOR.Lowpass argA_iv' argB_iv' + , value: unit } -instance changeLowshelf :: +instance oneShotChangeGain :: OneShotChange CTOR.TGain AudioParameter (CTOR.Gain (Maybe AudioParameter)) where + oneShotChange _ gain = CTOR.Gain (Just gain) + +instance changeGain :: ( IsSymbol ptr - , SetterVal argA - , SetterVal argB - , R.Cons ptr (NodeC CTOR.TLowshelf edges) ignore graphi + , MM mArgA (Maybe argA) + , Paramable argA + , R.Cons ptr (NodeC CTOR.TGain edges) ignore graph ) => - Change' ptr (CTOR.Lowshelf argA argB) graphi (CTOR.Lowshelf AudioParameter AudioParameter) where + Change' ptr (CTOR.Gain mArgA) graph where change' ptr w = o where - { context: i, value: (CTOR.Lowshelf argA argB) } = unsafeUnWAG w + { context: i, value: (CTOR.Gain argA) } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes + argA_iv' = paramize <$> (mm argA) - partial :: Partial => Maybe AnAudioUnit -> Tuple AudioParameter AudioParameter - partial (Just (ALowshelf a b)) = a /\ b + argA_Changes = maybe [] (\argA_iv'' -> [ setGain nn argA_iv'' ]) argA_iv' - v_argA@(AudioParameter v_argA') /\ v_argB@(AudioParameter v_argB') = unsafePartial $ partial lookup + o = + unsafeWAG + { context: + i + { instructions = i.instructions <> argA_Changes + } + , value: unit + } + +instance oneShotChangeHighpass :: OneShotChange CTOR.THighpass AudioParameter (CTOR.Highpass (Maybe AudioParameter) (Maybe AudioParameter)) where + oneShotChange _ freq = CTOR.Highpass (Just freq) Nothing - s_argA = setterVal argA +instance changeHighpass :: + ( IsSymbol ptr + , MM mArgA (Maybe argA) + , Paramable argA + , MM mArgB (Maybe argB) + , Paramable argB + , R.Cons ptr (NodeC CTOR.THighpass edges) ignore graph + ) => + Change' ptr (CTOR.Highpass mArgA mArgB) graph where + change' ptr w = o + where + { context: i, value: (CTOR.Highpass argA argB) } = unsafeUnWAG w - argA_iv' = s_argA v_argA + nn = reflectSymbol ptr - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet then [] else [ setFrequency nn argA_iv' ] + argA_iv' = paramize <$> (mm argA) - s_argB = setterVal argB + argA_Changes = maybe [] (\argA_iv'' -> [ setFrequency nn argA_iv'' ]) argA_iv' - argB_iv' = s_argB v_argB + argB_iv' = paramize <$> (mm argB) - argB_Changes = let AudioParameter argB_iv = argB_iv' in if argB_iv.param == v_argB'.param && not argB_iv.forceSet then [] else [ setGain nn argB_iv' ] + argB_Changes = maybe [] (\argB_iv'' -> [ setQ nn argB_iv'' ]) argB_iv' o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ALowshelf argA_iv' argB_iv') i.internalNodes) - , instructions = i.instructions <> (argA_Changes <> argB_Changes) + { instructions = i.instructions <> argA_Changes <> argB_Changes } - , value: CTOR.Lowshelf argA_iv' argB_iv' + , value: unit } -instance changeMicrophone :: - ( R.Cons "microphone" (NodeC CTOR.TMicrophone edges) ignore graphi - ) => - Change' - "microphone" - CTOR.Microphone - graphi - CTOR.Microphone where - change' _ w = w +instance oneShotChangeHighshelf :: OneShotChange CTOR.THighshelf AudioParameter (CTOR.Highshelf (Maybe AudioParameter) (Maybe AudioParameter)) where + oneShotChange _ freq = CTOR.Highshelf (Just freq) Nothing -instance changeNotch :: +instance changeHighshelf :: ( IsSymbol ptr - , SetterVal argA - , SetterVal argB - , R.Cons ptr (NodeC CTOR.TNotch edges) ignore graphi + , MM mArgA (Maybe argA) + , Paramable argA + , MM mArgB (Maybe argB) + , Paramable argB + , R.Cons ptr (NodeC CTOR.THighshelf edges) ignore graph ) => - Change' ptr (CTOR.Notch argA argB) graphi (CTOR.Notch AudioParameter AudioParameter) where + Change' ptr (CTOR.Highshelf mArgA mArgB) graph where change' ptr w = o where - { context: i, value: (CTOR.Notch argA argB) } = unsafeUnWAG w + { context: i, value: (CTOR.Highshelf argA argB) } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes + argA_iv' = paramize <$> (mm argA) + + argA_Changes = maybe [] (\argA_iv'' -> [ setFrequency nn argA_iv'' ]) argA_iv' + + argB_iv' = paramize <$> (mm argB) + + argB_Changes = maybe [] (\argB_iv'' -> [ setGain nn argB_iv'' ]) argB_iv' - partial :: Partial => Maybe AnAudioUnit -> Tuple AudioParameter AudioParameter - partial (Just (ANotch a b)) = a /\ b + o = + unsafeWAG + { context: + i + { instructions = i.instructions <> argA_Changes <> argB_Changes + } + , value: unit + } - v_argA@(AudioParameter v_argA') /\ v_argB@(AudioParameter v_argB') = unsafePartial $ partial lookup +instance oneShotChangeLoopBuf :: OneShotChange CTOR.TLoopBuf AudioParameter (CTOR.LoopBuf (Maybe String) (Maybe OnOff) (Maybe AudioParameter) (Maybe Number) (Maybe Number)) where + oneShotChange _ rate = CTOR.LoopBuf Nothing Nothing (Just rate) Nothing Nothing - s_argA = setterVal argA +instance oneShotChangeLoopBufOO :: OneShotChange CTOR.TLoopBuf OnOff (CTOR.LoopBuf (Maybe String) (Maybe OnOff) (Maybe AudioParameter) (Maybe Number) (Maybe Number)) where + oneShotChange _ onOff = CTOR.LoopBuf Nothing (Just onOff) Nothing Nothing Nothing - argA_iv' = s_argA v_argA +instance oneShotChangeLoopBufStr :: OneShotChange CTOR.TLoopBuf String (CTOR.LoopBuf (Maybe String) (Maybe OnOff) (Maybe AudioParameter) (Maybe Number) (Maybe Number)) where + oneShotChange _ buffer = CTOR.LoopBuf (Just buffer) Nothing Nothing Nothing Nothing - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet then [] else [ setFrequency nn argA_iv' ] +instance changeLoopBuf :: + ( IsSymbol ptr + , MM mBuffer (Maybe String) + , MM mOnOff (Maybe OnOff) + , MM mArgA (Maybe argA) + , MM mLoopStart (Maybe Number) + , MM mLoopEnd (Maybe Number) + , Paramable argA + , R.Cons ptr (NodeC CTOR.TLoopBuf edges) ignore graph + ) => + Change' ptr (CTOR.LoopBuf mBuffer mOnOff mArgA mLoopStart mLoopEnd) graph where + change' ptr w = o + where + { context: i, value: (CTOR.LoopBuf buffer onOff argA loopStart loopEnd) } = unsafeUnWAG w - s_argB = setterVal argB + nn = reflectSymbol ptr - argB_iv' = s_argB v_argB + buffer_Changes = maybe [] (\buffer' -> [ setBuffer nn buffer' ]) (mm buffer) - argB_Changes = let AudioParameter argB_iv = argB_iv' in if argB_iv.param == v_argB'.param && not argB_iv.forceSet then [] else [ setQ nn argB_iv' ] + oo_Changes = maybe [] (\onOff' -> [ (if onOff' == On then setOn else setOff) nn ]) (mm onOff) + + argA_iv' = paramize <$> (mm argA) + + argA_Changes = maybe [] (\argA_iv'' -> [ setPlaybackRate nn argA_iv'' ]) argA_iv' + + loopStart_Changes = maybe [] (\loopStart' -> [ setLoopStart nn loopStart' ]) (mm loopStart) + + loopEnd_Changes = maybe [] (\loopEnd' -> [ setLoopEnd nn loopEnd' ]) (mm loopEnd) o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ANotch argA_iv' argB_iv') i.internalNodes) - , instructions = i.instructions <> (argA_Changes <> argB_Changes) + { instructions = + i.instructions + <> buffer_Changes + <> oo_Changes + <> argA_Changes + <> loopStart_Changes + <> loopEnd_Changes } - , value: CTOR.Notch argA_iv' argB_iv' + , value: unit } -instance changePeaking :: +instance oneShotChangeLowpass :: OneShotChange CTOR.TLowpass AudioParameter (CTOR.Lowpass (Maybe AudioParameter) (Maybe AudioParameter)) where + oneShotChange _ freq = CTOR.Lowpass (Just freq) Nothing + +instance changeLowpass :: ( IsSymbol ptr - , SetterVal argA - , SetterVal argB - , SetterVal argC - , R.Cons ptr (NodeC CTOR.TPeaking edges) ignore graphi + , MM mArgA (Maybe argA) + , Paramable argA + , MM mArgB (Maybe argB) + , Paramable argB + , R.Cons ptr (NodeC CTOR.TLowpass edges) ignore graph ) => - Change' ptr (CTOR.Peaking argA argB argC) graphi (CTOR.Peaking AudioParameter AudioParameter AudioParameter) where + Change' ptr (CTOR.Lowpass mArgA mArgB) graph where change' ptr w = o where - { context: i, value: (CTOR.Peaking argA argB argC) } = unsafeUnWAG w + { context: i, value: (CTOR.Lowpass argA argB) } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes + argA_iv' = paramize <$> (mm argA) - partial :: Partial => Maybe AnAudioUnit -> AudioParameter /\ AudioParameter /\ AudioParameter - partial (Just (APeaking a b c)) = a /\ b /\ c + argA_Changes = maybe [] (\argA_iv'' -> [ setFrequency nn argA_iv'' ]) argA_iv' - v_argA@(AudioParameter v_argA') /\ v_argB@(AudioParameter v_argB') /\ v_argC@(AudioParameter v_argC') = unsafePartial $ partial lookup + argB_iv' = paramize <$> (mm argB) - s_argA = setterVal argA + argB_Changes = maybe [] (\argB_iv'' -> [ setQ nn argB_iv'' ]) argB_iv' - argA_iv' = s_argA v_argA + o = + unsafeWAG + { context: + i + { instructions = i.instructions <> argA_Changes <> argB_Changes + } + , value: unit + } - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet then [] else [ setFrequency nn argA_iv' ] +instance oneShotChangeLowshelf :: OneShotChange CTOR.TLowshelf AudioParameter (CTOR.Lowshelf (Maybe AudioParameter) (Maybe AudioParameter)) where + oneShotChange _ freq = CTOR.Lowshelf (Just freq) Nothing - s_argB = setterVal argB +instance changeLowshelf :: + ( IsSymbol ptr + , MM mArgA (Maybe argA) + , Paramable argA + , MM mArgB (Maybe argB) + , Paramable argB + , R.Cons ptr (NodeC CTOR.TLowshelf edges) ignore graph + ) => + Change' ptr (CTOR.Lowshelf mArgA mArgB) graph where + change' ptr w = o + where + { context: i, value: (CTOR.Lowshelf argA argB) } = unsafeUnWAG w - argB_iv' = s_argB v_argB + nn = reflectSymbol ptr - argB_Changes = let AudioParameter argB_iv = argB_iv' in if argB_iv.param == v_argB'.param && not argB_iv.forceSet then [] else [ setQ nn argB_iv' ] + argA_iv' = paramize <$> (mm argA) - s_argC = setterVal argC + argA_Changes = maybe [] (\argA_iv'' -> [ setFrequency nn argA_iv'' ]) argA_iv' - argC_iv' = s_argC v_argC + argB_iv' = paramize <$> (mm argB) - argC_Changes = let AudioParameter argC_iv = argC_iv' in if argC_iv.param == v_argC'.param && not argC_iv.forceSet then [] else [ setGain nn argC_iv' ] + argB_Changes = maybe [] (\argB_iv'' -> [ setGain nn argB_iv'' ]) argB_iv' o = unsafeWAG { context: i - { internalNodes = (M.insert nn (APeaking argA_iv' argB_iv' argC_iv') i.internalNodes) - , instructions = i.instructions <> (argA_Changes <> argB_Changes <> argC_Changes) + { instructions = i.instructions <> argA_Changes <> argB_Changes } - , value: CTOR.Peaking argA_iv' argB_iv' argC_iv' + , value: unit } -instance changePeriodicOsc :: +instance changeMicrophone :: + ( R.Cons "microphone" (NodeC CTOR.TMicrophone edges) ignore graph + ) => + Change' + "microphone" + CTOR.Microphone + graph where + change' _ w = w $> unit + +instance oneShotChangeNotch :: OneShotChange CTOR.TNotch AudioParameter (CTOR.Notch (Maybe AudioParameter) (Maybe AudioParameter)) where + oneShotChange _ freq = CTOR.Notch (Just freq) Nothing + +instance changeNotch :: ( IsSymbol ptr - , SetterVal argA - , R.Cons ptr (NodeC CTOR.TPeriodicOsc edges) ignore graphi + , MM mArgA (Maybe argA) + , Paramable argA + , MM mArgB (Maybe argB) + , Paramable argB + , R.Cons ptr (NodeC CTOR.TNotch edges) ignore graph ) => - Change' ptr (CTOR.PeriodicOsc String argA) graphi (CTOR.PeriodicOsc String AudioParameter) where + Change' ptr (CTOR.Notch mArgA mArgB) graph where change' ptr w = o where - { context: i, value: (CTOR.PeriodicOsc periodicWave onOff argA) } = unsafeUnWAG w + { context: i, value: (CTOR.Notch argA argB) } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes - - partial :: Partial => Maybe AnAudioUnit -> Either String (Array Number /\ Array Number) /\ OnOff /\ AudioParameter - partial (Just (APeriodicOsc a b c)) = a /\ b /\ c + argA_iv' = paramize <$> (mm argA) - oldPeriodicWave /\ oldOnOff /\ v_argA@(AudioParameter v_argA') = unsafePartial $ partial lookup + argA_Changes = maybe [] (\argA_iv'' -> [ setFrequency nn argA_iv'' ]) argA_iv' - onOffDiff = oldOnOff /= onOff + argB_iv' = paramize <$> (mm argB) - s_argA = setterVal argA - - argA_iv' = s_argA v_argA - - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet then [] else [ setFrequency nn argA_iv' ] + argB_Changes = maybe [] (\argB_iv'' -> [ setQ nn argB_iv'' ]) argB_iv' o = unsafeWAG { context: i - { internalNodes = (M.insert nn (APeriodicOsc (Left periodicWave) onOff argA_iv') i.internalNodes) - , instructions = i.instructions <> ((if (Left periodicWave) /= oldPeriodicWave then [ setPeriodicOsc nn periodicWave ] else []) <> argA_Changes <> (if onOffDiff then [ (if onOff == On then setOn else setOff) nn ] else [])) + { instructions = i.instructions <> argA_Changes <> argB_Changes } - , value: CTOR.PeriodicOsc periodicWave onOff argA_iv' + , value: unit } -instance changePeriodicOsc2 :: +instance oneShotChangePeaking :: OneShotChange CTOR.TPeaking AudioParameter (CTOR.Peaking (Maybe AudioParameter) (Maybe AudioParameter) (Maybe AudioParameter)) where + oneShotChange _ freq = CTOR.Peaking (Just freq) Nothing Nothing + +instance changePeaking :: ( IsSymbol ptr - , SetterVal argA - , R.Cons ptr (NodeC CTOR.TPeriodicOsc edges) ignore graphi + , MM mArgA (Maybe argA) + , Paramable argA + , MM mArgB (Maybe argB) + , Paramable argB + , MM mArgC (Maybe argC) + , Paramable argC + , R.Cons ptr (NodeC CTOR.TPeaking edges) ignore graph ) => - Change' ptr (CTOR.PeriodicOsc (V.Vec size Number /\ V.Vec size Number) argA) graphi (CTOR.PeriodicOsc (V.Vec size Number /\ V.Vec size Number) AudioParameter) where + Change' ptr (CTOR.Peaking mArgA mArgB mArgC) graph where change' ptr w = o where - { context: i, value: (CTOR.PeriodicOsc periodicWave onOff argA) } = unsafeUnWAG w + { context: i, value: (CTOR.Peaking argA argB argC) } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes + argA_iv' = paramize <$> (mm argA) + + argA_Changes = maybe [] (\argA_iv'' -> [ setFrequency nn argA_iv'' ]) argA_iv' + + argB_iv' = paramize <$> (mm argB) + + argB_Changes = maybe [] (\argB_iv'' -> [ setQ nn argB_iv'' ]) argB_iv' + + argC_iv' = paramize <$> (mm argC) + + argC_Changes = maybe [] (\argC_iv'' -> [ setGain nn argC_iv'' ]) argC_iv' + + o = + unsafeWAG + { context: + i + { instructions = i.instructions <> argA_Changes <> argB_Changes <> argC_Changes + } + , value: unit + } + +instance oneShotChangePeriodicOsc :: OneShotChange CTOR.TPeriodicOsc AudioParameter (CTOR.PeriodicOsc (Maybe String) (Maybe OnOff) (Maybe AudioParameter)) where + oneShotChange _ freq = CTOR.PeriodicOsc Nothing Nothing (Just freq) + +instance oneShotChangePeriodicOscOO :: OneShotChange CTOR.TPeriodicOsc OnOff (CTOR.PeriodicOsc (Maybe String) (Maybe OnOff) (Maybe AudioParameter)) where + oneShotChange _ oo = CTOR.PeriodicOsc Nothing (Just oo) Nothing + +instance oneShotChangePeriodicOscStr :: OneShotChange CTOR.TPeriodicOsc String (CTOR.PeriodicOsc (Maybe String) (Maybe OnOff) (Maybe AudioParameter)) where + oneShotChange _ osc = CTOR.PeriodicOsc (Just osc) Nothing Nothing + +instance oneShotChangePeriodicOscVec :: OneShotChange CTOR.TPeriodicOsc (V.Vec size Number /\ V.Vec size Number) (CTOR.PeriodicOsc (Maybe (V.Vec size Number /\ V.Vec size Number)) (Maybe OnOff) (Maybe AudioParameter)) where + oneShotChange _ osc = CTOR.PeriodicOsc (Just osc) Nothing Nothing + +class ChangePeriodicOsc a where + setPosc :: forall audio engine. AudioInterpret audio engine => String -> a -> audio -> engine - partial :: Partial => Maybe AnAudioUnit -> Either String (Array Number /\ Array Number) /\ OnOff /\ AudioParameter - partial (Just (APeriodicOsc a b c)) = a /\ b /\ c +instance changePeriodicOscV :: ChangePeriodicOsc (V.Vec size Number /\ V.Vec size Number) where + setPosc = setPeriodicOscV - oldPeriodicWave /\ oldOnOff /\ v_argA@(AudioParameter v_argA') = unsafePartial $ partial lookup +instance changePeriodicOscS :: ChangePeriodicOsc String where + setPosc = setPeriodicOsc + +instance changePeriodicOsc :: + ( IsSymbol ptr + , MM mOsc (Maybe osc) + , MM mOnOff (Maybe OnOff) + , ChangePeriodicOsc osc + , MM mArgA (Maybe argA) + , Paramable argA + , R.Cons ptr (NodeC CTOR.TPeriodicOsc edges) ignore graph + ) => + Change' ptr (CTOR.PeriodicOsc mOsc mOnOff mArgA) graph where + change' ptr w = o + where + { context: i, value: (CTOR.PeriodicOsc periodicWave onOff argA) } = unsafeUnWAG w - onOffDiff = oldOnOff /= onOff + nn = reflectSymbol ptr - s_argA = setterVal argA + pw_Changes = maybe [] (\periodicWave' -> [ setPosc nn periodicWave' ]) (mm periodicWave) - argA_iv' = s_argA v_argA + oo_Changes = maybe [] (\onOff' -> [ (if onOff' == On then setOn else setOff) nn ]) (mm onOff) - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet then [] else [ setFrequency nn argA_iv' ] + argA_iv' = paramize <$> (mm argA) - rPeriodicWave = Right (tmap V.toArray periodicWave) + argA_Changes = maybe [] (\argA_iv'' -> [ setFrequency nn argA_iv'' ]) argA_iv' o = unsafeWAG { context: i - { internalNodes = (M.insert nn (APeriodicOsc rPeriodicWave onOff argA_iv') i.internalNodes) - , instructions = i.instructions <> ((if rPeriodicWave /= oldPeriodicWave then [ setPeriodicOscV nn periodicWave ] else []) <> argA_Changes <> (if onOffDiff then [ (if onOff == On then setOn else setOff) nn ] else [])) + { instructions = i.instructions <> pw_Changes <> oo_Changes <> argA_Changes } - , value: CTOR.PeriodicOsc periodicWave onOff argA_iv' + , value: unit } +instance oneShotChangePlayBuf :: OneShotChange CTOR.TPlayBuf AudioParameter (CTOR.PlayBuf (Maybe String) (Maybe Number) (Maybe OnOff) (Maybe AudioParameter)) where + oneShotChange _ rate = CTOR.PlayBuf Nothing Nothing Nothing (Just rate) + +instance oneShotChangePlayBufOO :: OneShotChange CTOR.TPlayBuf OnOff (CTOR.PlayBuf (Maybe String) (Maybe Number) (Maybe OnOff) (Maybe AudioParameter)) where + oneShotChange _ oo = CTOR.PlayBuf Nothing Nothing (Just oo) Nothing + +instance oneShotChangePlayBufStr :: OneShotChange CTOR.TPlayBuf String (CTOR.PlayBuf (Maybe String) (Maybe Number) (Maybe OnOff) (Maybe AudioParameter)) where + oneShotChange _ buffer = CTOR.PlayBuf (Just buffer) Nothing Nothing Nothing + instance changePlayBuf :: ( IsSymbol ptr - , SetterVal argA - , R.Cons ptr (NodeC CTOR.TPlayBuf edges) ignore graphi + , MM mBuffer (Maybe String) + , MM mOffset (Maybe Number) + , MM mOnOff (Maybe OnOff) + , MM mArgA (Maybe argA) + , Paramable argA + , R.Cons ptr (NodeC CTOR.TPlayBuf edges) ignore graph ) => - Change' ptr (CTOR.PlayBuf argA) graphi (CTOR.PlayBuf AudioParameter) where + Change' ptr (CTOR.PlayBuf mBuffer mOffset mOnOff mArgA) graph where change' ptr w = o where { context: i, value: (CTOR.PlayBuf buffer offset onOff argA) } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes - - partial :: Partial => Maybe AnAudioUnit -> String /\ Number /\ OnOff /\ AudioParameter - partial (Just (APlayBuf a b c d)) = a /\ b /\ c /\ d - - oldBuffer /\ oldOffset /\ oldOnOff /\ v_argA@(AudioParameter v_argA') = unsafePartial $ partial lookup + buffer_Changes = maybe [] (\buffer' -> [ setBuffer nn buffer' ]) (mm buffer) - onOffDiff = oldOnOff /= onOff + offset_Changes = maybe [] (\offset' -> [ setBufferOffset nn offset' ]) (mm offset) - s_argA = setterVal argA + oo_Changes = maybe [] (\onOff' -> [ (if onOff' == On then setOn else setOff) nn ]) (mm onOff) - argA_iv' = s_argA v_argA + argA_iv' = paramize <$> (mm argA) - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet && not (onOffDiff && onOff == On) then [] else [ setPlaybackRate nn argA_iv' ] + argA_Changes = maybe [] (\argA_iv'' -> [ setPlaybackRate nn argA_iv'' ]) argA_iv' o = unsafeWAG { context: i - { internalNodes = (M.insert nn (APlayBuf buffer offset onOff argA_iv') i.internalNodes) - , instructions = + { instructions = i.instructions - <> ( (if buffer /= oldBuffer then [ setBuffer nn buffer ] else []) - <> argA_Changes - <> (if (oldOffset /= offset) || (onOffDiff && onOff == On) then [ setBufferOffset nn offset ] else []) - <> (if onOffDiff then [ (if onOff == On then setOn else setOff) nn ] else []) - ) + <> buffer_Changes + <> offset_Changes + <> oo_Changes + <> argA_Changes } - , value: CTOR.PlayBuf buffer offset onOff argA_iv' + , value: unit } instance changeRecorder :: - ( IsSymbol ptr, R.Cons ptr (NodeC (CTOR.TRecorder sym) edges) ignore graphi + ( IsSymbol ptr, R.Cons ptr (NodeC (CTOR.TRecorder sym) edges) ignore graph ) => Change' ptr (CTOR.Recorder sym) - graphi - (CTOR.Recorder sym) where - change' _ w = w + graph where + change' _ w = w $> unit + +instance oneShotChangeSawtoothOsc :: OneShotChange CTOR.TSawtoothOsc AudioParameter (CTOR.SawtoothOsc (Maybe OnOff) (Maybe AudioParameter)) where + oneShotChange _ freq = CTOR.SawtoothOsc Nothing (Just freq) + +instance oneShotChangeSawtoothOscOO :: OneShotChange CTOR.TSawtoothOsc OnOff (CTOR.SawtoothOsc (Maybe OnOff) (Maybe AudioParameter)) where + oneShotChange _ oo = CTOR.SawtoothOsc (Just oo) Nothing instance changeSawtoothOsc :: ( IsSymbol ptr - , SetterVal argA - , R.Cons ptr (NodeC CTOR.TSawtoothOsc edges) ignore graphi + , MM mOnOff (Maybe OnOff) + , MM mArgA (Maybe argA) + , Paramable argA + , R.Cons ptr (NodeC CTOR.TSawtoothOsc edges) ignore graph ) => - Change' ptr (CTOR.SawtoothOsc argA) graphi (CTOR.SawtoothOsc AudioParameter) where + Change' ptr (CTOR.SawtoothOsc mOnOff mArgA) graph where change' ptr w = o where { context: i, value: (CTOR.SawtoothOsc onOff argA) } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes - - partial :: Partial => Maybe AnAudioUnit -> Tuple OnOff AudioParameter - partial (Just (ASawtoothOsc a b)) = a /\ b - - oldOnOff /\ v_argA@(AudioParameter v_argA') = unsafePartial $ partial lookup - - onOffDiff = oldOnOff /= onOff + oo_Changes = maybe [] (\onOff' -> [ (if onOff' == On then setOn else setOff) nn ]) (mm onOff) - s_argA = setterVal argA + argA_iv' = paramize <$> (mm argA) - argA_iv' = s_argA v_argA - - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet then [] else [ setFrequency nn argA_iv' ] + argA_Changes = maybe [] (\argA_iv'' -> [ setFrequency nn argA_iv'' ]) argA_iv' o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ASawtoothOsc onOff argA_iv') i.internalNodes) - , instructions = i.instructions <> (argA_Changes <> (if onOffDiff then [ (if onOff == On then setOn else setOff) nn ] else [])) + { instructions = i.instructions <> oo_Changes <> argA_Changes } - , value: CTOR.SawtoothOsc onOff argA_iv' + , value: unit } +instance oneShotChangeSinOsc :: OneShotChange CTOR.TSinOsc AudioParameter (CTOR.SinOsc (Maybe OnOff) (Maybe AudioParameter)) where + oneShotChange _ freq = CTOR.SinOsc Nothing (Just freq) + +instance oneShotChangeSinOscOO :: OneShotChange CTOR.TSinOsc OnOff (CTOR.SinOsc (Maybe OnOff) (Maybe AudioParameter)) where + oneShotChange _ oo = CTOR.SinOsc (Just oo) Nothing + instance changeSinOsc :: ( IsSymbol ptr - , SetterVal argA - , R.Cons ptr (NodeC CTOR.TSinOsc edges) ignore graphi + , MM mOnOff (Maybe OnOff) + , MM mArgA (Maybe argA) + , Paramable argA + , R.Cons ptr (NodeC CTOR.TSinOsc edges) ignore graph ) => - Change' ptr (CTOR.SinOsc argA) graphi (CTOR.SinOsc AudioParameter) where + Change' ptr (CTOR.SinOsc mOnOff mArgA) graph where change' ptr w = o where { context: i, value: (CTOR.SinOsc onOff argA) } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes - - partial :: Partial => Maybe AnAudioUnit -> Tuple OnOff AudioParameter - partial (Just (ASinOsc a b)) = a /\ b - - oldOnOff /\ v_argA@(AudioParameter v_argA') = unsafePartial $ partial lookup - - onOffDiff = oldOnOff /= onOff - - s_argA = setterVal argA + oo_Changes = maybe [] (\onOff' -> [ (if onOff' == On then setOn else setOff) nn ]) (mm onOff) - argA_iv' = s_argA v_argA + argA_iv' = paramize <$> (mm argA) - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet then [] else [ setFrequency nn argA_iv' ] + argA_Changes = maybe [] (\argA_iv'' -> [ setFrequency nn argA_iv'' ]) argA_iv' o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ASinOsc onOff argA_iv') i.internalNodes) - , instructions = i.instructions <> (argA_Changes <> (if onOffDiff then [ (if onOff == On then setOn else setOff) nn ] else [])) + { instructions = i.instructions <> oo_Changes <> argA_Changes } - , value: CTOR.SinOsc onOff argA_iv' + , value: unit } instance changeSpeaker :: - ( R.Cons "speaker" (NodeC (CTOR.TSpeaker) edges) ignore graphi + ( R.Cons "speaker" (NodeC (CTOR.TSpeaker) edges) ignore graph ) => Change' "speaker" (CTOR.Speaker) - graphi - (CTOR.Speaker) where - change' _ w = w + graph where + change' _ w = w $> unit + +instance oneShotChangeSquareOsc :: OneShotChange CTOR.TSquareOsc AudioParameter (CTOR.SquareOsc (Maybe OnOff) (Maybe AudioParameter)) where + oneShotChange _ freq = CTOR.SquareOsc Nothing (Just freq) + +instance oneShotChangeSquareOscOO :: OneShotChange CTOR.TSquareOsc OnOff (CTOR.SquareOsc (Maybe OnOff) (Maybe AudioParameter)) where + oneShotChange _ oo = CTOR.SquareOsc (Just oo) Nothing instance changeSquareOsc :: ( IsSymbol ptr - , SetterVal argA - , R.Cons ptr (NodeC CTOR.TSquareOsc edges) ignore graphi + , MM mOnOff (Maybe OnOff) + , MM mArgA (Maybe argA) + , Paramable argA + , R.Cons ptr (NodeC CTOR.TSquareOsc edges) ignore graph ) => - Change' ptr (CTOR.SquareOsc argA) graphi (CTOR.SquareOsc AudioParameter) where + Change' ptr (CTOR.SquareOsc mOnOff mArgA) graph where change' ptr w = o where { context: i, value: (CTOR.SquareOsc onOff argA) } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes - - partial :: Partial => Maybe AnAudioUnit -> Tuple OnOff AudioParameter - partial (Just (ASquareOsc a b)) = a /\ b - - oldOnOff /\ v_argA@(AudioParameter v_argA') = unsafePartial $ partial lookup - - onOffDiff = oldOnOff /= onOff + oo_Changes = maybe [] (\onOff' -> [ (if onOff' == On then setOn else setOff) nn ]) (mm onOff) - s_argA = setterVal argA + argA_iv' = paramize <$> (mm argA) - argA_iv' = s_argA v_argA - - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet then [] else [ setFrequency nn argA_iv' ] + argA_Changes = maybe [] (\argA_iv'' -> [ setFrequency nn argA_iv'' ]) argA_iv' o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ASquareOsc onOff argA_iv') i.internalNodes) - , instructions = i.instructions <> (argA_Changes <> (if onOffDiff then [ (if onOff == On then setOn else setOff) nn ] else [])) + { instructions = i.instructions <> oo_Changes <> argA_Changes } - , value: CTOR.SquareOsc onOff argA_iv' + , value: unit } +instance oneShotChangeStereoPanner :: OneShotChange CTOR.TStereoPanner AudioParameter (CTOR.StereoPanner (Maybe AudioParameter)) where + oneShotChange _ pan = CTOR.StereoPanner (Just pan) + instance changeStereoPanner :: ( IsSymbol ptr - , SetterVal argA - , R.Cons ptr (NodeC CTOR.TStereoPanner edges) ignore graphi + , MM mArgA (Maybe argA) + , Paramable argA + , R.Cons ptr (NodeC CTOR.TStereoPanner edges) ignore graph ) => - Change' ptr (CTOR.StereoPanner argA) graphi (CTOR.StereoPanner AudioParameter) where + Change' ptr (CTOR.StereoPanner mArgA) graph where change' ptr w = o where { context: i, value: (CTOR.StereoPanner argA) } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes - - partial :: Partial => Maybe AnAudioUnit -> AudioParameter - partial (Just (AStereoPanner a)) = a - - v_argA@(AudioParameter v_argA') = unsafePartial $ partial lookup + argA_iv' = paramize <$> (mm argA) - s_argA = setterVal argA - - argA_iv' = s_argA v_argA - - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet then [] else [ setPan nn argA_iv' ] + argA_Changes = maybe [] (\argA_iv'' -> [ setPan nn argA_iv'' ]) argA_iv' o = unsafeWAG { context: i - { internalNodes = (M.insert nn (AStereoPanner argA_iv') i.internalNodes) - , instructions = i.instructions <> argA_Changes + { instructions = i.instructions <> argA_Changes } - , value: CTOR.StereoPanner argA_iv' + , value: unit } +instance oneShotChangeTriangleOsc :: OneShotChange CTOR.TTriangleOsc AudioParameter (CTOR.TriangleOsc (Maybe OnOff) (Maybe AudioParameter)) where + oneShotChange _ freq = CTOR.TriangleOsc Nothing (Just freq) + +instance oneShotChangeTriangleOscOO :: OneShotChange CTOR.TTriangleOsc OnOff (CTOR.TriangleOsc (Maybe OnOff) (Maybe AudioParameter)) where + oneShotChange _ oo = CTOR.TriangleOsc (Just oo) Nothing + instance changeTriangleOsc :: ( IsSymbol ptr - , SetterVal argA - , R.Cons ptr (NodeC CTOR.TTriangleOsc edges) ignore graphi + , MM mOnOff (Maybe OnOff) + , MM mArgA (Maybe argA) + , Paramable argA + , R.Cons ptr (NodeC CTOR.TTriangleOsc edges) ignore graph ) => - Change' ptr (CTOR.TriangleOsc argA) graphi (CTOR.TriangleOsc AudioParameter) where + Change' ptr (CTOR.TriangleOsc mOnOff mArgA) graph where change' ptr w = o where { context: i, value: (CTOR.TriangleOsc onOff argA) } = unsafeUnWAG w nn = reflectSymbol ptr - lookup = M.lookup nn i.internalNodes - - partial :: Partial => Maybe AnAudioUnit -> Tuple OnOff AudioParameter - partial (Just (ATriangleOsc a b)) = a /\ b - - oldOnOff /\ v_argA@(AudioParameter v_argA') = unsafePartial $ partial lookup + oo_Changes = maybe [] (\onOff' -> [ (if onOff' == On then setOn else setOff) nn ]) (mm onOff) - onOffDiff = oldOnOff /= onOff + argA_iv' = paramize <$> (mm argA) - s_argA = setterVal argA - - argA_iv' = s_argA v_argA - - argA_Changes = let AudioParameter argA_iv = argA_iv' in if argA_iv.param == v_argA'.param && not argA_iv.forceSet then [] else [ setFrequency nn argA_iv' ] + argA_Changes = maybe [] (\argA_iv'' -> [ setFrequency nn argA_iv'' ]) argA_iv' o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ATriangleOsc onOff argA_iv') i.internalNodes) - , instructions = i.instructions <> (argA_Changes <> (if onOffDiff then [ (if onOff == On then setOn else setOff) nn ] else [])) + { instructions = i.instructions <> oo_Changes <> argA_Changes } - , value: CTOR.TriangleOsc onOff argA_iv' + , value: unit } instance changeWaveShaper :: - ( IsSymbol ptr, R.Cons ptr (NodeC (CTOR.TWaveShaper a b) edges) ignore graphi + ( IsSymbol ptr, R.Cons ptr (NodeC (CTOR.TWaveShaper a b) edges) ignore graph ) => Change' ptr (CTOR.WaveShaper a b) - graphi - (CTOR.WaveShaper a b) where - change' _ w = w + graph where + change' _ w = w $> unit diff --git a/src/WAGS/Change/Optionals.purs b/src/WAGS/Change/Optionals.purs new file mode 100644 index 00000000..c1fd72ce --- /dev/null +++ b/src/WAGS/Change/Optionals.purs @@ -0,0 +1,831 @@ +-- | This module provides functions for the construction of audio units that more closely resemble the overloaded constructors of the Web Audio API. +module WAGS.Change.Optionals where + +import Prelude +import ConvertableOptions (class ConvertOption, class ConvertOptionsWithDefaults, convertOptionsWithDefaults) +import Data.Maybe (Maybe(..)) +import Data.Tuple.Nested ((/\), type (/\)) +import Data.Vec as V +import WAGS.Graph.AudioUnit (OnOff(..)) +import WAGS.Graph.AudioUnit as CTOR +import WAGS.Graph.Parameter (class MM, class Paramable, AudioParameter, mm, paramize) + +----------- +data Allpass + = Allpass + +instance change_convertAllpassFrequency :: (Paramable b, MM a (Maybe b)) => ConvertOption Allpass "freq" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertAllpassQ :: (Paramable b, MM a (Maybe b)) => ConvertOption Allpass "q" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +type AllpassOptional + = ( q :: Maybe AudioParameter, freq :: Maybe AudioParameter ) + +type AllpassAll + = ( | AllpassOptional ) + +defaultAllpass :: { | AllpassOptional } +defaultAllpass = { freq: Nothing, q: Nothing } + +class AllpassCtor i allpass | i -> allpass where + -- | Change an allpass filter + -- | + -- | ```purescript + -- | allpass { freq: 440.0 } + -- | allpass { freq: 440.0, q: 1.0 } + -- | allpass 440.0 + -- | ``` + allpass :: i -> allpass + +instance change_allpassCtor1 :: + ( ConvertOptionsWithDefaults Allpass { | AllpassOptional } { | provided } { | AllpassAll } + ) => + AllpassCtor { | provided } (CTOR.Allpass (Maybe AudioParameter) (Maybe AudioParameter)) where + allpass provided = CTOR.Allpass all.freq all.q + where + all :: { | AllpassAll } + all = convertOptionsWithDefaults Allpass defaultAllpass provided +else instance change_allpassCtor2 :: (Paramable b, MM a (Maybe b)) => AllpassCtor a (CTOR.Allpass (Maybe AudioParameter) (Maybe AudioParameter)) where + allpass a = CTOR.Allpass (paramize <$> mm a) defaultAllpass.q + +type DAllpass + = CTOR.Allpass (Maybe AudioParameter) (Maybe AudioParameter) + +------ +data Bandpass + = Bandpass + +instance change_convertBandpassFrequency :: (Paramable b, MM a (Maybe b)) => ConvertOption Bandpass "freq" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertBandpassQ :: (Paramable b, MM a (Maybe b)) => ConvertOption Bandpass "q" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +type BandpassOptional + = ( freq :: Maybe AudioParameter, q :: Maybe AudioParameter ) + +type BandpassAll + = ( | BandpassOptional ) + +defaultBandpass :: { | BandpassOptional } +defaultBandpass = { freq: Nothing, q: Nothing } + +class BandpassCtor i bandpass | i -> bandpass where + -- | Create a bandpass filter, connecting it to another unit + -- | + -- | ```purescript + -- | bandpass { freq: 440.0 } { sinOsc: unit } + -- | bandpass { freq: 440.0, q: 1.0 } { sinOsc: unit } + -- | bandpass 440.0 { sinOsc: unit } + -- | ``` + bandpass :: i -> bandpass + +instance change_bandpassCtor1 :: + ( ConvertOptionsWithDefaults Bandpass { | BandpassOptional } { | provided } { | BandpassAll } + ) => + BandpassCtor { | provided } (CTOR.Bandpass (Maybe AudioParameter) (Maybe AudioParameter)) where + bandpass provided = CTOR.Bandpass all.freq all.q + where + all :: { | BandpassAll } + all = convertOptionsWithDefaults Bandpass defaultBandpass provided +else instance change_bandpassCtor2 :: (Paramable b, MM a (Maybe b)) => BandpassCtor a (CTOR.Bandpass (Maybe AudioParameter) (Maybe AudioParameter)) where + bandpass a = CTOR.Bandpass (paramize <$> mm a) defaultBandpass.q + +type DBandpass + = CTOR.Bandpass (Maybe AudioParameter) (Maybe AudioParameter) + +------ +data Constant + = Constant + +instance change_convertConstantOffset :: (Paramable b, MM a (Maybe b)) => ConvertOption Constant "offset" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertConstantOnOff :: (MM a (Maybe OnOff)) => ConvertOption Constant "onOff" a (Maybe OnOff) where + convertOption _ _ = mm + +type ConstantOptional + = ( onOff :: OnOff ) + +type ConstantAll + = ( offset :: AudioParameter + | ConstantOptional + ) + +defaultConstant :: { | ConstantOptional } +defaultConstant = { onOff: On } + +class ConstantCtor i o | i -> o where + -- | Change a constant value + -- | + -- | ```purescript + -- | constant 0.5 + -- | ``` + constant :: i -> o + +instance change_constantCtor1 :: + ( ConvertOptionsWithDefaults Constant { | ConstantOptional } { | provided } { | ConstantAll } + ) => + ConstantCtor { | provided } (CTOR.Constant OnOff AudioParameter /\ {}) where + constant provided = CTOR.Constant all.onOff all.offset /\ {} + where + all :: { | ConstantAll } + all = convertOptionsWithDefaults Constant defaultConstant provided +else instance change_constantCtor2 :: Paramable a => ConstantCtor a (CTOR.Constant OnOff AudioParameter /\ {}) where + constant a = CTOR.Constant defaultConstant.onOff (paramize a) /\ {} + +type DConstant + = CTOR.Constant (Maybe OnOff) (Maybe AudioParameter) + +------ +-- | Change a delay unit. +-- | +-- | ```purescript +-- | delay 0.5 (playBuf "track") +-- | ``` +delay :: + forall a b. + Paramable b => + MM a (Maybe b) => + a -> CTOR.Delay (Maybe AudioParameter) +delay gvsv = CTOR.Delay (paramize <$> (mm gvsv)) + +type DDelay + = CTOR.Delay AudioParameter + +------ +data DynamicsCompressor + = DynamicsCompressor + +instance change_convertDynamicsCompressorThreshold :: (Paramable b, MM a (Maybe b)) => ConvertOption DynamicsCompressor "threshold" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertDynamicsCompressorKnee :: (Paramable b, MM a (Maybe b)) => ConvertOption DynamicsCompressor "knee" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertDynamicsCompressorRatio :: (Paramable b, MM a (Maybe b)) => ConvertOption DynamicsCompressor "ratio" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertDynamicsCompressorAttack :: (Paramable b, MM a (Maybe b)) => ConvertOption DynamicsCompressor "attack" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertDynamicsCompressorRelease :: (Paramable b, MM a (Maybe b)) => ConvertOption DynamicsCompressor "release" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +type DynamicsCompressorOptional + = ( threshold :: Maybe AudioParameter + , knee :: Maybe AudioParameter + , ratio :: Maybe AudioParameter + , attack :: Maybe AudioParameter + , release :: Maybe AudioParameter + ) + +type DynamicsCompressorAll + = ( | DynamicsCompressorOptional ) + +defaultDynamicsCompressor :: { | DynamicsCompressorOptional } +defaultDynamicsCompressor = + { threshold: Nothing + , knee: Nothing + , ratio: Nothing + , attack: Nothing + , release: Nothing + } + +class DynamicsCompressorCtor i compressor | i -> compressor where + -- | Change a compressor. + -- | + -- | ```purescript + -- | compressor { threshold: -10.0 } { buf: playBuf "track" } + -- | compressor { knee: 20.0, ratio: 10.0 } { buf: playBuf "track" } + -- | compressor { attack: 0.01, release: 0.3 } { buf: playBuf "track" } + -- | ``` + compressor :: i -> compressor + +instance change_compressorCTor :: + ( ConvertOptionsWithDefaults DynamicsCompressor { | DynamicsCompressorOptional } { | provided } { | DynamicsCompressorAll } + ) => + DynamicsCompressorCtor { | provided } (CTOR.DynamicsCompressor (Maybe AudioParameter) (Maybe AudioParameter) (Maybe AudioParameter) (Maybe AudioParameter) (Maybe AudioParameter)) where + compressor provided = + CTOR.DynamicsCompressor + all.threshold + all.knee + all.ratio + all.attack + all.release + where + all :: { | DynamicsCompressorAll } + all = convertOptionsWithDefaults DynamicsCompressor defaultDynamicsCompressor provided + +type DDynamicsCompressor + = CTOR.DynamicsCompressor (Maybe AudioParameter) (Maybe AudioParameter) (Maybe AudioParameter) (Maybe AudioParameter) (Maybe AudioParameter) + +------ +gain :: forall a b. Paramable b => MM a (Maybe b) => a -> CTOR.Gain (Maybe AudioParameter) +gain a = CTOR.Gain (paramize <$> mm a) + +type Mix + = CTOR.Gain AudioParameter + +type DGain + = CTOR.Gain AudioParameter + +------ +data Highpass + = Highpass + +instance change_convertHighpassFrequency :: (Paramable b, MM a (Maybe b)) => ConvertOption Highpass "freq" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertHighpassQ :: (Paramable b, MM a (Maybe b)) => ConvertOption Highpass "q" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +type HighpassOptional + = ( freq :: Maybe AudioParameter, q :: Maybe AudioParameter ) + +type HighpassAll + = ( | HighpassOptional ) + +defaultHighpass :: { | HighpassOptional } +defaultHighpass = { freq: Nothing, q: Nothing } + +class HighpassCtor i highpass | i -> highpass where + -- | Change a highpass filter + -- | + -- | ```purescript + -- | highpass { freq: 440.0 } + -- | highpass { freq: 440.0, q: 1.0 } + -- | highpass 440.0 + -- | ``` + highpass :: i -> highpass + +instance change_highpassCtor1 :: + ( ConvertOptionsWithDefaults Highpass { | HighpassOptional } { | provided } { | HighpassAll } + ) => + HighpassCtor { | provided } (CTOR.Highpass (Maybe AudioParameter) (Maybe AudioParameter)) where + highpass provided = CTOR.Highpass all.freq all.q + where + all :: { | HighpassAll } + all = convertOptionsWithDefaults Highpass defaultHighpass provided +else instance change_highpassCtor2 :: (Paramable b, MM a (Maybe b)) => HighpassCtor a (CTOR.Highpass (Maybe AudioParameter) (Maybe AudioParameter)) where + highpass a = CTOR.Highpass (paramize <$> mm a) defaultHighpass.q + +type DHighpass + = CTOR.Highpass (Maybe AudioParameter) (Maybe AudioParameter) + +------ +data Highshelf + = Highshelf + +instance change_convertHighshelfFrequency :: (Paramable b, MM a (Maybe b)) => ConvertOption Highshelf "freq" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertHighshelfQ :: (Paramable b, MM a (Maybe b)) => ConvertOption Highshelf "gain" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +type HighshelfOptional + = ( freq :: Maybe AudioParameter, gain :: Maybe AudioParameter ) + +type HighshelfAll + = ( | HighshelfOptional ) + +defaultHighshelf :: { | HighshelfOptional } +defaultHighshelf = { freq: Nothing, gain: Nothing } + +class HighshelfCtor i highshelf | i -> highshelf where + -- | Change a highshelf filter + -- | + -- | ```purescript + -- | highshelf { freq: 440.0 } + -- | highshelf { freq: 440.0, gain: 1.0 } + -- | highshelf 440.0 + -- | ``` + highshelf :: i -> highshelf + +instance change_highshelfCtor1 :: + ( ConvertOptionsWithDefaults Highshelf { | HighshelfOptional } { | provided } { | HighshelfAll } + ) => + HighshelfCtor { | provided } (CTOR.Highshelf (Maybe AudioParameter) (Maybe AudioParameter)) where + highshelf provided = CTOR.Highshelf all.freq all.gain + where + all :: { | HighshelfAll } + all = convertOptionsWithDefaults Highshelf defaultHighshelf provided +else instance change_highshelfCtor2 :: (Paramable b, MM a (Maybe b)) => HighshelfCtor a (CTOR.Highshelf (Maybe AudioParameter) (Maybe AudioParameter)) where + highshelf a = CTOR.Highshelf (paramize <$> mm a) defaultHighshelf.gain + +type DHighshelf + = CTOR.Highshelf (Maybe AudioParameter) (Maybe AudioParameter) + +---- +data LoopBuf + = LoopBuf + +instance change_convertLoopBufBuffer :: (MM a (Maybe String)) => ConvertOption LoopBuf "buffer" a (Maybe String) where + convertOption _ _ = mm + +instance change_convertLoopBufPlaybackRate :: (Paramable b, MM a (Maybe b)) => ConvertOption LoopBuf "playbackRate" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertLoopBufOnOff :: (MM a (Maybe OnOff)) => ConvertOption LoopBuf "onOff" a (Maybe OnOff) where + convertOption _ _ = mm + +instance change_convertLoopBufStart :: (MM a (Maybe Number)) => ConvertOption LoopBuf "loopStart" a (Maybe Number) where + convertOption _ _ = mm + +instance change_convertLoopBufEnd :: (MM a (Maybe Number)) => ConvertOption LoopBuf "loopEnd" a (Maybe Number) where + convertOption _ _ = mm + +type LoopBufOptional + = ( buffer :: Maybe String + , playbackRate :: Maybe AudioParameter + , onOff :: Maybe OnOff + , loopStart :: Maybe Number + , loopEnd :: Maybe Number + ) + +type LoopBufAll + = ( | LoopBufOptional ) + +defaultLoopBuf :: { | LoopBufOptional } +defaultLoopBuf = { buffer: Nothing, playbackRate: Nothing, onOff: Nothing, loopStart: Nothing, loopEnd: Nothing } + +class LoopBufCtor i loopBuf | i -> loopBuf where + -- | Change a looping buffer. + -- | + -- | ```purescript + -- | loopBuf { playbackRate: 1.0 } "track" + -- | loopBuf { playbackRate: 1.0, loopStart: 0.5 } "track" + -- | loopBuf "track" + -- | ``` + loopBuf :: i -> loopBuf + +instance change_loopBufCtor1 :: + ( ConvertOptionsWithDefaults LoopBuf { | LoopBufOptional } { | provided } { | LoopBufAll } + ) => + LoopBufCtor { | provided } (CTOR.LoopBuf (Maybe String) (Maybe OnOff) (Maybe AudioParameter) (Maybe Number) (Maybe Number)) where + loopBuf provided = CTOR.LoopBuf all.buffer all.onOff all.playbackRate all.loopStart all.loopEnd + where + all :: { | LoopBufAll } + all = convertOptionsWithDefaults LoopBuf defaultLoopBuf provided +else instance change_loopBufCtor2 :: (Paramable b, MM a (Maybe b)) => LoopBufCtor a (CTOR.LoopBuf (Maybe String) (Maybe OnOff) (Maybe AudioParameter) (Maybe Number) (Maybe Number)) where + loopBuf rate = + CTOR.LoopBuf + defaultLoopBuf.buffer + defaultLoopBuf.onOff + (paramize <$> mm rate) + defaultLoopBuf.loopStart + defaultLoopBuf.loopEnd + +type DLoopBuf + = CTOR.LoopBuf String (Maybe OnOff) (Maybe AudioParameter) Number Number + +----- +data Lowpass + = Lowpass + +instance change_convertLowpassFrequency :: (Paramable b, MM a (Maybe b)) => ConvertOption Lowpass "freq" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertLowpassQ :: (Paramable b, MM a (Maybe b)) => ConvertOption Lowpass "q" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +type LowpassOptional + = ( q :: Maybe AudioParameter, freq :: Maybe AudioParameter ) + +type LowpassAll + = ( | LowpassOptional ) + +defaultLowpass :: { | LowpassOptional } +defaultLowpass = { freq: Nothing, q: Nothing } + +class LowpassCtor i lowpass | i -> lowpass where + -- | Change a lowpass filter + -- | + -- | ```purescript + -- | lowpass { freq: 440.0 } + -- | lowpass { freq: 440.0, q: 1.0 } + -- | lowpass 440.0 + -- | ``` + lowpass :: i -> lowpass + +instance change_lowpassCtor1 :: + ( ConvertOptionsWithDefaults Lowpass { | LowpassOptional } { | provided } { | LowpassAll } + ) => + LowpassCtor { | provided } (CTOR.Lowpass (Maybe AudioParameter) (Maybe AudioParameter)) where + lowpass provided = CTOR.Lowpass all.freq all.q + where + all :: { | LowpassAll } + all = convertOptionsWithDefaults Lowpass defaultLowpass provided +else instance change_lowpassCtor2 :: (Paramable b, MM a (Maybe b)) => LowpassCtor a (CTOR.Lowpass (Maybe AudioParameter) (Maybe AudioParameter)) where + lowpass a = CTOR.Lowpass (paramize <$> mm a) defaultLowpass.q + +type DLowpass + = CTOR.Lowpass (Maybe AudioParameter) (Maybe AudioParameter) + +----- +data Lowshelf + = Lowshelf + +instance change_convertLowshelfFrequency :: (Paramable b, MM a (Maybe b)) => ConvertOption Lowshelf "freq" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertLowshelfQ :: (Paramable b, MM a (Maybe b)) => ConvertOption Lowshelf "gain" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +type LowshelfOptional + = ( freq :: Maybe AudioParameter, gain :: Maybe AudioParameter ) + +type LowshelfAll + = ( | LowshelfOptional ) + +defaultLowshelf :: { | LowshelfOptional } +defaultLowshelf = { freq: Nothing, gain: Nothing } + +class LowshelfCtor i lowshelf | i -> lowshelf where + -- | Change a lowshelf filter + -- | + -- | ```purescript + -- | lowshelf { freq: 440.0 } + -- | lowshelf { freq: 440.0, gain: 1.0 } + -- | lowshelf 440.0 + -- | ``` + lowshelf :: i -> lowshelf + +instance change_lowshelfCtor1 :: + ( ConvertOptionsWithDefaults Lowshelf { | LowshelfOptional } { | provided } { | LowshelfAll } + ) => + LowshelfCtor { | provided } (CTOR.Lowshelf (Maybe AudioParameter) (Maybe AudioParameter)) where + lowshelf provided = CTOR.Lowshelf all.freq all.gain + where + all :: { | LowshelfAll } + all = convertOptionsWithDefaults Lowshelf defaultLowshelf provided +else instance change_lowshelfCtor2 :: (Paramable b, MM a (Maybe b)) => LowshelfCtor a (CTOR.Lowshelf (Maybe AudioParameter) (Maybe AudioParameter)) where + lowshelf a = CTOR.Lowshelf (paramize <$> mm a) defaultLowshelf.gain + +type DLowshelf + = CTOR.Lowshelf (Maybe AudioParameter) (Maybe AudioParameter) + +-------- +data Notch + = Notch + +instance change_convertNotchFrequency :: (Paramable b, MM a (Maybe b)) => ConvertOption Notch "freq" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertNotchQ :: (Paramable b, MM a (Maybe b)) => ConvertOption Notch "q" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +type NotchOptional + = ( q :: Maybe AudioParameter, freq :: Maybe AudioParameter ) + +type NotchAll + = ( | NotchOptional ) + +defaultNotch :: { | NotchOptional } +defaultNotch = { freq: Nothing, q: Nothing } + +class NotchCtor i notch | i -> notch where + -- | Change a notch (band-reject) filter + -- | + -- | ```purescript + -- | notch { freq: 440.0 } + -- | notch { freq: 440.0, gain: 1.0 } + -- | notch 440.0 + -- | ``` + notch :: i -> notch + +instance change_notchCtor1 :: + ( ConvertOptionsWithDefaults Notch { | NotchOptional } { | provided } { | NotchAll } + ) => + NotchCtor { | provided } (CTOR.Notch (Maybe AudioParameter) (Maybe AudioParameter)) where + notch provided = CTOR.Notch all.freq all.q + where + all :: { | NotchAll } + all = convertOptionsWithDefaults Notch defaultNotch provided +else instance change_notchCtor2 :: (Paramable b, MM a (Maybe b)) => NotchCtor a (CTOR.Notch (Maybe AudioParameter) (Maybe AudioParameter)) where + notch a = CTOR.Notch (paramize <$> mm a) defaultNotch.q + +type DNotch + = CTOR.Notch (Maybe AudioParameter) (Maybe AudioParameter) + +---------------- +data Peaking + = Peaking + +instance change_convertPeakingFrequency :: (Paramable b, MM a (Maybe b)) => ConvertOption Peaking "freq" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertPeakingQ :: (Paramable b, MM a (Maybe b)) => ConvertOption Peaking "q" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertPeakingGain :: (Paramable b, MM a (Maybe b)) => ConvertOption Peaking "gain" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +type PeakingOptional + = ( q :: Maybe AudioParameter, gain :: Maybe AudioParameter, freq :: Maybe AudioParameter ) + +type PeakingAll + = ( | PeakingOptional ) + +defaultPeaking :: { | PeakingOptional } +defaultPeaking = { freq: Nothing, q: Nothing, gain: Nothing } + +class PeakingCtor i peaking | i -> peaking where + -- | Change a peaking filter + -- | + -- | ```purescript + -- | peaking { freq: 440.0 } + -- | peaking { freq: 440.0, gain: 1.0 } + -- | peaking 440.0 + -- | ``` + peaking :: i -> peaking + +instance change_peakingCtor1 :: + ( ConvertOptionsWithDefaults Peaking { | PeakingOptional } { | provided } { | PeakingAll } + ) => + PeakingCtor { | provided } (CTOR.Peaking (Maybe AudioParameter) (Maybe AudioParameter) (Maybe AudioParameter)) where + peaking provided = (CTOR.Peaking all.freq all.q all.gain) + where + all :: { | PeakingAll } + all = convertOptionsWithDefaults Peaking defaultPeaking provided +else instance change_peakingCtor2 :: (Paramable b, MM a (Maybe b)) => PeakingCtor a (CTOR.Peaking (Maybe AudioParameter) (Maybe AudioParameter) (Maybe AudioParameter)) where + peaking a = (CTOR.Peaking (paramize <$> mm a) defaultPeaking.q defaultPeaking.gain) + +type DPeaking + = CTOR.Peaking (Maybe AudioParameter) (Maybe AudioParameter) (Maybe AudioParameter) + +------ +------ +class CanBeCoercedToPeriodicOsc (canBeCoercedToPeriodicOsc :: Type) + +instance change_canBeCoercedToPeriodicOscString :: CanBeCoercedToPeriodicOsc String + +instance change_canBeCoercedToPeriodicOscV :: CanBeCoercedToPeriodicOsc (V.Vec size Number /\ V.Vec size Number) + +data PeriodicOsc + = PeriodicOsc + +instance change_convertPeriodicOscFrequency :: (Paramable b, MM a (Maybe b)) => ConvertOption PeriodicOsc "freq" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertPeriodicOscOnOff :: MM a (Maybe OnOff) => ConvertOption PeriodicOsc "onOff" a (Maybe OnOff) where + convertOption _ _ = mm + +instance change_convertPeriodicOscWave :: (MM mWave (Maybe wave), CanBeCoercedToPeriodicOsc wave) => ConvertOption PeriodicOsc "waveform" mWave (Maybe wave) where + convertOption _ _ = mm + +type PeriodicOscOptional wave + = ( onOff :: Maybe OnOff + , freq :: Maybe AudioParameter + , wave :: Maybe wave + ) + +type PeriodicOscAll wave + = ( | PeriodicOscOptional wave ) + +defaultPeriodicOsc :: forall wave. { | PeriodicOscOptional wave } +defaultPeriodicOsc = { onOff: Nothing, freq: Nothing, wave: Nothing } + +class PeriodicOscCtor i o | i -> o where + -- | Change a periodicOsc value + -- | + -- | ```purescript + -- | periodicOsc "my-osc" 0.5 + -- | ``` + periodicOsc :: i -> o + +instance change_periodicOscCtor1 :: + ( ConvertOptionsWithDefaults PeriodicOsc { | PeriodicOscOptional wave } { | provided } { | PeriodicOscAll wave } + ) => + PeriodicOscCtor { | provided } (CTOR.PeriodicOsc (Maybe wave) (Maybe OnOff) (Maybe AudioParameter)) where + periodicOsc provided = CTOR.PeriodicOsc all.wave all.onOff all.freq + where + all :: { | PeriodicOscAll wave } + all = convertOptionsWithDefaults PeriodicOsc defaultPeriodicOsc provided +else instance change_periodicOscCtor2 :: (MM mWave (Maybe wave), CanBeCoercedToPeriodicOsc wave, Paramable b, MM a (Maybe b)) => PeriodicOscCtor mWave (a -> CTOR.PeriodicOsc (Maybe wave) (Maybe OnOff) (Maybe AudioParameter)) where + periodicOsc wave a = CTOR.PeriodicOsc (mm wave) defaultPeriodicOsc.onOff (paramize <$> mm a) + +type DPeriodicOsc periodicOsc + = CTOR.PeriodicOsc periodicOsc OnOff AudioParameter + +--- +data PlayBuf + = PlayBuf + +instance change_convertPlayBufBuffer :: (MM a (Maybe String)) => ConvertOption PlayBuf "buffer" a (Maybe String) where + convertOption _ _ = mm + +instance change_convertPlayBufPlaybackRate :: (Paramable b, MM a (Maybe b)) => ConvertOption PlayBuf "playbackRate" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertPlayBufOnOff :: (MM mOnOff (Maybe OnOff)) => ConvertOption PlayBuf "onOff" mOnOff (Maybe OnOff) where + convertOption _ _ = mm + +instance change_convertPlayBufBufferOffset :: (MM mOffset (Maybe Number)) => ConvertOption PlayBuf "bufferOffset" mOffset (Maybe Number) where + convertOption _ _ = mm + +type PlayBufOptional + = ( buffer :: Maybe String, playbackRate :: Maybe AudioParameter, onOff :: Maybe OnOff, bufferOffset :: Maybe Number ) + +type PlayBufAll + = ( | PlayBufOptional ) + +defaultPlayBuf :: { | PlayBufOptional } +defaultPlayBuf = { buffer: Nothing, playbackRate: Nothing, onOff: Nothing, bufferOffset: Nothing } + +class PlayBufCtor i playBuf | i -> playBuf where + -- | Change a unit that plays from a buffer. + -- | + -- | ```purescript + -- | playBuf { playbackRate: 1.0 } "track" + -- | playBuf { playbackRate: 1.0, bufferOffset: 0.5 } "track" + -- | playBuf "track" + -- | ``` + playBuf :: i -> playBuf + +instance change_playBufCtor1 :: + ConvertOptionsWithDefaults PlayBuf { | PlayBufOptional } { | provided } { | PlayBufAll } => + PlayBufCtor { | provided } (CTOR.PlayBuf (Maybe String) (Maybe Number) (Maybe OnOff) (Maybe AudioParameter)) where + playBuf provided = CTOR.PlayBuf all.buffer all.bufferOffset all.onOff all.playbackRate + where + all :: { | PlayBufAll } + all = convertOptionsWithDefaults PlayBuf defaultPlayBuf provided +else instance change_playBufCtor2 :: (Paramable b, MM a (Maybe b)) => PlayBufCtor a (CTOR.PlayBuf (Maybe String) (Maybe Number) (Maybe OnOff) (Maybe AudioParameter)) where + playBuf rate = + CTOR.PlayBuf + defaultPlayBuf.buffer + defaultPlayBuf.bufferOffset + defaultPlayBuf.onOff + (paramize <$> mm rate) + +type DPlayBuf + = CTOR.PlayBuf String Number (Maybe OnOff) (Maybe AudioParameter) + +------ +class SawtoothOscCtor i o | i -> o where + -- | Change a sawtooth oscillator + -- | + -- | ```purescript + -- | sawtoothOsc 440.0 + -- | sawtoothOsc On 440.0 + -- | ``` + sawtoothOsc :: i -> o + +instance change_sawtoothOsc2 :: + (MM mOnOff (Maybe OnOff), Paramable b, MM a (Maybe b)) => + SawtoothOscCtor mOnOff (a -> CTOR.SawtoothOsc (Maybe OnOff) (Maybe AudioParameter)) where + sawtoothOsc oo gvsv = CTOR.SawtoothOsc (mm oo) (paramize <$> (mm gvsv)) +else instance change_sawtoothOsc1 :: + (Paramable b, MM a (Maybe b)) => + SawtoothOscCtor a (CTOR.SawtoothOsc (Maybe OnOff) (Maybe AudioParameter)) where + sawtoothOsc gvsv = CTOR.SawtoothOsc Nothing (paramize <$> (mm gvsv)) + +type DSawtoothOsc + = CTOR.SawtoothOsc (Maybe OnOff) (Maybe AudioParameter) + +------ +data SinOsc + = SinOsc + +instance change_convertSinOscFrequency :: (Paramable b, MM a (Maybe b)) => ConvertOption SinOsc "freq" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertSinOscOnOff :: MM a (Maybe OnOff) => ConvertOption SinOsc "onOff" a (Maybe OnOff) where + convertOption _ _ = mm + +type SinOscOptional + = ( onOff :: OnOff ) + +type SinOscAll + = ( freq :: AudioParameter + | SinOscOptional + ) + +defaultSinOsc :: { | SinOscOptional } +defaultSinOsc = { onOff: On } + +class SinOscCtor i o | i -> o where + -- | Change a sinOsc value + -- | + -- | ```purescript + -- | sinOsc 0.5 + -- | ``` + sinOsc :: i -> o + +instance change_sinOscCtor1 :: + ( ConvertOptionsWithDefaults SinOsc { | SinOscOptional } { | provided } { | SinOscAll } + ) => + SinOscCtor { | provided } (CTOR.SinOsc OnOff AudioParameter /\ {}) where + sinOsc provided = CTOR.SinOsc all.onOff all.freq /\ {} + where + all :: { | SinOscAll } + all = convertOptionsWithDefaults SinOsc defaultSinOsc provided +else instance change_sinOscCtor2 :: Paramable a => SinOscCtor a (CTOR.SinOsc OnOff AudioParameter /\ {}) where + sinOsc a = CTOR.SinOsc defaultSinOsc.onOff (paramize a) /\ {} + +type DSinOsc + = CTOR.SinOsc (Maybe OnOff) (Maybe AudioParameter) + +------ +data SquareOsc + = SquareOsc + +instance change_convertSquareOscFrequency :: (Paramable b, MM a (Maybe b)) => ConvertOption SquareOsc "freq" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertSquareOscOnOff :: MM a (Maybe OnOff) => ConvertOption SquareOsc "onOff" a (Maybe OnOff) where + convertOption _ _ = mm + +type SquareOscOptional + = ( onOff :: OnOff ) + +type SquareOscAll + = ( freq :: AudioParameter + | SquareOscOptional + ) + +defaultSquareOsc :: { | SquareOscOptional } +defaultSquareOsc = { onOff: On } + +class SquareOscCtor i o | i -> o where + -- | Change a squareOsc value + -- | + -- | ```purescript + -- | squareOsc 0.5 + -- | ``` + squareOsc :: i -> o + +instance change_squareOscCtor1 :: + ( ConvertOptionsWithDefaults SquareOsc { | SquareOscOptional } { | provided } { | SquareOscAll } + ) => + SquareOscCtor { | provided } (CTOR.SquareOsc OnOff AudioParameter /\ {}) where + squareOsc provided = CTOR.SquareOsc all.onOff all.freq /\ {} + where + all :: { | SquareOscAll } + all = convertOptionsWithDefaults SquareOsc defaultSquareOsc provided +else instance change_squareOscCtor2 :: Paramable a => SquareOscCtor a (CTOR.SquareOsc OnOff AudioParameter /\ {}) where + squareOsc a = CTOR.SquareOsc defaultSquareOsc.onOff (paramize a) /\ {} + +type DSquareOsc + = CTOR.SquareOsc (Maybe OnOff) (Maybe AudioParameter) + +------ +-- | Pan audio. +-- | +-- | ```purescript +-- | pan 0.5 { buf: playBuf "my-track" } +-- | ``` +pan :: + forall a b. + Paramable b => + MM a (Maybe b) => + a -> CTOR.StereoPanner (Maybe AudioParameter) +pan gvsv = CTOR.StereoPanner (paramize <$> (mm gvsv)) + +type DStereoPanner + = CTOR.StereoPanner (Maybe AudioParameter) + +------ +data TriangleOsc + = TriangleOsc + +instance change_convertTriangleOscFrequency :: (Paramable b, MM a (Maybe b)) => ConvertOption TriangleOsc "freq" a (Maybe AudioParameter) where + convertOption _ _ = map paramize <<< mm + +instance change_convertTriangleOscOnOff :: MM a (Maybe OnOff) => ConvertOption TriangleOsc "onOff" a (Maybe OnOff) where + convertOption _ _ = mm + +type TriangleOscOptional + = ( onOff :: OnOff ) + +type TriangleOscAll + = ( freq :: AudioParameter + | TriangleOscOptional + ) + +defaultTriangleOsc :: { | TriangleOscOptional } +defaultTriangleOsc = { onOff: On } + +class TriangleOscCtor i o | i -> o where + -- | Change a triangleOsc value + -- | + -- | ```purescript + -- | triangleOsc 0.5 + -- | ``` + triangleOsc :: i -> o + +instance change_triangleOscCtor1 :: + ( ConvertOptionsWithDefaults TriangleOsc { | TriangleOscOptional } { | provided } { | TriangleOscAll } + ) => + TriangleOscCtor { | provided } (CTOR.TriangleOsc OnOff AudioParameter /\ {}) where + triangleOsc provided = CTOR.TriangleOsc all.onOff all.freq /\ {} + where + all :: { | TriangleOscAll } + all = convertOptionsWithDefaults TriangleOsc defaultTriangleOsc provided +else instance change_triangleOscCtor2 :: Paramable a => TriangleOscCtor a (CTOR.TriangleOsc OnOff AudioParameter /\ {}) where + triangleOsc a = CTOR.TriangleOsc defaultTriangleOsc.onOff (paramize a) /\ {} + +type DTriangleOsc + = CTOR.TriangleOsc (Maybe OnOff) (Maybe AudioParameter) diff --git a/src/WAGS/Connect.purs b/src/WAGS/Connect.purs index b6e65453..34aaf520 100644 --- a/src/WAGS/Connect.purs +++ b/src/WAGS/Connect.purs @@ -4,8 +4,6 @@ import Prelude hiding (Ordering(..)) import Control.Comonad (extract) import Data.Functor (voidRight) -import Data.Map as M -import Data.Set as S import Data.Symbol (class IsSymbol, reflectSymbol) import Heterogeneous.Folding (class FoldingWithIndex) import Prim.Row as R @@ -45,8 +43,7 @@ instance connectInstance :: unsafeWAG { context: i - { internalEdges = M.insertWith S.union toI (S.singleton fromI) i.internalEdges - , instructions = i.instructions <> [ connectXToY fromI toI ] + { instructions = i.instructions <> [ connectXToY fromI toI ] } , value: unit } diff --git a/src/WAGS/Control/Functions.purs b/src/WAGS/Control/Functions.purs index 4263cf04..ff849c21 100644 --- a/src/WAGS/Control/Functions.purs +++ b/src/WAGS/Control/Functions.purs @@ -27,7 +27,6 @@ module WAGS.Control.Functions import Prelude import Control.Comonad (extract) import Data.Either (Either(..)) -import Data.Map as M import WAGS.Control.Indexed (IxWAG(..), IxFrame) import WAGS.Control.Types (AudioState', EFrame, Frame, Frame0, InitialWAG, Scene(..), Scene', WAG, oneFrame, unsafeUnWAG, unsafeWAG) import WAGS.Interpret (class AudioInterpret) @@ -59,8 +58,6 @@ initialAudioState :: forall audio engine res. Monoid res => AudioState' audio en initialAudioState = { res: mempty , instructions: [] - , internalNodes: M.empty - , internalEdges: M.empty } -- | Make a scene. The infix operator for this operation is `@>`. @@ -90,9 +87,7 @@ makeScene m trans = Scene go let { context, value } = unsafeUnWAG r in - { nodes: context.internalNodes - , edges: context.internalEdges - , instructions: context.instructions + { instructions: context.instructions , res: context.res , next: trans diff --git a/src/WAGS/Control/Types.purs b/src/WAGS/Control/Types.purs index 4c0a0160..b0e044f6 100644 --- a/src/WAGS/Control/Types.purs +++ b/src/WAGS/Control/Types.purs @@ -20,10 +20,7 @@ import Prelude import Control.Comonad (class Comonad) import Control.Extend (class Extend) import Data.Either (Either) -import Data.Map as M -import Data.Set (Set) import Data.Tuple.Nested ((/\), type (/\)) -import WAGS.Rendered (AnAudioUnit) newtype WAG (audio :: Type) (engine :: Type) (proof :: Type) (res :: Type) (graph :: Type) (a :: Type) = WAG { context :: AudioState' audio engine res, value :: a } @@ -75,16 +72,12 @@ newtype Scene env audio engine proofA res -- | The information yielded by `oneFrame`. -- | If `Scene` were a cofree comonad, this would be what is returned by `head` _and_ `tail` combined into one record. - -- | - `nodes`: A map of pointers to audio units. - -- | - `edges`: A map of pointers to incoming edges. -- | - `instructions`: An array of instructions, ie making things, changing them, or turning them on/off, to be actualized by `audio` and rendered in `engine`. -- | - `res`: A monoid containing a residual from the audio computation. Use this if you need to pass computations from an audio graph to downstream consumers. In general, it is best if computations happen before audio graph rendering, so it's best to use `res` only in cases where a computation is dependent on values that can only be calculated in the audio-graph, ie scheduling based on the audio clock. -- | - `next`: The next `Scene`, aka `tail` if `Scene` were a cofree comonad. type Scene' :: forall k. Type -> Type -> Type -> k -> Type -> Type type Scene' env audio engine proof res - = { nodes :: M.Map String AnAudioUnit - , edges :: M.Map String (Set String) - , instructions :: Array (audio -> engine) + = { instructions :: Array (audio -> engine) , res :: res , next :: Scene env audio engine proof res } @@ -93,19 +86,17 @@ oneFrame :: forall env audio engine proofA res. Scene env audio engine proofA re oneFrame (Scene scene) = scene -- | This represents the output of `oneFrame` as a tuple instead of a record. -oneFrame' :: forall env audio engine proofA res. Scene env audio engine proofA res -> env -> (M.Map String AnAudioUnit /\ M.Map String (Set String) /\ Array (audio -> engine) /\ res /\ Scene env audio engine proofA res) +oneFrame' :: forall env audio engine proofA res. Scene env audio engine proofA res -> env -> (Array (audio -> engine) /\ res /\ Scene env audio engine proofA res) oneFrame' s e = go (oneFrame s e) where - go x = nodes /\ edges /\ instructions /\ res /\ next + go x = instructions /\ res /\ next where - { nodes, edges, instructions, res, next } = x + { instructions, res, next } = x -- | Type used for the internal representation of the current audio state. type AudioState' audio (engine :: Type) res = { res :: res , instructions :: Array (audio -> engine) - , internalNodes :: M.Map String (AnAudioUnit) - , internalEdges :: M.Map String (Set String) } -- | "For office use only" way to access the innards of a frame. Obliterates type safety. Use at your own risk. diff --git a/src/WAGS/Create.purs b/src/WAGS/Create.purs index d8e9cfff..a297a1cc 100644 --- a/src/WAGS/Create.purs +++ b/src/WAGS/Create.purs @@ -1,13 +1,12 @@ module WAGS.Create where import Prelude + import Control.Comonad (extract) import Data.Either (Either(..)) import Data.Functor (voidRight) -import Data.Map as M -import Data.Maybe (Maybe(..)) import Data.Symbol (class IsSymbol, reflectSymbol) -import Data.Tuple (Tuple, fst) +import Data.Tuple (Tuple) import Data.Tuple.Nested ((/\), type (/\)) import Data.Vec as V import Heterogeneous.Folding (class FoldingWithIndex, class HFoldlWithIndex, hfoldlWithIndex) @@ -17,13 +16,13 @@ import WAGS.Connect (ConnectFoldingWithIndex(..)) import WAGS.Control.Indexed (IxWAG(..)) import WAGS.Control.Types (WAG, unsafeUnWAG, unsafeWAG) import WAGS.Edgeable (class Edgeable, withEdge) +import WAGS.Graph.AudioUnit (OnOff) import WAGS.Graph.AudioUnit as CTOR import WAGS.Graph.Graph (Graph) import WAGS.Graph.Node (NodeC) import WAGS.Graph.Oversample (class IsOversample, reflectOversample) -import WAGS.Graph.Parameter (AudioParameter_(..), AudioParameter, defaultParam) +import WAGS.Graph.Parameter (class Paramable, paramize) import WAGS.Interpret (class AudioInterpret, makeAllpass, makeBandpass, makeConstant, makeConvolver, makeDelay, makeDynamicsCompressor, makeGain, makeHighpass, makeHighshelf, makeLoopBuf, makeLowpass, makeLowshelf, makeMicrophone, makeNotch, makePeaking, makePeriodicOsc, makePeriodicOscV, makePlayBuf, makeRecorder, makeSawtoothOsc, makeSinOsc, makeSpeaker, makeSquareOsc, makeStereoPanner, makeTriangleOsc, makeWaveShaper) -import WAGS.Rendered (AnAudioUnit(..)) import WAGS.Util (tmap) data CreateFoldingWithIndex @@ -314,20 +313,6 @@ icreate' :: IxWAG audio engine proof res { | i } { | o } Unit icreate' ptr node = IxWAG (create' ptr <<< voidRight node) --- | A value that can be coerced to an initial control-rate audio parameter. -class InitialVal a where - initialVal :: a -> AudioParameter - -instance initialValNumber :: InitialVal Number where - initialVal a = AudioParameter $ defaultParam { param = Just a } - -instance initialValAudioParameter :: InitialVal AudioParameter where - initialVal = identity - --- convention of getter and setter -instance initialValTuple :: InitialVal a => InitialVal (Tuple a b) where - initialVal = initialVal <<< fst - instance createUnit :: Create' ptr @@ -338,8 +323,8 @@ instance createUnit :: instance createAllpass :: ( IsSymbol ptr - , InitialVal argA - , InitialVal argB + , Paramable argA + , Paramable argB , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.TAllpass {}) graphi grapho ) => @@ -354,24 +339,23 @@ instance createAllpass :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA - argB_iv' = initialVal argB + argB_iv' = paramize argB o = unsafeWAG { context: i - { internalNodes = (M.insert nn (AAllpass argA_iv' argB_iv') i.internalNodes) - , instructions = i.instructions <> [ makeAllpass nn argA_iv' argB_iv' ] + { instructions = i.instructions <> [ makeAllpass nn argA_iv' argB_iv' ] } , value: unit } instance createBandpass :: ( IsSymbol ptr - , InitialVal argA - , InitialVal argB + , Paramable argA + , Paramable argB , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.TBandpass {}) graphi grapho ) => @@ -386,29 +370,28 @@ instance createBandpass :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA - argB_iv' = initialVal argB + argB_iv' = paramize argB o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ABandpass argA_iv' argB_iv') i.internalNodes) - , instructions = i.instructions <> [ makeBandpass nn argA_iv' argB_iv' ] + { instructions = i.instructions <> [ makeBandpass nn argA_iv' argB_iv' ] } , value: unit } instance createConstant :: ( IsSymbol ptr - , InitialVal argA + , Paramable argA , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.TConstant {}) graphi grapho ) => Create' ptr - (CTOR.Constant argA) + (CTOR.Constant OnOff argA) graphi grapho where create' ptr w = o @@ -417,14 +400,13 @@ instance createConstant :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA o = unsafeWAG { context: i - { internalNodes = (M.insert nn (AConstant onOff argA_iv') i.internalNodes) - , instructions = i.instructions <> [ makeConstant nn onOff argA_iv' ] + { instructions = i.instructions <> [ makeConstant nn onOff argA_iv' ] } , value: unit } @@ -452,15 +434,14 @@ instance createConvolver :: unsafeWAG { context: i - { internalNodes = (M.insert nn (AConvolver buffer) i.internalNodes) - , instructions = i.instructions <> [ makeConvolver nn buffer ] + { instructions = i.instructions <> [ makeConvolver nn buffer ] } , value: unit } instance createDelay :: ( IsSymbol ptr - , InitialVal argA + , Paramable argA , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.TDelay {}) graphi grapho ) => @@ -475,25 +456,24 @@ instance createDelay :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ADelay argA_iv') i.internalNodes) - , instructions = i.instructions <> [ makeDelay nn argA_iv' ] + { instructions = i.instructions <> [ makeDelay nn argA_iv' ] } , value: unit } instance createDynamicsCompressor :: ( IsSymbol ptr - , InitialVal argA - , InitialVal argB - , InitialVal argC - , InitialVal argD - , InitialVal argE + , Paramable argA + , Paramable argB + , Paramable argC + , Paramable argD + , Paramable argE , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.TDynamicsCompressor {}) graphi grapho ) => @@ -508,29 +488,28 @@ instance createDynamicsCompressor :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA - argB_iv' = initialVal argB + argB_iv' = paramize argB - argC_iv' = initialVal argC + argC_iv' = paramize argC - argD_iv' = initialVal argD + argD_iv' = paramize argD - argE_iv' = initialVal argE + argE_iv' = paramize argE o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ADynamicsCompressor argA_iv' argB_iv' argC_iv' argD_iv' argE_iv') i.internalNodes) - , instructions = i.instructions <> [ makeDynamicsCompressor nn argA_iv' argB_iv' argC_iv' argD_iv' argE_iv' ] + { instructions = i.instructions <> [ makeDynamicsCompressor nn argA_iv' argB_iv' argC_iv' argD_iv' argE_iv' ] } , value: unit } instance createGain :: ( IsSymbol ptr - , InitialVal argA + , Paramable argA , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.TGain {}) graphi grapho ) => @@ -545,22 +524,21 @@ instance createGain :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA o = unsafeWAG { context: i - { internalNodes = (M.insert nn (AGain argA_iv') i.internalNodes) - , instructions = i.instructions <> [ makeGain nn argA_iv' ] + { instructions = i.instructions <> [ makeGain nn argA_iv' ] } , value: unit } instance createHighpass :: ( IsSymbol ptr - , InitialVal argA - , InitialVal argB + , Paramable argA + , Paramable argB , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.THighpass {}) graphi grapho ) => @@ -575,24 +553,23 @@ instance createHighpass :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA - argB_iv' = initialVal argB + argB_iv' = paramize argB o = unsafeWAG { context: i - { internalNodes = (M.insert nn (AHighpass argA_iv' argB_iv') i.internalNodes) - , instructions = i.instructions <> [ makeHighpass nn argA_iv' argB_iv' ] + { instructions = i.instructions <> [ makeHighpass nn argA_iv' argB_iv' ] } , value: unit } instance createHighshelf :: ( IsSymbol ptr - , InitialVal argA - , InitialVal argB + , Paramable argA + , Paramable argB , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.THighshelf {}) graphi grapho ) => @@ -607,29 +584,28 @@ instance createHighshelf :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA - argB_iv' = initialVal argB + argB_iv' = paramize argB o = unsafeWAG { context: i - { internalNodes = (M.insert nn (AHighshelf argA_iv' argB_iv') i.internalNodes) - , instructions = i.instructions <> [ makeHighshelf nn argA_iv' argB_iv' ] + { instructions = i.instructions <> [ makeHighshelf nn argA_iv' argB_iv' ] } , value: unit } instance createLoopBuf :: ( IsSymbol ptr - , InitialVal argA + , Paramable argA , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.TLoopBuf {}) graphi grapho ) => Create' ptr - (CTOR.LoopBuf argA) + (CTOR.LoopBuf String OnOff argA Number Number) graphi grapho where create' ptr w = o @@ -638,22 +614,21 @@ instance createLoopBuf :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ALoopBuf bufname onOff argA_iv' loopStart loopEnd) i.internalNodes) - , instructions = i.instructions <> [ makeLoopBuf nn bufname onOff argA_iv' loopStart loopEnd ] + { instructions = i.instructions <> [ makeLoopBuf nn bufname onOff argA_iv' loopStart loopEnd ] } , value: unit } instance createLowpass :: ( IsSymbol ptr - , InitialVal argA - , InitialVal argB + , Paramable argA + , Paramable argB , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.TLowpass {}) graphi grapho ) => @@ -668,24 +643,23 @@ instance createLowpass :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA - argB_iv' = initialVal argB + argB_iv' = paramize argB o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ALowpass argA_iv' argB_iv') i.internalNodes) - , instructions = i.instructions <> [ makeLowpass nn argA_iv' argB_iv' ] + { instructions = i.instructions <> [ makeLowpass nn argA_iv' argB_iv' ] } , value: unit } instance createLowshelf :: ( IsSymbol ptr - , InitialVal argA - , InitialVal argB + , Paramable argA + , Paramable argB , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.TLowshelf {}) graphi grapho ) => @@ -700,16 +674,15 @@ instance createLowshelf :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA - argB_iv' = initialVal argB + argB_iv' = paramize argB o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ALowshelf argA_iv' argB_iv') i.internalNodes) - , instructions = i.instructions <> [ makeLowshelf nn argA_iv' argB_iv' ] + { instructions = i.instructions <> [ makeLowshelf nn argA_iv' argB_iv' ] } , value: unit } @@ -733,16 +706,15 @@ instance createMicrophone :: unsafeWAG { context: i - { internalNodes = (M.insert nn AMicrophone i.internalNodes) - , instructions = i.instructions <> [ makeMicrophone ] + { instructions = i.instructions <> [ makeMicrophone ] } , value: unit } instance createNotch :: ( IsSymbol ptr - , InitialVal argA - , InitialVal argB + , Paramable argA + , Paramable argB , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.TNotch {}) graphi grapho ) => @@ -757,25 +729,24 @@ instance createNotch :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA - argB_iv' = initialVal argB + argB_iv' = paramize argB o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ANotch argA_iv' argB_iv') i.internalNodes) - , instructions = i.instructions <> [ makeNotch nn argA_iv' argB_iv' ] + { instructions = i.instructions <> [ makeNotch nn argA_iv' argB_iv' ] } , value: unit } instance createPeaking :: ( IsSymbol ptr - , InitialVal argA - , InitialVal argB - , InitialVal argC + , Paramable argA + , Paramable argB + , Paramable argC , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.TPeaking {}) graphi grapho ) => @@ -790,31 +761,30 @@ instance createPeaking :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA - argB_iv' = initialVal argB + argB_iv' = paramize argB - argC_iv' = initialVal argC + argC_iv' = paramize argC o = unsafeWAG { context: i - { internalNodes = (M.insert nn (APeaking argA_iv' argB_iv' argC_iv') i.internalNodes) - , instructions = i.instructions <> [ makePeaking nn argA_iv' argB_iv' argC_iv' ] + { instructions = i.instructions <> [ makePeaking nn argA_iv' argB_iv' argC_iv' ] } , value: unit } instance createPeriodicOsc :: ( IsSymbol ptr - , InitialVal argA + , Paramable argA , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.TPeriodicOsc {}) graphi grapho ) => Create' ptr - (CTOR.PeriodicOsc String argA) + (CTOR.PeriodicOsc String OnOff argA) graphi grapho where create' ptr w = o @@ -823,27 +793,26 @@ instance createPeriodicOsc :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA o = unsafeWAG { context: i - { internalNodes = (M.insert nn (APeriodicOsc (Left oscName) onOff argA_iv') i.internalNodes) - , instructions = i.instructions <> [ makePeriodicOsc nn oscName onOff argA_iv' ] + { instructions = i.instructions <> [ makePeriodicOsc nn oscName onOff argA_iv' ] } , value: unit } instance createPeriodicOsc2 :: ( IsSymbol ptr - , InitialVal argA + , Paramable argA , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.TPeriodicOsc {}) graphi grapho ) => Create' ptr - (CTOR.PeriodicOsc (V.Vec a Number /\ V.Vec a Number) argA) + (CTOR.PeriodicOsc (V.Vec a Number /\ V.Vec a Number) OnOff argA) graphi grapho where create' ptr w = o @@ -852,7 +821,7 @@ instance createPeriodicOsc2 :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA rPeriodicWave = Right (tmap V.toArray oscSpec) @@ -860,21 +829,20 @@ instance createPeriodicOsc2 :: unsafeWAG { context: i - { internalNodes = (M.insert nn (APeriodicOsc rPeriodicWave onOff argA_iv') i.internalNodes) - , instructions = i.instructions <> [ makePeriodicOscV nn oscSpec onOff argA_iv' ] + { instructions = i.instructions <> [ makePeriodicOscV nn oscSpec onOff argA_iv' ] } , value: unit } instance createPlayBuf :: ( IsSymbol ptr - , InitialVal argA + , Paramable argA , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.TPlayBuf {}) graphi grapho ) => Create' ptr - (CTOR.PlayBuf argA) + (CTOR.PlayBuf String Number OnOff argA) graphi grapho where create' ptr w = o @@ -883,14 +851,13 @@ instance createPlayBuf :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA o = unsafeWAG { context: i - { internalNodes = (M.insert nn (APlayBuf bufname offset onOff argA_iv') i.internalNodes) - , instructions = i.instructions <> [ makePlayBuf nn bufname offset onOff argA_iv' ] + { instructions = i.instructions <> [ makePlayBuf nn bufname offset onOff argA_iv' ] } , value: unit } @@ -918,21 +885,20 @@ instance createRecorder :: unsafeWAG { context: i - { internalNodes = (M.insert nn (ARecorder recorder) i.internalNodes) - , instructions = i.instructions <> [ makeRecorder nn recorder ] + { instructions = i.instructions <> [ makeRecorder nn recorder ] } , value: unit } instance createSawtoothOsc :: ( IsSymbol ptr - , InitialVal argA + , Paramable argA , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.TSawtoothOsc {}) graphi grapho ) => Create' ptr - (CTOR.SawtoothOsc argA) + (CTOR.SawtoothOsc OnOff argA) graphi grapho where create' ptr w = o @@ -941,27 +907,26 @@ instance createSawtoothOsc :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ASawtoothOsc onOff argA_iv') i.internalNodes) - , instructions = i.instructions <> [ makeSawtoothOsc nn onOff argA_iv' ] + { instructions = i.instructions <> [ makeSawtoothOsc nn onOff argA_iv' ] } , value: unit } instance createSinOsc :: ( IsSymbol ptr - , InitialVal argA + , Paramable argA , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.TSinOsc {}) graphi grapho ) => Create' ptr - (CTOR.SinOsc argA) + (CTOR.SinOsc OnOff argA) graphi grapho where create' ptr w = o @@ -970,14 +935,13 @@ instance createSinOsc :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ASinOsc onOff argA_iv') i.internalNodes) - , instructions = i.instructions <> [ makeSinOsc nn onOff argA_iv' ] + { instructions = i.instructions <> [ makeSinOsc nn onOff argA_iv' ] } , value: unit } @@ -1001,21 +965,20 @@ instance createSpeaker :: unsafeWAG { context: i - { internalNodes = (M.insert nn ASpeaker i.internalNodes) - , instructions = i.instructions <> [ makeSpeaker ] + { instructions = i.instructions <> [ makeSpeaker ] } , value: unit } instance createSquareOsc :: ( IsSymbol ptr - , InitialVal argA + , Paramable argA , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.TSquareOsc {}) graphi grapho ) => Create' ptr - (CTOR.SquareOsc argA) + (CTOR.SquareOsc OnOff argA) graphi grapho where create' ptr w = o @@ -1024,21 +987,20 @@ instance createSquareOsc :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ASquareOsc onOff argA_iv') i.internalNodes) - , instructions = i.instructions <> [ makeSquareOsc nn onOff argA_iv' ] + { instructions = i.instructions <> [ makeSquareOsc nn onOff argA_iv' ] } , value: unit } instance createStereoPanner :: ( IsSymbol ptr - , InitialVal argA + , Paramable argA , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.TStereoPanner {}) graphi grapho ) => @@ -1053,27 +1015,26 @@ instance createStereoPanner :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA o = unsafeWAG { context: i - { internalNodes = (M.insert nn (AStereoPanner argA_iv') i.internalNodes) - , instructions = i.instructions <> [ makeStereoPanner nn argA_iv' ] + { instructions = i.instructions <> [ makeStereoPanner nn argA_iv' ] } , value: unit } instance createTriangleOsc :: ( IsSymbol ptr - , InitialVal argA + , Paramable argA , R.Lacks ptr graphi , R.Cons ptr (NodeC CTOR.TTriangleOsc {}) graphi grapho ) => Create' ptr - (CTOR.TriangleOsc argA) + (CTOR.TriangleOsc OnOff argA) graphi grapho where create' ptr w = o @@ -1082,14 +1043,13 @@ instance createTriangleOsc :: nn = reflectSymbol ptr - argA_iv' = initialVal argA + argA_iv' = paramize argA o = unsafeWAG { context: i - { internalNodes = (M.insert nn (ATriangleOsc onOff argA_iv') i.internalNodes) - , instructions = i.instructions <> [ makeTriangleOsc nn onOff argA_iv' ] + { instructions = i.instructions <> [ makeTriangleOsc nn onOff argA_iv' ] } , value: unit } @@ -1120,8 +1080,7 @@ instance createWaveShaper :: unsafeWAG { context: i - { internalNodes = (M.insert nn (AWaveShaper floatArray oversample) i.internalNodes) - , instructions = i.instructions <> [ makeWaveShaper nn floatArray oversample ] + { instructions = i.instructions <> [ makeWaveShaper nn floatArray oversample ] } , value: unit } diff --git a/src/WAGS/Create/Optionals.purs b/src/WAGS/Create/Optionals.purs new file mode 100644 index 00000000..004b567d --- /dev/null +++ b/src/WAGS/Create/Optionals.purs @@ -0,0 +1,945 @@ +-- | This module provides functions for the construction of audio units that more closely resemble the overloaded constructors of the Web Audio API. +module WAGS.Create.Optionals where + +import Prelude +import ConvertableOptions (class ConvertOption, class ConvertOptionsWithDefaults, convertOptionsWithDefaults) +import Data.Symbol (class IsSymbol) +import Data.Tuple (Tuple(..)) +import Data.Tuple.Nested ((/\), type (/\)) +import Data.Vec as V +import Type.Proxy (Proxy) +import WAGS.Graph.AudioUnit (OnOff(..)) +import WAGS.Graph.AudioUnit as CTOR +import WAGS.Graph.Oversample (class IsOversample) +import WAGS.Graph.Parameter (class Paramable, AudioParameter, paramize) + +----------- +data Allpass + = Allpass + +instance convertAllpassFrequency :: Paramable a => ConvertOption Allpass "freq" a AudioParameter where + convertOption _ _ = paramize + +instance convertAllpassQ :: Paramable a => ConvertOption Allpass "q" a AudioParameter where + convertOption _ _ = paramize + +type AllpassOptional + = ( q :: AudioParameter ) + +type AllpassAll + = ( freq :: AudioParameter + | AllpassOptional + ) + +defaultAllpass :: { | AllpassOptional } +defaultAllpass = { q: pure 1.0 } + +class AllpassCtor i allpass | i -> allpass where + -- | Create an allpass filter, connecting it to another unit + -- | + -- | ```purescript + -- | allpass { freq: 440.0 } { sinOsc: unit } + -- | allpass { freq: 440.0, q: 1.0 } { sinOsc: unit } + -- | allpass 440.0 { sinOsc: unit } + -- | ``` + allpass :: i -> allpass + +instance allpassCtor1 :: + ( ConvertOptionsWithDefaults Allpass { | AllpassOptional } { | provided } { | AllpassAll } + ) => + AllpassCtor { | provided } (b -> CTOR.Allpass AudioParameter AudioParameter /\ b) where + allpass provided b = CTOR.Allpass all.freq all.q /\ b + where + all :: { | AllpassAll } + all = convertOptionsWithDefaults Allpass defaultAllpass provided +else instance allpassCtor2 :: Paramable a => AllpassCtor a (b -> CTOR.Allpass AudioParameter AudioParameter /\ b) where + allpass a b = CTOR.Allpass (paramize a) defaultAllpass.q /\ b + +type CAllpass a + = CTOR.Allpass AudioParameter AudioParameter /\ a + +------ +data Bandpass + = Bandpass + +instance convertBandpassFrequency :: Paramable a => ConvertOption Bandpass "freq" a AudioParameter where + convertOption _ _ = paramize + +instance convertBandpassQ :: Paramable a => ConvertOption Bandpass "q" a AudioParameter where + convertOption _ _ = paramize + +type BandpassOptional + = ( q :: AudioParameter ) + +type BandpassAll + = ( freq :: AudioParameter + | BandpassOptional + ) + +defaultBandpass :: { | BandpassOptional } +defaultBandpass = { q: pure 1.0 } + +class BandpassCtor i bandpass | i -> bandpass where + -- | Create a bandpass filter, connecting it to another unit + -- | + -- | ```purescript + -- | bandpass { freq: 440.0 } { sinOsc: unit } + -- | bandpass { freq: 440.0, q: 1.0 } { sinOsc: unit } + -- | bandpass 440.0 { sinOsc: unit } + -- | ``` + bandpass :: i -> bandpass + +instance bandpassCtor1 :: + ( ConvertOptionsWithDefaults Bandpass { | BandpassOptional } { | provided } { | BandpassAll } + ) => + BandpassCtor { | provided } (b -> CTOR.Bandpass AudioParameter AudioParameter /\ b) where + bandpass provided b = CTOR.Bandpass all.freq all.q /\ b + where + all :: { | BandpassAll } + all = convertOptionsWithDefaults Bandpass defaultBandpass provided +else instance bandpassCtor2 :: Paramable a => BandpassCtor a (b -> CTOR.Bandpass AudioParameter AudioParameter /\ b) where + bandpass a b = CTOR.Bandpass (paramize a) defaultBandpass.q /\ b + +type CBandpass a + = CTOR.Bandpass AudioParameter AudioParameter /\ a + +------ +data Constant + = Constant + +instance convertConstantFrequency :: Paramable a => ConvertOption Constant "offset" a AudioParameter where + convertOption _ _ = paramize + +instance convertConstantOnOff :: ConvertOption Constant "onOff" OnOff OnOff where + convertOption _ _ = identity + +type ConstantOptional + = ( onOff :: OnOff ) + +type ConstantAll + = ( offset :: AudioParameter + | ConstantOptional + ) + +defaultConstant :: { | ConstantOptional } +defaultConstant = { onOff: On } + +class ConstantCtor i o | i -> o where + -- | Make a constant value + -- | + -- | ```purescript + -- | constant 0.5 + -- | ``` + constant :: i -> o + +instance constantCtor1 :: + ( ConvertOptionsWithDefaults Constant { | ConstantOptional } { | provided } { | ConstantAll } + ) => + ConstantCtor { | provided } (CTOR.Constant OnOff AudioParameter /\ {}) where + constant provided = CTOR.Constant all.onOff all.offset /\ {} + where + all :: { | ConstantAll } + all = convertOptionsWithDefaults Constant defaultConstant provided +else instance constantCtor2 :: Paramable a => ConstantCtor a (CTOR.Constant OnOff AudioParameter /\ {}) where + constant a = CTOR.Constant defaultConstant.onOff (paramize a) /\ {} + +type CConstant + = CTOR.Constant OnOff AudioParameter /\ {} + +------ +-- | Make a convolver, aka reverb. +-- | +-- | ```purescript +-- | convolver (Proxy :: _ "room") (playBuf "track") +-- | ``` +convolver :: + forall s b. + IsSymbol s => + Proxy s -> b -> CTOR.Convolver s /\ b +convolver = Tuple <<< CTOR.Convolver + +type CConvolver a b + = CTOR.Convolver a /\ b + +------ +-- | Make a delay unit. +-- | +-- | ```purescript +-- | delay 0.5 (playBuf "track") +-- | ``` +delay :: + forall a b. + Paramable a => + a -> b -> CTOR.Delay AudioParameter /\ b +delay gvsv = Tuple (CTOR.Delay (paramize gvsv)) + +type CDelay a + = CTOR.Delay AudioParameter /\ a + +------ +data DynamicsCompressor + = DynamicsCompressor + +instance convertDynamicsCompressorThreshold :: Paramable a => ConvertOption DynamicsCompressor "threshold" a AudioParameter where + convertOption _ _ = paramize + +instance convertDynamicsCompressorKnee :: Paramable a => ConvertOption DynamicsCompressor "knee" a AudioParameter where + convertOption _ _ = paramize + +instance convertDynamicsCompressorRatio :: Paramable a => ConvertOption DynamicsCompressor "ratio" a AudioParameter where + convertOption _ _ = paramize + +instance convertDynamicsCompressorAttack :: Paramable a => ConvertOption DynamicsCompressor "attack" a AudioParameter where + convertOption _ _ = paramize + +instance convertDynamicsCompressorRelease :: Paramable a => ConvertOption DynamicsCompressor "release" a AudioParameter where + convertOption _ _ = paramize + +type DynamicsCompressorOptional + = ( threshold :: AudioParameter + , knee :: AudioParameter + , ratio :: AudioParameter + , attack :: AudioParameter + , release :: AudioParameter + ) + +type DynamicsCompressorAll + = ( + | DynamicsCompressorOptional + ) + +defaultDynamicsCompressor :: { | DynamicsCompressorOptional } +defaultDynamicsCompressor = + { threshold: pure (-24.0) + , knee: pure 30.0 + , ratio: pure 12.0 + , attack: pure 0.003 + , release: pure 0.25 + } + +class DynamicsCompressorCtor i compressor | i -> compressor where + -- | Make a compressor. + -- | + -- | ```purescript + -- | compressor { threshold: -10.0 } { buf: playBuf "track" } + -- | compressor { knee: 20.0, ratio: 10.0 } { buf: playBuf "track" } + -- | compressor { attack: 0.01, release: 0.3 } { buf: playBuf "track" } + -- | ``` + compressor :: i -> compressor + +instance compressorCTor :: + ( ConvertOptionsWithDefaults DynamicsCompressor { | DynamicsCompressorOptional } { | provided } { | DynamicsCompressorAll } + ) => + DynamicsCompressorCtor { | provided } (b -> CTOR.DynamicsCompressor AudioParameter AudioParameter AudioParameter AudioParameter AudioParameter /\ b) where + compressor provided b = + CTOR.DynamicsCompressor + all.threshold + all.knee + all.ratio + all.attack + all.release + /\ b + where + all :: { | DynamicsCompressorAll } + all = convertOptionsWithDefaults DynamicsCompressor defaultDynamicsCompressor provided + +type CDynamicsCompressor a + = CTOR.DynamicsCompressor AudioParameter AudioParameter AudioParameter AudioParameter AudioParameter /\ a + +------ +gain :: forall a b. Paramable a => a -> b -> CTOR.Gain AudioParameter /\ b +gain a = Tuple (CTOR.Gain (paramize a)) + +-- | Mix together several audio units +-- | +-- | ```purescript +-- | mix (playBuf (Proxy :: _ "hello") /\ playBuf (Proxy :: _ "world") /\ unit) +-- | ``` +mix :: forall a. a -> CTOR.Gain AudioParameter /\ a +mix = Tuple (CTOR.Gain (pure 1.0)) + +type Mix + = CTOR.Gain AudioParameter + +type CGain a + = CTOR.Gain AudioParameter /\ a + +------ +data Highpass + = Highpass + +instance convertHighpassFrequency :: Paramable a => ConvertOption Highpass "freq" a AudioParameter where + convertOption _ _ = paramize + +instance convertHighpassQ :: Paramable a => ConvertOption Highpass "q" a AudioParameter where + convertOption _ _ = paramize + +type HighpassOptional + = ( q :: AudioParameter ) + +type HighpassAll + = ( freq :: AudioParameter + | HighpassOptional + ) + +defaultHighpass :: { | HighpassOptional } +defaultHighpass = { q: pure 1.0 } + +class HighpassCtor i highpass | i -> highpass where + -- | Make a highpass filter + -- | + -- | ```purescript + -- | highpass { freq: 440.0 } { osc: sinOsc 440.0 } + -- | highpass { freq: 440.0, q: 1.0 } { osc: sinOsc 440.0 } + -- | highpass 440.0 { osc: sinOsc 440.0 } + -- | ``` + highpass :: i -> highpass + +instance highpassCtor1 :: + ( ConvertOptionsWithDefaults Highpass { | HighpassOptional } { | provided } { | HighpassAll } + ) => + HighpassCtor { | provided } (b -> CTOR.Highpass AudioParameter AudioParameter /\ b) where + highpass provided = Tuple (CTOR.Highpass all.freq all.q) + where + all :: { | HighpassAll } + all = convertOptionsWithDefaults Highpass defaultHighpass provided +else instance highpassCtor2 :: Paramable a => HighpassCtor a (b -> CTOR.Highpass AudioParameter AudioParameter /\ b) where + highpass a = Tuple (CTOR.Highpass (paramize a) defaultHighpass.q) + +type CHighpass a + = CTOR.Highpass AudioParameter AudioParameter /\ a + +------ +data Highshelf + = Highshelf + +instance convertHighshelfFrequency :: Paramable a => ConvertOption Highshelf "freq" a AudioParameter where + convertOption _ _ = paramize + +instance convertHighshelfQ :: Paramable a => ConvertOption Highshelf "gain" a AudioParameter where + convertOption _ _ = paramize + +type HighshelfOptional + = ( gain :: AudioParameter ) + +type HighshelfAll + = ( freq :: AudioParameter + | HighshelfOptional + ) + +defaultHighshelf :: { | HighshelfOptional } +defaultHighshelf = { gain: pure 0.0 } + +class HighshelfCtor i highshelf | i -> highshelf where + -- | Make a highshelf filter + -- | + -- | ```purescript + -- | highshelf { freq: 440.0 } { osc: sinOsc 440.0 } + -- | highshelf { freq: 440.0, gain: 1.0 } { osc: sinOsc 440.0 } + -- | highshelf 440.0 { osc: sinOsc 440.0 } + -- | ``` + highshelf :: i -> highshelf + +instance highshelfCtor1 :: + ( ConvertOptionsWithDefaults Highshelf { | HighshelfOptional } { | provided } { | HighshelfAll } + ) => + HighshelfCtor { | provided } (b -> CTOR.Highshelf AudioParameter AudioParameter /\ b) where + highshelf provided = Tuple (CTOR.Highshelf all.freq all.gain) + where + all :: { | HighshelfAll } + all = convertOptionsWithDefaults Highshelf defaultHighshelf provided +else instance highshelfCtor2 :: Paramable a => HighshelfCtor a (b -> CTOR.Highshelf AudioParameter AudioParameter /\ b) where + highshelf a = Tuple (CTOR.Highshelf (paramize a) defaultHighshelf.gain) + +type CHighshelf a + = CTOR.Highshelf AudioParameter AudioParameter /\ a + +---- +data LoopBuf + = LoopBuf + +instance convertLoopBufPlaybackRate :: Paramable a => ConvertOption LoopBuf "playbackRate" a AudioParameter where + convertOption _ _ = paramize + +instance convertLoopBufOnOff :: ConvertOption LoopBuf "onOff" OnOff OnOff where + convertOption _ _ = identity + +instance convertLoopBufStart :: ConvertOption LoopBuf "loopStart" Number Number where + convertOption _ _ = identity + +instance convertLoopBufEnd :: ConvertOption LoopBuf "loopEnd" Number Number where + convertOption _ _ = identity + +type LoopBufOptional + = ( playbackRate :: AudioParameter, onOff :: OnOff, loopStart :: Number, loopEnd :: Number ) + +type LoopBufAll + = ( | LoopBufOptional ) + +defaultLoopBuf :: { | LoopBufOptional } +defaultLoopBuf = { playbackRate: pure 1.0, onOff: On, loopStart: 0.0, loopEnd: 0.0 } + +class LoopBufCtor i loopBuf | i -> loopBuf where + -- | Make a looping buffer. + -- | + -- | ```purescript + -- | loopBuf { playbackRate: 1.0 } "track" + -- | loopBuf { playbackRate: 1.0, loopStart: 0.5 } "track" + -- | loopBuf "track" + -- | ``` + loopBuf :: i -> loopBuf + +instance loopBufCtor1 :: + ( ConvertOptionsWithDefaults LoopBuf { | LoopBufOptional } { | provided } { | LoopBufAll } + ) => + LoopBufCtor { | provided } (String -> CTOR.LoopBuf String OnOff AudioParameter Number Number /\ {}) where + loopBuf provided proxy = CTOR.LoopBuf proxy all.onOff all.playbackRate all.loopStart all.loopEnd /\ {} + where + all :: { | LoopBufAll } + all = convertOptionsWithDefaults LoopBuf defaultLoopBuf provided +else instance loopBufCtor2 :: LoopBufCtor String (CTOR.LoopBuf String OnOff AudioParameter Number Number /\ {}) where + loopBuf name = + CTOR.LoopBuf + name + defaultLoopBuf.onOff + defaultLoopBuf.playbackRate + defaultLoopBuf.loopStart + defaultLoopBuf.loopEnd + /\ {} + +type CLoopBuf + = CTOR.LoopBuf String OnOff AudioParameter Number Number /\ {} + +----- +data Lowpass + = Lowpass + +instance convertLowpassFrequency :: Paramable a => ConvertOption Lowpass "freq" a AudioParameter where + convertOption _ _ = paramize + +instance convertLowpassQ :: Paramable a => ConvertOption Lowpass "q" a AudioParameter where + convertOption _ _ = paramize + +type LowpassOptional + = ( q :: AudioParameter ) + +type LowpassAll + = ( freq :: AudioParameter + | LowpassOptional + ) + +defaultLowpass :: { | LowpassOptional } +defaultLowpass = { q: pure 1.0 } + +class LowpassCtor i lowpass | i -> lowpass where + -- | Make a lowpass filter + -- | + -- | ```purescript + -- | lowpass { freq: 440.0 } { osc: sinOsc 440.0 } + -- | lowpass { freq: 440.0, q: 1.0 } { osc: sinOsc 440.0 } + -- | lowpass 440.0 { osc: sinOsc 440.0 } + -- | ``` + lowpass :: i -> lowpass + +instance lowpassCtor1 :: + ( ConvertOptionsWithDefaults Lowpass { | LowpassOptional } { | provided } { | LowpassAll } + ) => + LowpassCtor { | provided } (b -> CTOR.Lowpass AudioParameter AudioParameter /\ b) where + lowpass provided = Tuple (CTOR.Lowpass all.freq all.q) + where + all :: { | LowpassAll } + all = convertOptionsWithDefaults Lowpass defaultLowpass provided +else instance lowpassCtor2 :: Paramable a => LowpassCtor a (b -> CTOR.Lowpass AudioParameter AudioParameter /\ b) where + lowpass a = Tuple (CTOR.Lowpass (paramize a) defaultLowpass.q) + +type CLowpass a + = CTOR.Lowpass AudioParameter AudioParameter /\ a + +----- +data Lowshelf + = Lowshelf + +instance convertLowshelfFrequency :: Paramable a => ConvertOption Lowshelf "freq" a AudioParameter where + convertOption _ _ = paramize + +instance convertLowshelfQ :: Paramable a => ConvertOption Lowshelf "gain" a AudioParameter where + convertOption _ _ = paramize + +type LowshelfOptional + = ( gain :: AudioParameter ) + +type LowshelfAll + = ( freq :: AudioParameter + | LowshelfOptional + ) + +defaultLowshelf :: { | LowshelfOptional } +defaultLowshelf = { gain: pure 0.0 } + +class LowshelfCtor i lowshelf | i -> lowshelf where + -- | Make a lowshelf filter + -- | + -- | ```purescript + -- | lowshelf { freq: 440.0 } { osc: sinOsc 440.0 } + -- | lowshelf { freq: 440.0, gain: 1.0 } { osc: sinOsc 440.0 } + -- | lowshelf 440.0 { osc: sinOsc 440.0 } + -- | ``` + lowshelf :: i -> lowshelf + +instance lowshelfCtor1 :: + ( ConvertOptionsWithDefaults Lowshelf { | LowshelfOptional } { | provided } { | LowshelfAll } + ) => + LowshelfCtor { | provided } (b -> CTOR.Lowshelf AudioParameter AudioParameter /\ b) where + lowshelf provided = Tuple (CTOR.Lowshelf all.freq all.gain) + where + all :: { | LowshelfAll } + all = convertOptionsWithDefaults Lowshelf defaultLowshelf provided +else instance lowshelfCtor2 :: Paramable a => LowshelfCtor a (b -> CTOR.Lowshelf AudioParameter AudioParameter /\ b) where + lowshelf a = Tuple (CTOR.Lowshelf (paramize a) defaultLowshelf.gain) + +type CLowshelf a + = CTOR.Lowshelf AudioParameter AudioParameter /\ a + +-------- +microphone :: CTOR.Microphone /\ {} +microphone = CTOR.Microphone /\ {} + +type CMicrophone + = CTOR.Microphone /\ {} + +-------- +data Notch + = Notch + +instance convertNotchFrequency :: Paramable a => ConvertOption Notch "freq" a AudioParameter where + convertOption _ _ = paramize + +instance convertNotchQ :: Paramable a => ConvertOption Notch "q" a AudioParameter where + convertOption _ _ = paramize + +type NotchOptional + = ( q :: AudioParameter ) + +type NotchAll + = ( freq :: AudioParameter + | NotchOptional + ) + +defaultNotch :: { | NotchOptional } +defaultNotch = { q: pure 1.0 } + +class NotchCtor i notch | i -> notch where + -- | Make a notch (band-reject) filter + -- | + -- | ```purescript + -- | notch { freq: 440.0 } { osc: sinOsc 440.0 } + -- | notch { freq: 440.0, gain: 1.0 } { osc: sinOsc 440.0 } + -- | notch 440.0 { osc: sinOsc 440.0 } + -- | ``` + notch :: i -> notch + +instance notchCtor1 :: + ( ConvertOptionsWithDefaults Notch { | NotchOptional } { | provided } { | NotchAll } + ) => + NotchCtor { | provided } (b -> CTOR.Notch AudioParameter AudioParameter /\ b) where + notch provided = Tuple (CTOR.Notch all.freq all.q) + where + all :: { | NotchAll } + all = convertOptionsWithDefaults Notch defaultNotch provided +else instance notchCtor2 :: Paramable a => NotchCtor a (b -> CTOR.Notch AudioParameter AudioParameter /\ b) where + notch a = Tuple (CTOR.Notch (paramize a) defaultNotch.q) + +type CNotch a + = CTOR.Notch AudioParameter AudioParameter /\ a + +---------------- +data Peaking + = Peaking + +instance convertPeakingFrequency :: Paramable a => ConvertOption Peaking "freq" a AudioParameter where + convertOption _ _ = paramize + +instance convertPeakingQ :: Paramable a => ConvertOption Peaking "q" a AudioParameter where + convertOption _ _ = paramize + +instance convertPeakingGain :: Paramable a => ConvertOption Peaking "gain" a AudioParameter where + convertOption _ _ = paramize + +type PeakingOptional + = ( q :: AudioParameter, gain :: AudioParameter ) + +type PeakingAll + = ( freq :: AudioParameter + | PeakingOptional + ) + +defaultPeaking :: { | PeakingOptional } +defaultPeaking = { q: pure 1.0, gain: pure 0.0 } + +class PeakingCtor i peaking | i -> peaking where + -- | Make a peaking filter + -- | + -- | ```purescript + -- | peaking { freq: 440.0 } { osc: sinOsc 440.0 } + -- | peaking { freq: 440.0, gain: 1.0 } { osc: sinOsc 440.0 } + -- | peaking 440.0 { osc: sinOsc 440.0 } + -- | ``` + peaking :: i -> peaking + +instance peakingCtor1 :: + ( ConvertOptionsWithDefaults Peaking { | PeakingOptional } { | provided } { | PeakingAll } + ) => + PeakingCtor { | provided } (b -> CTOR.Peaking AudioParameter AudioParameter AudioParameter /\ b) where + peaking provided = Tuple (CTOR.Peaking all.freq all.q all.gain) + where + all :: { | PeakingAll } + all = convertOptionsWithDefaults Peaking defaultPeaking provided +else instance peakingCtor2 :: Paramable a => PeakingCtor a (b -> CTOR.Peaking AudioParameter AudioParameter AudioParameter /\ b) where + peaking a = Tuple (CTOR.Peaking (paramize a) defaultPeaking.q defaultPeaking.gain) + +type CPeaking a + = CTOR.Peaking AudioParameter AudioParameter AudioParameter /\ a + +------ +class CanBeCoercedToPeriodicOsc (canBeCoercedToPeriodicOsc :: Type) + +instance canBeCoercedToPeriodicOscString :: CanBeCoercedToPeriodicOsc String + +instance canBeCoercedToPeriodicOscV :: CanBeCoercedToPeriodicOsc (V.Vec size Number /\ V.Vec size Number) + +data PeriodicOsc + = PeriodicOsc + +instance convertPeriodicOscFrequency :: Paramable a => ConvertOption PeriodicOsc "freq" a AudioParameter where + convertOption _ _ = paramize + +instance convertPeriodicOscOnOff :: ConvertOption PeriodicOsc "onOff" OnOff OnOff where + convertOption _ _ = identity + +instance convertPeriodicOscWave :: CanBeCoercedToPeriodicOsc wave => ConvertOption PeriodicOsc "waveform" wave wave where + convertOption _ _ = identity + +type PeriodicOscOptional + = ( onOff :: OnOff ) + +type PeriodicOscAll wave + = ( freq :: AudioParameter + , wave :: wave + | PeriodicOscOptional + ) + +defaultPeriodicOsc :: { | PeriodicOscOptional } +defaultPeriodicOsc = { onOff: On } + +class PeriodicOscCtor i o | i -> o where + -- | Make a periodicOsc value + -- | + -- | ```purescript + -- | periodicOsc "my-osc" 0.5 + -- | ``` + periodicOsc :: i -> o + +instance periodicOscCtor1 :: + ( ConvertOptionsWithDefaults PeriodicOsc { | PeriodicOscOptional } { | provided } { | PeriodicOscAll wave } + ) => + PeriodicOscCtor { | provided } (CTOR.PeriodicOsc wave OnOff AudioParameter /\ {}) where + periodicOsc provided = CTOR.PeriodicOsc all.wave all.onOff all.freq /\ {} + where + all :: { | PeriodicOscAll wave } + all = convertOptionsWithDefaults PeriodicOsc defaultPeriodicOsc provided +else instance periodicOscCtor2 :: (CanBeCoercedToPeriodicOsc wave, Paramable a) => PeriodicOscCtor wave (a -> CTOR.PeriodicOsc wave OnOff AudioParameter /\ {}) where + periodicOsc wave a = CTOR.PeriodicOsc wave defaultPeriodicOsc.onOff (paramize a) /\ {} + +type CPeriodicOsc periodicOsc + = CTOR.PeriodicOsc periodicOsc OnOff AudioParameter /\ {} + +--- +data PlayBuf + = PlayBuf + +instance convertPlayBufPlaybackRate :: Paramable a => ConvertOption PlayBuf "playbackRate" a AudioParameter where + convertOption _ _ = paramize + +instance convertPlayBufOnOff :: ConvertOption PlayBuf "onOff" OnOff OnOff where + convertOption _ _ = identity + +type PlayBufOptional + = ( playbackRate :: AudioParameter, onOff :: OnOff, bufferOffset :: Number ) + +type PlayBufAll + = ( | PlayBufOptional ) + +defaultPlayBuf :: { | PlayBufOptional } +defaultPlayBuf = { playbackRate: pure 1.0, onOff: On, bufferOffset: 0.0 } + +class PlayBufCtor i playBuf | i -> playBuf where + -- | Make a unit that plays from a buffer. + -- | + -- | ```purescript + -- | playBuf { playbackRate: 1.0 } "track" + -- | playBuf { playbackRate: 1.0, bufferOffset: 0.5 } "track" + -- | playBuf "track" + -- | ``` + playBuf :: i -> playBuf + +instance playBufCtor1 :: + ConvertOptionsWithDefaults PlayBuf { | PlayBufOptional } { | provided } { | PlayBufAll } => + PlayBufCtor { | provided } (String -> CTOR.PlayBuf String Number OnOff AudioParameter /\ {}) where + playBuf provided proxy = CTOR.PlayBuf proxy all.bufferOffset all.onOff all.playbackRate /\ {} + where + all :: { | PlayBufAll } + all = convertOptionsWithDefaults PlayBuf defaultPlayBuf provided +else instance playBufCtor2 :: PlayBufCtor String (CTOR.PlayBuf String Number OnOff AudioParameter /\ {}) where + playBuf str = + CTOR.PlayBuf + str + defaultPlayBuf.bufferOffset + defaultPlayBuf.onOff + defaultPlayBuf.playbackRate + /\ {} + +type CPlayBuf + = CTOR.PlayBuf String Number OnOff AudioParameter /\ {} + +------ +-- | Make a recorder. +-- | +-- | ```purescript +-- | recorder "track" +-- | ``` +recorder :: + forall a b. + IsSymbol a => + Proxy a -> b -> CTOR.Recorder a /\ b +recorder = Tuple <<< CTOR.Recorder + +type CRecorder a b + = CTOR.Recorder a /\ b + +------ +data SawtoothOsc + = SawtoothOsc + +instance convertSawtoothOscFrequency :: Paramable a => ConvertOption SawtoothOsc "freq" a AudioParameter where + convertOption _ _ = paramize + +instance convertSawtoothOscOnOff :: ConvertOption SawtoothOsc "onOff" OnOff OnOff where + convertOption _ _ = identity + +type SawtoothOscOptional + = ( onOff :: OnOff ) + +type SawtoothOscAll + = ( freq :: AudioParameter + | SawtoothOscOptional + ) + +defaultSawtoothOsc :: { | SawtoothOscOptional } +defaultSawtoothOsc = { onOff: On } + +class SawtoothOscCtor i o | i -> o where + -- | Make a sawtoothOsc value + -- | + -- | ```purescript + -- | sawtoothOsc 0.5 + -- | ``` + sawtoothOsc :: i -> o + +instance sawtoothOscCtor1 :: + ( ConvertOptionsWithDefaults SawtoothOsc { | SawtoothOscOptional } { | provided } { | SawtoothOscAll } + ) => + SawtoothOscCtor { | provided } (CTOR.SawtoothOsc OnOff AudioParameter /\ {}) where + sawtoothOsc provided = CTOR.SawtoothOsc all.onOff all.freq /\ {} + where + all :: { | SawtoothOscAll } + all = convertOptionsWithDefaults SawtoothOsc defaultSawtoothOsc provided +else instance sawtoothOscCtor2 :: Paramable a => SawtoothOscCtor a (CTOR.SawtoothOsc OnOff AudioParameter /\ {}) where + sawtoothOsc a = CTOR.SawtoothOsc defaultSawtoothOsc.onOff (paramize a) /\ {} + +type CSawtoothOsc + = CTOR.SawtoothOsc OnOff AudioParameter /\ {} + +------ +data SinOsc + = SinOsc + +instance convertSinOscFrequency :: Paramable a => ConvertOption SinOsc "freq" a AudioParameter where + convertOption _ _ = paramize + +instance convertSinOscOnOff :: ConvertOption SinOsc "onOff" OnOff OnOff where + convertOption _ _ = identity + +type SinOscOptional + = ( onOff :: OnOff ) + +type SinOscAll + = ( freq :: AudioParameter + | SinOscOptional + ) + +defaultSinOsc :: { | SinOscOptional } +defaultSinOsc = { onOff: On } + +class SinOscCtor i o | i -> o where + -- | Make a sinOsc value + -- | + -- | ```purescript + -- | sinOsc 0.5 + -- | ``` + sinOsc :: i -> o + +instance sinOscCtor1 :: + ( ConvertOptionsWithDefaults SinOsc { | SinOscOptional } { | provided } { | SinOscAll } + ) => + SinOscCtor { | provided } (CTOR.SinOsc OnOff AudioParameter /\ {}) where + sinOsc provided = CTOR.SinOsc all.onOff all.freq /\ {} + where + all :: { | SinOscAll } + all = convertOptionsWithDefaults SinOsc defaultSinOsc provided +else instance sinOscCtor2 :: Paramable a => SinOscCtor a (CTOR.SinOsc OnOff AudioParameter /\ {}) where + sinOsc a = CTOR.SinOsc defaultSinOsc.onOff (paramize a) /\ {} + +type CSinOsc + = CTOR.SinOsc OnOff AudioParameter /\ {} + +------ +-- | Send sound to the loudspeaker. +-- | +-- | ```purescript +-- | speaker +-- | ``` +speaker :: forall b. b -> { speaker :: CTOR.Speaker /\ b } +speaker b = { speaker: CTOR.Speaker /\ b } + +-- | The raw constructor for speaker. Probably not useful... +speaker' :: forall b. b -> CTOR.Speaker /\ b +speaker' = Tuple CTOR.Speaker + +type CSpeaker a + = { speaker :: CTOR.Speaker /\ a } + +------ +data SquareOsc + = SquareOsc + +instance convertSquareOscFrequency :: Paramable a => ConvertOption SquareOsc "freq" a AudioParameter where + convertOption _ _ = paramize + +instance convertSquareOscOnOff :: ConvertOption SquareOsc "onOff" OnOff OnOff where + convertOption _ _ = identity + +type SquareOscOptional + = ( onOff :: OnOff ) + +type SquareOscAll + = ( freq :: AudioParameter + | SquareOscOptional + ) + +defaultSquareOsc :: { | SquareOscOptional } +defaultSquareOsc = { onOff: On } + +class SquareOscCtor i o | i -> o where + -- | Make a squareOsc value + -- | + -- | ```purescript + -- | squareOsc 0.5 + -- | ``` + squareOsc :: i -> o + +instance squareOscCtor1 :: + ( ConvertOptionsWithDefaults SquareOsc { | SquareOscOptional } { | provided } { | SquareOscAll } + ) => + SquareOscCtor { | provided } (CTOR.SquareOsc OnOff AudioParameter /\ {}) where + squareOsc provided = CTOR.SquareOsc all.onOff all.freq /\ {} + where + all :: { | SquareOscAll } + all = convertOptionsWithDefaults SquareOsc defaultSquareOsc provided +else instance squareOscCtor2 :: Paramable a => SquareOscCtor a (CTOR.SquareOsc OnOff AudioParameter /\ {}) where + squareOsc a = CTOR.SquareOsc defaultSquareOsc.onOff (paramize a) /\ {} + +type CSquareOsc + = CTOR.SquareOsc OnOff AudioParameter /\ {} + +------ +-- | Pan audio. +-- | +-- | ```purescript +-- | pan 0.5 { buf: playBuf "my-track" } +-- | ``` +pan :: + forall a b. + Paramable a => + a -> b -> CTOR.StereoPanner AudioParameter /\ b +pan gvsv = Tuple (CTOR.StereoPanner (paramize gvsv)) + +type CStereoPanner a + = CTOR.StereoPanner AudioParameter /\ a + +------ +data TriangleOsc + = TriangleOsc + +instance convertTriangleOscFrequency :: Paramable a => ConvertOption TriangleOsc "freq" a AudioParameter where + convertOption _ _ = paramize + +instance convertTriangleOscOnOff :: ConvertOption TriangleOsc "onOff" OnOff OnOff where + convertOption _ _ = identity + +type TriangleOscOptional + = ( onOff :: OnOff ) + +type TriangleOscAll + = ( freq :: AudioParameter + | TriangleOscOptional + ) + +defaultTriangleOsc :: { | TriangleOscOptional } +defaultTriangleOsc = { onOff: On } + +class TriangleOscCtor i o | i -> o where + -- | Make a triangleOsc value + -- | + -- | ```purescript + -- | triangleOsc 0.5 + -- | ``` + triangleOsc :: i -> o + +instance triangleOscCtor1 :: + ( ConvertOptionsWithDefaults TriangleOsc { | TriangleOscOptional } { | provided } { | TriangleOscAll } + ) => + TriangleOscCtor { | provided } (CTOR.TriangleOsc OnOff AudioParameter /\ {}) where + triangleOsc provided = CTOR.TriangleOsc all.onOff all.freq /\ {} + where + all :: { | TriangleOscAll } + all = convertOptionsWithDefaults TriangleOsc defaultTriangleOsc provided +else instance triangleOscCtor2 :: Paramable a => TriangleOscCtor a (CTOR.TriangleOsc OnOff AudioParameter /\ {}) where + triangleOsc a = CTOR.TriangleOsc defaultTriangleOsc.onOff (paramize a) /\ {} + +type CTriangleOsc + = CTOR.TriangleOsc OnOff AudioParameter /\ {} + +---------- +-- | Apply distorion to audio +-- | +-- | ```purescript +-- | waveShaper (Proxy :: _ "my-wave") OversampleNone { buf: playBuf "my-track" } +-- | ``` +waveShaper :: + forall a b c. + IsSymbol a => + IsOversample b => + Proxy a -> b -> c -> CTOR.WaveShaper a b /\ c +waveShaper a = Tuple <<< CTOR.WaveShaper a + +type CWaveShaper a b c + = CTOR.WaveShaper a b /\ c + +--------------- +-- | A reference to a node in a graph. +type Ref + = Unit /\ {} + +-- | A reference to a node in a graph. +ref :: Ref +ref = unit /\ {} diff --git a/src/WAGS/Destroy.purs b/src/WAGS/Destroy.purs index 684a4858..14c6e310 100644 --- a/src/WAGS/Destroy.purs +++ b/src/WAGS/Destroy.purs @@ -1,9 +1,7 @@ module WAGS.Destroy where import Prelude - import Data.Functor (voidRight) -import Data.Map as M import Data.Symbol (class IsSymbol, reflectSymbol) import Data.Tuple.Nested (type (/\)) import Prim.Row as R @@ -42,9 +40,7 @@ instance destroyer :: unsafeWAG $ { context: i - { internalNodes = M.delete ptrI (i.internalNodes) - , internalEdges = M.delete ptrI (i.internalEdges) - , instructions = i.instructions <> [ destroyUnit ptrI ] + { instructions = i.instructions <> [ destroyUnit ptrI ] } , value: unit } diff --git a/src/WAGS/Disconnect.purs b/src/WAGS/Disconnect.purs index b97d9561..f95e6b4b 100644 --- a/src/WAGS/Disconnect.purs +++ b/src/WAGS/Disconnect.purs @@ -1,10 +1,7 @@ module WAGS.Disconnect where import Prelude hiding (Ordering(..)) - import Data.Functor (voidRight) -import Data.Map as M -import Data.Set as S import Data.Symbol (class IsSymbol, reflectSymbol) import Prim.Row as R import WAGS.Control.Indexed (IxWAG(..)) @@ -43,8 +40,7 @@ instance disconnector :: unsafeWAG { context: i - { internalEdges = M.insertWith S.difference toI (S.singleton fromI) (i.internalEdges) - , instructions = i.instructions <> [ disconnectXFromY fromI toI ] + { instructions = i.instructions <> [ disconnectXFromY fromI toI ] } , value: unit } diff --git a/src/WAGS/Graph/AudioUnit.purs b/src/WAGS/Graph/AudioUnit.purs index e4a2e3b8..d6dc639d 100644 --- a/src/WAGS/Graph/AudioUnit.purs +++ b/src/WAGS/Graph/AudioUnit.purs @@ -11,7 +11,6 @@ import Prim.Row as R import Record as Record import Type.Proxy (Proxy(..)) import WAGS.Edgeable (class Edgeable, withEdge) -import WAGS.Graph.Parameter (AudioParameter) -- | Term-level constructor for an allpass filter. -- | - `frequency` - the frequency where the phase transition occurs. @@ -19,42 +18,29 @@ import WAGS.Graph.Parameter (AudioParameter) data Allpass frequency q = Allpass frequency q -type GetAllpass - = Allpass AudioParameter AudioParameter - -- | Term-level constructor for a bandpass filter. -- | - `frequency` - the frequency of the isolated band. -- | - `q` - the width of the filter. data Bandpass frequency q = Bandpass frequency q -type GetBandpass - = Bandpass AudioParameter AudioParameter - -- | Term-level constructor for a constant value, aka DC offset. --- | - `OnOff` - whether the generator is on or off. +-- | - `onOff` - whether the generator is on or off. -- | - `offset` - the amount of DC offset. -data Constant offset - = Constant OnOff offset - -type GetConstant - = Constant AudioParameter +data Constant onOff offset + = Constant onOff offset -- | Term-level constructor for a convolver, aka reverb. -- | - `buffer` - the buffer of the impulse response of the space. data Convolver (buffer :: Symbol) = Convolver (Proxy buffer) -type GetConvolver buffer - = Convolver buffer -- | Term-level constructor for a delay unit. -- | - `delay` - the delay to apply. data Delay delay = Delay delay -type GetDelay - = Delay AudioParameter -- | Term-level constructor for a compressor. -- | - `threshold` - The threshold under which compression kicks in. @@ -65,30 +51,17 @@ type GetDelay data DynamicsCompressor threshold knee ratio attack release = DynamicsCompressor threshold knee ratio attack release -type GetDynamicsCompressor - = DynamicsCompressor - AudioParameter - AudioParameter - AudioParameter - AudioParameter - AudioParameter - -- | Term-level constructor for a gain unit. -- | - `volume` - the volume of the gain from 0 to 1. data Gain volume = Gain volume -type GetGain - = Gain AudioParameter - -- | Term-level constructor for a highpass filter. -- | - `frequency` - the frequency below which we start to filter. -- | - `q` - the width of the filter. data Highpass frequency q = Highpass frequency q -type GetHighpass - = Highpass AudioParameter AudioParameter -- | Term-level constructor for a highshelf filter. -- | - `frequency` - the frequency above which we start to filter. @@ -96,20 +69,14 @@ type GetHighpass data Highshelf frequency gain = Highshelf frequency gain -type GetHighshelf - = Highshelf AudioParameter AudioParameter - -- | Term-level constructor for a looping buffer. -- | - `buffer` - a string representing the buffer to use. Note that this string, when reset, will only reset the buffer when it is stopped. --- | - `OnOff` - whether or not the generator is on or off. +-- | - `onOff` - whether or not the generator is on or off. -- | - `playbackRate` - the playback rate. --- | - `Number` - where in the file the loop should start. --- | - `Number` - where in the file the loop should end. A value of 0.0 or less means play to the end of the buffer. -data LoopBuf playbackRate - = LoopBuf String OnOff playbackRate Number Number - -type GetLoopBuf - = LoopBuf AudioParameter +-- | - `loopStart` - where in the file the loop should start. +-- | - `loopEnd` - where in the file the loop should end. A value of 0.0 or less means play to the end of the buffer. +data LoopBuf buffer onOff playbackRate loopStart loopEnd + = LoopBuf buffer onOff playbackRate loopStart loopEnd -- | Term-level constructor for a lowpass filter. -- | - `frequency` - the frequency above which we start to filter. @@ -117,34 +84,22 @@ type GetLoopBuf data Lowpass frequency q = Lowpass frequency q -type GetLowpass - = Lowpass AudioParameter AudioParameter - -- | Term-level constructor for a lowshelf filter. -- | - `frequency` - the frequency below which we start to filter. -- | - `q` - the width of the filter. data Lowshelf frequency gain = Lowshelf frequency gain -type GetLowshelf - = Lowshelf AudioParameter AudioParameter - -- | Term-level constructor for a microphone data Microphone = Microphone -type GetMicrophone - = Microphone - -- | Term-level constructor for a notch (aka band-reject) filter. -- | - `frequency` - the frequency we are rejecting. -- | - `q` - the width of the filter. data Notch frequency q = Notch frequency q -type GetNotch - = Notch AudioParameter AudioParameter - -- | Term-level constructor for a peaking filter. A peaking filter is a combination of bandpass and notch where the gain parameter modulates whether we are reinforcing or attenuating a frequency. -- | - `frequency` - the frequency we are emphasizing _or_ rejecting. -- | - `q` - the width of the filter. @@ -152,88 +107,58 @@ type GetNotch data Peaking frequency q gain = Peaking frequency q gain -type GetPeaking - = Peaking AudioParameter AudioParameter AudioParameter - -- | Term-level constructor for a periodic oscillator. -- | - `periodicOsc` - the name of the wave table we'll be using. Note that, for a chance to take effect, the periodic oscillator must be stopped. --- | - `OnOff` - whether the generator is on or off. +-- | - `onOff` - whether the generator is on or off. -- | - `frequency` - the frequency of the oscillator. -data PeriodicOsc periodicOsc frequency - = PeriodicOsc periodicOsc OnOff frequency - -type GetPeriodicOsc - = PeriodicOsc AudioParameter +data PeriodicOsc periodicOsc onOff frequency + = PeriodicOsc periodicOsc onOff frequency -- | Term-level constructor for a playback buffer. -- | - `buffer` - a string representing the buffer to use. Note that this string, when reset, will only reset the buffer when it is stopped. --- | - `Number` - where in the file the playback should start. --- | - `OnOff` - whether or not the generator is on or off. +-- | - `offset` - where in the file the playback should start. +-- | - `onOff` - whether or not the generator is on or off. -- | - `playbackRate` - the playback rate. -data PlayBuf playbackRate - = PlayBuf String Number OnOff playbackRate - -type GetPlayBuf - = PlayBuf AudioParameter +data PlayBuf buffer offset onOff playbackRate + = PlayBuf buffer offset onOff playbackRate -- | Term-level constructor for a recorder. -- | - `recorder` - the recorder to which we write data. data Recorder (recorder :: Symbol) = Recorder (Proxy recorder) -type GetRecorder recorder - = Recorder recorder - -- | Term-level constructor for a sawtooth oscillator. --- | - `OnOff` - whether the generator is on or off. +-- | - `onOff` - whether the generator is on or off. -- | - `frequency` - the frequency of the oscillator. -data SawtoothOsc frequency - = SawtoothOsc OnOff frequency - -type GetSawtoothOsc - = SawtoothOsc AudioParameter +data SawtoothOsc onOff frequency + = SawtoothOsc onOff frequency -- | Term-level constructor for a sine-wave oscillator. --- | - `OnOff` - whether the generator is on or off. +-- | - `onOff` - whether the generator is on or off. -- | - `frequency` - the frequency of the oscillator. -data SinOsc frequency - = SinOsc OnOff frequency - -type GetSinOsc - = SinOsc AudioParameter +data SinOsc onOff frequency + = SinOsc onOff frequency -- | Term-level constructor for a loudspeaker. data Speaker = Speaker -type GetSpeaker - = Speaker - -- | Term-level constructor for a square-wave oscillator. --- | - `OnOff` - whether the generator is on or off. +-- | - `onOff` - whether the generator is on or off. -- | - `frequency` - the frequency of the oscillator. -data SquareOsc frequency - = SquareOsc OnOff frequency - -type GetSquareOsc - = SquareOsc AudioParameter +data SquareOsc onOff frequency + = SquareOsc onOff frequency -- | Term-level constructor for a stereo panner. -- | - `pan` - the amount of pan to apply, where -1.0 is fully to the left and 1.0 is fully to the right. data StereoPanner pan = StereoPanner pan -type GetStereoPanner - = StereoPanner AudioParameter - -- | Term-level constructor for a triangle oscillator. --- | - `OnOff` - whether the generator is on or off. +-- | - `onOff` - whether the generator is on or off. -- | - `frequency` - the frequency of the oscillator. -data TriangleOsc frequency - = TriangleOsc OnOff frequency - -type GetTriangleOsc - = TriangleOsc AudioParameter +data TriangleOsc onOff frequency + = TriangleOsc onOff frequency -- | Term-level constructor for a WaveShaper, aka distortion. -- | - `floatArray` - the shape of the distortion. @@ -241,9 +166,6 @@ type GetTriangleOsc data WaveShaper (floatArray :: Symbol) oversample = WaveShaper (Proxy floatArray) oversample -type GetWaveShaper floatArray oversample - = WaveShaper floatArray oversample - -- | Term-level constructor for a generator being on or off data OnOff = On @@ -325,7 +247,7 @@ instance semigroupTConstant :: Semigroup TConstant where instance monoidTConstant :: Monoid TConstant where mempty = TConstant -instance reifyTConstant :: ReifyAU (Constant a) TConstant where +instance reifyTConstant :: ReifyAU (Constant a b) TConstant where reifyAU = const mempty -- | Type-level constructor for a convolver, aka reverb. @@ -416,7 +338,7 @@ instance semigroupTLoopBuf :: Semigroup TLoopBuf where instance monoidTLoopBuf :: Monoid TLoopBuf where mempty = TLoopBuf -instance reifyTLoopBuf :: ReifyAU (LoopBuf a) TLoopBuf where +instance reifyTLoopBuf :: ReifyAU (LoopBuf a b c d e) TLoopBuf where reifyAU = const mempty -- | Type-level constructor for a lowpass filter. @@ -494,7 +416,7 @@ instance semigroupTPeriodicOsc :: Semigroup TPeriodicOsc where instance monoidTPeriodicOsc :: Monoid TPeriodicOsc where mempty = TPeriodicOsc -instance reifyTPeriodicOsc :: ReifyAU (PeriodicOsc periodicOsc a) TPeriodicOsc where +instance reifyTPeriodicOsc :: ReifyAU (PeriodicOsc a b c) TPeriodicOsc where reifyAU = const mempty -- | Type-level constructor for playback from a buffer. @@ -507,7 +429,7 @@ instance semigroupTPlayBuf :: Semigroup TPlayBuf where instance monoidTPlayBuf :: Monoid TPlayBuf where mempty = TPlayBuf -instance reifyTPlayBuf :: ReifyAU (PlayBuf a) TPlayBuf where +instance reifyTPlayBuf :: ReifyAU (PlayBuf a b c d) TPlayBuf where reifyAU = const mempty -- | Type-level constructor for a recorder. @@ -533,7 +455,7 @@ instance semigroupTSawtoothOsc :: Semigroup TSawtoothOsc where instance monoidTSawtoothOsc :: Monoid TSawtoothOsc where mempty = TSawtoothOsc -instance reifyTSawtoothOsc :: ReifyAU (SawtoothOsc a) TSawtoothOsc where +instance reifyTSawtoothOsc :: ReifyAU (SawtoothOsc a b) TSawtoothOsc where reifyAU = const mempty -- | Type-level constructor for a sine-wave oscillator. @@ -546,7 +468,7 @@ instance semigroupTSinOsc :: Semigroup TSinOsc where instance monoidTSinOsc :: Monoid TSinOsc where mempty = TSinOsc -instance reifyTSinOsc :: ReifyAU (SinOsc a) TSinOsc where +instance reifyTSinOsc :: ReifyAU (SinOsc a b) TSinOsc where reifyAU = const mempty -- | Type-level constructor for a loudspeaker. @@ -572,7 +494,7 @@ instance semigroupTSquareOsc :: Semigroup TSquareOsc where instance monoidTSquareOsc :: Monoid TSquareOsc where mempty = TSquareOsc -instance reifyTSquareOsc :: ReifyAU (SquareOsc a) TSquareOsc where +instance reifyTSquareOsc :: ReifyAU (SquareOsc a b) TSquareOsc where reifyAU = const mempty -- | Type-level constructor for a stereo panner. @@ -598,7 +520,7 @@ instance semigroupTTriangleOsc :: Semigroup TTriangleOsc where instance monoidTTriangleOsc :: Monoid TTriangleOsc where mempty = TTriangleOsc -instance reifyTTriangleOsc :: ReifyAU (TriangleOsc a) TTriangleOsc where +instance reifyTTriangleOsc :: ReifyAU (TriangleOsc a b) TTriangleOsc where reifyAU = const mempty -- | Type-level constructor for a wave shaper. diff --git a/src/WAGS/Graph/Optionals.purs b/src/WAGS/Graph/Optionals.purs deleted file mode 100644 index fae45bea..00000000 --- a/src/WAGS/Graph/Optionals.purs +++ /dev/null @@ -1,1329 +0,0 @@ --- | This module provides functions for the construction of audio units that more closely resemble the overloaded constructors of the Web Audio API. -module WAGS.Graph.Optionals where - -import Prelude -import ConvertableOptions (class ConvertOption, class ConvertOptionsWithDefaults, convertOptionsWithDefaults) -import Data.Symbol (class IsSymbol) -import Data.Tuple (Tuple(..), fst) -import Data.Tuple.Nested ((/\), type (/\)) -import Data.Vec as V -import Type.Proxy (Proxy) -import WAGS.Change (class SetterVal, setterVal) -import WAGS.Create (class InitialVal, initialVal) -import WAGS.Graph.AudioUnit (OnOff(..)) -import WAGS.Graph.AudioUnit as CTOR -import WAGS.Graph.Oversample (class IsOversample) -import WAGS.Graph.Parameter (AudioParameter, param) - -type GetSetAP - = Tuple AudioParameter (AudioParameter -> AudioParameter) - -defaultGetSetAP :: Number -> GetSetAP -defaultGetSetAP n = Tuple p (const p) - where - p = param n - ------------ -data Allpass' - = Allpass' - -instance convertAllpassFrequency :: (InitialVal a, SetterVal a) => ConvertOption Allpass' "freq" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -instance convertAllpassQ :: (InitialVal a, SetterVal a) => ConvertOption Allpass' "q" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -type AllpassOptional - = ( q :: GetSetAP ) - -type AllpassAll - = ( freq :: GetSetAP - | AllpassOptional - ) - -defaultAllpass :: { | AllpassOptional } -defaultAllpass = { q: defaultGetSetAP 1.0 } - -class AllpassCtor i allpass | i -> allpass where - -- | Create an allpass filter, connecting it to another unit - -- | - -- | ```purescript - -- | allpass { freq: 440.0 } { sinOsc: unit } - -- | allpass { freq: 440.0, q: 1.0 } { sinOsc: unit } - -- | allpass 440.0 { sinOsc: unit } - -- | ``` - allpass :: i -> allpass - -instance allpassCtor1 :: - ( ConvertOptionsWithDefaults Allpass' { | AllpassOptional } { | provided } { | AllpassAll } - ) => - AllpassCtor { | provided } (b -> CTOR.Allpass GetSetAP GetSetAP /\ b) where - allpass provided b = CTOR.Allpass all.freq all.q /\ b - where - all :: { | AllpassAll } - all = convertOptionsWithDefaults Allpass' defaultAllpass provided -else instance allpassCtor2 :: (InitialVal a, SetterVal a) => AllpassCtor a (b -> CTOR.Allpass GetSetAP GetSetAP /\ b) where - allpass a b = CTOR.Allpass (Tuple (initialVal a) (setterVal a)) defaultAllpass.q /\ b - -class AllpassCtor_ i allpass | i -> allpass where - -- | Change an allpass filter - -- | - -- | ```purescript - -- | allpass_ { freq: 440.0 } - -- | allpass_ { freq: 440.0, q: 1.0 } - -- | allpass_ 440.0 - -- | ``` - allpass_ :: i -> allpass - -instance allpassCtor1_ :: - ( ConvertOptionsWithDefaults Allpass' { | AllpassOptional } { | provided } { | AllpassAll } - ) => - AllpassCtor_ { | provided } (CTOR.Allpass GetSetAP GetSetAP) where - allpass_ provided = CTOR.Allpass all.freq all.q - where - all :: { | AllpassAll } - all = convertOptionsWithDefaults Allpass' defaultAllpass provided -else instance allpassCtor2_ :: (InitialVal a, SetterVal a) => AllpassCtor_ a (CTOR.Allpass GetSetAP GetSetAP) where - allpass_ a = CTOR.Allpass (Tuple (initialVal a) (setterVal a)) defaultAllpass.q - --- | The type of a created allpass filter -type CAllpass a - = CTOR.Allpass GetSetAP GetSetAP /\ a - --- | The type of a changing allpass filter -type DAllpass - = CTOR.Allpass GetSetAP GetSetAP - ------- -data Bandpass' - = Bandpass' - -instance convertBandpassFrequency :: (InitialVal a, SetterVal a) => ConvertOption Bandpass' "freq" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -instance convertBandpassQ :: (InitialVal a, SetterVal a) => ConvertOption Bandpass' "q" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -type BandpassOptional - = ( q :: GetSetAP ) - -type BandpassAll - = ( freq :: GetSetAP - | BandpassOptional - ) - -defaultBandpass :: { | BandpassOptional } -defaultBandpass = { q: defaultGetSetAP 1.0 } - -class BandpassCtor i bandpass | i -> bandpass where - -- | Create a bandpass filter, connecting it to another unit - -- | - -- | ```purescript - -- | bandpass { freq: 440.0 } { sinOsc: unit } - -- | bandpass { freq: 440.0, q: 1.0 } { sinOsc: unit } - -- | bandpass 440.0 { sinOsc: unit } - -- | ``` - bandpass :: i -> bandpass - -instance bandpassCtor1 :: - ( ConvertOptionsWithDefaults Bandpass' { | BandpassOptional } { | provided } { | BandpassAll } - ) => - BandpassCtor { | provided } (b -> CTOR.Bandpass GetSetAP GetSetAP /\ b) where - bandpass provided b = CTOR.Bandpass all.freq all.q /\ b - where - all :: { | BandpassAll } - all = convertOptionsWithDefaults Bandpass' defaultBandpass provided -else instance bandpassCtor2 :: (InitialVal a, SetterVal a) => BandpassCtor a (b -> CTOR.Bandpass GetSetAP GetSetAP /\ b) where - bandpass a b = CTOR.Bandpass (Tuple (initialVal a) (setterVal a)) defaultBandpass.q /\ b - -class BandpassCtor_ i bandpass | i -> bandpass where - -- | Change a bandpass filter - -- | - -- | ```purescript - -- | bandpass_ { freq: 440.0 } - -- | bandpass_ { freq: 440.0, q: 1.0 } - -- | bandpass_ 440.0 - -- | ``` - bandpass_ :: i -> bandpass - -instance bandpass_Ctor1 :: - ( ConvertOptionsWithDefaults Bandpass' { | BandpassOptional } { | provided } { | BandpassAll } - ) => - BandpassCtor_ { | provided } (CTOR.Bandpass GetSetAP GetSetAP) where - bandpass_ provided = CTOR.Bandpass all.freq all.q - where - all :: { | BandpassAll } - all = convertOptionsWithDefaults Bandpass' defaultBandpass provided -else instance bandpass_Ctor2 :: (InitialVal a, SetterVal a) => BandpassCtor_ a ((CTOR.Bandpass GetSetAP GetSetAP)) where - bandpass_ a = CTOR.Bandpass (Tuple (initialVal a) (setterVal a)) defaultBandpass.q - -type CBandpass a - = CTOR.Bandpass GetSetAP GetSetAP /\ a - -type DBandpass - = CTOR.Bandpass GetSetAP GetSetAP - ------- -class ConstantCtor_ i o | i -> o where - -- | Change a constant value - -- | - -- | ```purescript - -- | constant_ 0.5 - -- | constant_ On 0.5 - -- | ``` - constant_ :: i -> o - -instance constantCtor2_ :: - ( InitialVal a - , SetterVal a - ) => - ConstantCtor_ OnOff (a -> CTOR.Constant GetSetAP) where - constant_ oo gvsv = CTOR.Constant oo (Tuple (initialVal gvsv) (setterVal gvsv)) -else instance constantCtor1_ :: - ( InitialVal a - , SetterVal a - ) => - ConstantCtor_ a (CTOR.Constant GetSetAP) where - constant_ gvsv = CTOR.Constant On (Tuple (initialVal gvsv) (setterVal gvsv)) - -class ConstantCtor i o | i -> o where - -- | Make a constant value - -- | - -- | ```purescript - -- | constant 0.5 - -- | constant On 0.5 - -- | ``` - constant :: i -> o - -instance constantCtor2 :: - ( InitialVal a - , SetterVal a - ) => - ConstantCtor OnOff (a -> CTOR.Constant GetSetAP /\ {}) where - constant oo gvsv = CTOR.Constant oo (Tuple (initialVal gvsv) (setterVal gvsv)) /\ {} -else instance constantCtor1 :: - ( InitialVal a - , SetterVal a - ) => - ConstantCtor a (CTOR.Constant GetSetAP /\ {}) where - constant gvsv = CTOR.Constant On (Tuple (initialVal gvsv) (setterVal gvsv)) /\ {} - -type CConstant - = CTOR.Constant GetSetAP /\ {} - -type DConstant - = CTOR.Constant GetSetAP - ------- --- | Make a convolver, aka reverb. --- | --- | ```purescript --- | convolver (Proxy :: _ "room") (playBuf "track") --- | ``` -convolver :: - forall s b. - IsSymbol s => - Proxy s -> b -> CTOR.Convolver s /\ b -convolver = Tuple <<< CTOR.Convolver - -type CConvolver a b - = CTOR.Convolver a /\ b - ------- --- | Make a delay unit. --- | --- | ```purescript --- | delay 0.5 (playBuf "track") --- | ``` -delay :: - forall a b. - InitialVal a => - SetterVal a => - a -> b -> CTOR.Delay GetSetAP /\ b -delay gvsv = Tuple (CTOR.Delay (Tuple (initialVal gvsv) (setterVal gvsv))) - -delay_ :: forall a. InitialVal a => SetterVal a => a -> CTOR.Delay GetSetAP -delay_ = fst <<< flip delay {} - -type CDelay a - = CTOR.Delay GetSetAP /\ a - -type DDelay - = CTOR.Delay GetSetAP - ------- -data DynamicsCompressor' - = DynamicsCompressor' - -instance convertDynamicsCompressorThreshold :: (InitialVal a, SetterVal a) => ConvertOption DynamicsCompressor' "threshold" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -instance convertDynamicsCompressorKnee :: (InitialVal a, SetterVal a) => ConvertOption DynamicsCompressor' "knee" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -instance convertDynamicsCompressorRatio :: (InitialVal a, SetterVal a) => ConvertOption DynamicsCompressor' "ratio" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -instance convertDynamicsCompressorAttack :: (InitialVal a, SetterVal a) => ConvertOption DynamicsCompressor' "attack" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -instance convertDynamicsCompressorRelease :: (InitialVal a, SetterVal a) => ConvertOption DynamicsCompressor' "release" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -type DynamicsCompressorOptional - = ( threshold :: GetSetAP - , knee :: GetSetAP - , ratio :: GetSetAP - , attack :: GetSetAP - , release :: GetSetAP - ) - -type DynamicsCompressorAll - = ( - | DynamicsCompressorOptional - ) - -defaultDynamicsCompressor :: { | DynamicsCompressorOptional } -defaultDynamicsCompressor = - { threshold: defaultGetSetAP (-24.0) - , knee: defaultGetSetAP 30.0 - , ratio: defaultGetSetAP 12.0 - , attack: defaultGetSetAP 0.003 - , release: defaultGetSetAP 0.25 - } - -class DynamicsCompressorCtor_ i compressor | i -> compressor where - -- | Change a compressor. - -- | - -- | ```purescript - -- | compressor_ { threshold: -10.0 } - -- | compressor_ { knee: 20.0, ratio: 10.0 } - -- | compressor_ { attack: 0.01, release: 0.3 } - -- | ``` - compressor_ :: i -> compressor - -instance compressorCTor_ :: - ( ConvertOptionsWithDefaults DynamicsCompressor' { | DynamicsCompressorOptional } { | provided } { | DynamicsCompressorAll } - ) => - DynamicsCompressorCtor_ { | provided } (CTOR.DynamicsCompressor GetSetAP GetSetAP GetSetAP GetSetAP GetSetAP) where - compressor_ provided = - CTOR.DynamicsCompressor - all.threshold - all.knee - all.ratio - all.attack - all.release - where - all :: { | DynamicsCompressorAll } - all = convertOptionsWithDefaults DynamicsCompressor' defaultDynamicsCompressor provided - -class DynamicsCompressorCtor i compressor | i -> compressor where - -- | Make a compressor. - -- | - -- | ```purescript - -- | compressor { threshold: -10.0 } { buf: playBuf "track" } - -- | compressor { knee: 20.0, ratio: 10.0 } { buf: playBuf "track" } - -- | compressor { attack: 0.01, release: 0.3 } { buf: playBuf "track" } - -- | ``` - compressor :: i -> compressor - -instance compressorCTor :: - ( ConvertOptionsWithDefaults DynamicsCompressor' { | DynamicsCompressorOptional } { | provided } { | DynamicsCompressorAll } - ) => - DynamicsCompressorCtor { | provided } (b -> CTOR.DynamicsCompressor GetSetAP GetSetAP GetSetAP GetSetAP GetSetAP /\ b) where - compressor provided b = - CTOR.DynamicsCompressor - all.threshold - all.knee - all.ratio - all.attack - all.release - /\ b - where - all :: { | DynamicsCompressorAll } - all = convertOptionsWithDefaults DynamicsCompressor' defaultDynamicsCompressor provided - -type CDynamicsCompressor a - = CTOR.DynamicsCompressor GetSetAP GetSetAP GetSetAP GetSetAP GetSetAP /\ a - -type DDynamicsCompressor - = CTOR.DynamicsCompressor GetSetAP GetSetAP GetSetAP GetSetAP GetSetAP - ------- -gain :: forall a b. InitialVal a => SetterVal a => a -> b -> CTOR.Gain GetSetAP /\ b -gain a = Tuple (CTOR.Gain (Tuple (initialVal a) (setterVal a))) - -gain_ :: forall a. InitialVal a => SetterVal a => a -> CTOR.Gain GetSetAP -gain_ = fst <<< flip gain {} - --- | Mix together several audio units --- | --- | ```purescript --- | mix (playBuf (Proxy :: _ "hello") /\ playBuf (Proxy :: _ "world") /\ unit) --- | ``` -mix :: forall a. a -> CTOR.Gain GetSetAP /\ a -mix = Tuple (CTOR.Gain (defaultGetSetAP 1.0)) - -type Mix - = CTOR.Gain GetSetAP - -type CGain a - = CTOR.Gain GetSetAP /\ a - -type DGain - = CTOR.Gain GetSetAP - ------- -data Highpass' - = Highpass' - -instance convertHighpassFrequency :: (InitialVal a, SetterVal a) => ConvertOption Highpass' "freq" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -instance convertHighpassQ :: (InitialVal a, SetterVal a) => ConvertOption Highpass' "q" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -type HighpassOptional - = ( q :: GetSetAP ) - -type HighpassAll - = ( freq :: GetSetAP - | HighpassOptional - ) - -defaultHighpass :: { | HighpassOptional } -defaultHighpass = { q: defaultGetSetAP 1.0 } - -class HighpassCtor_ i highpass | i -> highpass where - -- | Change a highpass filter - -- | - -- | ```purescript - -- | highpass_ { freq: 440.0 } - -- | highpass_ { freq: 440.0, q: 1.0 } - -- | highpass_ 440.0 - -- | ``` - highpass_ :: i -> highpass - -instance highpassCtor1_ :: - ( ConvertOptionsWithDefaults Highpass' { | HighpassOptional } { | provided } { | HighpassAll } - ) => - HighpassCtor_ { | provided } (CTOR.Highpass GetSetAP GetSetAP) where - highpass_ provided = CTOR.Highpass all.freq all.q - where - all :: { | HighpassAll } - all = convertOptionsWithDefaults Highpass' defaultHighpass provided -else instance highpassCtor2_ :: (InitialVal a, SetterVal a) => HighpassCtor_ a ((CTOR.Highpass GetSetAP GetSetAP)) where - highpass_ a = CTOR.Highpass (Tuple (initialVal a) (setterVal a)) defaultHighpass.q - -class HighpassCtor i highpass | i -> highpass where - -- | Make a highpass filter - -- | - -- | ```purescript - -- | highpass { freq: 440.0 } { osc: sinOsc 440.0 } - -- | highpass { freq: 440.0, q: 1.0 } { osc: sinOsc 440.0 } - -- | highpass 440.0 { osc: sinOsc 440.0 } - -- | ``` - highpass :: i -> highpass - -instance highpassCtor1 :: - ( ConvertOptionsWithDefaults Highpass' { | HighpassOptional } { | provided } { | HighpassAll } - ) => - HighpassCtor { | provided } (b -> CTOR.Highpass GetSetAP GetSetAP /\ b) where - highpass provided = Tuple (CTOR.Highpass all.freq all.q) - where - all :: { | HighpassAll } - all = convertOptionsWithDefaults Highpass' defaultHighpass provided -else instance highpassCtor2 :: (InitialVal a, SetterVal a) => HighpassCtor a (b -> CTOR.Highpass GetSetAP GetSetAP /\ b) where - highpass a = Tuple (CTOR.Highpass (Tuple (initialVal a) (setterVal a)) defaultHighpass.q) - -type CHighpass a - = CTOR.Highpass GetSetAP GetSetAP /\ a - -type DHighpass - = CTOR.Highpass GetSetAP GetSetAP - ------- -data Highshelf' - = Highshelf' - -instance convertHighshelfFrequency :: (InitialVal a, SetterVal a) => ConvertOption Highshelf' "freq" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -instance convertHighshelfQ :: (InitialVal a, SetterVal a) => ConvertOption Highshelf' "gain" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -type HighshelfOptional - = ( gain :: GetSetAP ) - -type HighshelfAll - = ( freq :: GetSetAP - | HighshelfOptional - ) - -defaultHighshelf :: { | HighshelfOptional } -defaultHighshelf = { gain: defaultGetSetAP 0.0 } - -class HighshelfCtor_ i highshelf | i -> highshelf where - -- | Change a highshelf filter - -- | - -- | ```purescript - -- | highshelf_ { freq: 440.0 } - -- | highshelf_ { freq: 440.0, gain: 1.0 } - -- | highshelf_ 440.0 - -- | ``` - highshelf_ :: i -> highshelf - -instance highshelfCtor1_ :: - ( ConvertOptionsWithDefaults Highshelf' { | HighshelfOptional } { | provided } { | HighshelfAll } - ) => - HighshelfCtor_ { | provided } (CTOR.Highshelf GetSetAP GetSetAP) where - highshelf_ provided = CTOR.Highshelf all.freq all.gain - where - all :: { | HighshelfAll } - all = convertOptionsWithDefaults Highshelf' defaultHighshelf provided -else instance highshelfCtor2_ :: (InitialVal a, SetterVal a) => HighshelfCtor_ a ((CTOR.Highshelf GetSetAP GetSetAP)) where - highshelf_ a = CTOR.Highshelf (Tuple (initialVal a) (setterVal a)) defaultHighshelf.gain - -class HighshelfCtor i highshelf | i -> highshelf where - -- | Make a highshelf filter - -- | - -- | ```purescript - -- | highshelf { freq: 440.0 } { osc: sinOsc 440.0 } - -- | highshelf { freq: 440.0, gain: 1.0 } { osc: sinOsc 440.0 } - -- | highshelf 440.0 { osc: sinOsc 440.0 } - -- | ``` - highshelf :: i -> highshelf - -instance highshelfCtor1 :: - ( ConvertOptionsWithDefaults Highshelf' { | HighshelfOptional } { | provided } { | HighshelfAll } - ) => - HighshelfCtor { | provided } (b -> CTOR.Highshelf GetSetAP GetSetAP /\ b) where - highshelf provided = Tuple (CTOR.Highshelf all.freq all.gain) - where - all :: { | HighshelfAll } - all = convertOptionsWithDefaults Highshelf' defaultHighshelf provided -else instance highshelfCtor2 :: (InitialVal a, SetterVal a) => HighshelfCtor a (b -> CTOR.Highshelf GetSetAP GetSetAP /\ b) where - highshelf a = Tuple (CTOR.Highshelf (Tuple (initialVal a) (setterVal a)) defaultHighshelf.gain) - -type CHighshelf a - = CTOR.Highshelf GetSetAP GetSetAP /\ a - -type DHighshelf - = CTOR.Highshelf GetSetAP GetSetAP - ----- -data LoopBuf' - = LoopBuf' - -instance convertLoopBufPlaybackRate :: (InitialVal a, SetterVal a) => ConvertOption LoopBuf' "playbackRate" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -instance convertLoopBufOnOff :: ConvertOption LoopBuf' "onOff" OnOff OnOff where - convertOption _ _ = identity - -instance convertLoopBufStart :: ConvertOption LoopBuf' "start" Number Number where - convertOption _ _ = identity - -instance convertLoopBufEnd :: ConvertOption LoopBuf' "end" Number Number where - convertOption _ _ = identity - -type LoopBufOptional - = ( playbackRate :: GetSetAP, onOff :: OnOff, start :: Number, end :: Number ) - -type LoopBufAll - = ( | LoopBufOptional ) - -defaultLoopBuf :: { | LoopBufOptional } -defaultLoopBuf = { playbackRate: defaultGetSetAP 1.0, onOff: On, start: 0.0, end: 0.0 } - -class LoopBufCtor_ i loopBuf | i -> loopBuf where - -- | Chage a looping buffer. - -- | - -- | ```purescript - -- | loopBuf_ { playbackRate: 1.0 } "track" - -- | loopBuf_ { playbackRate: 1.0, start: 0.5 } "track" - -- | loopBuf_ "track" - -- | ``` - loopBuf_ :: i -> loopBuf - -instance loopBufCtor1_ :: - ( ConvertOptionsWithDefaults LoopBuf' { | LoopBufOptional } { | provided } { | LoopBufAll } - ) => - LoopBufCtor_ { | provided } (String -> CTOR.LoopBuf GetSetAP) where - loopBuf_ provided proxy = CTOR.LoopBuf proxy all.onOff all.playbackRate all.start all.end - where - all :: { | LoopBufAll } - all = convertOptionsWithDefaults LoopBuf' defaultLoopBuf provided -else instance loopBufCtor2_ :: LoopBufCtor_ String (CTOR.LoopBuf GetSetAP) where - loopBuf_ name = - CTOR.LoopBuf - name - defaultLoopBuf.onOff - defaultLoopBuf.playbackRate - defaultLoopBuf.start - defaultLoopBuf.end - -class LoopBufCtor i loopBuf | i -> loopBuf where - -- | Make a looping buffer. - -- | - -- | ```purescript - -- | loopBuf { playbackRate: 1.0 } "track" - -- | loopBuf { playbackRate: 1.0, start: 0.5 } "track" - -- | loopBuf "track" - -- | ``` - loopBuf :: i -> loopBuf - -instance loopBufCtor1 :: - ( ConvertOptionsWithDefaults LoopBuf' { | LoopBufOptional } { | provided } { | LoopBufAll } - ) => - LoopBufCtor { | provided } (String -> CTOR.LoopBuf GetSetAP /\ {}) where - loopBuf provided proxy = CTOR.LoopBuf proxy all.onOff all.playbackRate all.start all.end /\ {} - where - all :: { | LoopBufAll } - all = convertOptionsWithDefaults LoopBuf' defaultLoopBuf provided -else instance loopBufCtor2 :: LoopBufCtor String (CTOR.LoopBuf GetSetAP /\ {}) where - loopBuf name = - CTOR.LoopBuf - name - defaultLoopBuf.onOff - defaultLoopBuf.playbackRate - defaultLoopBuf.start - defaultLoopBuf.end - /\ {} - -type CLoopBuf - = CTOR.LoopBuf GetSetAP /\ {} - -type DLoopBuf - = CTOR.LoopBuf GetSetAP - ------ -data Lowpass' - = Lowpass' - -instance convertLowpassFrequency :: (InitialVal a, SetterVal a) => ConvertOption Lowpass' "freq" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -instance convertLowpassQ :: (InitialVal a, SetterVal a) => ConvertOption Lowpass' "q" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -type LowpassOptional - = ( q :: GetSetAP ) - -type LowpassAll - = ( freq :: GetSetAP - | LowpassOptional - ) - -defaultLowpass :: { | LowpassOptional } -defaultLowpass = { q: defaultGetSetAP 1.0 } - -class LowpassCtor_ i lowpass | i -> lowpass where - -- | Change a lowpass filter - -- | - -- | ```purescript - -- | lowpass_ { freq: 440.0 } - -- | lowpass_ { freq: 440.0, q: 1.0 } - -- | lowpass_ 440.0 - -- | ``` - lowpass_ :: i -> lowpass - -instance lowpass_Ctor1 :: - ( ConvertOptionsWithDefaults Lowpass' { | LowpassOptional } { | provided } { | LowpassAll } - ) => - LowpassCtor_ { | provided } (CTOR.Lowpass GetSetAP GetSetAP) where - lowpass_ provided = CTOR.Lowpass all.freq all.q - where - all :: { | LowpassAll } - all = convertOptionsWithDefaults Lowpass' defaultLowpass provided -else instance lowpass_Ctor2 :: (InitialVal a, SetterVal a) => LowpassCtor_ a ((CTOR.Lowpass GetSetAP GetSetAP)) where - lowpass_ a = CTOR.Lowpass (Tuple (initialVal a) (setterVal a)) defaultLowpass.q - -class LowpassCtor i lowpass | i -> lowpass where - -- | Make a lowpass filter - -- | - -- | ```purescript - -- | lowpass { freq: 440.0 } { osc: sinOsc 440.0 } - -- | lowpass { freq: 440.0, q: 1.0 } { osc: sinOsc 440.0 } - -- | lowpass 440.0 { osc: sinOsc 440.0 } - -- | ``` - lowpass :: i -> lowpass - -instance lowpassCtor1 :: - ( ConvertOptionsWithDefaults Lowpass' { | LowpassOptional } { | provided } { | LowpassAll } - ) => - LowpassCtor { | provided } (b -> CTOR.Lowpass GetSetAP GetSetAP /\ b) where - lowpass provided = Tuple (CTOR.Lowpass all.freq all.q) - where - all :: { | LowpassAll } - all = convertOptionsWithDefaults Lowpass' defaultLowpass provided -else instance lowpassCtor2 :: (InitialVal a, SetterVal a) => LowpassCtor a (b -> CTOR.Lowpass GetSetAP GetSetAP /\ b) where - lowpass a = Tuple (CTOR.Lowpass (Tuple (initialVal a) (setterVal a)) defaultLowpass.q) - -type CLowpass a - = CTOR.Lowpass GetSetAP GetSetAP /\ a - -type DLowpass - = CTOR.Lowpass GetSetAP GetSetAP - ------ -data Lowshelf' - = Lowshelf' - -instance convertLowshelfFrequency :: (InitialVal a, SetterVal a) => ConvertOption Lowshelf' "freq" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -instance convertLowshelfQ :: (InitialVal a, SetterVal a) => ConvertOption Lowshelf' "gain" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -type LowshelfOptional - = ( gain :: GetSetAP ) - -type LowshelfAll - = ( freq :: GetSetAP - | LowshelfOptional - ) - -defaultLowshelf :: { | LowshelfOptional } -defaultLowshelf = { gain: defaultGetSetAP 0.0 } - -class LowshelfCtor_ i lowshelf | i -> lowshelf where - -- | Change a lowshelf filter - -- | - -- | ```purescript - -- | lowshelf_ { freq: 440.0 } - -- | lowshelf_ { freq: 440.0, gain: 1.0 } - -- | lowshelf_ 440.0 - -- | ``` - lowshelf_ :: i -> lowshelf - -instance lowshelf_Ctor1 :: - ( ConvertOptionsWithDefaults Lowshelf' { | LowshelfOptional } { | provided } { | LowshelfAll } - ) => - LowshelfCtor_ { | provided } (CTOR.Lowshelf GetSetAP GetSetAP) where - lowshelf_ provided = CTOR.Lowshelf all.freq all.gain - where - all :: { | LowshelfAll } - all = convertOptionsWithDefaults Lowshelf' defaultLowshelf provided -else instance lowshelf_Ctor2 :: (InitialVal a, SetterVal a) => LowshelfCtor_ a ((CTOR.Lowshelf GetSetAP GetSetAP)) where - lowshelf_ a = CTOR.Lowshelf (Tuple (initialVal a) (setterVal a)) defaultLowshelf.gain - -class LowshelfCtor i lowshelf | i -> lowshelf where - -- | Make a lowshelf filter - -- | - -- | ```purescript - -- | lowshelf { freq: 440.0 } { osc: sinOsc 440.0 } - -- | lowshelf { freq: 440.0, gain: 1.0 } { osc: sinOsc 440.0 } - -- | lowshelf 440.0 { osc: sinOsc 440.0 } - -- | ``` - lowshelf :: i -> lowshelf - -instance lowshelfCtor1 :: - ( ConvertOptionsWithDefaults Lowshelf' { | LowshelfOptional } { | provided } { | LowshelfAll } - ) => - LowshelfCtor { | provided } (b -> CTOR.Lowshelf GetSetAP GetSetAP /\ b) where - lowshelf provided = Tuple (CTOR.Lowshelf all.freq all.gain) - where - all :: { | LowshelfAll } - all = convertOptionsWithDefaults Lowshelf' defaultLowshelf provided -else instance lowshelfCtor2 :: (InitialVal a, SetterVal a) => LowshelfCtor a (b -> CTOR.Lowshelf GetSetAP GetSetAP /\ b) where - lowshelf a = Tuple (CTOR.Lowshelf (Tuple (initialVal a) (setterVal a)) defaultLowshelf.gain) - -type CLowshelf a - = CTOR.Lowshelf GetSetAP GetSetAP /\ a - -type DLowshelf - = CTOR.Lowshelf GetSetAP GetSetAP - --------- -microphone :: CTOR.Microphone /\ {} -microphone = CTOR.Microphone /\ {} - -microphone_ :: CTOR.Microphone -microphone_ = CTOR.Microphone - -type CMicrophone - = CTOR.Microphone /\ {} - --------- -data Notch' - = Notch' - -instance convertNotchFrequency :: (InitialVal a, SetterVal a) => ConvertOption Notch' "freq" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -instance convertNotchQ :: (InitialVal a, SetterVal a) => ConvertOption Notch' "q" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -type NotchOptional - = ( q :: GetSetAP ) - -type NotchAll - = ( freq :: GetSetAP - | NotchOptional - ) - -defaultNotch :: { | NotchOptional } -defaultNotch = { q: defaultGetSetAP 1.0 } - -class NotchCtor_ i notch | i -> notch where - -- | Change a notch (band-reject) filter - -- | - -- | ```purescript - -- | notch_ { freq: 440.0 } - -- | notch_ { freq: 440.0, gain: 1.0 } - -- | notch_ 440.0 - -- | ``` - notch_ :: i -> notch - -instance notch_Ctor1 :: - ( ConvertOptionsWithDefaults Notch' { | NotchOptional } { | provided } { | NotchAll } - ) => - NotchCtor_ { | provided } (CTOR.Notch GetSetAP GetSetAP) where - notch_ provided = CTOR.Notch all.freq all.q - where - all :: { | NotchAll } - all = convertOptionsWithDefaults Notch' defaultNotch provided -else instance notch_Ctor2 :: (InitialVal a, SetterVal a) => NotchCtor_ a ((CTOR.Notch GetSetAP GetSetAP)) where - notch_ a = CTOR.Notch (Tuple (initialVal a) (setterVal a)) defaultNotch.q - -class NotchCtor i notch | i -> notch where - -- | Make a notch (band-reject) filter - -- | - -- | ```purescript - -- | notch { freq: 440.0 } { osc: sinOsc 440.0 } - -- | notch { freq: 440.0, gain: 1.0 } { osc: sinOsc 440.0 } - -- | notch 440.0 { osc: sinOsc 440.0 } - -- | ``` - notch :: i -> notch - -instance notchCtor1 :: - ( ConvertOptionsWithDefaults Notch' { | NotchOptional } { | provided } { | NotchAll } - ) => - NotchCtor { | provided } (b -> CTOR.Notch GetSetAP GetSetAP /\ b) where - notch provided = Tuple (CTOR.Notch all.freq all.q) - where - all :: { | NotchAll } - all = convertOptionsWithDefaults Notch' defaultNotch provided -else instance notchCtor2 :: (InitialVal a, SetterVal a) => NotchCtor a (b -> CTOR.Notch GetSetAP GetSetAP /\ b) where - notch a = Tuple (CTOR.Notch (Tuple (initialVal a) (setterVal a)) defaultNotch.q) - -type CNotch a - = CTOR.Notch GetSetAP GetSetAP /\ a - -type DNotch - = CTOR.Notch GetSetAP GetSetAP - ----------------- -data Peaking' - = Peaking' - -instance convertPeakingFrequency :: (InitialVal a, SetterVal a) => ConvertOption Peaking' "freq" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -instance convertPeakingQ :: (InitialVal a, SetterVal a) => ConvertOption Peaking' "q" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -instance convertPeakingGain :: (InitialVal a, SetterVal a) => ConvertOption Peaking' "gain" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -type PeakingOptional - = ( q :: GetSetAP, gain :: GetSetAP ) - -type PeakingAll - = ( freq :: GetSetAP - | PeakingOptional - ) - -defaultPeaking :: { | PeakingOptional } -defaultPeaking = { q: defaultGetSetAP 1.0, gain: defaultGetSetAP 0.0 } - -class PeakingCtor i peaking | i -> peaking where - -- | Make a peaking filter - -- | - -- | ```purescript - -- | peaking { freq: 440.0 } { osc: sinOsc 440.0 } - -- | peaking { freq: 440.0, gain: 1.0 } { osc: sinOsc 440.0 } - -- | peaking 440.0 { osc: sinOsc 440.0 } - -- | ``` - peaking :: i -> peaking - -instance peakingCtor1 :: - ( ConvertOptionsWithDefaults Peaking' { | PeakingOptional } { | provided } { | PeakingAll } - ) => - PeakingCtor { | provided } (b -> CTOR.Peaking GetSetAP GetSetAP GetSetAP /\ b) where - peaking provided = Tuple (CTOR.Peaking all.freq all.q all.gain) - where - all :: { | PeakingAll } - all = convertOptionsWithDefaults Peaking' defaultPeaking provided -else instance peakingCtor2 :: (InitialVal a, SetterVal a) => PeakingCtor a (b -> CTOR.Peaking GetSetAP GetSetAP GetSetAP /\ b) where - peaking a = Tuple (CTOR.Peaking (Tuple (initialVal a) (setterVal a)) defaultPeaking.q defaultPeaking.gain) - -class PeakingCtor_ i peaking | i -> peaking where - -- | Change a peaking filter - -- | - -- | ```purescript - -- | peaking_ { freq: 440.0 } - -- | peaking_ { freq: 440.0, gain: 1.0 } - -- | peaking_ 440.0 - -- | ``` - peaking_ :: i -> peaking - -instance peaking_Ctor1 :: - ( ConvertOptionsWithDefaults Peaking' { | PeakingOptional } { | provided } { | PeakingAll } - ) => - PeakingCtor_ { | provided } (CTOR.Peaking GetSetAP GetSetAP GetSetAP) where - peaking_ provided = CTOR.Peaking all.freq all.q all.gain - where - all :: { | PeakingAll } - all = convertOptionsWithDefaults Peaking' defaultPeaking provided -else instance peaking_Ctor2 :: (InitialVal a, SetterVal a) => PeakingCtor_ a (CTOR.Peaking GetSetAP GetSetAP GetSetAP) where - peaking_ a = CTOR.Peaking (Tuple (initialVal a) (setterVal a)) defaultPeaking.q defaultPeaking.gain - -type CPeaking a - = CTOR.Peaking GetSetAP GetSetAP GetSetAP /\ a - -type DPeaking - = CTOR.Peaking GetSetAP GetSetAP GetSetAP - ------- -class PeriodicOscCtor_ i o | i -> o where - -- | Change a periodic oscillator - -- | - -- | ```purescript - -- | periodicOsc_ "my-wavetable" 440.0 - -- | periodicOsc_ On "my-wavetable" 440.0 - -- | ``` - periodicOsc_ :: i -> o - -instance periodicOsc1_ :: - ( InitialVal a - , SetterVal a - ) => - PeriodicOscCtor_ String (a -> CTOR.PeriodicOsc String GetSetAP) where - periodicOsc_ px gvsv = CTOR.PeriodicOsc px On (Tuple (initialVal gvsv) (setterVal gvsv)) - -instance periodicOsc2_ :: - ( InitialVal a - , SetterVal a - ) => - PeriodicOscCtor_ (V.Vec size Number /\ V.Vec size Number) (a -> CTOR.PeriodicOsc (V.Vec size Number /\ V.Vec size Number) GetSetAP) where - periodicOsc_ px gvsv = CTOR.PeriodicOsc px On (Tuple (initialVal gvsv) (setterVal gvsv)) - -class IsPoscable (isPoscable :: Type) - -instance isPoscableString :: IsPoscable String - -instance isPoscableV :: IsPoscable (V.Vec size Number /\ V.Vec size Number) - -instance periodicOsc3_ :: - ( InitialVal a - , SetterVal a - , IsPoscable isPoscable - ) => - PeriodicOscCtor_ OnOff (isPoscable -> a -> CTOR.PeriodicOsc isPoscable GetSetAP) where - periodicOsc_ oo px gvsv = CTOR.PeriodicOsc px oo (Tuple (initialVal gvsv) (setterVal gvsv)) - -class PeriodicOscCtor i o | i -> o where - -- | Make a periodic oscillator - -- | - -- | ```purescript - -- | periodicOsc "my-wavetable" 440.0 - -- | periodicOsc On "my-wavetable" 440.0 - -- | ``` - periodicOsc :: i -> o - -instance periodicOsc1 :: - ( InitialVal a - , SetterVal a - ) => - PeriodicOscCtor String (a -> CTOR.PeriodicOsc String GetSetAP /\ {}) where - periodicOsc px gvsv = CTOR.PeriodicOsc px On (Tuple (initialVal gvsv) (setterVal gvsv)) /\ {} - -instance periodicOsc2 :: - ( InitialVal a - , SetterVal a - ) => - PeriodicOscCtor (V.Vec size Number /\ V.Vec size Number) (a -> CTOR.PeriodicOsc (V.Vec size Number /\ V.Vec size Number) GetSetAP /\ {}) where - periodicOsc px gvsv = CTOR.PeriodicOsc px On (Tuple (initialVal gvsv) (setterVal gvsv)) /\ {} - -instance periodicOsc3 :: - ( InitialVal a - , SetterVal a - , IsPoscable isPoscable - ) => - PeriodicOscCtor OnOff (isPoscable -> a -> CTOR.PeriodicOsc isPoscable GetSetAP /\ {}) where - periodicOsc oo px gvsv = CTOR.PeriodicOsc px oo (Tuple (initialVal gvsv) (setterVal gvsv)) /\ {} - -type CPeriodicOsc periodicOsc - = CTOR.PeriodicOsc periodicOsc GetSetAP /\ {} - -type DPeriodicOsc periodicOsc - = CTOR.PeriodicOsc periodicOsc GetSetAP - ---- -data PlayBuf' - = PlayBuf' - -instance convertPlayBufPlaybackRate :: (InitialVal a, SetterVal a) => ConvertOption PlayBuf' "playbackRate" a GetSetAP where - convertOption _ _ gvsv = Tuple (initialVal gvsv) (setterVal gvsv) - -instance convertPlayBufOnOff :: ConvertOption PlayBuf' "onOff" OnOff OnOff where - convertOption _ _ = identity - -type PlayBufOptional - = ( playbackRate :: GetSetAP, onOff :: OnOff, start :: Number ) - -type PlayBufAll - = ( | PlayBufOptional ) - -defaultPlayBuf :: { | PlayBufOptional } -defaultPlayBuf = { playbackRate: defaultGetSetAP 1.0, onOff: On, start: 0.0 } - -class PlayBufCtor_ i playBuf | i -> playBuf where - -- | Change a unit that plays from a buffer. - -- | - -- | ```purescript - -- | playBuf_ { playbackRate: 1.0 } "track" - -- | playBuf_ { playbackRate: 1.0, start: 0.5 } "track" - -- | playBuf_ "track" - -- | ``` - playBuf_ :: i -> playBuf - -instance playBufCtor1_ :: - ( ConvertOptionsWithDefaults PlayBuf' { | PlayBufOptional } { | provided } { | PlayBufAll } - ) => - PlayBufCtor_ { | provided } (String -> CTOR.PlayBuf GetSetAP) where - playBuf_ provided proxy = CTOR.PlayBuf proxy all.start all.onOff all.playbackRate - where - all :: { | PlayBufAll } - all = convertOptionsWithDefaults PlayBuf' defaultPlayBuf provided -else instance playBufCtor2_ :: PlayBufCtor_ String (CTOR.PlayBuf GetSetAP) where - playBuf_ str = - CTOR.PlayBuf - str - defaultPlayBuf.start - defaultPlayBuf.onOff - defaultPlayBuf.playbackRate - -class PlayBufCtor i playBuf | i -> playBuf where - -- | Make a unit that plays from a buffer. - -- | - -- | ```purescript - -- | playBuf { playbackRate: 1.0 } "track" - -- | playBuf { playbackRate: 1.0, start: 0.5 } "track" - -- | playBuf "track" - -- | ``` - playBuf :: i -> playBuf - -instance playBufCtor1 :: - ConvertOptionsWithDefaults PlayBuf' { | PlayBufOptional } { | provided } { | PlayBufAll } => - PlayBufCtor { | provided } (String -> CTOR.PlayBuf GetSetAP /\ {}) where - playBuf provided proxy = CTOR.PlayBuf proxy all.start all.onOff all.playbackRate /\ {} - where - all :: { | PlayBufAll } - all = convertOptionsWithDefaults PlayBuf' defaultPlayBuf provided -else instance playBufCtor2 :: PlayBufCtor String (CTOR.PlayBuf GetSetAP /\ {}) where - playBuf str = - CTOR.PlayBuf - str - defaultPlayBuf.start - defaultPlayBuf.onOff - defaultPlayBuf.playbackRate - /\ {} - -type CPlayBuf - = CTOR.PlayBuf GetSetAP /\ {} - -type DPlayBuf - = CTOR.PlayBuf GetSetAP - ------- --- | Make a recorder. --- | --- | ```purescript --- | recorder "track" --- | ``` -recorder :: - forall a b. - IsSymbol a => - Proxy a -> b -> CTOR.Recorder a /\ b -recorder = Tuple <<< CTOR.Recorder - -type CRecorder a b - = CTOR.Recorder a /\ b - ------- -class SawtoothOscCtor_ i o | i -> o where - -- | Change a sawtooth oscillator - -- | - -- | ```purescript - -- | sawtoothOsc_ 440.0 - -- | sawtoothOsc_ On 440.0 - -- | ``` - sawtoothOsc_ :: i -> o - -instance sawtoothOsc2_ :: - ( InitialVal a - , SetterVal a - ) => - SawtoothOscCtor_ OnOff (a -> CTOR.SawtoothOsc GetSetAP) where - sawtoothOsc_ oo gvsv = CTOR.SawtoothOsc oo (Tuple (initialVal gvsv) (setterVal gvsv)) -else instance sawtoothOsc1_ :: - ( InitialVal a - , SetterVal a - ) => - SawtoothOscCtor_ a (CTOR.SawtoothOsc GetSetAP) where - sawtoothOsc_ gvsv = CTOR.SawtoothOsc On (Tuple (initialVal gvsv) (setterVal gvsv)) - -class SawtoothOscCtor i o | i -> o where - -- | Make a sawtooth oscillator - -- | - -- | ```purescript - -- | sawtoothOsc 440.0 - -- | sawtoothOsc On 440.0 - -- | ``` - sawtoothOsc :: i -> o - -instance sawtoothOsc2 :: - ( InitialVal a - , SetterVal a - ) => - SawtoothOscCtor OnOff (a -> CTOR.SawtoothOsc GetSetAP /\ {}) where - sawtoothOsc oo gvsv = CTOR.SawtoothOsc oo (Tuple (initialVal gvsv) (setterVal gvsv)) /\ {} -else instance sawtoothOsc1 :: - ( InitialVal a - , SetterVal a - ) => - SawtoothOscCtor a (CTOR.SawtoothOsc GetSetAP /\ {}) where - sawtoothOsc gvsv = CTOR.SawtoothOsc On (Tuple (initialVal gvsv) (setterVal gvsv)) /\ {} - -type CSawtoothOsc - = CTOR.SawtoothOsc GetSetAP /\ {} - -type DSawtoothOsc - = CTOR.SawtoothOsc GetSetAP - ------- -class SinOscCtor_ i o | i -> o where - -- | Change a sine-wave oscillator - -- | - -- | ```purescript - -- | sinOsc_ 440.0 - -- | sinOsc_ On 440.0 - -- | ``` - sinOsc_ :: i -> o - -instance sinOscCtor2_ :: - ( InitialVal a - , SetterVal a - ) => - SinOscCtor_ OnOff (a -> CTOR.SinOsc GetSetAP) where - sinOsc_ oo gvsv = CTOR.SinOsc oo (Tuple (initialVal gvsv) (setterVal gvsv)) -else instance sinOscCtor1_ :: - ( InitialVal a - , SetterVal a - ) => - SinOscCtor_ a (CTOR.SinOsc GetSetAP) where - sinOsc_ gvsv = CTOR.SinOsc On (Tuple (initialVal gvsv) (setterVal gvsv)) - -class SinOscCtor i o | i -> o where - -- | Make a sine-wave oscillator - -- | - -- | ```purescript - -- | sinOsc 440.0 - -- | sinOsc On 440.0 - -- | ``` - sinOsc :: i -> o - -instance sinOscCtor2 :: - ( InitialVal a - , SetterVal a - ) => - SinOscCtor OnOff (a -> CTOR.SinOsc GetSetAP /\ {}) where - sinOsc oo gvsv = CTOR.SinOsc oo (Tuple (initialVal gvsv) (setterVal gvsv)) /\ {} -else instance sinOscCtor1 :: - ( InitialVal a - , SetterVal a - ) => - SinOscCtor a (CTOR.SinOsc GetSetAP /\ {}) where - sinOsc gvsv = CTOR.SinOsc On (Tuple (initialVal gvsv) (setterVal gvsv)) /\ {} - -type CSinOsc - = CTOR.SinOsc GetSetAP /\ {} - -type DSinOsc - = CTOR.SinOsc GetSetAP - ------- --- | Send sound to the loudspeaker. --- | --- | ```purescript --- | speaker --- | ``` -speaker :: forall b. b -> { speaker :: CTOR.Speaker /\ b } -speaker b = { speaker: CTOR.Speaker /\ b } - --- | The raw constructor for speaker. Probably not useful... -speaker' :: forall b. b -> CTOR.Speaker /\ b -speaker' = Tuple CTOR.Speaker - -type CSpeaker a - = { speaker :: CTOR.Speaker /\ a } - ------- -class SquareOscCtor_ i o | i -> o where - -- | Change a square-wave oscillator - -- | - -- | ```purescript - -- | squareOsc_ 440.0 - -- | squareOsc_ On 440.0 - -- | ``` - squareOsc_ :: i -> o - -instance squareOscCtor2_ :: - ( InitialVal a - , SetterVal a - ) => - SquareOscCtor_ OnOff (a -> CTOR.SquareOsc GetSetAP) where - squareOsc_ oo gvsv = CTOR.SquareOsc oo (Tuple (initialVal gvsv) (setterVal gvsv)) -else instance squareOscCtor1_ :: - ( InitialVal a - , SetterVal a - ) => - SquareOscCtor_ a (CTOR.SquareOsc GetSetAP) where - squareOsc_ gvsv = CTOR.SquareOsc On (Tuple (initialVal gvsv) (setterVal gvsv)) - -class SquareOscCtor i o | i -> o where - -- | Make a square-wave oscillator - -- | - -- | ```purescript - -- | squareOsc 440.0 - -- | squareOsc On 440.0 - -- | ``` - squareOsc :: i -> o - -instance squareOscCtor2 :: - ( InitialVal a - , SetterVal a - ) => - SquareOscCtor OnOff (a -> CTOR.SquareOsc GetSetAP /\ {}) where - squareOsc oo gvsv = CTOR.SquareOsc oo (Tuple (initialVal gvsv) (setterVal gvsv)) /\ {} -else instance squareOscCtor1 :: - ( InitialVal a - , SetterVal a - ) => - SquareOscCtor a (CTOR.SquareOsc GetSetAP /\ {}) where - squareOsc gvsv = CTOR.SquareOsc On (Tuple (initialVal gvsv) (setterVal gvsv)) /\ {} - -type CSquareOsc - = CTOR.SquareOsc GetSetAP /\ {} - -type DSquareOsc - = CTOR.SquareOsc GetSetAP - ------- --- | Pan audio. --- | --- | ```purescript --- | pan 0.5 { buf: playBuf "my-track" } --- | ``` -pan :: - forall a b. - InitialVal a => - SetterVal a => - a -> b -> CTOR.StereoPanner GetSetAP /\ b -pan gvsv = Tuple (CTOR.StereoPanner (Tuple (initialVal gvsv) (setterVal gvsv))) - --- | Change panned audio. --- | --- | ```purescript --- | pan_ (-0.33) --- | ``` -pan_ :: forall a. InitialVal a => SetterVal a => a -> CTOR.StereoPanner GetSetAP -pan_ = fst <<< flip pan {} - -type CStereoPanner a - = CTOR.StereoPanner GetSetAP /\ a - -type DStereoPanner - = CTOR.StereoPanner GetSetAP - ------- -class TriangleOscCtor_ i o | i -> o where - -- | Change a triangle-wave oscillator - -- | - -- | ```purescript - -- | triangleOsc_ 440.0 - -- | triangleOsc_ On 440.0 - -- | ``` - triangleOsc_ :: i -> o - -instance triangleOscCtor2_ :: - ( InitialVal a - , SetterVal a - ) => - TriangleOscCtor_ OnOff (a -> CTOR.TriangleOsc GetSetAP) where - triangleOsc_ oo gvsv = CTOR.TriangleOsc oo (Tuple (initialVal gvsv) (setterVal gvsv)) -else instance triangleOscCtor1_ :: - ( InitialVal a - , SetterVal a - ) => - TriangleOscCtor_ a (CTOR.TriangleOsc GetSetAP) where - triangleOsc_ gvsv = CTOR.TriangleOsc On (Tuple (initialVal gvsv) (setterVal gvsv)) - -class TriangleOscCtor i o | i -> o where - -- | Make a triangle-wave oscillator - -- | - -- | ```purescript - -- | triangleOsc 440.0 - -- | triangleOsc On 440.0 - -- | ``` - triangleOsc :: i -> o - -instance triangleOscCtor2 :: - ( InitialVal a - , SetterVal a - ) => - TriangleOscCtor OnOff (a -> CTOR.TriangleOsc GetSetAP /\ {}) where - triangleOsc oo gvsv = CTOR.TriangleOsc oo (Tuple (initialVal gvsv) (setterVal gvsv)) /\ {} -else instance triangleOscCtor1 :: - ( InitialVal a - , SetterVal a - ) => - TriangleOscCtor a (CTOR.TriangleOsc GetSetAP /\ {}) where - triangleOsc gvsv = CTOR.TriangleOsc On (Tuple (initialVal gvsv) (setterVal gvsv)) /\ {} - -type CTriangleOsc - = CTOR.TriangleOsc GetSetAP /\ {} - -type DTriangleOsc - = CTOR.TriangleOsc GetSetAP - ----------- --- | Apply distorion to audio --- | --- | ```purescript --- | waveShaper (Proxy :: _ "my-wave") OversampleNone { buf: playBuf "my-track" } --- | ``` -waveShaper :: - forall a b c. - IsSymbol a => - IsOversample b => - Proxy a -> b -> c -> CTOR.WaveShaper a b /\ c -waveShaper a = Tuple <<< CTOR.WaveShaper a - -waveShaper_ :: forall a b. IsSymbol a => IsOversample b => Proxy a -> b -> CTOR.WaveShaper a b -waveShaper_ a b = fst $ waveShaper a b {} - -type CWaveShaper a b c - = CTOR.WaveShaper a b /\ c - ---------------- --- | A reference to a node in a graph. -type Ref - = Unit /\ {} - --- | A reference to a node in a graph. -ref :: Ref -ref = unit /\ {} diff --git a/src/WAGS/Graph/Parameter.purs b/src/WAGS/Graph/Parameter.purs index 382ac300..43a52c2e 100644 --- a/src/WAGS/Graph/Parameter.purs +++ b/src/WAGS/Graph/Parameter.purs @@ -1,6 +1,9 @@ module WAGS.Graph.Parameter where import Prelude hiding (apply) + +import Control.Alt (class Alt) +import Control.Plus (class Plus) import Data.Function (apply) import Data.Generic.Rep (class Generic) import Data.Maybe (Maybe(..), maybe) @@ -20,11 +23,20 @@ derive instance eqAudioParameter :: Eq a => Eq (AudioParameter_ a) derive instance functorAudioParameter :: Functor AudioParameter_ +instance altAudioParameter :: Alt AudioParameter_ where + alt l@(AudioParameter { param: Just a }) r@(AudioParameter { param: Just b }) = l + alt l@(AudioParameter { param: Nothing }) r@(AudioParameter { param: Just b }) = r + alt l@(AudioParameter { param: Just a }) r@(AudioParameter { param: Nothing }) = l + alt l@(AudioParameter { param: Nothing }) r@(AudioParameter { param: Nothing }) = l + +instance plusAudioParameter :: Plus AudioParameter_ where + empty = AudioParameter (R.set (Proxy :: _ "param") Nothing defaultParam) + instance applyAudioParameter :: Apply AudioParameter_ where apply = bop apply instance applicativeAudioParameter :: Applicative AudioParameter_ where - pure = param + pure a = AudioParameter (R.set (Proxy :: _ "param") (Just a) defaultParam) instance bindAudioParameter :: Bind AudioParameter_ where bind ma@(AudioParameter i@{ param: Nothing }) _ = AudioParameter (i { param = Nothing }) @@ -36,21 +48,21 @@ instance semigroupAudioParameter :: Semigroup a => Semigroup (AudioParameter_ a) append = bop append instance monoidAudioParameter :: Monoid a => Monoid (AudioParameter_ a) where - mempty = param mempty + mempty = pure mempty derive instance newtypeAudioParameter :: Newtype (AudioParameter_ a) _ derive newtype instance showAudioParameter :: Show a => Show (AudioParameter_ a) uop :: forall a b. (a -> b) -> AudioParameter_ a -> AudioParameter_ b -uop f (AudioParameter a0@{ param: param0, timeOffset: timeOffset0, transition: transition0, forceSet: forceSet0 }) = AudioParameter { param: f <$> param0, timeOffset: timeOffset0, transition: transition0, forceSet: forceSet0 } +uop f (AudioParameter a0@{ param: param0, timeOffset: timeOffset0, transition: transition0 }) = AudioParameter { param: f <$> param0, timeOffset: timeOffset0, transition: transition0 } bop :: forall a b c. (a -> b -> c) -> AudioParameter_ a -> AudioParameter_ b -> AudioParameter_ c -bop f (AudioParameter a0@{ param: param0, timeOffset: timeOffset0, transition: transition0, forceSet: forceSet0 }) (AudioParameter a1@{ param: param1, timeOffset: timeOffset1, transition: transition1, forceSet: forceSet1 }) = AudioParameter { param: f <$> param0 <*> param1, timeOffset: timeOffset0 + timeOffset1 / 2.0, transition: transition0 <> transition1, forceSet: forceSet0 || forceSet1 } +bop f (AudioParameter a0@{ param: param0, timeOffset: timeOffset0, transition: transition0}) (AudioParameter a1@{ param: param1, timeOffset: timeOffset1, transition: transition1 }) = AudioParameter { param: f <$> param0 <*> param1, timeOffset: timeOffset0 + timeOffset1 / 2.0, transition: transition0 <> transition1 } instance semiringAudioParameter :: Semiring a => Semiring (AudioParameter_ a) where - zero = AudioParameter { param: Just zero, timeOffset: 0.0, transition: LinearRamp, forceSet: false } - one = AudioParameter { param: Just one, timeOffset: 0.0, transition: LinearRamp, forceSet: false } + zero = AudioParameter { param: Just zero, timeOffset: 0.0, transition: LinearRamp } + one = AudioParameter { param: Just one, timeOffset: 0.0, transition: LinearRamp } add = bop add mul = bop mul @@ -72,12 +84,10 @@ instance euclideanRingAudioParameter :: EuclideanRing a => EuclideanRing (AudioP -- | `param`: The parameter as a floating-point value _or_ an instruction to cancel all future parameters. -- | `timeOffset`: How far ahead of the current playhead to set the parameter. This can be used in conjunction with the `headroom` parameter in `run` to execute precisely-timed events. For example, if the `headroom` is `20ms` and an attack should happen in `10ms`, use `timeOffset: 10.0` to make sure that the taret parameter happens exactly at the point of attack. -- | `transition`: Transition between two points in time. --- | `forceSet`: Should we force the setting of this parameter? type AudioParameter_' a = { param :: Maybe a , timeOffset :: Number , transition :: AudioParameterTransition - , forceSet :: Boolean } type AudioParameter' @@ -110,10 +120,6 @@ instance semigroupAudioParameterTransition :: Semigroup AudioParameterTransition append _ LinearRamp = LinearRamp append _ _ = NoRamp --- | Create an audio parameter from a number using default parameters. -param :: forall a. a -> AudioParameter_ a -param a = AudioParameter (R.set (Proxy :: _ "param") (Just a) defaultParam) - ff :: forall a. Number -> AudioParameter_ a -> AudioParameter_ a ff n (AudioParameter i) = AudioParameter (i { timeOffset = i.timeOffset + n }) @@ -123,15 +129,6 @@ modTime f (AudioParameter i) = AudioParameter (i { timeOffset = f i.timeOffset } modParam :: forall a. (a -> a) -> AudioParameter_ a -> AudioParameter_ a modParam f (AudioParameter i) = AudioParameter (i { param = f <$> i.param }) -forceSet :: forall a. AudioParameter_ a -> AudioParameter_ a -forceSet = modForceSet (const true) - -unForceSet :: forall a. AudioParameter_ a -> AudioParameter_ a -unForceSet = modForceSet (const false) - -modForceSet :: forall a. (Boolean -> Boolean) -> AudioParameter_ a -> AudioParameter_ a -modForceSet f (AudioParameter i) = AudioParameter (i { forceSet = f i.forceSet }) - modRamp :: forall a. (AudioParameterTransition -> AudioParameterTransition) -> AudioParameter_ a -> AudioParameter_ a modRamp f (AudioParameter i) = AudioParameter (i { transition = f i.transition }) @@ -151,4 +148,22 @@ immediately = modRamp (const Immediately) -- | -- | defaultParam = { param: 0.0, timeOffset: 0.0, transition: LinearRamp } defaultParam :: AudioParameter' -defaultParam = { param: Just 0.0, timeOffset: 0.0, transition: LinearRamp, forceSet: false } +defaultParam = { param: Just 0.0, timeOffset: 0.0, transition: LinearRamp } + +-- | A value that can be coerced to an initial control-rate audio parameter. +class Paramable a where + paramize :: a -> AudioParameter + +instance paramableNumber :: Paramable Number where + paramize = pure + +instance paramableAudioParameter :: Paramable AudioParameter where + paramize = identity + +class MM a b | a -> b where + mm :: a -> b + +instance maybeMM :: MM (Maybe a) (Maybe a) where + mm = identity +else instance justMM :: MM a (Maybe a) where + mm = pure \ No newline at end of file diff --git a/src/WAGS/Interpret.js b/src/WAGS/Interpret.js index 030d3c23..bbfc697c 100644 --- a/src/WAGS/Interpret.js +++ b/src/WAGS/Interpret.js @@ -99,15 +99,14 @@ exports.rebaseAllUnits_ = function (toRebase) { }; }; }; -exports.renderAudio = function (ffiAudio) { - return function (arrayToApply) { - return function () { - for (var i = 0; i < arrayToApply.length; i++) { - arrayToApply[i](ffiAudio)(); - } - }; +exports.renderAudio = function (arrayToApply) { + return function () { + for (var i = 0; i < arrayToApply.length; i++) { + arrayToApply[i](); + } }; }; + exports.getAudioClockTime = function (ctx) { return function () { return ctx.currentTime; @@ -173,6 +172,7 @@ exports.makeConstant_ = function (ptr) { if (onOff) { state.units[ptr].main.start(); } + state.units[ptr].onOff = onOff; }; }; }; @@ -339,6 +339,7 @@ exports.makeLoopBuf_ = function (ptr) { c ); } + state.units[ptr].onOff = onOff; }; }; }; @@ -481,6 +482,7 @@ exports.makePeriodicOsc_ = function (ptr) { if (onOff) { state.units[ptr].main.start(state.writeHead + b.timeOffset); } + state.units[ptr].onOff = onOff; }; }; }; @@ -517,6 +519,7 @@ exports.makePeriodicOscV_ = function (ptr) { if (onOff) { state.units[ptr].main.start(state.writeHead + b.timeOffset); } + state.units[ptr].onOff = onOff; }; }; }; @@ -569,6 +572,7 @@ exports.makePlayBuf_ = function (ptr) { state.units[ptr].main.buffer = state.buffers[a]; state.units[ptr].main.start(state.writeHead + c.timeOffset, b); } + state.units[ptr].onOff = onOff; }; }; }; @@ -621,6 +625,7 @@ exports.makeSawtoothOsc_ = function (ptr) { if (onOff) { state.units[ptr].main.start(state.writeHead + a.timeOffset); } + state.units[ptr].onOff = onOff; }; }; }; @@ -651,6 +656,7 @@ exports.makeSinOsc_ = function (ptr) { if (onOff) { state.units[ptr].main.start(state.writeHead + a.timeOffset); } + state.units[ptr].onOff = onOff; }; }; }; @@ -692,6 +698,7 @@ exports.makeSquareOsc_ = function (ptr) { if (onOff) { state.units[ptr].main.start(state.writeHead + a.timeOffset); } + state.units[ptr].onOff = onOff; }; }; }; @@ -736,6 +743,7 @@ exports.makeTriangleOsc_ = function (ptr) { if (onOff) { state.units[ptr].main.start(state.writeHead + a.timeOffset); } + state.units[ptr].onOff = onOff; }; }; }; @@ -807,6 +815,10 @@ var applyResumeClosure = function (i) { exports.setOn_ = function (ptr) { return function (state) { return function () { + if (state.units[ptr].onOff) { + return; + } + state.units[ptr].onOff = true; if (state.units[ptr].resumeClosure) { applyResumeClosure(state.units[ptr]); } @@ -821,6 +833,10 @@ exports.setOn_ = function (ptr) { exports.setOff_ = function (ptr) { return function (state) { return function () { + if (!state.units[ptr].onOff) { + return; + } + state.units[ptr].onOff = false; state.units[ptr].main.stop(); for (var i = 0; i < state.units[ptr].outgoing.length; i++) { state.units[ptr].main.disconnect( diff --git a/src/WAGS/Interpret.purs b/src/WAGS/Interpret.purs index 9191c3da..6f683bfa 100644 --- a/src/WAGS/Interpret.purs +++ b/src/WAGS/Interpret.purs @@ -194,7 +194,7 @@ foreign import makeUnitCache :: Effect Foreign -- | taking `Array Effect Unit -> Effect Unit` and doing `map fold <<< sequence`. -- | The reason this version is used is because it is ~2x more computationally efficient, -- | which is important in order to be able to hit audio deadlines. -foreign import renderAudio :: FFIAudio -> Array (FFIAudio -> Effect Unit) -> Effect Unit +foreign import renderAudio :: Array (Effect Unit) -> Effect Unit -- | Make a browser periodic wave. A PureScript-ified version of the periodic wave constructor -- | from the [Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/PeriodicWave/PeriodicWave). @@ -635,3 +635,57 @@ instance safeToFFI_AudioParameter :: , transition: show transition , cancel: isNothing param } + +instance mixedAudioInterpret :: (AudioInterpret a c, AudioInterpret b d) => AudioInterpret (a /\ b) (c /\ d) where + connectXToY a b (x /\ y) = connectXToY a b x /\ connectXToY a b y + disconnectXFromY a b (x /\ y) = disconnectXFromY a b x /\ disconnectXFromY a b y + destroyUnit a (x /\ y) = destroyUnit a x /\ destroyUnit a y + makeAllpass a b c (x /\ y) = makeAllpass a b c x /\ makeAllpass a b c y + makeBandpass a b c (x /\ y) = makeBandpass a b c x /\ makeBandpass a b c y + makeConstant a b c (x /\ y) = makeConstant a b c x /\ makeConstant a b c y + makeConvolver a b (x /\ y) = makeConvolver a b x /\ makeConvolver a b y + makeDelay a b (x /\ y) = makeDelay a b x /\ makeDelay a b y + makeDynamicsCompressor a b c d e f (x /\ y) = makeDynamicsCompressor a b c d e f x /\ makeDynamicsCompressor a b c d e f y + makeGain a b (x /\ y) = makeGain a b x /\ makeGain a b y + makeHighpass a b c (x /\ y) = makeHighpass a b c x /\ makeHighpass a b c y + makeHighshelf a b c (x /\ y) = makeHighshelf a b c x /\ makeHighshelf a b c y + makeLoopBufWithDeferredBuffer a (x /\ y) = makeLoopBufWithDeferredBuffer a x /\ makeLoopBufWithDeferredBuffer a y + makeLoopBuf a b c d e f (x /\ y) = makeLoopBuf a b c d e f x /\ makeLoopBuf a b c d e f y + makeLowpass a b c (x /\ y) = makeLowpass a b c x /\ makeLowpass a b c y + makeLowshelf a b c (x /\ y) = makeLowshelf a b c x /\ makeLowshelf a b c y + makeMicrophone (x /\ y) = makeMicrophone x /\ makeMicrophone y + makeNotch a b c (x /\ y) = makeNotch a b c x /\ makeNotch a b c y + makePeaking a b c d (x /\ y) = makePeaking a b c d x /\ makePeaking a b c d y + makePeriodicOsc a b c d (x /\ y) = makePeriodicOsc a b c d x /\ makePeriodicOsc a b c d y + makePeriodicOscV a b c d (x /\ y) = makePeriodicOscV a b c d x /\ makePeriodicOscV a b c d y + makePeriodicOscWithDeferredOsc a (x /\ y) = makePeriodicOscWithDeferredOsc a x /\ makePeriodicOscWithDeferredOsc a y + makePlayBufWithDeferredBuffer a (x /\ y) = makePlayBufWithDeferredBuffer a x /\ makePlayBufWithDeferredBuffer a y + makePlayBuf a b c d e (x /\ y) = makePlayBuf a b c d e x /\ makePlayBuf a b c d e y + makeRecorder a b (x /\ y) = makeRecorder a b x /\ makeRecorder a b y + makeSawtoothOsc a b c (x /\ y) = makeSawtoothOsc a b c x /\ makeSawtoothOsc a b c y + makeSinOsc a b c (x /\ y) = makeSinOsc a b c x /\ makeSinOsc a b c y + makeSpeaker (x /\ y) = makeSpeaker x /\ makeSpeaker y + makeSquareOsc a b c (x /\ y) = makeSquareOsc a b c x /\ makeSquareOsc a b c y + makeStereoPanner a b (x /\ y) = makeStereoPanner a b x /\ makeStereoPanner a b y + makeTriangleOsc a b c (x /\ y) = makeTriangleOsc a b c x /\ makeTriangleOsc a b c y + makeWaveShaper a b c (x /\ y) = makeWaveShaper a b c x /\ makeWaveShaper a b c y + setBuffer a b (x /\ y) = setBuffer a b x /\ setBuffer a b y + setPeriodicOsc a b (x /\ y) = setPeriodicOsc a b x /\ setPeriodicOsc a b y + setPeriodicOscV a b (x /\ y) = setPeriodicOscV a b x /\ setPeriodicOscV a b y + setOn a (x /\ y) = setOn a x /\ setOn a y + setOff a (x /\ y) = setOff a x /\ setOff a y + setBufferOffset a b (x /\ y) = setBufferOffset a b x /\ setBufferOffset a b y + setLoopStart a b (x /\ y) = setLoopStart a b x /\ setLoopStart a b y + setLoopEnd a b (x /\ y) = setLoopEnd a b x /\ setLoopEnd a b y + setRatio a b (x /\ y) = setRatio a b x /\ setRatio a b y + setOffset a b (x /\ y) = setOffset a b x /\ setOffset a b y + setAttack a b (x /\ y) = setAttack a b x /\ setAttack a b y + setGain a b (x /\ y) = setGain a b x /\ setGain a b y + setQ a b (x /\ y) = setQ a b x /\ setQ a b y + setPan a b (x /\ y) = setPan a b x /\ setPan a b y + setThreshold a b (x /\ y) = setThreshold a b x /\ setThreshold a b y + setRelease a b (x /\ y) = setRelease a b x /\ setRelease a b y + setKnee a b (x /\ y) = setKnee a b x /\ setKnee a b y + setDelay a b (x /\ y) = setDelay a b x /\ setDelay a b y + setPlaybackRate a b (x /\ y) = setPlaybackRate a b x /\ setPlaybackRate a b y + setFrequency a b (x /\ y) = setFrequency a b x /\ setFrequency a b y diff --git a/src/WAGS/NE2CF.purs b/src/WAGS/NE2CF.purs index 51ac1fae..cc3faacb 100644 --- a/src/WAGS/NE2CF.purs +++ b/src/WAGS/NE2CF.purs @@ -1,7 +1,6 @@ module WAGS.NE2CF where import Prelude - import Control.Comonad.Cofree (Cofree, hoistCofree, (:<)) import Control.Semigroupoid (composeFlipped) import Data.Lens (_2, over) @@ -21,35 +20,30 @@ type ASDR -- | From a non-empty list of times and values, make a cofree comonad that emits audio parameters -- | Based on a current time and a look-ahead makePiecewise :: NonEmpty List (Number /\ Number) -> ASDR -makePiecewise = makePiecewise' true - where - makePiecewise' :: Boolean -> NonEmpty List (Number /\ Number) -> ASDR - makePiecewise' forceSet (a /\ b :| Nil) _ = - AudioParameter - { param: Just b - , timeOffset: 0.0 - , transition: LinearRamp - , forceSet - } - :< makePiecewise' false (a /\ b :| Nil) +makePiecewise (a /\ b :| Nil) _ = + AudioParameter + { param: Just b + , timeOffset: 0.0 + , transition: LinearRamp + } + :< makePiecewise (a /\ b :| Nil) - makePiecewise' forceSet v@(a /\ b :| (Cons (c /\ d) e)) { time, headroom } - | time <= c = - let - lookahead = time + headroom - in - ( if lookahead >= c then - AudioParameter - { param: Just d - , timeOffset: c - time - , transition: LinearRamp - , forceSet - } - else - AudioParameter { param: Just (calcSlope a b c d time), timeOffset: 0.0, transition: LinearRamp, forceSet } - ) - :< makePiecewise' false v - | otherwise = makePiecewise' false (c /\ d :| e) { time, headroom } +makePiecewise v@(a /\ b :| (Cons (c /\ d) e)) { time, headroom } + | time <= c = + let + lookahead = time + headroom + in + ( if lookahead >= c then + AudioParameter + { param: Just d + , timeOffset: c - time + , transition: LinearRamp + } + else + AudioParameter { param: Just (calcSlope a b c d time), timeOffset: 0.0, transition: LinearRamp } + ) + :< makePiecewise v + | otherwise = makePiecewise (c /\ d :| e) { time, headroom } type NonEmptyToCofree a b = { time :: Number, value :: a } -> Cofree ((->) { time :: Number, value :: a }) b @@ -76,4 +70,4 @@ nonEmptyToCofreeFull maybeOtherwise (h :| t) = go (h : t) Just f -> let q i = f i :< q in q Nothing -> go (h : t) - go ((tf /\ vf) : b) = let q i@{ time } = if tf time then (vf i :< q) else go b i in q \ No newline at end of file + go ((tf /\ vf) : b) = let q i@{ time } = if tf time then (vf i :< q) else go b i in q diff --git a/src/WAGS/Patch.purs b/src/WAGS/Patch.purs index 9c4d9582..cca0f437 100644 --- a/src/WAGS/Patch.purs +++ b/src/WAGS/Patch.purs @@ -1,11 +1,8 @@ module WAGS.Patch where import Prelude hiding (Ordering(..)) -import Data.Either (Either(..)) -import Data.Map as M -import Data.Set as S import Data.Symbol (class IsSymbol, reflectSymbol) -import Data.Tuple.Nested (type (/\), (/\)) +import Data.Tuple.Nested (type (/\)) import Data.Typelevel.Bool (False, True) import Prim.Ordering (Ordering, LT, GT, EQ) import Prim.RowList (class RowToList) @@ -17,9 +14,7 @@ import WAGS.Control.Types (WAG, unsafeUnWAG, unsafeWAG) import WAGS.Graph.AudioUnit (OnOff(..)) import WAGS.Graph.AudioUnit as AU import WAGS.Graph.Oversample (class IsOversample, reflectOversample) -import WAGS.Graph.Parameter (param) import WAGS.Interpret (class AudioInterpret, connectXToY, destroyUnit, disconnectXFromY, makeAllpass, makeBandpass, makeConstant, makeConvolver, makeDelay, makeDynamicsCompressor, makeGain, makeHighpass, makeHighshelf, makeLoopBufWithDeferredBuffer, makeLowpass, makeLowshelf, makeMicrophone, makeNotch, makePeaking, makePeriodicOscWithDeferredOsc, makePlayBufWithDeferredBuffer, makeRecorder, makeSawtoothOsc, makeSinOsc, makeSpeaker, makeSquareOsc, makeStereoPanner, makeTriangleOsc, makeWaveShaper) -import WAGS.Rendered as Rendered import WAGS.Util (class TypeEqualTF) data ConnectXToY (x :: Symbol) (y :: Symbol) @@ -310,13 +305,9 @@ class ToGraphEffects (i :: Type) where forall audio engine. AudioInterpret audio engine => Proxy i -> - { internalNodes :: M.Map String Rendered.AnAudioUnit - , internalEdges :: M.Map String (S.Set String) - , instructions :: Array (audio -> engine) + { instructions :: Array (audio -> engine) } -> - { internalNodes :: M.Map String Rendered.AnAudioUnit - , internalEdges :: M.Map String (S.Set String) - , instructions :: Array (audio -> engine) + { instructions :: Array (audio -> engine) } instance toGraphEffectsUnit :: ToGraphEffects Unit where @@ -326,8 +317,7 @@ instance toGraphEffectsConnectXToY :: (IsSymbol from, IsSymbol to, ToGraphEffect toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalEdges = M.insertWith S.union to' (S.singleton from') i.internalEdges - , instructions = i.instructions <> [ connectXToY from' to' ] + { instructions = i.instructions <> [ connectXToY from' to' ] } ) where @@ -339,8 +329,7 @@ instance toGraphEffectsDisconnectXFromY :: (IsSymbol from, IsSymbol to, ToGraphE toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalEdges = M.insertWith S.difference to' (S.singleton from') (i.internalEdges) - , instructions = i.instructions <> [ disconnectXFromY from' to' ] + { instructions = i.instructions <> [ disconnectXFromY from' to' ] } ) where @@ -352,9 +341,7 @@ instance toGraphEffectsDestroyUnit :: (IsSymbol ptr, ToGraphEffects rest) => ToG toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.delete ptr' i.internalNodes - , internalEdges = M.delete ptr' i.internalEdges - , instructions = i.instructions <> [ destroyUnit ptr' ] + { instructions = i.instructions <> [ destroyUnit ptr' ] } ) where @@ -364,8 +351,7 @@ instance toGraphEffectsMakeAllpass :: (IsSymbol ptr, ToGraphEffects rest) => ToG toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.AAllpass (param 440.0) (param 1.0)) i.internalNodes - , instructions = i.instructions <> [ makeAllpass ptr' (param 440.0) (param 1.0) ] + { instructions = i.instructions <> [ makeAllpass ptr' (pure 440.0) (pure 1.0) ] } ) where @@ -375,8 +361,7 @@ instance toGraphEffectsMakeBandpass :: (IsSymbol ptr, ToGraphEffects rest) => To toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.ABandpass (param 440.0) (param 1.0)) i.internalNodes - , instructions = i.instructions <> [ makeBandpass ptr' (param 440.0) (param 1.0) ] + { instructions = i.instructions <> [ makeBandpass ptr' (pure 440.0) (pure 1.0) ] } ) where @@ -386,8 +371,7 @@ instance toGraphEffectsMakeConstant :: (IsSymbol ptr, ToGraphEffects rest) => To toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.AConstant Off (param 0.0)) i.internalNodes - , instructions = i.instructions <> [ makeConstant ptr' Off (param 0.0) ] + { instructions = i.instructions <> [ makeConstant ptr' Off (pure 0.0) ] } ) where @@ -397,8 +381,7 @@ instance toGraphEffectsMakeConvolver :: (IsSymbol ptr, IsSymbol sym, ToGraphEffe toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.AConvolver sym') i.internalNodes - , instructions = i.instructions <> [ makeConvolver ptr' sym' ] + { instructions = i.instructions <> [ makeConvolver ptr' sym' ] } ) where @@ -410,8 +393,7 @@ instance toGraphEffectsMakeDelay :: (IsSymbol ptr, ToGraphEffects rest) => ToGra toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.ADelay (param 1.0)) i.internalNodes - , instructions = i.instructions <> [ makeDelay ptr' (param 1.0) ] + { instructions = i.instructions <> [ makeDelay ptr' (pure 1.0) ] } ) where @@ -421,8 +403,7 @@ instance toGraphEffectsMakeDynamicsCompressor :: (IsSymbol ptr, ToGraphEffects r toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.ADynamicsCompressor (param (-24.0)) (param 30.0) (param 12.0) (param 0.003) (param 0.25)) i.internalNodes - , instructions = i.instructions <> [ makeDynamicsCompressor ptr' (param (-24.0)) (param 30.0) (param 12.0) (param 0.003) (param 0.25) ] + { instructions = i.instructions <> [ makeDynamicsCompressor ptr' (pure (-24.0)) (pure 30.0) (pure 12.0) (pure 0.003) (pure 0.25) ] } ) where @@ -432,8 +413,7 @@ instance toGraphEffectsMakeGain :: (IsSymbol ptr, ToGraphEffects rest) => ToGrap toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.AGain (param 0.0)) i.internalNodes - , instructions = i.instructions <> [ makeGain ptr' (param 0.0) ] + { instructions = i.instructions <> [ makeGain ptr' (pure 0.0) ] } ) where @@ -443,8 +423,7 @@ instance toGraphEffectsMakeHighpass :: (IsSymbol ptr, ToGraphEffects rest) => To toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.AHighpass (param 440.0) (param 1.0)) i.internalNodes - , instructions = i.instructions <> [ makeHighpass ptr' (param 440.0) (param 1.0) ] + { instructions = i.instructions <> [ makeHighpass ptr' (pure 440.0) (pure 1.0) ] } ) where @@ -454,8 +433,7 @@ instance toGraphEffectsMakeHighshelf :: (IsSymbol ptr, ToGraphEffects rest) => T toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.AHighshelf (param 440.0) (param 0.0)) i.internalNodes - , instructions = i.instructions <> [ makeHighshelf ptr' (param 440.0) (param 0.0) ] + { instructions = i.instructions <> [ makeHighshelf ptr' (pure 440.0) (pure 0.0) ] } ) where @@ -465,8 +443,7 @@ instance toGraphEffectsMakeLoopBuf :: (IsSymbol ptr, ToGraphEffects rest) => ToG toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.ALoopBuf "" Off (param 1.0) 0.0 0.0) i.internalNodes - , instructions = i.instructions <> [ makeLoopBufWithDeferredBuffer ptr' ] + { instructions = i.instructions <> [ makeLoopBufWithDeferredBuffer ptr' ] } ) where @@ -476,8 +453,7 @@ instance toGraphEffectsMakeLowpass :: (IsSymbol ptr, ToGraphEffects rest) => ToG toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.ALowpass (param 440.0) (param 1.0)) i.internalNodes - , instructions = i.instructions <> [ makeLowpass ptr' (param 440.0) (param 1.0) ] + { instructions = i.instructions <> [ makeLowpass ptr' (pure 440.0) (pure 1.0) ] } ) where @@ -487,8 +463,7 @@ instance toGraphEffectsMakeLowshelf :: (IsSymbol ptr, ToGraphEffects rest) => To toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.ALowshelf (param 440.0) (param 0.0)) i.internalNodes - , instructions = i.instructions <> [ makeLowshelf ptr' (param 440.0) (param 0.0) ] + { instructions = i.instructions <> [ makeLowshelf ptr' (pure 440.0) (pure 0.0) ] } ) where @@ -498,8 +473,7 @@ instance toGraphEffectsMakeMicrophone :: (ToGraphEffects rest) => ToGraphEffects toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert "microphone" (Rendered.AMicrophone) i.internalNodes - , instructions = i.instructions <> [ makeMicrophone ] + { instructions = i.instructions <> [ makeMicrophone ] } ) @@ -507,8 +481,7 @@ instance toGraphEffectsMakeNotch :: (IsSymbol ptr, ToGraphEffects rest) => ToGra toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.ANotch (param 440.0) (param 1.0)) i.internalNodes - , instructions = i.instructions <> [ makeNotch ptr' (param 440.0) (param 1.0) ] + { instructions = i.instructions <> [ makeNotch ptr' (pure 440.0) (pure 1.0) ] } ) where @@ -518,8 +491,7 @@ instance toGraphEffectsMakePeaking :: (IsSymbol ptr, ToGraphEffects rest) => ToG toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.APeaking (param 440.0) (param 1.0) (param 0.0)) i.internalNodes - , instructions = i.instructions <> [ makePeaking ptr' (param 440.0) (param 1.0) (param 0.0) ] + { instructions = i.instructions <> [ makePeaking ptr' (pure 440.0) (pure 1.0) (pure 0.0) ] } ) where @@ -529,8 +501,7 @@ instance toGraphEffectsMakePeriodicOsc :: (IsSymbol ptr, ToGraphEffects rest) => toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.APeriodicOsc (Right ([ 0.0 ] /\ [ 0.0 ])) Off (param 440.0)) i.internalNodes - , instructions = i.instructions <> [ makePeriodicOscWithDeferredOsc ptr' ] + { instructions = i.instructions <> [ makePeriodicOscWithDeferredOsc ptr' ] } ) where @@ -540,8 +511,7 @@ instance toGraphEffectsMakePlayBuf :: (IsSymbol ptr, ToGraphEffects rest) => ToG toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.APlayBuf "" 0.0 Off (param 1.0)) i.internalNodes - , instructions = i.instructions <> [ makePlayBufWithDeferredBuffer ptr' ] + { instructions = i.instructions <> [ makePlayBufWithDeferredBuffer ptr' ] } ) where @@ -551,8 +521,7 @@ instance toGraphEffectsMakeRecorder :: (IsSymbol ptr, IsSymbol sym, ToGraphEffec toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.ARecorder sym') i.internalNodes - , instructions = i.instructions <> [ makeRecorder ptr' sym' ] + { instructions = i.instructions <> [ makeRecorder ptr' sym' ] } ) where @@ -564,8 +533,7 @@ instance toGraphEffectsMakeSawtoothOsc :: (IsSymbol ptr, ToGraphEffects rest) => toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.ASawtoothOsc Off (param 440.0)) i.internalNodes - , instructions = i.instructions <> [ makeSawtoothOsc ptr' Off (param 440.0) ] + { instructions = i.instructions <> [ makeSawtoothOsc ptr' Off (pure 440.0) ] } ) where @@ -575,8 +543,7 @@ instance toGraphEffectsMakeSinOsc :: (IsSymbol ptr, ToGraphEffects rest) => ToGr toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.ASinOsc Off (param 440.0)) i.internalNodes - , instructions = i.instructions <> [ makeSinOsc ptr' Off (param 440.0) ] + { instructions = i.instructions <> [ makeSinOsc ptr' Off (pure 440.0) ] } ) where @@ -586,8 +553,7 @@ instance toGraphEffectsMakeSquareOsc :: (IsSymbol ptr, ToGraphEffects rest) => T toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.ASquareOsc Off (param 440.0)) i.internalNodes - , instructions = i.instructions <> [ makeSquareOsc ptr' Off (param 440.0) ] + { instructions = i.instructions <> [ makeSquareOsc ptr' Off (pure 440.0) ] } ) where @@ -597,8 +563,7 @@ instance toGraphEffectsMakeSpeaker :: (ToGraphEffects rest) => ToGraphEffects (M toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert "speaker" Rendered.ASpeaker i.internalNodes - , instructions = i.instructions <> [ makeSpeaker ] + { instructions = i.instructions <> [ makeSpeaker ] } ) @@ -606,8 +571,7 @@ instance toGraphEffectsMakeStereoPanner :: (IsSymbol ptr, ToGraphEffects rest) = toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.AStereoPanner (param 0.0)) i.internalNodes - , instructions = i.instructions <> [ makeStereoPanner ptr' (param 0.0) ] + { instructions = i.instructions <> [ makeStereoPanner ptr' (pure 0.0) ] } ) where @@ -617,8 +581,7 @@ instance toGraphEffectsMakeTriangleOsc :: (IsSymbol ptr, ToGraphEffects rest) => toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.ATriangleOsc Off (param 440.0)) i.internalNodes - , instructions = i.instructions <> [ makeTriangleOsc ptr' Off (param 440.0) ] + { instructions = i.instructions <> [ makeTriangleOsc ptr' Off (pure 440.0) ] } ) where @@ -628,8 +591,7 @@ instance toGraphEffectsMakeWaveShaper :: (IsSymbol ptr, IsSymbol sym, IsOversamp toGraphEffects _ i = toGraphEffects (Proxy :: _ rest) ( i - { internalNodes = M.insert ptr' (Rendered.AWaveShaper ptr' oversample') i.internalNodes - , instructions = i.instructions <> [ makeWaveShaper ptr' sym' oversample' ] + { instructions = i.instructions <> [ makeWaveShaper ptr' sym' oversample' ] } ) where @@ -664,13 +626,11 @@ instance patchAll :: unsafeWAG { context: i - { internalNodes = n.internalNodes - , internalEdges = n.internalEdges - , instructions = n.instructions + { instructions = n.instructions } , value } where - { context: i@{ internalNodes, internalEdges, instructions }, value } = unsafeUnWAG w + { context: i@{ instructions }, value } = unsafeUnWAG w - n = toGraphEffects (Proxy :: _ instructions) { internalNodes, internalEdges, instructions } + n = toGraphEffects (Proxy :: _ instructions) { instructions } diff --git a/src/WAGS/Rendered.purs b/src/WAGS/Rendered.purs index 1ef1ae26..59d985be 100644 --- a/src/WAGS/Rendered.purs +++ b/src/WAGS/Rendered.purs @@ -87,40 +87,3 @@ derive instance genericOversample :: Generic Oversample _ instance showOversample :: Show Oversample where show = genericShow - --- | A term-level representation of audio units. Used for testing as well as internally to --- | represent the audio graph. They are also present in the output of `run` for downstream --- | graph visualization. -data AnAudioUnit - = AAllpass AudioParameter AudioParameter - | ABandpass AudioParameter AudioParameter - | AConstant OnOff AudioParameter - | AConvolver String - | ADelay AudioParameter - | ADynamicsCompressor AudioParameter AudioParameter AudioParameter AudioParameter AudioParameter - | AGain AudioParameter - | AHighpass AudioParameter AudioParameter - | AHighshelf AudioParameter AudioParameter - | ALoopBuf String OnOff AudioParameter Number Number - | ALowpass AudioParameter AudioParameter - | ALowshelf AudioParameter AudioParameter - | AMicrophone - | ANotch AudioParameter AudioParameter - | APeaking AudioParameter AudioParameter AudioParameter - | APeriodicOsc (Either String (Array Number /\ Array Number)) OnOff AudioParameter - | APlayBuf String Number OnOff AudioParameter - | ARecorder String - | ASawtoothOsc OnOff AudioParameter - | ASinOsc OnOff AudioParameter - | ASpeaker - | ASquareOsc OnOff AudioParameter - | AStereoPanner AudioParameter - | ATriangleOsc OnOff AudioParameter - | AWaveShaper String Oversample - -derive instance eqAnAudioUnit :: Eq AnAudioUnit - -derive instance genericAnAudioUnit :: Generic AnAudioUnit _ - -instance showAnAudioUnit :: Show AnAudioUnit where - show = genericShow diff --git a/src/WAGS/Run.purs b/src/WAGS/Run.purs index 075d9b0b..c27b4cf0 100644 --- a/src/WAGS/Run.purs +++ b/src/WAGS/Run.purs @@ -4,6 +4,8 @@ module WAGS.Run , EngineInfo , Run , SceneI + , RunAudio + , RunEngine , bufferToList , run ) where @@ -14,9 +16,9 @@ import Data.DateTime.Instant (Instant) import Data.Foldable (for_) import Data.Int (floor, toNumber) import Data.List (List(..)) -import Data.Map as M import Data.Maybe (Maybe(..), isNothing) -import Data.Set (Set) +import Data.Tuple (fst, snd) +import Data.Tuple.Nested ((/\), type (/\)) import Effect (Effect) import Effect.Ref as Ref import Effect.Timer (TimeoutId, clearTimeout, setTimeout) @@ -27,7 +29,13 @@ import FRP.Event.Time (withTime, delay) import Record as R import WAGS.Control.Types (Frame0, Scene, oneFrame) import WAGS.Interpret (FFIAudio(..), FFIAudio', getAudioClockTime, renderAudio) -import WAGS.Rendered (AnAudioUnit) +import WAGS.Rendered (Instruction) + +type RunAudio + = Unit /\ FFIAudio + +type RunEngine + = Instruction /\ Effect Unit -- | Run a scene. -- | @@ -45,8 +53,8 @@ run :: FFIAudio -> Scene (SceneI trigger world) - FFIAudio - (Effect Unit) + (Unit /\ FFIAudio) + (Instruction /\ Effect Unit) Frame0 res -> Event (Run res) @@ -99,15 +107,8 @@ type EngineInfo type EasingAlgorithm = Cofree ((->) Int) Int --- | The output of `run` to be consumed downstream (or not). It contains: --- | - `nodes`: the nodes in the audio graph including information about things like their frequency, Q value, on/off state etc. --- | - `edges`: incoming edges into nodes. --- | - `res`: the residual from the computation. --- | --- | This information can be used for visualizing the audio graph or for other instruments outside of a browser that are using the browser as a control layer. type Run res - = { nodes :: M.Map String AnAudioUnit - , edges :: M.Map String (Set String) + = { instructions :: Array Instruction , res :: res } @@ -190,8 +191,8 @@ runInternal :: Ref.Ref ( Scene (SceneI trigger world) - FFIAudio - (Effect Unit) + (Unit /\ FFIAudio) + (Instruction /\ Effect Unit) Frame0 res ) -> @@ -215,20 +216,22 @@ runInternal audioClockStart worldAndTrigger world' currentTimeoutCanceler curren fromScene = oneFrame sceneNow (R.union worldAndTrigger { time, headroom }) audioClockAfterComputation <- getAudioClockTime audio'.context - renderAudio - ( FFIAudio + let + ffi = + FFIAudio $ audio' { writeHead = max audioClockAfterComputation (audioClockPriorToComputation + headroomInSeconds) } - ) - fromScene.instructions + + applied = map (\f -> f (unit /\ ffi)) fromScene.instructions + renderAudio (map snd applied) let remainingTimeInMs = floor $ 1000.0 * (audioClockPriorToComputation + headroomInSeconds - audioClockAfterComputation) Ref.write (tail easingAlgNow remainingTimeInMs) currentEasingAlg Ref.write fromScene.next currentScene - reporter { nodes: fromScene.nodes, edges: fromScene.edges, res: fromScene.res } + reporter { instructions: map fst applied, res: fromScene.res } -- we thunk the world and move on to the next event -- note that if we did not allocate enough time, we still -- set a timeout of 1 so that th canceler can run in case it needs to diff --git a/test/Computed.purs b/test/Computed.purs index d20e7de4..ba9b3e43 100644 --- a/test/Computed.purs +++ b/test/Computed.purs @@ -3,7 +3,7 @@ module Test.Computed where import Prelude import Data.Tuple.Nested (type (/\)) import WAGS.Graph.AudioUnit (TGain, TLoopBuf, TSpeaker, reifyAUs) -import WAGS.Graph.Optionals (gain, loopBuf, speaker) +import WAGS.Create.Optionals (gain, loopBuf, speaker) type SceneType = { speaker :: TSpeaker /\ { gain0 :: Unit, gain1 :: Unit, gain2 :: Unit } @@ -21,20 +21,18 @@ testReifyAUs = $ speaker { gain0: gain (0.3) - { loop0: loopBuf { playbackRate: 1.0 + 0.1 } "atar" - } + { loop0: loopBuf { playbackRate: 1.0 + 0.1 } "atar" } , gain1: gain (0.15) { loop1: loopBuf { playbackRate: 1.5 + 0.1 - , start: 0.1 + 0.1 - , end: 0.5 + 0.25 + , loopStart: 0.1 + 0.1 + , loopEnd: 0.5 + 0.25 } "atar" } , gain2: gain (0.3) - { loop2: loopBuf { playbackRate: 0.25 } "atar" - } + { loop2: loopBuf { playbackRate: 0.25 } "atar" } } diff --git a/test/Instructions.purs b/test/Instructions.purs index d7bc06ff..689715f8 100644 --- a/test/Instructions.purs +++ b/test/Instructions.purs @@ -1,22 +1,19 @@ module Test.Instructions where import Prelude +import Control.Applicative.Indexed (ipure) import Control.Monad.Reader (ask) import Data.Either (Either(..)) -import Data.Functor.Indexed (ivoid) -import Data.Map as M -import Data.Set as S import Data.Tuple.Nested ((/\), type (/\)) import Test.Spec (Spec, describe, it) import Test.Spec.Assertions (shouldEqual) import WAGS.Change (change, ichange) -import WAGS.Control.Functions (branch, freeze, ibranch, icont, iloop, loop, start, (@|>), (@||>)) +import WAGS.Control.Functions (branch, freeze, ibranch, icont, iloop, loop, start, (@|>)) import WAGS.Control.Types (Frame, Frame0, oneFrame') import WAGS.Create (create) +import WAGS.Create.Optionals (CGain, CHighpass, CSinOsc, CSpeaker, Ref, gain, highpass, ref, sinOsc, speaker) import WAGS.Graph.AudioUnit (OnOff(..), TGain, THighpass, TSinOsc, TSpeaker) -import WAGS.Graph.Optionals (CGain, CHighpass, CSinOsc, CSpeaker, Ref, gain, highpass, highpass_, ref, sinOsc, sinOsc_, speaker) -import WAGS.Graph.Parameter (param) -import WAGS.Rendered (AnAudioUnit(..), Instruction(..)) +import WAGS.Rendered (Instruction(..)) type Time = { time :: Number } @@ -74,38 +71,22 @@ testInstructions = do simpleScene = simpleFrame @|> freeze - (frame0Nodes /\ frame0Edges /\ frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene { time: 0.0 } + (frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene { time: 0.0 } - (frame1Nodes /\ frame1Edges /\ frame1Instr /\ _ /\ frame2) = oneFrame' frame1 { time: 0.1 } + (frame1Instr /\ _ /\ frame2) = oneFrame' frame1 { time: 0.1 } - (frame2Nodes /\ frame2Edges /\ frame2Instr /\ _ /\ _) = oneFrame' frame2 { time: 0.2 } - - nodeAssertion = M.fromFoldable [ "speaker" /\ ASpeaker, "mix" /\ (AGain (param 1.0)), "highpass" /\ (AHighpass (param 330.0) (param 1.0)), "sinOsc" /\ (ASinOsc On (param 440.0)) ] - - edgeAssertion = M.fromFoldable [ "speaker" /\ S.singleton "mix", "mix" /\ S.fromFoldable [ "mix", "highpass" ], "highpass" /\ S.singleton "sinOsc" ] + (frame2Instr /\ _ /\ _) = oneFrame' frame2 { time: 0.2 } instructionAssertion = [ MakeSpeaker - , MakeGain "mix" (param 1.0) - , MakeHighpass "highpass" (param 330.0) (param 1.0) - , MakeSinOsc "sinOsc" On (param 440.0) + , MakeGain "mix" (pure 1.0) + , MakeHighpass "highpass" (pure 330.0) (pure 1.0) + , MakeSinOsc "sinOsc" On (pure 440.0) , ConnectXToY "mix" "speaker" , ConnectXToY "highpass" "mix" , ConnectXToY "mix" "mix" , ConnectXToY "sinOsc" "highpass" ] - it "is coherent at frame0Nodes" do - frame0Nodes `shouldEqual` nodeAssertion - it "is coherent at frame1Nodes" do - frame1Nodes `shouldEqual` nodeAssertion - it "is coherent at frame2Nodes" do - frame2Nodes `shouldEqual` nodeAssertion - it "is coherent at frame0Edges" do - frame0Edges `shouldEqual` edgeAssertion - it "is coherent at frame1Edges" do - frame1Edges `shouldEqual` edgeAssertion - it "is coherent at frame2Edges" do - frame2Edges `shouldEqual` edgeAssertion it "is coherent at frame0Instr" do resolveInstructions frame0Instr `shouldEqual` instructionAssertion it "is coherent at frame1Instr" do @@ -121,54 +102,34 @@ testInstructions = do simpleFrame @|> loop \fr -> do e <- ask - pure $ void $ change (fr $> { sinOsc: sinOsc_ (440.0 + e.time * 50.0) }) - - (frame0Nodes /\ frame0Edges /\ frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene { time: 0.0 } - - (frame1Nodes /\ frame1Edges /\ frame1Instr /\ _ /\ frame2) = oneFrame' frame1 { time: 0.1 } + pure $ change (fr $> { sinOsc: 440.0 + e.time * 50.0 }) - (frame2Nodes /\ frame2Edges /\ frame2Instr /\ _ /\ frame3) = oneFrame' frame2 { time: 0.2 } + (frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene { time: 0.0 } - (frame3Nodes /\ _ /\ _ /\ _ /\ frame4) = oneFrame' frame3 { time: 0.3 } + (frame1Instr /\ _ /\ frame2) = oneFrame' frame1 { time: 0.1 } - (frame4Nodes /\ _ /\ _ /\ _ /\ _) = oneFrame' frame4 { time: 0.4 } + (frame2Instr /\ _ /\ frame3) = oneFrame' frame2 { time: 0.2 } - nodeAssertion i = M.fromFoldable [ "speaker" /\ ASpeaker, "mix" /\ (AGain (param 1.0)), "highpass" /\ (AHighpass (param $ 330.0) (param 1.0)), "sinOsc" /\ (ASinOsc On (param $ 440.0 + i)) ] + (_ /\ _ /\ frame4) = oneFrame' frame3 { time: 0.3 } - edgeAssertion = M.fromFoldable [ "speaker" /\ S.singleton "mix", "mix" /\ S.fromFoldable [ "mix", "highpass" ], "highpass" /\ S.singleton "sinOsc" ] + (_ /\ _ /\ _) = oneFrame' frame4 { time: 0.4 } instructionAssertion = [ MakeSpeaker - , MakeGain "mix" (param 1.0) - , MakeHighpass "highpass" (param 330.0) (param 1.0) - , MakeSinOsc "sinOsc" On (param 440.0) + , MakeGain "mix" (pure 1.0) + , MakeHighpass "highpass" (pure 330.0) (pure 1.0) + , MakeSinOsc "sinOsc" On (pure 440.0) , ConnectXToY "mix" "speaker" , ConnectXToY "highpass" "mix" , ConnectXToY "mix" "mix" , ConnectXToY "sinOsc" "highpass" ] - it "is coherent after frame0Nodes" do - frame0Nodes `shouldEqual` (nodeAssertion 0.0) - it "is coherent after frame1Nodes" do - frame1Nodes `shouldEqual` (nodeAssertion 5.0) - it "is coherent after frame2Nodes" do - frame2Nodes `shouldEqual` (nodeAssertion 10.0) - it "is coherent after frame3Nodes" do - frame3Nodes `shouldEqual` (nodeAssertion 15.0) - it "is coherent after frame4Nodes" do - frame4Nodes `shouldEqual` (nodeAssertion 20.0) - it "is coherent after frame0Edges" do - frame0Edges `shouldEqual` edgeAssertion - it "is coherent after frame1Edges" do - frame1Edges `shouldEqual` edgeAssertion - it "is coherent after frame2Edges" do - frame2Edges `shouldEqual` edgeAssertion it "is coherent after frame0Instr" do resolveInstructions frame0Instr `shouldEqual` instructionAssertion it "is coherent after frame1Instr" do - resolveInstructions frame1Instr `shouldEqual` [ SetFrequency "sinOsc" $ param 445.0 ] + resolveInstructions frame1Instr `shouldEqual` [ SetFrequency "sinOsc" $ pure 445.0 ] it "is coherent after frame2Instr" do - resolveInstructions frame2Instr `shouldEqual` [ SetFrequency "sinOsc" $ param 450.0 ] + resolveInstructions frame2Instr `shouldEqual` [ SetFrequency "sinOsc" $ pure 450.0 ] describe "a simple scene that changes several elements as a function of time" do let simpleFrame :: Frame Time Unit Instruction Frame0 Unit SceneType Unit @@ -182,56 +143,36 @@ testInstructions = do $ void $ change $ fr - $> { sinOsc: sinOsc_ (440.0 + e.time * 50.0) - , highpass: highpass_ (330.0 + e.time * 10.0) + $> { sinOsc: 440.0 + e.time * 50.0 + , highpass: 330.0 + e.time * 10.0 } - (frame0Nodes /\ frame0Edges /\ frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene { time: 0.0 } + (frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene { time: 0.0 } - (frame1Nodes /\ frame1Edges /\ frame1Instr /\ _ /\ frame2) = oneFrame' frame1 { time: 0.1 } + (frame1Instr /\ _ /\ frame2) = oneFrame' frame1 { time: 0.1 } - (frame2Nodes /\ frame2Edges /\ frame2Instr /\ _ /\ frame3) = oneFrame' frame2 { time: 0.2 } + (frame2Instr /\ _ /\ frame3) = oneFrame' frame2 { time: 0.2 } - (frame3Nodes /\ _ /\ _ /\ _ /\ frame4) = oneFrame' frame3 { time: 0.3 } + (_ /\ _ /\ frame4) = oneFrame' frame3 { time: 0.3 } - (frame4Nodes /\ _ /\ _ /\ _ /\ _) = oneFrame' frame4 { time: 0.4 } - - nodeAssertion i = M.fromFoldable [ "speaker" /\ ASpeaker, "mix" /\ (AGain (param 1.0)), "highpass" /\ (AHighpass (param $ 330.0 + i) (param 1.0)), "sinOsc" /\ (ASinOsc On (param $ 440.0 + i * 5.0)) ] - - edgeAssertion = M.fromFoldable [ "speaker" /\ S.singleton "mix", "mix" /\ S.fromFoldable [ "mix", "highpass" ], "highpass" /\ S.singleton "sinOsc" ] + (_ /\ _ /\ _) = oneFrame' frame4 { time: 0.4 } instructionAssertion = [ MakeSpeaker - , MakeGain "mix" (param 1.0) - , MakeHighpass "highpass" (param 330.0) (param 1.0) - , MakeSinOsc "sinOsc" On (param 440.0) + , MakeGain "mix" (pure 1.0) + , MakeHighpass "highpass" (pure 330.0) (pure 1.0) + , MakeSinOsc "sinOsc" On (pure 440.0) , ConnectXToY "mix" "speaker" , ConnectXToY "highpass" "mix" , ConnectXToY "mix" "mix" , ConnectXToY "sinOsc" "highpass" ] - it "is coherent after frame0Nodes" do - frame0Nodes `shouldEqual` (nodeAssertion 0.0) - it "is coherent after frame1Nodes" do - frame1Nodes `shouldEqual` (nodeAssertion 1.0) - it "is coherent after frame2Nodes" do - frame2Nodes `shouldEqual` (nodeAssertion 2.0) - it "is coherent after frame3Nodes" do - frame3Nodes `shouldEqual` (nodeAssertion 3.0) - it "is coherent after frame4Nodes" do - frame4Nodes `shouldEqual` (nodeAssertion 4.0) - it "is coherent after frame0Edges" do - frame0Edges `shouldEqual` edgeAssertion - it "is coherent after frame1Edges" do - frame1Edges `shouldEqual` edgeAssertion - it "is coherent after frame2Edges" do - frame2Edges `shouldEqual` edgeAssertion it "is coherent after frame0Instr" do resolveInstructions frame0Instr `shouldEqual` instructionAssertion it "is coherent after frame1Instr" do - resolveInstructions frame1Instr `shouldEqual` [ SetFrequency "highpass" $ param 331.0, SetFrequency "sinOsc" $ param 445.0 ] + resolveInstructions frame1Instr `shouldEqual` [ SetFrequency "highpass" $ pure 331.0, SetFrequency "sinOsc" $ pure 445.0 ] it "is coherent after frame2Instr" do - resolveInstructions frame2Instr `shouldEqual` [ SetFrequency "highpass" $ param 332.0, SetFrequency "sinOsc" $ param 450.0 ] + resolveInstructions frame2Instr `shouldEqual` [ SetFrequency "highpass" $ pure 332.0, SetFrequency "sinOsc" $ pure 450.0 ] describe "a scene that forks at 0.3 seconds" do let simpleFrame :: Frame Time Unit Instruction Frame0 Unit SceneType Unit @@ -243,71 +184,47 @@ testInstructions = do { time } <- ask pure $ if time < 0.3 then - Right $ void $ change $ fr $> { highpass: highpass_ (330.0 + time * 10.0) } + Right $ change $ fr $> { highpass: 330.0 + time * 10.0 } else Left - ( change - (fr $> { highpass: highpass_ (330.0 + time * 50.0) }) - @||> loop \fr' -> do - e <- ask - pure - $ change - ( fr' - $> { highpass: highpass_ (330.0 + e.time * 50.0) - } - ) + ( fr + # loop \fr' e -> + change + $ fr' + $> { highpass: 330.0 + e.time * 50.0 + } ) - (frame0Nodes /\ frame0Edges /\ frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene { time: 0.0 } - - (frame1Nodes /\ frame1Edges /\ frame1Instr /\ _ /\ frame2) = oneFrame' frame1 { time: 0.1 } - - (frame2Nodes /\ frame2Edges /\ frame2Instr /\ _ /\ frame3) = oneFrame' frame2 { time: 0.2 } + (frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene { time: 0.0 } - (frame3Nodes /\ _ /\ frame3Instr /\ _ /\ frame4) = oneFrame' frame3 { time: 0.3 } + (frame1Instr /\ _ /\ frame2) = oneFrame' frame1 { time: 0.1 } - (frame4Nodes /\ _ /\ frame4Instr /\ _ /\ _) = oneFrame' frame4 { time: 0.4 } + (frame2Instr /\ _ /\ frame3) = oneFrame' frame2 { time: 0.2 } - nodeAssertion i = M.fromFoldable [ "speaker" /\ ASpeaker, "mix" /\ (AGain (param 1.0)), "highpass" /\ (AHighpass (param $ 330.0 + i) (param 1.0)), "sinOsc" /\ (ASinOsc On (param 440.0)) ] + (frame3Instr /\ _ /\ frame4) = oneFrame' frame3 { time: 0.3 } - edgeAssertion = M.fromFoldable [ "speaker" /\ S.singleton "mix", "mix" /\ S.fromFoldable [ "mix", "highpass" ], "highpass" /\ S.singleton "sinOsc" ] + (frame4Instr /\ _ /\ _) = oneFrame' frame4 { time: 0.4 } instructionAssertion = [ MakeSpeaker - , MakeGain "mix" (param 1.0) - , MakeHighpass "highpass" (param 330.0) (param 1.0) - , MakeSinOsc "sinOsc" On (param 440.0) + , MakeGain "mix" (pure 1.0) + , MakeHighpass "highpass" (pure 330.0) (pure 1.0) + , MakeSinOsc "sinOsc" On (pure 440.0) , ConnectXToY "mix" "speaker" , ConnectXToY "highpass" "mix" , ConnectXToY "mix" "mix" , ConnectXToY "sinOsc" "highpass" ] - it "branches at frame0Nodes" do - frame0Nodes `shouldEqual` (nodeAssertion 0.0) - it "branches at frame1Nodes" do - frame1Nodes `shouldEqual` (nodeAssertion 1.0) - it "branches at frame2Nodes" do - frame2Nodes `shouldEqual` (nodeAssertion 2.0) - it "branches at frame3Nodes" do - frame3Nodes `shouldEqual` (nodeAssertion 15.0) - it "branches at frame4Nodes" do - frame4Nodes `shouldEqual` (nodeAssertion 20.0) - it "branches at frame0Edges" do - frame0Edges `shouldEqual` edgeAssertion - it "branches at edgeAssertion" do - frame1Edges `shouldEqual` edgeAssertion - it "branches at edgeAssertion" do - frame2Edges `shouldEqual` edgeAssertion - it "branches at edgeAssertion" do - resolveInstructions frame0Instr `shouldEqual` instructionAssertion it "branches at frame0Instr" do - resolveInstructions frame1Instr `shouldEqual` [ SetFrequency "highpass" $ param 331.0 ] + resolveInstructions frame0Instr `shouldEqual` instructionAssertion it "branches at frame1Instr" do - resolveInstructions frame2Instr `shouldEqual` [ SetFrequency "highpass" $ param 332.0 ] + resolveInstructions frame1Instr `shouldEqual` [ SetFrequency "highpass" $ pure 331.0 ] it "branches at frame2Instr" do - resolveInstructions frame3Instr `shouldEqual` [ SetFrequency "highpass" $ param 345.0 ] + resolveInstructions frame2Instr `shouldEqual` [ SetFrequency "highpass" $ pure 332.0 ] it "branches at frame3Instr" do - resolveInstructions frame4Instr `shouldEqual` [ SetFrequency "highpass" $ param 350.0 ] + resolveInstructions frame3Instr `shouldEqual` [ SetFrequency "highpass" $ pure 345.0 ] + it "branches at frame4Instr" do + resolveInstructions frame4Instr `shouldEqual` [ SetFrequency "highpass" $ pure 350.0 ] describe "a scene that forks at 0.3 seconds with ibranch" do let simpleFrame :: Frame Time Unit Instruction Frame0 Unit SceneType Unit @@ -317,63 +234,40 @@ testInstructions = do simpleFrame @|> ibranch \{ time } _ -> if time < 0.3 then - Right $ ivoid $ ichange { highpass: highpass_ (330.0 + time * 10.0) } + Right $ ichange { highpass: 330.0 + time * 10.0 } else Left $ icont - ( iloop \e _ -> - ivoid - $ ichange { highpass: highpass_ (330.0 + e.time * 50.0) } - ) - (ivoid $ ichange { highpass: highpass_ (330.0 + time * 50.0) }) - - (frame0Nodes /\ frame0Edges /\ frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene { time: 0.0 } + (iloop \e -> const $ ichange { highpass: { freq: 330.0 + e.time * 50.0, q: e.time } }) + (ipure unit) - (frame1Nodes /\ frame1Edges /\ frame1Instr /\ _ /\ frame2) = oneFrame' frame1 { time: 0.1 } + (frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene { time: 0.0 } - (frame2Nodes /\ frame2Edges /\ frame2Instr /\ _ /\ frame3) = oneFrame' frame2 { time: 0.2 } + (frame1Instr /\ _ /\ frame2) = oneFrame' frame1 { time: 0.1 } - (frame3Nodes /\ _ /\ frame3Instr /\ _ /\ frame4) = oneFrame' frame3 { time: 0.3 } + (frame2Instr /\ _ /\ frame3) = oneFrame' frame2 { time: 0.2 } - (frame4Nodes /\ _ /\ frame4Instr /\ _ /\ _) = oneFrame' frame4 { time: 0.4 } + (frame3Instr /\ _ /\ frame4) = oneFrame' frame3 { time: 0.3 } - nodeAssertion i = M.fromFoldable [ "speaker" /\ ASpeaker, "mix" /\ (AGain (param 1.0)), "highpass" /\ (AHighpass (param $ 330.0 + i) (param 1.0)), "sinOsc" /\ (ASinOsc On (param 440.0)) ] - - edgeAssertion = M.fromFoldable [ "speaker" /\ S.singleton "mix", "mix" /\ S.fromFoldable [ "mix", "highpass" ], "highpass" /\ S.singleton "sinOsc" ] + (frame4Instr /\ _ /\ _) = oneFrame' frame4 { time: 0.4 } instructionAssertion = [ MakeSpeaker - , MakeGain "mix" (param 1.0) - , MakeHighpass "highpass" (param 330.0) (param 1.0) - , MakeSinOsc "sinOsc" On (param 440.0) + , MakeGain "mix" (pure 1.0) + , MakeHighpass "highpass" (pure 330.0) (pure 1.0) + , MakeSinOsc "sinOsc" On (pure 440.0) , ConnectXToY "mix" "speaker" , ConnectXToY "highpass" "mix" , ConnectXToY "mix" "mix" , ConnectXToY "sinOsc" "highpass" ] - it "branches at frame0Nodes" do - frame0Nodes `shouldEqual` (nodeAssertion 0.0) - it "branches at frame1Nodes" do - frame1Nodes `shouldEqual` (nodeAssertion 1.0) - it "branches at frame2Nodes" do - frame2Nodes `shouldEqual` (nodeAssertion 2.0) - it "branches at frame3Nodes" do - frame3Nodes `shouldEqual` (nodeAssertion 15.0) - it "branches at frame4Nodes" do - frame4Nodes `shouldEqual` (nodeAssertion 20.0) - it "branches at frame0Edges" do - frame0Edges `shouldEqual` edgeAssertion - it "branches at edgeAssertion" do - frame1Edges `shouldEqual` edgeAssertion - it "branches at edgeAssertion" do - frame2Edges `shouldEqual` edgeAssertion - it "branches at edgeAssertion" do - resolveInstructions frame0Instr `shouldEqual` instructionAssertion it "branches at frame0Instr" do - resolveInstructions frame1Instr `shouldEqual` [ SetFrequency "highpass" $ param 331.0 ] + resolveInstructions frame0Instr `shouldEqual` instructionAssertion it "branches at frame1Instr" do - resolveInstructions frame2Instr `shouldEqual` [ SetFrequency "highpass" $ param 332.0 ] + resolveInstructions frame1Instr `shouldEqual` [ SetFrequency "highpass" $ pure 331.0 ] it "branches at frame2Instr" do - resolveInstructions frame3Instr `shouldEqual` [ SetFrequency "highpass" $ param 345.0 ] + resolveInstructions frame2Instr `shouldEqual` [ SetFrequency "highpass" $ pure 332.0 ] it "branches at frame3Instr" do - resolveInstructions frame4Instr `shouldEqual` [ SetFrequency "highpass" $ param 350.0 ] + resolveInstructions frame3Instr `shouldEqual` [ SetFrequency "highpass" $ pure 345.0, SetQ "highpass" $ pure 0.3 ] + it "branches at frame4Instr" do + resolveInstructions frame4Instr `shouldEqual` [ SetFrequency "highpass" $ pure 350.0, SetQ "highpass" $ pure 0.4 ] diff --git a/test/Ops.purs b/test/Ops.purs index e5748ffc..4ed4926b 100644 --- a/test/Ops.purs +++ b/test/Ops.purs @@ -3,13 +3,14 @@ module Test.Ops where import Prelude import Data.Tuple.Nested (type (/\)) import Type.Proxy (Proxy(..)) +import WAGS.Change (change) import WAGS.Control.Functions (start) import WAGS.Control.Types (Frame0, WAG) import WAGS.Create (create) +import WAGS.Create.Optionals (gain, highpass, ref, sinOsc, speaker, speaker') import WAGS.Destroy (destroy) import WAGS.Disconnect (disconnect) -import WAGS.Graph.AudioUnit (TGain, THighpass, TSinOsc, TSpeaker) -import WAGS.Graph.Optionals (gain, highpass, ref, sinOsc, speaker, speaker') +import WAGS.Graph.AudioUnit (OnOff(..), TGain, THighpass, TSinOsc, TSpeaker) import WAGS.Interpret (class AudioInterpret) opsTest0 :: @@ -70,6 +71,44 @@ opsTest2 = } # create +opsTest3 :: + forall audio engine. + AudioInterpret audio engine => + WAG audio engine Frame0 Unit + { mySine :: TSinOsc /\ {} + , gain :: TGain /\ { highpass :: Unit, mySine :: Unit } + , highpass :: THighpass /\ { mySine :: Unit } + , speaker :: TSpeaker /\ { gain :: Unit } + } + Unit +opsTest3 = + start + $> speaker + { gain: + gain 1.0 + { highpass: + highpass 330.0 { mySine: ref } + , mySine: sinOsc 440.0 + } + } + # create + -- test various changes to make sure they compile + + # (<$) { highpass: 400.0 } + # change + # (<$) { highpass: { freq: 400.0 } } + # change + # (<$) { highpass: { q: 50.0 } } + # change + # (<$) { mySine: 330.0 } + # change + # (<$) { mySine: On } + # change + # (<$) { mySine: { freq: 550.0 } } + # change + # (<$) { mySine: { freq: 550.0, onOff: On } } + # change + opsTest6 :: forall audio engine. AudioInterpret audio engine => diff --git a/test/Patch.purs b/test/Patch.purs index 7be6d6f6..a79969d0 100644 --- a/test/Patch.purs +++ b/test/Patch.purs @@ -1,18 +1,14 @@ module Test.Patch where import Prelude -import Data.Map as M -import Data.Set as S -import Data.Tuple (Tuple(..)) import Data.Tuple.Nested (type (/\), (/\)) import Test.Spec (Spec, describe, it) import Test.Spec.Assertions (shouldEqual) import WAGS.Control.Functions (freeze, start, (@||>)) import WAGS.Control.Types (Frame0, WAG, oneFrame') import WAGS.Graph.AudioUnit (OnOff(..), THighpass, TSinOsc, TSpeaker, TLowpass, TSawtoothOsc) -import WAGS.Graph.Parameter (param) import WAGS.Patch (patch) -import WAGS.Rendered (AnAudioUnit(..), Instruction(..)) +import WAGS.Rendered (Instruction(..)) testPatch :: Spec Unit testPatch = do @@ -31,10 +27,8 @@ testPatch = do simpleScene = simpleFrame start @||> freeze - (frame0Nodes /\ frame0Edges /\ frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene unit - frame0Nodes `shouldEqual` (M.fromFoldable [ "sinOsc" /\ ASinOsc Off (param 440.0), "speaker" /\ ASpeaker ]) - frame0Edges `shouldEqual` (M.fromFoldable [ "speaker" /\ S.fromFoldable [ "sinOsc" ] ]) - (map ((#) unit) frame0Instr) `shouldEqual` [ MakeSpeaker, MakeSinOsc "sinOsc" Off (param 440.0), ConnectXToY "sinOsc" "speaker" ] + (frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene unit + (map ((#) unit) frame0Instr) `shouldEqual` [ MakeSpeaker, MakeSinOsc "sinOsc" Off (pure 440.0), ConnectXToY "sinOsc" "speaker" ] it "makes a no op a no op" do let startingFrame = @@ -72,9 +66,9 @@ testPatch = do @||> freeze ) - (frame0Nodes /\ frame0Edges /\ frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene unit + (frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene unit - (frame1Nodes /\ frame1Edges /\ frame1Instr /\ _ /\ frame2) = oneFrame' frame1 unit + (frame1Instr /\ _ /\ frame2) = oneFrame' frame1 unit (map ((#) unit) frame1Instr) `shouldEqual` [] it "removes a single connection" do let @@ -113,9 +107,9 @@ testPatch = do @||> freeze ) - (frame0Nodes /\ frame0Edges /\ frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene unit + ( frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene unit - (frame1Nodes /\ frame1Edges /\ frame1Instr /\ _ /\ frame2) = oneFrame' frame1 unit + (frame1Instr /\ _ /\ frame2) = oneFrame' frame1 unit (map ((#) unit) frame1Instr) `shouldEqual` [ DisconnectXFromY "sinOsc" "speaker" ] it "correctly handles complex graph" do let @@ -155,12 +149,10 @@ testPatch = do @||> freeze ) - (frame0Nodes /\ frame0Edges /\ frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene unit + (frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene unit - (frame1Nodes /\ frame1Edges /\ frame1Instr /\ _ /\ frame2) = oneFrame' frame1 unit - frame1Nodes `shouldEqual` (M.fromFoldable [ (Tuple "anotherOsc" (ASinOsc Off (param 440.0))), (Tuple "speaker" ASpeaker) ]) - frame1Edges `shouldEqual` (M.fromFoldable [ (Tuple "speaker" (S.fromFoldable [ "anotherOsc" ])) ]) - (map ((#) unit) frame1Instr) `shouldEqual` [ (DisconnectXFromY "sinOsc" "highpass"), (DisconnectXFromY "highpass" "speaker"), (DisconnectXFromY "sinOsc" "speaker"), (DestroyUnit "highpass"), (DestroyUnit "sinOsc"), (MakeSinOsc "anotherOsc" Off (param 440.0)), (ConnectXToY "anotherOsc" "speaker") ] + (frame1Instr /\ _ /\ frame2) = oneFrame' frame1 unit + (map ((#) unit) frame1Instr) `shouldEqual` [ (DisconnectXFromY "sinOsc" "highpass"), (DisconnectXFromY "highpass" "speaker"), (DisconnectXFromY "sinOsc" "speaker"), (DestroyUnit "highpass"), (DestroyUnit "sinOsc"), (MakeSinOsc "anotherOsc" Off (pure 440.0)), (ConnectXToY "anotherOsc" "speaker") ] it "leaves noop in complex graph" do let startingFrame = @@ -205,7 +197,7 @@ testPatch = do @||> freeze ) - (frame0Nodes /\ frame0Edges /\ frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene unit + (frame0Instr /\ _ /\ frame1) = oneFrame' simpleScene unit - (frame1Nodes /\ frame1Edges /\ frame1Instr /\ _ /\ frame2) = oneFrame' frame1 unit - (map ((#) unit) frame1Instr) `shouldEqual` [ (DisconnectXFromY "sinOsc" "highpass"), (DisconnectXFromY "highpass" "speaker"), (DisconnectXFromY "sinOsc" "speaker"), (DestroyUnit "highpass"), (DestroyUnit "sinOsc"), (MakeSinOsc "anotherOsc" Off (param 440.0)), (ConnectXToY "anotherOsc" "speaker") ] + (frame1Instr /\ _ /\ frame2) = oneFrame' frame1 unit + (map ((#) unit) frame1Instr) `shouldEqual` [ (DisconnectXFromY "sinOsc" "highpass"), (DisconnectXFromY "highpass" "speaker"), (DisconnectXFromY "sinOsc" "speaker"), (DestroyUnit "highpass"), (DestroyUnit "sinOsc"), (MakeSinOsc "anotherOsc" Off (pure 440.0)), (ConnectXToY "anotherOsc" "speaker") ]