essence-of-live-coding-vivid (empty) → 0.2.6
raw patch · 4 files changed
+181/−0 lines, 4 filesdep +basedep +essence-of-live-codingdep +vivid
Dependencies added: base, essence-of-live-coding, vivid
Files
- CHANGELOG.md +5/−0
- LICENSE +30/−0
- essence-of-live-coding-vivid.cabal +36/−0
- src/LiveCoding/Vivid.hs +110/−0
+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for essence-of-live-coding-vivid++## 0.2.5++* Thank you, Miguel Negrão, for extensive support, suggestions, testing, and debugging!
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2021, Manuel Bärenz++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Manuel Bärenz nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ essence-of-live-coding-vivid.cabal view
@@ -0,0 +1,36 @@+name: essence-of-live-coding-vivid+version: 0.2.6+synopsis: General purpose live coding framework - vivid backend+description:+ essence-of-live-coding is a general purpose and type safe live coding framework.+ .+ You can run programs in it, and edit, recompile and reload them while they're running.+ Internally, the state of the live program is automatically migrated when performing hot code swap.+ .+ The library also offers an easy to use FRP interface.+ It is parametrized by its side effects,+ separates data flow cleanly from control flow,+ and allows to develop live programs from reusable, modular components.+ There are also useful utilities for debugging and quickchecking.+ .+ This package contains the backend for vivid, a Supercollider library.+license: BSD3+license-file: LICENSE+author: Manuel Bärenz+maintainer: programming@manuelbaerenz.de+copyright: 2021 Manuel Bärenz+category: Sound+build-type: Simple+cabal-version: >=1.10+extra-source-files: CHANGELOG.md++library+ exposed-modules:+ LiveCoding.Vivid++ build-depends:+ base >= 4.7 && < 5+ , vivid >= 0.5.2.0+ , essence-of-live-coding >= 0.2.6+ hs-source-dirs: src+ default-language: Haskell2010
+ src/LiveCoding/Vivid.hs view
@@ -0,0 +1,110 @@+{- | Support for [@vivid@](https://hackage.haskell.org/package/vivid),+a Haskell library for [SuperCollider](https://supercollider.github.io/).++With this module, you can create cells corresponding to synthesizers.++The synthesizers automatically start and stop on reload.+-}++{-# LANGUAGE Arrows #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE StandaloneDeriving #-}+module LiveCoding.Vivid where++-- base+import Data.Foldable (traverse_)+import GHC.TypeLits (KnownSymbol)++-- vivid+import Vivid++-- essence-of-live-coding+import LiveCoding.Handle+import LiveCoding++{- | Whether a synthesizer should currently be running or not.++Typically, you will either statically supply the value and change it in the code to start and stop the synth,+or you can connect another cell to it.+-}+data SynthState+ = Started+ | Stopped+ deriving (Eq)++{- | A 'ParametrisedHandle' corresponding to one @vivid@/@SuperCollider@ synthesizer.++Usually, you will want to use 'liveSynth' instead, it is easier to handle.+-}+vividHandleParametrised+ :: (VividAction m, Eq params, VarList params, Subset (InnerVars params) args, Elem "gate" args)+ => ParametrisedHandle (params, SynthDef args, SynthState) m (Maybe (Synth args))+vividHandleParametrised = ParametrisedHandle { .. }+ where+ createParametrised (params, synthDef, Started) = Just <$> synth synthDef params+ createParametrised (params, synthDef, Stopped) = defineSD synthDef >> pure Nothing++ destroyParametrised _ synthMaybe = traverse_ release synthMaybe++ -- Only the synth parameters changed and it's still running.+ -- So simply set new parameters without stopping it.+ changeParametrised (paramsOld, synthDefOld, Started) (paramsNew, synthDefNew, Started) (Just synth)+ | paramsOld /= paramsNew && synthDefOld == synthDefNew = do+ set synth paramsNew+ return $ Just synth+ -- Synthdef or start/stop state changed, need to release and reinitialise+ changeParametrised old new synth = defaultChange createParametrised destroyParametrised old new synth++deriving instance Data SynthState+deriving instance KnownSymbol a => Data (I a)++{- | Create a synthesizer.++When you add 'liveSynth' to your live program,+it will be started upon reload immediately.++Feed the definition of the synthesizer and its current intended state to this cell.+The input has the form @(params, sdbody, synthState)@.++* A change in @params@ will reload the synthesizer quickly,+ unless the types of the parameters change.+* A change in the @sdbody :: 'SDBody' ...@ or the _types_ of the @params@ will 'release' the synthesizer and start a new one.+* The input @synthState :: 'SynthState'@ represent whether the synthesizer should currently be running or not.+ Changes in it quickly start or stop it.+ * When it is started, @'Just' synth@ is returned, where @synth@ represents the running synthesizer.+ * When it is stopped, 'Nothing' is returned.++You have to use 'envGate' in your @sdbody@,+or another way of gating your output signals+in order to ensure release of the synths without clipping.++For an example, have a look at the source code of 'sine'.+-}+liveSynth+ :: ( VividAction m+ , Eq params, Typeable params, VarList params+ , Typeable (InnerVars params), Subset (InnerVars params) (InnerVars params)+ , Elem "gate" (InnerVars params), Data params+ )+ => Cell (HandlingStateT m)+ (params, SDBody' (InnerVars params) [Signal], SynthState)+ (Maybe (Synth (InnerVars params)))+liveSynth = proc (params, sdbody, synthstate) -> do+ paramsFirstValue <- holdFirst -< params+ handlingParametrised vividHandleParametrised -< (params, sd paramsFirstValue sdbody, synthstate)++-- | Example sine synthesizer that creates a sine wave at the given input frequency.+sine :: (VividAction m) => Cell (HandlingStateT m) Float ()+sine = proc frequency -> do+ liveSynth -<+ (+ ( 1 :: I "gate"+ , 2 :: I "fadeSecs"+ , I frequency :: I "freq"+ )+ , out (0 :: Int) [envGate ~* sinOsc (freq_ (V :: V "freq"))]+ , Started)+ returnA -< ()