diff --git a/musicw.cabal b/musicw.cabal
--- a/musicw.cabal
+++ b/musicw.cabal
@@ -1,5 +1,5 @@
 name:                musicw
-version:             0.2.0
+version:             0.3.0
 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
diff --git a/src/Sound/MusicW/Node.hs b/src/Sound/MusicW/Node.hs
--- a/src/Sound/MusicW/Node.hs
+++ b/src/Sound/MusicW/Node.hs
@@ -212,10 +212,22 @@
   setNodeField node "isSink" True
   setNodeField node "startable" True
 
+createAnalyser :: AudioIO m => Int -> Double -> m Node
+createAnalyser fftSize smoothingTimeConstant = do
+  ctx <- audioContext
+  node <- liftIO $ js_createAnalyser ctx
+  setNodeField node "fftSize" fftSize
+  setNodeField node "smoothingTimeConstant" smoothingTimeConstant
+  setNodeField node "isSource" False -- technically, not true, but...
+  setNodeField node "isSink" True
+  setNodeField node "startable" False
+
+
 -- | There is no function in the Web Audio API to "create" the context's
 -- destination but we provide one anyway, as a convenient way to get a node
 -- that, like all the other nodes, can be used in connections.
 
+
 createDestination :: AudioIO m => m Node
 createDestination = do
   node <- Node <$> destination
@@ -400,6 +412,10 @@
   \  $1.___stream = $1.createMediaStreamDestination(); \
   \} $r = $1.___stream;"
   js_getContextSharedMediaStreamDestination :: AudioContext -> IO Node
+
+foreign import javascript unsafe
+  "$1.createAnalyser()"
+  js_createAnalyser :: AudioContext -> IO Node
 
 foreign import javascript unsafe
   "$1.connect($2);"
diff --git a/src/Sound/MusicW/SynthDef.hs b/src/Sound/MusicW/SynthDef.hs
--- a/src/Sound/MusicW/SynthDef.hs
+++ b/src/Sound/MusicW/SynthDef.hs
@@ -168,6 +168,12 @@
   connect input y
   return y
 
+analyser :: AudioIO m => Int -> Double -> NodeRef -> SynthDef m NodeRef
+analyser fftSize smoothingTimeConstant input = do
+  y <- addNodeBuilder (1,0) $ createAnalyser fftSize smoothingTimeConstant
+  connect input y
+  return y
+
 audioOut :: AudioIO m => NodeRef -> SynthDef m ()
 audioOut input = connect input DestinationRef
 
diff --git a/src/Sound/MusicW/Worklets.hs b/src/Sound/MusicW/Worklets.hs
--- a/src/Sound/MusicW/Worklets.hs
+++ b/src/Sound/MusicW/Worklets.hs
@@ -53,7 +53,10 @@
 safeDivideWorklet :: AudioIO m => NodeRef -> NodeRef -> SynthDef m NodeRef
 safeDivideWorklet in1 in2 = audioWorklet "safeDivide-processor" [in1,in2]
 
+powWorklet :: AudioIO m => NodeRef -> NodeRef -> SynthDef m NodeRef
+powWorklet in1 in2 = audioWorklet "pow-processor" [in1,in2]
 
+
 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
@@ -306,4 +309,19 @@
 \    return true;\
 \  }\
 \ }\
-\ registerProcessor('safeDivide-processor',SafeDivideProcessor);"
+\ registerProcessor('safeDivide-processor',SafeDivideProcessor);\
+\ \
+\ class PowProcessor extends AudioWorkletProcessor {\
+\  static get parameterDescriptors() { return []; }\
+\  constructor() { super(); }\
+\  process(inputs,outputs,parameters) {\
+\    const input1 = inputs[0];\
+\    const input2 = inputs[1];\
+\    const output = outputs[0];\
+\    for(let i = 0; i < input1[0].length; i++) {\
+\      output[0][i] = Math.pow(input1[0][i],input2[0][i]);\
+\    }\
+\    return true;\
+\  }\
+\ }\
+\ registerProcessor('pow-processor',PowProcessor);"
