{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE NoIncoherentInstances #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE NoUndecidableInstances #-}
module Vivid.UGens.Multichannel (
pan2
, splay
, select
, mix
, addChannels
) where
import Vivid.SC.SynthDef.Types (CalculationRate(..))
import Vivid.SynthDef
import Vivid.UGens.Algebraic
import Vivid.UGens.Args
import Vivid.UGens.Generators.SingleValue (dc)
import Vivid.SynthDef.FromUA
import Control.Monad (foldM, zipWithM)
import Data.List.Split (chunksOf)
pan2 :: Args '["in","pos"] '["level"] a => a -> SDBody a [Signal]
pan2 = makePolyUGen
2 "Pan2" AR
(Vs::Vs '["in","pos","level"])
(level_ (1::Float))
splay :: ToSig s a => [s] -> SDBody' a [Signal]
splay sigsMono = do
let numChans :: Float
numChans = toEnum $ max 2 $ (length::[a]->Int) sigsMono
let positions :: [Float]
positions =
map ((\x->x-1) . (*(2/(numChans-1)))) [0..(numChans-1)]
let level = sqrt (recip numChans)
sigsStereo <- (\x -> zipWithM x sigsMono positions) $ \sig pos ->
pan2 (in_ sig, pos_ pos)
mapM (level ~*) =<< foldM addChannels [] sigsStereo
select :: ToSig s as => s -> [SDBody' as Signal] -> SDBody' as Signal
select which array = do
which' <- toSig which
array' <- mapM toSig array
addUGen $ UGen (UGName_S "Select") AR (which' : array') 1
mix :: ToSig s a => [s] -> SDBody' a Signal
mix [] = dc 0
mix [x] = toSig x
mix xs = mix =<< (mapM mix' . chunksOf 4) =<< mapM toSig xs
where
mix' :: [Signal] -> SDBody' a Signal
mix' [] = error "something's broken"
mix' [x] = return x
mix' [a,b] = a ~+ b
mix' ins@[_,_,_] = addUGen $ UGen (UGName_S "Sum3") AR ins 1
mix' ins@[_,_,_,_] = addUGen $ UGen (UGName_S "Sum4") AR ins 1
mix' _ = error "that would be weird"
addChannels :: (ToSig s0 a, ToSig s1 a) => [s0] -> [s1] -> SDBody' a [Signal]
addChannels [] xs = mapM toSig xs
addChannels xs [] = mapM toSig xs
addChannels (x:xs) (y:ys) = do
foo <- toSig x ~+ toSig y
(foo:) <$> addChannels xs ys