packages feed

musicw 0.3.0 → 0.3.2

raw patch · 6 files changed

+93/−13 lines, 6 filesdep ~basedep ~containers

Dependency ranges changed: base, containers

Files

musicw.cabal view
@@ -1,8 +1,8 @@ name:                musicw-version:             0.3.0+version:             0.3.2 synopsis:            Sound synthesis library, to be used with GHCJS and Web Audio API description:         A library for sound synthesis, currently targeting GHCJS and the Web Audio API. Used in the Inner Ear and Estuary projects.-homepage:            http://github.com/d0kt0r0/reflex-synth/blob/master/README.md+homepage:            https://github.com/dktr0/musicw/blob/master/README.md license:             BSD3 license-file:        LICENSE author:              David Ogborn, Jamie Beverley, Luis Navarro del Angel, Spencer Park and others@@ -11,14 +11,15 @@ category:            Web build-type:          Simple cabal-version:       >=1.10+tested-with:         GHCJS == 8.6.0.1 extra-source-files:  Library   hs-source-dirs:  src   js-sources:      MusicW.js   Build-Depends:-      base >= 4.11.1.0 && < 4.12,-      containers >= 0.5.11.0 && < 0.6,+      base >= 4.11.1.0 && < 4.13,+      containers >= 0.5.11.0 && < 0.7,       safe >= 0.3.17 && < 0.4,       ghcjs-base >= 0.2.0.0 && < 0.3,       ghcjs-dom >= 0.9.2.0 && < 0.10,
src/Sound/MusicW/AudioContext.hs view
@@ -35,7 +35,7 @@ foreign import javascript unsafe "\"closed\"" js_acClosed :: JSVal  foreign import javascript safe-  "new (window.AudioContext || window.webkitAudioContext)()"+  "new (window.AudioContext || window.webkitAudioContext)({ latencyHint: \"playback\", sampleRate: 48000 })"   newAudioContext :: IO AudioContext  foreign import javascript unsafe@@ -44,7 +44,9 @@  foreign import javascript safe   "if (window.___ac == null) { \-  \    window.___ac = new (window.AudioContext || window.webkitAudioContext)();\+  \    window.___ac = new (window.AudioContext || window.webkitAudioContext)(\+  \      { latencyHint: \"playback\", sampleRate: 48000 } \+  \      );\   \} $r = window.___ac;"   getGlobalAudioContext :: IO AudioContext 
src/Sound/MusicW/Node.hs view
@@ -179,6 +179,14 @@   setNodeField node "isSink" True   setNodeField node "startable" False +createChannelSplitter :: AudioIO m => Int -> m Node+createChannelSplitter nChnls = do+  ctx <- audioContext+  node <- liftIO $ js_createChannelSplitter ctx nChnls+  setNodeField node "isSource" True+  setNodeField node "isSink" True+  setNodeField node "startable" False+ data OversampleAmount   = NoOversampling   | X2Oversampling@@ -275,6 +283,12 @@   | not (js_isSink toNode) = error $ (show toNode) ++ " can't be connect target."   | otherwise   = liftIO $ js_connect' fromNode toNode fromChannel toChannel +connectNodes'' :: MonadIO m => Node -> Int -> Node -> m ()+connectNodes'' fromNode fromChannel toNode+  | not (js_isSource fromNode) = error $ (show fromNode) ++ " can't be connect source."+  | not (js_isSink toNode) = error $ (show toNode) ++ " can't be connect target."+  | otherwise   = liftIO $ js_connect'' fromNode toNode fromChannel+ disconnectNodes :: MonadIO m => Node -> Node -> m () disconnectNodes from to   | not (js_isSource from) = error $ (show from) ++ " can't be disconnect source."@@ -396,6 +410,10 @@   js_createChannelMerger :: AudioContext -> Int -> IO Node  foreign import javascript unsafe+  "$1.createChannelSplitter($2)"+  js_createChannelSplitter :: AudioContext -> Int -> IO Node++foreign import javascript unsafe   "$1.createWaveShaper()"   js_createWaveShaper :: AudioContext -> IO Node @@ -424,6 +442,10 @@ foreign import javascript unsafe   "$1.connect($2,$3,$4);"   js_connect' :: Node -> Node -> Int -> Int -> IO ()++foreign import javascript unsafe+  "$1.connect($2,$3);"+  js_connect'' :: Node -> Node -> Int -> IO ()  foreign import javascript unsafe   "$1.disconnect($2);"
src/Sound/MusicW/Synth.hs view
@@ -64,6 +64,8 @@ makeConnections dest ns (NodeRef from (_,_)) DestinationRef = connectNodes (ns!!from) dest makeConnections _ ns (NodeRef from (_,_)) (NodeRef to (_,_)) = connectNodes (ns!!from) (ns!!to) makeConnections _ ns (NodeRef from (_,_)) (ParamRef to pType) = createParameter (ns!!to) pType >>= connectNodes (ns!!from)+makeConnections _ ns (NodeOutputRef fromNode fromChannel) (NodeRef to (_,_)) = connectNodes'' (ns!!fromNode) fromChannel (ns!!to)+makeConnections _ ns (NodeOutputRef fromNode fromChannel) (ParamRef to pType) = createParameter (ns!!to) pType >>= connectNodes'' (ns!!fromNode) fromChannel makeConnections _ ns (NodeOutputRef fromNode fromChannel) (NodeInputRef toNode toChannel) = connectNodes' (ns!!fromNode) fromChannel (ns!!toNode) toChannel makeConnections _ _ _ _ = error "Malformed graph structure." 
src/Sound/MusicW/SynthDef.hs view
@@ -126,13 +126,14 @@   zipWithM_ (\x i -> connect' x 0 y i) xs [0..]   return y --- note: channelSplitter does not actually create any new synthesis nodes--- it just turns all of the output channels of a node with outputs into--- individual node references. channelSplitter :: AudioIO m => NodeRef -> SynthDef m [NodeRef]-channelSplitter (NodeOutputRef n o) = return [NodeOutputRef n o]-channelSplitter (NodeRef n (_,oChnls)) = return $ fmap (NodeOutputRef n) [0 .. (oChnls-1)]-channelSplitter _ = error "MusicW: channelSplitter called on NodeInputRef ParamRef or DestinationRef"+channelSplitter input | nodeRefOutputCount input < 1 = error "MusicW: channelSplitter called on NodeRef not representing a node output"+                      | otherwise = do+  let nchnls = nodeRefOutputCount input+  y <- addNodeBuilder (1,nchnls) $ createChannelSplitter nchnls+  let (NodeRef n _) = y+  connect input y+  return $ fmap (NodeOutputRef n) [0 .. (nchnls-1)]  convolver :: AudioIO m => Either Float32Array FloatArraySpec -> Bool -> NodeRef -> SynthDef m NodeRef convolver spec normalize input = do
src/Sound/MusicW/Worklets.hs view
@@ -56,7 +56,15 @@ powWorklet :: AudioIO m => NodeRef -> NodeRef -> SynthDef m NodeRef powWorklet in1 in2 = audioWorklet "pow-processor" [in1,in2] +floorWorklet :: AudioIO m => NodeRef -> SynthDef m NodeRef+floorWorklet x = audioWorklet "floor-processor" [x] +fractWorklet :: AudioIO m => NodeRef -> SynthDef m NodeRef+fractWorklet x = audioWorklet "fract-processor" [x]++clipWorklet :: AudioIO m => NodeRef -> NodeRef -> NodeRef -> SynthDef m NodeRef+clipWorklet lo hi input = audioWorklet "clip-processor" [lo,hi,input]+ audioWorklet :: AudioIO m => String -> [NodeRef] -> SynthDef m NodeRef audioWorklet workletName inputs = do   let iChnls = length inputs -- NOTE limiting assumption that each input NodeRef provides only one channel of input@@ -324,4 +332,48 @@ \    return true;\ \  }\ \ }\-\ registerProcessor('pow-processor',PowProcessor);"+\ registerProcessor('pow-processor',PowProcessor);\+\ \+\ class FloorProcessor extends AudioWorkletProcessor {\+\  static get parameterDescriptors() { return []; }\+\  constructor() { super(); }\+\  process(inputs,outputs,parameters) {\+\    const input1 = inputs[0];\+\    const output = outputs[0];\+\    for(let i = 0; i < input1[0].length; i++) {\+\      output[0][i] = Math.floor(input1[0][i]);\+\    }\+\    return true;\+\  }\+\ }\+\ registerProcessor('floor-processor',FloorProcessor);\+\ \+\ class FractProcessor extends AudioWorkletProcessor {\+\  static get parameterDescriptors() { return []; }\+\  constructor() { super(); }\+\  process(inputs,outputs,parameters) {\+\    const input1 = inputs[0];\+\    const output = outputs[0];\+\    for(let i = 0; i < input1[0].length; i++) {\+\      output[0][i] = input1[0][i] % 1;\+\    }\+\    return true;\+\  }\+\ }\+\ registerProcessor('fract-processor',FractProcessor);\+\ \+\ class ClipProcessor extends AudioWorkletProcessor {\+\  static get parameterDescriptors() { return []; }\+\  constructor() { super(); }\+\  process(inputs,outputs,parameters) {\+\    const min = inputs[0];\+\    const max = inputs[1];\+\    const input = inputs[2];\+\    const output = outputs[0];\+\    for(let i = 0; i < input[0].length; i++) {\+\      output[0][i] = Math.min(Math.max(input[0][i], min[0][i]), max[0][i]);\+\    }\+\    return true;\+\  }\+\ }\+\ registerProcessor('clip-processor',ClipProcessor);"