-- | Optimisations of UGen graphs. module Sound.SC3.UGen.Optimise where import System.Random {- random -} import Sound.SC3.UGen.Math import Sound.SC3.UGen.Rate import Sound.SC3.UGen.Type import Sound.SC3.UGen.UGen -- | Constant form of 'rand' UGen. c_rand :: Random a => Int -> a -> a -> a c_rand z l r = fst (randomR (l,r) (mkStdGen z)) -- | Constant form of 'iRand' UGen. c_irand :: (Num b, RealFrac a, Random a) => Int -> a -> a -> b c_irand z l r = fromInteger (round (c_rand z l r)) -- | Optimise 'UGen' graph by re-writing 'rand' and 'iRand' UGens that -- have 'Constant' inputs. This, of course, changes the nature of the -- graph, it is no longer randomised at the server. It's a useful -- transformation for very large graphs which are being constructed -- and sent each time the graph is played. -- -- > import Sound.SC3.UGen.Dot -- -- > let u = sinOsc AR (rand 'a' 220 440) 0 * 0.1 -- > in draw (u + ugen_optimise_ir_rand u) ugen_optimise_ir_rand :: UGen -> UGen ugen_optimise_ir_rand = let f u = case u of Primitive_U p -> case p of Primitive IR "Rand" [Constant_U (Constant l),Constant_U (Constant r)] [IR] _ (UId z) -> Constant_U (Constant (c_rand z l r)) Primitive IR "IRand" [Constant_U (Constant l),Constant_U (Constant r)] [IR] _ (UId z) -> Constant_U (Constant (c_irand z l r)) _ -> u _ -> u in ugenTraverse f -- | Optimise 'UGen' graph by re-writing binary operators with -- 'Constant' inputs. The standard graph constructors already do -- this, however subsequent optimisations, ie. 'ugen_optimise_ir_rand' -- can re-introduce these sub-graphs, and the /Plain/ graph -- constructors are un-optimised. -- -- > let u = constant -- > u 5 * u 10 == u 50 -- > u 5 ==* u 5 == u 1 -- > u 5 >* u 4 == u 1 -- > u 5 <=* u 5 == u 1 -- > abs (u (-1)) == u 1 -- > u 5 / u 2 == u 2.5 -- -- > let {u = lfPulse AR (2 ** rand 'α' (-9) 1) 0 0.5 -- > ;u' = ugen_optimise_ir_rand u} -- > in draw (mix (mce [u,u',ugen_optimise_const_operator u'])) ugen_optimise_const_operator :: UGen -> UGen ugen_optimise_const_operator = let f u = case u of Primitive_U p -> case p of Primitive _ "BinaryOpUGen" [Constant_U (Constant l),Constant_U (Constant r)] [_] (Special z) _ -> case binop_special_hs z of Just fn -> Constant_U (Constant (fn l r)) _ -> u Primitive _ "UnaryOpUGen" [Constant_U (Constant i)] [_] (Special z) _ -> case uop_special_hs z of Just fn -> Constant_U (Constant (fn i)) _ -> u _ -> u _ -> u in ugenTraverse f constant_opt :: UGen -> Maybe Sample constant_opt = u_constant . ugen_optimise_ir_rand