packages feed

essence-of-live-coding-pulse (empty) → 0.1.0.1

raw patch · 6 files changed

+201/−0 lines, 6 filesdep +basedep +essence-of-live-codingdep +foreign-storesetup-changed

Dependencies added: base, essence-of-live-coding, foreign-store, pulse-simple, transformers

Files

+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for essence-of-live-coding-pulse++## 0.1.0.0 -- YYYY-mm-dd++* First version. Released on an unsuspecting world.
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2019, 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.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ essence-of-live-coding-pulse.cabal view
@@ -0,0 +1,39 @@+name:                essence-of-live-coding-pulse+version:             0.1.0.1+synopsis: General purpose live coding framework - pulse 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 PulseAudio.++license:             BSD3+license-file:        LICENSE+author:              Manuel Bärenz+maintainer:          programming@manuelbaerenz.de+homepage:            https://www.manuelbaerenz.de/#computerscience+category:            FRP, Live coding+build-type:          Simple+extra-source-files:  CHANGELOG.md+cabal-version:       >=1.10++library+  exposed-modules:+    LiveCoding.Pulse+    LiveCoding.Pulse.GHCi+  build-depends:+      base >= 4.11 && <4.13+    , essence-of-live-coding+    , transformers+    , pulse-simple == 0.1.*+    , foreign-store+  hs-source-dirs:      src+  default-language:    Haskell2010
+ src/LiveCoding/Pulse.hs view
@@ -0,0 +1,96 @@+{-# LANGUAGE Arrows #-}+module LiveCoding.Pulse where++-- base+import Control.Arrow as X+import Control.Concurrent+import Control.Monad (forever)+import Control.Monad.Fix++-- transformers+import Control.Monad.Trans.Reader++-- pulse-simple+import Sound.Pulse.Simple++-- essence-of-live-coding+import LiveCoding++type PulseCell = Cell IO () Float++playPulseCell :: PulseCell -> IO (MVar PulseCell)+playPulseCell pulseCell = do+  var <- newMVar pulseCell+  pulseClient <- simpleNew+    Nothing+    "example"+    Play+    Nothing+    "this is an example application"+    (SampleSpec (F32 LittleEndian) 44100 1)+    Nothing+    Nothing+  forkIO $ forever $ do+    cell <- takeMVar var+    (samples, cell') <- steps cell $ replicate 1024 ()+    simpleWrite pulseClient samples+    putMVar var cell'+  return var++-- TODO Generalisable+updatePulse :: MVar PulseCell -> PulseCell -> IO ()+updatePulse var newCell = do+  oldCell <- takeMVar var+  putMVar var $ hotCodeSwapCell newCell oldCell++-- Returns the sum between -1 and 1+wrapSum :: (Monad m, Data a, RealFloat a) => Cell m a a+wrapSum = Cell+  { cellState = 0+  , cellStep  = \accum a ->+    let+        (_, accum')  = properFraction $ accum + a+    in return (accum', accum')+  }++modSum :: (Monad m, Data a, Integral a) => a -> Cell m a a+modSum denominator = Cell+  { cellState = 0+  , cellStep  = \accum a -> let accum' = (accum + a) `mod` denominator in return (accum', accum')+  }+++clamp :: (Ord a, Num a) => a -> a -> a -> a+clamp lower upper a = min upper $ max lower a++osc :: (Data a, RealFloat a, MonadFix m) => Cell (ReaderT a m) () a+osc = proc _ -> do+  f <- constM ask -< ()+  phase <- wrapSum -< f / 44100+  returnA -< sin $ 2 * pi * phase++osc' :: (Data a, RealFloat a, MonadFix m) => Cell m a a+osc' = proc a -> do+  runReaderC' osc -< (a, ())++data Note+  = A+  | Bb+  | B+  | C+  | Cis+  | D+  | Dis+  | E+  | F+  | Fis+  | G+  | Gis+  deriving (Enum, Show)++f :: Note -> Float+f note = 220 * (2 ** (fromIntegral (fromEnum note) / 12))++o :: Float -> Float+o = (* 2)+
+ src/LiveCoding/Pulse/GHCi.hs view
@@ -0,0 +1,29 @@+module LiveCoding.Pulse.GHCi where++-- base+import Control.Concurrent++-- foreign-store+import Foreign.Store++-- essence-of-live-coding+import LiveCoding.LiveProgram++-- essence-of-live-coding-pulse+import LiveCoding.Pulse++livepulse "" = livepulse "pulseCell"+livepulse pulseCell = return $ unlines+  [ "var <- playPulseCell " ++ pulseCell+  , "savePulse var"+  ]+livereloadpulse "" = livereloadpulse "pulseCell"+livereloadpulse pulseCell  = return $ unlines+  [ ":reload"+  , "var <- loadPulse"+  , "updatePulse var " ++ pulseCell+  ]+loadPulse :: IO (MVar PulseCell)+loadPulse = readStore (Store 0)+savePulse :: MVar PulseCell -> IO ()+savePulse var = writeStore (Store 0) var