content: -- | The fixities of the operators ("~+", "~*", "~<", etc) are the same as those of
  --   their non-'~' equivalents (+, *, < etc)
  --
  --   (So you can e.g. multiply then add without parens!)
  
  {-# LANGUAGE DataKinds #-}
  {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE TypeFamilies, NoMonoLocalBinds #-}
  
  {-# LANGUAGE NoIncoherentInstances #-}
  {-# LANGUAGE NoMonomorphismRestriction #-}
  {-# LANGUAGE NoUndecidableInstances #-}
  
  module Vivid.UGens.Algebraic (
       (~+)
     , (~-)
     , (~*)
     , (~**)
     , (~/)
  
  {- -- removed these to be compatible with tidal, which also uses some of these:
     , (~>)
     , (~>=)
     , (~<)
     , (~<=)
  -}
     , binaryOp
     , biOp
     , unaryOp
     , uOp
     , midiCPS
     , cpsMIDI
     , abs'
     , neg
     , tanh'
     , clip2
     , xor
     ) where
  
  import Vivid.SynthDef
  -- import Vivid.UGens.Args
  
  import Prelude
  
  infixl 7 ~*
  -- | Multiply signals
  (~*) :: (ToSig i0 a, ToSig i1 a) => i0 -> i1 -> SDBody' a Signal
  (~*) = binaryOp Mul
  
  infixr 8 ~**
  -- | Exponentiation of signals
  (~**) :: (ToSig i0 a, ToSig i1 a) => i0 -> i1 -> SDBody' a Signal
  (~**) = binaryOp Pow
  
  infixl 6 ~+
  -- | Add signals
  (~+) :: (ToSig i0 a, ToSig i1 a) => i0 -> i1 -> SDBody' a Signal
  (~+) = binaryOp Add
  
  infixl 7 ~/
  -- | Divide signals
  (~/) :: (ToSig i0 a, ToSig i1 a) => i0 -> i1 -> SDBody' a Signal
  (~/) = binaryOp FDiv
  
  {-
  infix 4 ~>
  -- | Test signals for left greater than right
  (~>) :: (ToSig i0 a, ToSig i1 a) => i0 -> i1 -> SDBody' a Signal
  (~>) = binaryOp Gt
  
  infix 4 ~>=
  -- | Test signals for left greater than or equal to right
  (~>=) :: (ToSig i0 a, ToSig i1 a) => i0 -> i1 -> SDBody' a Signal
  (~>=) = binaryOp Ge
  
  infix 4 ~<
  -- | Test signals for left less than right
  (~<) :: (ToSig i0 a, ToSig i1 a) => i0 -> i1 -> SDBody' a Signal
  (~<) = binaryOp Lt
  
  infix 4 ~<=
  -- | Test signals for left less than or equal to right
  (~<=) :: (ToSig i0 a, ToSig i1 a) => i0 -> i1 -> SDBody' a Signal
  (~<=) = binaryOp Le
  -}
  
  infixl 6 ~-
  -- | Subtract signals
  (~-) :: (ToSig i0 a, ToSig i1 a) => i0 -> i1 -> SDBody' a Signal
  (~-) = binaryOp Sub
  
  -- | Build your own!
  -- 
  --   The calculation rate of the result is the larger (more frequent) of the 2 input
  --   signals
  --   (So you shouldn't need to use "?" very much!)
  binaryOp :: (ToSig s0 a, ToSig s1 a) => BinaryOp -> s0 -> s1 -> SDBody' a Signal
  binaryOp theBiOp s0 s1 = do
     s0' <- toSig s0
     s1' <-  toSig s1
     calcRate <- max <$> getCalcRate s0' <*> getCalcRate s1'
     let sigs = [s0', s1']
     addUGen $ UGen (UGName_B theBiOp) calcRate sigs 1
  
  -- | Alias of 'binaryOp'. Shorter, fer livecodin
  biOp :: (ToSig s0 a, ToSig s1 a) => BinaryOp -> s0 -> s1 -> SDBody' a Signal
  biOp = binaryOp
  
  -- | Build your own, from 'UnaryOp's
  unaryOp :: (ToSig sig a) => UnaryOp -> sig -> SDBody' a Signal
  unaryOp theUOp sig = do
     sig' <- toSig sig
     calcRate <- getCalcRate sig'
     addUGen $ UGen (UGName_U theUOp) calcRate [sig'] 1
  
  -- | Alias of 'unaryOp'
  uOp :: (ToSig sig a) => UnaryOp -> sig -> SDBody' a Signal
  uOp = unaryOp
  
  -- | Convert from a midi note number (0-127, each representing a musical half step) to a
  --   frequency in hz (cycles per second)
  midiCPS :: (ToSig i a) => i -> SDBody' a Signal
  midiCPS = unaryOp MIDICPS
  
  -- | Inverse of 'midiCPS'
  cpsMIDI :: (ToSig i a) => i -> SDBody' a Signal
  cpsMIDI = unaryOp CPSMIDI
  
  
  
  -- | The prime is to not conflict with \"abs\" in the prelude. May just use
  --   \"uOp Abs\" in the future
  abs' :: (ToSig i a) => i -> SDBody' a Signal
  abs' = unaryOp Abs
  
  neg :: (ToSig i a) => i -> SDBody' a Signal
  neg = unaryOp Neg
  
  -- | The prime, like 'abs'', is to not conflict with a prelude definition.
  -- 
  --   Remember you can always just use:
  -- 
  --   > uOp TanH
  tanh' :: ToSig i a => i -> SDBody' a Signal
  tanh' i = uOp TanH i
  
  -- | Like 'Vivid.UGens.Maths.clip' but the lo value is always negative the hi value
  clip2 :: (ToSig s0 a, ToSig s1 a) => s0 -> s1 -> SDBody' a Signal
  clip2 = biOp Clip2
  
  -- | Bitwise xor. Short for @biOp BitXor@
  xor :: (ToSig s0 a, ToSig s1 a) => s0 -> s1 -> SDBody' a Signal
  xor = biOp BitXor
  