tidal-midi 0.6 → 0.8
raw patch · 19 files changed
+594/−1401 lines, 19 filesdep +transformersdep −bytestringdep −hashabledep −hoscdep ~PortMididep ~tidal
Dependencies added: transformers
Dependencies removed: bytestring, hashable, hosc, process
Dependency ranges changed: PortMidi, tidal
Files
- Sound/Tidal/Blofeld.hs +0/−78
- Sound/Tidal/MBase01.hs +0/−34
- Sound/Tidal/MIDI/Context.hs +6/−0
- Sound/Tidal/MIDI/Control.hs +54/−37
- Sound/Tidal/MIDI/Output.hs +0/−263
- Sound/Tidal/MIDI/Stream.hs +368/−0
- Sound/Tidal/MIDI/Synth.hs +17/−0
- Sound/Tidal/MIDI/SynthParams.hs +46/−0
- Sound/Tidal/MIDI/VolcaBass.hs +27/−0
- Sound/Tidal/MIDI/VolcaBeats.hs +35/−0
- Sound/Tidal/MIDI/VolcaKeys.hs +30/−0
- Sound/Tidal/Rytm.hs +0/−203
- Sound/Tidal/SimpleSynth.hs +0/−26
- Sound/Tidal/Synthino.hs +0/−52
- Sound/Tidal/Tetra.hs +0/−530
- Sound/Tidal/VolcaBass.hs +0/−42
- Sound/Tidal/VolcaBeats.hs +0/−72
- Sound/Tidal/VolcaKeys.hs +0/−50
- tidal-midi.cabal +11/−14
− Sound/Tidal/Blofeld.hs
@@ -1,78 +0,0 @@-module Sound.Tidal.Blofeld where--import Sound.Tidal.Stream (makeI, makeF)--import Sound.Tidal.MIDI.Control--keys :: ControllerShape-keys = ControllerShape {params = [- mCC "portamento" 5,- mCC "expression" 11,- CC "lfoshape" 15 (0, 5) 0 passThru, -- 0..5 - sine,triangle,square,saw,random,sample&hold- mCC "lforate" 16,- CC "lfosync" 17 (0, 1) 0 passThru, -- 0 off, 1 on- mCC "lfodelay" 18,- CC "octave" 27 (16, 112) 0 passThru, -- 16, 28, 40 .. 112 - 128' .. 1/2'- CC "semitone" 28 (52, 76) 0.5 passThru, -- 52 .. 76 - -12 - +12 semitones- mCC "detune" 29,- mCC "osc1fm" 30,- SysEx "osc1fmsrc" 6 (0, 11) 0 passThru,- CC "osc1shape" 31 (0, 5) 0 passThru, -- 0..5 - pulse, saw, tri, sine, alt 1, alt 2- mCC "osc1pw" 33,- mCC "osc1pwm" 34,- SysEx "osc1pwmsrc" 10 (0, 30) 0 passThru,- mCC "osc1vol" 52,- mCC "osc1pan" 53,- mCC "ringmod" 54,- mCC "ringpan" 55,- mCC "noise" 60,- mCC "noisepan" 61,- mCC "noisecol" 62,- mCC "kcutoff" 69,- mCC "attack" 101,- mCC "decay" 102,- mCC "sustain" 103,- mCC "release" 106- ],- duration = ("dur", 0.05),- velocity = ("vel", 0.5),- latency = 0.1}--oscKeys = toOscShape keys--note = makeI oscKeys "note"-dur = makeF oscKeys "dur"--portamento = makeF oscKeys "portamento"-expression = makeF oscKeys "expression"-octave = makeF oscKeys "octave"-semitone = makeF oscKeys "semitone"-detune = makeF oscKeys "detune"--kcutoff = makeF oscKeys "kcutoff"--lforate = makeF oscKeys "lforate"-lfoshape = makeF oscKeys "lfoshape"-lfodelay = makeF oscKeys "lfodelay"-lfosync = makeF oscKeys "lfosyn"--attack = makeF oscKeys "attack"-decay = makeF oscKeys "decay"-sustain = makeF oscKeys "sustain"-release = makeF oscKeys "release"--osc1fm = makeF oscKeys "osc1fm"-osc1fmsrc = makeF oscKeys "osc1fmsrc"-osc1shape = makeF oscKeys "osc1shape"-osc1pw = makeF oscKeys "osc1pw"-osc1pwm = makeF oscKeys "osc1pwm"-osc1pwmsrc = makeF oscKeys "osc1pwmsrc"-osc1vol = makeF oscKeys "osc1vol"-osc1pan = makeF oscKeys "osc1pan"--ringmod = makeF oscKeys "ringmod"-ringpan = makeF oscKeys "ringpan"--noise = makeF oscKeys "noise"-noisepan = makeF oscKeys "noisepan"-noisecol = makeF oscKeys "noisecol"
− Sound/Tidal/MBase01.hs
@@ -1,34 +0,0 @@-module Sound.Tidal.MBase01 where-import Sound.Tidal.Stream (makeI, makeF)--import Sound.Tidal.MIDI.Control--mbase01 :: ControllerShape-mbase01 = ControllerShape {params = [- mCC "tune" 100,- mCC "pitch" 101,- mCC "decay" 102,- mCC "harmonics" 103,- mCC "pulse" 104,- mCC "noise" 105,- mCC "attack" 106,- mCC "eqlzr" 107- ],- duration = ("dur", 0.05),- velocity = ("vel", 0.5),- latency = 0.1}--oscKeys = toOscShape mbase01--note = makeI oscKeys "note"-dur = makeF oscKeys "dur"---tune = makeF oscKeys "tune"-pitch = makeF oscKeys "pitch"-decay = makeF oscKeys "decay"-harmonics = makeF oscKeys "harmonics"-pulse = makeF oscKeys "pulse"-noise = makeF oscKeys "noise"-attack = makeF oscKeys "attack"-eqlzr = makeF oscKeys "eqlzr"
+ Sound/Tidal/MIDI/Context.hs view
@@ -0,0 +1,6 @@+module Sound.Tidal.MIDI.Context (module C) where++import Sound.Tidal.MIDI.Device as C+import Sound.Tidal.MIDI.Control as C+import Sound.Tidal.MIDI.Stream as C+import Sound.Tidal.MIDI.Synth as C
Sound/Tidal/MIDI/Control.hs view
@@ -2,56 +2,73 @@ import qualified Sound.Tidal.Stream as S -type RangeMapFunc = (Int, Int) -> Float -> Int+import Sound.Tidal.Params -data Param = CC { name :: String, midi :: Int, range :: (Int, Int), vdefault :: Double, scalef :: RangeMapFunc }- | NRPN { name :: String, midi :: Int, range :: (Int, Int), vdefault :: Double, scalef :: RangeMapFunc }- | SysEx { name :: String, midi :: Int, range :: (Int, Int), vdefault :: Double, scalef :: RangeMapFunc }+type RangeMapFunc = (Int, Int) -> Double -> Int -data ControllerShape = ControllerShape {params :: [Param],duration :: (String, Double), velocity :: (String, Double), latency :: Double}+data ControlChange =+ CC { param :: S.Param,+ midi :: Int,+ range :: (Int, Int),+ vdefault :: Double,+ scalef :: RangeMapFunc+ }+ | NRPN { param :: S.Param,+ midi :: Int,+ range :: (Int, Int),+ vdefault :: Double,+ scalef :: RangeMapFunc+ }+ | SysEx { param :: S.Param,+ midi :: Int,+ range :: (Int, Int),+ vdefault :: Double,+ scalef :: RangeMapFunc+ } -toOscShape :: ControllerShape -> S.OscShape-toOscShape cs =- let oscparams = [S.I "note" Nothing] ++ [S.F durn (Just durv), S.F veln (Just velv)] ++ oscparams'- oscparams' = [S.F (name p) (Just (-1)) | p <- (params cs)]- (durn, durv) = duration cs- (veln, velv) = velocity cs- in S.OscShape {S.path = "/note",- S.params = oscparams,- S.timestamp = S.MessageStamp,+data ControllerShape = ControllerShape {+ controls :: [ControlChange],+ latency :: Double+ }+++toShape :: ControllerShape -> S.Shape+toShape cs =+ let params = [dur_p, n_p, velocity_p] ++ params'+ params' = [param p | p <- (controls cs)]+ in S.Shape { S.params = params, S.cpsStamp = False,- S.latency = latency cs,- S.namedParams = False,- S.preamble = []- }+ S.latency = latency cs+ } -passThru :: (Int, Int) -> Float -> Int+passThru :: (Int, Int) -> Double -> Int passThru (_, _) = floor -- no sanitizing of range… -mapRange :: (Int, Int) -> Float -> Int+mapRange :: (Int, Int) -> Double -> Int mapRange (low, high) = floor . (+ (fromIntegral low)) . (* ratio) where ratio = fromIntegral $ high - low -mCC :: String -> Int -> Param-mCC n m = CC {name=n, midi=m, range=(0, 127), vdefault=0, scalef=mapRange }+mCC :: S.Param -> Int -> ControlChange+mCC p m = CC {param=p, midi=m, range=(0, 127), vdefault=0, scalef=mapRange } -mNRPN :: String -> Int -> Param-mNRPN n m = NRPN {name=n, midi=m, range=(0, 127), vdefault=0, scalef=mapRange }+mNRPN :: S.Param -> Int -> ControlChange+mNRPN p m = NRPN {param=p, midi=m, range=(0, 127), vdefault=0, scalef=mapRange } -mrNRPN :: String -> Int -> (Int, Int) -> Double -> Param-mrNRPN n m r d = NRPN {name=n, midi=m, range=r, vdefault=d, scalef=mapRange }+mrNRPN :: S.Param -> Int -> (Int, Int) -> Double -> ControlChange+mrNRPN p m r d = NRPN {param=p, midi=m, range=r, vdefault=d, scalef=mapRange } -toKeynames :: ControllerShape -> [String]-toKeynames shape = map name (params shape)+toParams :: ControllerShape -> [S.Param]+toParams shape = map param (controls shape) -ctrlN :: Num b => ControllerShape -> String -> b-ctrlN shape x = fromIntegral $ midi $ paramN shape x+ctrlN :: Num b => ControllerShape -> S.Param -> Maybe b+ctrlN shape x = fmap fromIntegral $ fmap midi (paramN shape x) -paramN :: ControllerShape -> String -> Param+paramN :: ControllerShape -> S.Param -> Maybe ControlChange paramN shape x- | x `elem` names = paramX x- | otherwise = error $ "No such Controller param: " ++ show x- where names = toKeynames shape- paramX x = head paramX'- paramX' = filter ((== x) . name) p- p = params shape+ | x `elem` names = paramX $ matching p+ | otherwise = Nothing -- error $ "No such Controller param: " ++ show x+ where names = toParams shape+ paramX [] = Nothing+ paramX (h:_) = Just h+ matching = filter ((== x) . param)+ p = controls shape
− Sound/Tidal/MIDI/Output.hs
@@ -1,263 +0,0 @@-module Sound.Tidal.MIDI.Output (midiproxy) where--import qualified Sound.PortMidi as PM--import Sound.Tidal.MIDI.Device--import Data.Time (getCurrentTime, UTCTime, diffUTCTime)-import Data.Time.Clock.POSIX-import qualified Data.ByteString as B-import qualified Data.ByteString.Char8 as BC--import Sound.OSC.FD-import Control.Monad-import Control.Concurrent.MVar--import Data.Bits-import Data.Char-import Data.List (sortBy)-import Data.Maybe-import Data.Ord (comparing)-import Data.Word (Word8)--import Control.Concurrent-import Foreign.C--import qualified Sound.Tidal.MIDI.Control as C--import Sound.Tidal.Pattern-import Sound.Tidal.Tempo-import qualified Sound.Tidal.Stream as S (stream, name, params, OscPattern, OscShape)--import System.IO.Error--data Output = Output {- conn :: PM.PMStream,- lock :: MVar (),- offset :: (Int, Int),- buffer :: MVar [PM.PMEvent]- }-midiproxy :: Int -> String-> [(C.ControllerShape, Int)] -> IO [IO (S.OscPattern -> IO ())]-midiproxy latency deviceName targets = do- let keyStreams = map (\(shape, channel) -> makeStream (C.toOscShape shape) (channel + 7303)) targets- deviceID <- getIDForDeviceName deviceName- case deviceID of- Nothing -> do putStrLn "List of Available Device Names"- putStrLn =<< displayOutputDevices- error ("Device '" ++ show deviceName ++ "' not found")- Just id -> do econn <- outputDevice id latency- case econn of- Right err -> error ("Failed opening MIDI Output on Device ID: " ++ show deviceID ++ " - " ++ show err)- Left conn -> do- sendevents conn- --midiclock conn- mapM_ (\(shape,channel) -> messageLoop conn shape (fromIntegral channel) (channel + 7303)) targets- return keyStreams--messageLoop :: Output -> C.ControllerShape -> CLong -> Int -> IO ThreadId-messageLoop stream shape ch port = do- putStrLn ("Starting message loop on port " ++ show port ++ " for MIDI channel " ++ show ch)- x <- udpServer "127.0.0.1" port-- forkIO $ loop stream x ch- where loop stream x ch = do m <- recvMessage x- act stream m ch- loop stream x ch- act stream (Just (Message "/note" (sec:usec:note:dur:vel:ctrls))) ch =- do- let diff = timeDiff (sec, usec) (offset stream)- note' = (fromJust $ d_get note) :: Int- vel' = (fromJust $ d_get vel) :: Float- dur' = (fromJust $ d_get dur) :: Float- ctrls' = (map (fromJust . d_get) ctrls) :: [Float]-- -- mTime <- PM.time- -- putStrLn ("MIDI in: " ++ (show (diff - mTime)))- sendmidi stream shape ch (fromIntegral note', fromIntegral $ C.mapRange (0, 127) (realToFrac vel'), realToFrac dur') (diff) ctrls'- return()--makeStream :: S.OscShape -> Int -> IO (S.OscPattern -> IO ())-makeStream shape port = S.stream "127.0.0.1" port shape---- EXPERIMENTAL-midiclock stream = do- forkIO $ do clockedTick 1 $ onClockTick stream--onClockTick stream current ticks = do- -- schedule MIDI Clock Ticks ahead of time to avoid jumps in timing- -- e.g. if one tick per cycle- -- schedule 24 ticks ahead of time starting now with PM.time and incrementing each timestamp by ((1/cycle per seconds)/24)*1000 for ms for each tick- time <- PM.time- mapM_ (makeMidiClockTick stream) (map ((+time).round.(/(24*(cps current))).(*1000)) [0..23])- return ()--- END EXPERIMENTAL--sendevents :: Output -> IO ThreadId-sendevents stream = do- forkIO $ do loop stream- where loop stream = do act stream- delay- loop stream- act stream = do- let buf = buffer stream- o = conn stream- buf' <- tryTakeMVar buf- case buf' of- Nothing -> do- return Nothing- Just [] -> do- putMVar buf []- return Nothing- (Just evts@(x:xs)) -> do- midiTime <- PM.time- let evts' = sortBy (comparing PM.timestamp) evts- nextTick = fromIntegral $ midiTime + 1 -- advance on millisecond, i.e. the next call of this loop- (evts'',later) = span (\x -> (((PM.timestamp x) < midiTime)) || ((PM.timestamp x) < nextTick)) evts'- putMVar buf later-- err <- PM.writeEvents o evts''- case err of- PM.NoError -> return Nothing- e -> return $ Just (userError ("Error '" ++ show e ++ "' sending Events: " ++ show evts))-- delay = threadDelay 1000 -- in microseconds, i.e. one millisecond--sendctrls :: Output -> C.ControllerShape -> CLong -> CULong -> [Float] -> IO ()-sendctrls stream shape ch t ctrls = do- let ctrls' = filter ((>=0) . snd) (zip (C.toKeynames shape) ctrls)- sequence_ $ map (\(name, ctrl) -> makeCtrl stream ch (C.paramN shape name) ctrl t) ctrls'- return ()--sendnote :: RealFrac s => Output -> t -> CLong -> (CLong, CLong, s) -> CULong -> IO ThreadId-sendnote stream shape ch (note,vel, dur) t =- do forkIO $ do noteOn stream ch note vel t- noteOff stream ch note (t + (floor $ 1000 * dur))- return ()--sendmidi :: RealFrac s => Output -> C.ControllerShape -> CLong -> (CLong, CLong, s) -> CULong -> [Float] -> IO ()-sendmidi stream shape ch (128,vel,dur) t ctrls = do- sendctrls stream shape ch t ctrls- return ()-sendmidi stream shape ch (note,vel,dur) t ctrls = do- sendnote stream shape ch (note,vel,dur) t- sendctrls stream shape ch t ctrls- return ()--timeDiff :: (Integral b, Integral a1, Integral a) => (Datum, Datum) -> (a, a1) -> b-timeDiff (ds, du) (s, u) = diff d i- where diff a b = floor ((a - b) * 1000) -- as millis- d = asFrac jds jdu- i = asFrac s u- jds = (fromJust $ d_get ds) :: Int- jdu = (fromJust $ d_get du) :: Int- asFrac a b = (fromIntegral a) + ((fromIntegral b) * 0.000001)----- MIDI Utils-encodeChannel :: (Bits a, Num a) => a -> a -> a-encodeChannel ch cc = (((-) ch 1) .|. cc)----- MIDI Messages-noteOn :: Output -> CLong -> CLong -> CLong -> CULong -> IO (Maybe a)-noteOn o ch val vel t = do- let evt = makeEvent 0x90 val ch vel t- sendEvent o evt--noteOff :: Output -> CLong -> CLong -> CULong -> IO (Maybe a)-noteOff o ch val t = do- let evt = makeEvent 0x80 val ch 60 t- sendEvent o evt--makeCtrl :: Output -> CLong -> C.Param -> Float -> CULong -> IO (Maybe a)-makeCtrl o ch (C.CC {C.midi=midi, C.range=range, C.scalef=f}) n t = makeCC o ch (fromIntegral midi) scaledN t- where scaledN = fromIntegral (f range (n))-makeCtrl o ch (C.NRPN {C.midi=midi, C.range=range, C.scalef=f}) n t = makeNRPN o ch (fromIntegral midi) scaledN t- where scaledN = fromIntegral $ (f range (n))-makeCtrl o ch (C.SysEx {C.midi=midi, C.range=range, C.scalef=f}) n t = makeSysEx o ch (fromIntegral midi) scaledN t- where scaledN = fromIntegral $ (f range (n))---- This is sending CC-makeCC :: Output -> CLong -> CLong -> CLong -> CULong -> IO (Maybe a)-makeCC o ch c n t = do- let evt = makeEvent 0xB0 c ch n t- sendEvent o evt---- This is sending NRPN-makeNRPN :: Output -> CLong -> CLong -> CLong -> CULong -> IO (Maybe a)-makeNRPN o ch c n t = do- let nrpn = makeEvent 0xB0- evts = [nrpn 0x63 ch (shift (c .&. 0x3F80) (-7)) t,- nrpn 0x62 ch (c .&. 0x7F) t,- nrpn 0x06 ch (shift (n .&. 0x3F80) (-7)) t,- nrpn 0x26 ch (n .&. 0x7F) t- ]- mapM (sendEvent o) evts- return Nothing--makeMidiClockTick o t = do- sendEvent o $ PM.PMEvent (PM.PMMsg 0xF8 0x00 0x00) t--makeSysEx :: Output -> t -> Word8 -> Word8 -> CULong -> IO (Maybe a)-makeSysEx o ch c n t = do- let bytes = [0xF0, -- SysEx Start- 0x3E, -- Vendor ID- 0x13, -- Equipment ID- 0x00, -- Device No.- 0x20, -- Message ID- 0x00, -- Location- shift (c .&. 0x3F80) (-7), -- Parameter Index high byte- (c .&. 0x7F), -- Parameter Index low byte- n, -- Parameter Value- 0xF7 -- End of SysEx- ]-- msg = B.pack $ bytes-- sendSysEx o t (BC.unpack msg)---- PortMIDI Wrapper--outputDevice :: PM.DeviceID -> Int -> IO (Either Output PM.PMError)-outputDevice deviceID latency = do- PM.initialize- now <- getCurrentTime- result <- PM.openOutput deviceID latency- case result of- Left dev ->- do- info <- PM.getDeviceInfo deviceID- putStrLn ("Opened: " ++ show (PM.interface info) ++ ": " ++ show (PM.name info))- sem <- newEmptyMVar- putMVar sem () -- initially fill MVar to be taken by the first user of this output- buffer <- newMVar []-- midiOffset <- PM.time-- let posixNow = realToFrac $ utcTimeToPOSIXSeconds now- syncedNow = posixNow - ((0.001*) $ fromIntegral midiOffset)- sec = floor syncedNow- usec = floor $ 1000000 * (syncedNow - (realToFrac sec))- return (Left Output { conn=dev, lock=sem, offset=(sec, usec), buffer=buffer })- Right err -> return (Right err)--makeEvent :: CLong -> CLong -> CLong -> CLong -> CULong -> PM.PMEvent-makeEvent st n ch v t = PM.PMEvent msg (t)- where msg = PM.PMMsg (encodeChannel ch st) (n) (v)--sendSysEx :: Output -> CULong -> String -> IO (Maybe a)-sendSysEx o t msg = do- let sem = lock o- takeMVar sem- err <- PM.writeSysEx (conn o) t msg- putMVar sem ()- return Nothing---- now with a semaphore since PortMIDI is NOT thread safe-sendEvent :: Output -> PM.PMEvent -> IO (Maybe a)-sendEvent o evt = do- let sem = lock o- buf = buffer o- cbuf <- takeMVar buf- putMVar buf (cbuf ++ [evt])- return Nothing
+ Sound/Tidal/MIDI/Stream.hs view
@@ -0,0 +1,368 @@+module Sound.Tidal.MIDI.Stream (midiStream, midiBackend, midiState, midiSetters, midiDevices,send) where++import Control.Monad.Trans.Maybe+-- generics+import qualified Data.Map as Map+import Data.List (sortBy)+import Data.Maybe+import Data.Ord (comparing)+import Data.Time (getCurrentTime, UTCTime, diffUTCTime)+import Data.Time.Clock.POSIX+import Control.Concurrent+import Control.Concurrent.MVar+import Data.Bits+import Foreign.C+import Control.Applicative++import Numeric++-- Tidal specific+import Sound.Tidal.Tempo (Tempo, cps, clockedTick)+import Sound.Tidal.Stream as S+import Sound.Tidal.Utils+import Sound.Tidal.Time+import Sound.Tidal.Transition (transition)++-- MIDI specific+import Sound.Tidal.MIDI.Device+import Sound.Tidal.MIDI.Control+import qualified Sound.PortMidi as PM+++type ConnectionCount = Int+type TickedConnectionCount = Int+type OutputOnline = Bool+type OutputState = (TickedConnectionCount, ConnectionCount, OutputOnline)+type MIDITime = (Tempo, Int, Double, Double)+type MIDIEncoder = CULong -> PM.PMEvent+type MIDIEvent = (MIDITime, MIDIEncoder)++data Output = Output {+ conn :: PM.PMStream,+ buffer :: MVar [MIDIEvent],+ bufferstate :: MVar OutputState+ }++type MidiMap = Map.Map S.Param (Maybe Int)+type MidiDeviceMap = Map.Map String Output+++toMidiEvent :: ControllerShape -> S.Param -> Value -> Maybe Int+toMidiEvent s p (VF x) = ($) <$> mscale <*> mrange <*> pure x+ where+ mrange = fmap range mcc+ mscale = fmap scalef mcc+ mcc = paramN s p+toMidiEvent s p (VI x) = Just x+toMidiEvent s p (VS x) = Nothing -- ignore strings for now, we might 'read' them later++toMidiMap :: ControllerShape -> S.ParamMap -> MidiMap+toMidiMap s m = Map.mapWithKey (toMidiEvent s) (Map.mapMaybe (id) m)++send s ch cshape shape change tick o ctrls (tdur:tnote:trest) = midi+ where+ midi = sendmidi s cshape ch' (note, vel, dur) (change, tick, o, offset) ctrls+ note = fromIntegral $ ivalue $ snd tnote+ dur = realToFrac $ fvalue $ snd tdur+ (vel, nudge) = case length trest of+ 2 -> (mkMidi $ trest !! 1, fvalue $ snd $ trest !! 0)+ 1 -> (mkMidi $ trest !! 0, 0)+ ch' = fromIntegral ch+ mkMidi = fromIntegral . floor . (*127) . fvalue . snd+ offset = ((Sound.Tidal.MIDI.Control.latency cshape) + nudge)++mkSend cshape channel s = return $ (\ shape change tick (o,m) -> do+ let defaulted = (S.applyShape' shape m)+ -- split ParamMap into Properties and Controls+ mpartition = fmap (Map.partitionWithKey (\k _ -> (name k) `elem` ["dur", "n", "velocity", "nudge"])) defaulted+ props = fmap fst mpartition+ ctrls = fmap snd mpartition+ props' = fmap (Map.toAscList) $ fmap (Map.mapMaybe (id)) props+ -- only send explicitly set Control values+ ctrls' = fmap (Map.filterWithKey (\k v -> v /= (defaultValue k))) ctrls+ ctrls'' = fmap (toMidiMap cshape) ctrls'+ send' = fmap (send s channel cshape shape change tick o) ctrls''+ ($) <$> send' <*> props'+ )++connected cshape channel name s = do+ putStrLn ("Successfully initialized Device '" ++ name ++ "'")+ changeState goOnline s+ mkSend cshape channel s++failed di err = do+ error (show err ++ ": " ++ show di)++notfound name = do+ putStrLn "List of Available Device Names"+ putStrLn =<< displayOutputDevices+ error ("Device '" ++ show name ++ "' not found")++readState f o = do+ s <- readMVar $ bufferstate o+ let fs = f s+ (ticked, conns, online) = s+ return fs++isCycling (0, conns, True) = True+isCycling _ = False++displayState (ticked, conns, online) = show ticked ++ "/" ++ show conns ++ "[" ++ show online ++ "]"++changeState f o = do+ bs <- takeMVar stateM+ let fs = f bs+ (ticked, conns, online) = fs + putMVar stateM $ fs+ where+ stateM = bufferstate o++goOnline (ticked, conns, online) = (ticked, conns, True)+addConnection (ticked, conns, online) = (ticked, conns + 1, online)+tickConnections (ticked, conns, online) = ((ticked + 1) `mod` conns, conns, online)++useOutput outsM name lat = do+ outs <- readMVar outsM -- blocks+ let outM = Map.lookup name outs -- maybe+ -- if we have a valid output by now, return+ case outM of+ Just o -> do+ putStrLn "Cached Device Output"+ changeState addConnection o -- blocks+ return $ Just o+ Nothing -> do+ -- otherwise open a new output and store the result in the mvar+ devidM <- (>>= maybe (failed name "Failed opening MIDI Output Device ID") return) (getIDForDeviceName name)+ econn <- outputDevice devidM lat -- either+ case econn of+ Left o -> do+ changeState addConnection o+ swapMVar outsM $ Map.insert name o outs+ return $ Just o+ Right _ -> return Nothing++makeConnection :: MVar (MidiDeviceMap) -> String -> Int -> ControllerShape -> IO ((S.ToMessageFunc), Output)+makeConnection devicesM deviceName channel cshape = do+ moutput <- useOutput devicesM deviceName 1+ case moutput of+ Just o -> do+ s <- connected cshape channel deviceName o+ return (s, o)+ Nothing ->+ --failed o+ error "Failed"++showLate :: (CULong, Double, PM.PMEvent, CULong, UTCTime) -> String+showLate (o, t, e, m, n) =+ unwords ["late",+ (show $ (\x -> [PM.status x, PM.data1 x, PM.data2 x]) $ PM.decodeMsg $ PM.message e),+ "midi now ", show m, " midi onset: ", show o,+ "onset (relative): ", show $ showFFloat (Just 3) (t - (realToFrac $ utcTimeToPOSIXSeconds n)) "",+ ", sched: ", show $ PM.timestamp e]+++-- should only send out events if all connections have ticked+flushBackend :: Output -> S.Shape -> Tempo -> Int -> IO ()+flushBackend o shape change ticks = do+ changeState tickConnections o+ cycling <- readState isCycling o++ case cycling of+ True -> do+ late <- sendevents o shape change ticks+ let len = length late+ + case len of+ 0 ->+ return ()+ _ -> do+ putStrLn $ showLate $ head late+ putStrLn $ "and " ++ show (len - 1) ++ " more"+ False -> do+ s <- readState displayState o+ + return ()+ ++midiDevices :: IO (MVar (MidiDeviceMap))+midiDevices = do+ newMVar $ Map.fromList []++midiBackend d n c cs = do+ (s, o) <- makeConnection d n c cs+ return $ Backend s (flushBackend o)++midiStream d n c s = do+ backend <- midiBackend d n c s+ stream backend (toShape s)++midiState d n c s = do+ backend <- midiBackend d n c s+ S.state backend (toShape s)++midiSetters :: MVar (MidiDeviceMap) -> String -> Int -> ControllerShape -> IO Time -> IO (ParamPattern -> IO (), (Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ())+midiSetters d n c s getNow = do+ ds <- midiState d n c s+ return (setter ds, transition getNow ds)+++toDescriptor midiTime now (o,m,t,e) = (o,t,e, midiTime, now)++calcOnsets (a@(tempo, tick, onset, offset), e) = (a, logicalOnset' tempo tick onset offset, e)++showEvent :: PM.PMEvent -> String+showEvent e = show t ++ " " ++ show msg + where msg = PM.decodeMsg $ PM.message e+ t = PM.timestamp e++showRawEvent :: (CULong, MIDITime, Double, PM.PMEvent) -> String+showRawEvent (midionset, (tempo,tick,onset,offset), logicalOnset, e) = show onset ++ " " ++ " / " ++ show logicalOnset ++ " " ++ showEvent e++sendevents :: Output -> S.Shape -> Tempo -> Int -> IO ([(CULong, Double, PM.PMEvent, CULong, UTCTime)])+sendevents stream shape change ticks = do+ let buf = buffer stream+ output = conn stream+ buf' <- tryTakeMVar buf+ case buf' of+ Nothing -> do+ return []+ Just [] -> do+ -- make sure we put back an empty buffer+ putMVar buf []+ return []+ (Just evts@(x:xs)) -> do+ midiTime <- PM.time+ now <- getCurrentTime+ + let offset = S.latency shape+ nextTick = logicalOnset' change (ticks+1) 0 offset+ onsets = map calcOnsets evts+ -- split into events sent now and later (e.g. a noteOff that would otherwise cut off noteOn's in the next tick)+ (evts', later) = span ((< nextTick).(\(_,o,_) -> o)) $ sortBy (comparing (\(_,o,_) -> o)) onsets+ -- calculate MIDI time to schedule events, putting time into fn to create PM.PMEvents+ evts'' = map (\(t, o, e) -> let midionset = scheduleTime midiTime now o+ in (midionset, t, o, e midionset)) evts'+ later' = map (\(t,o,e) -> (t,e)) later+ evts''' = map (\(_,_,_,e) -> e) evts''+ -- filter events that are too late+ late = map (toDescriptor midiTime now) $ filter (\(_,_,t,_) -> t < (realToFrac $ utcTimeToPOSIXSeconds now)) $ evts''++ -- write events for this tick to stream+ err <- PM.writeEvents output evts'''+ -- store later events for nextTick+ putMVar buf later'+ case err of+ PM.NoError -> do+ -- return events for logging in outer scope+ return late+ e -> do+ putStrLn "sending failed"+ return []+++sendctrls :: Output -> ControllerShape -> CLong -> MIDITime -> MidiMap -> IO ()+sendctrls stream shape ch t ctrls = do+ let ctrls' = filter ((>=0) . snd) $ Map.toList $ Map.mapMaybe (id) ctrls+ sequence_ $ map (\(param, ctrl) -> makeCtrl stream ch (fromJust $ paramN shape param) (fromIntegral ctrl) t) ctrls' -- FIXME: we should be sure param has ControlChange+ return ()++sendnote :: Output -> t -> CLong -> (CLong, CLong, Double) -> MIDITime -> IO ()+sendnote stream shape ch (note,vel, dur) (tempo,tick,onset,offset) =+ do+ noteOn stream ch midinote vel (tempo,tick,onset,offset)+ noteOff stream ch midinote (tempo, tick, onset, offset + dur)+ return ()+ where midinote = note + 60++scheduleTime :: CULong -> UTCTime -> Double -> CULong+scheduleTime mnow' now' logicalOnset = t+ where+ now = realToFrac $ utcTimeToPOSIXSeconds $ now'+ mnow = fromIntegral mnow'+ t = floor $ mnow + (1000 * (logicalOnset - now)) -- 1 second are 1000 microseconds as is the unit of timestamps in PortMidi+ ++sendmidi :: Output -> ControllerShape -> CLong -> (CLong, CLong, Double) -> MIDITime -> MidiMap -> IO ()+sendmidi stream shape ch n t ctrls = do+ sendmidi' stream shape ch n t ctrls+ return ()+++sendmidi' stream shape ch (128,vel,dur) t ctrls = do+ sendctrls stream shape ch t ctrls+ return ()+sendmidi' stream shape ch (note,vel,dur) t ctrls = do+ sendnote stream shape ch (note,vel,dur) t+ sendctrls stream shape ch t ctrls+ return ()+++-- MIDI Utils+encodeChannel :: (Bits a, Num a) => a -> a -> a+encodeChannel ch cc = (((-) ch 1) .|. cc)+++-- MIDI Messages+noteOn :: Output -> CLong -> CLong -> CLong -> MIDITime -> IO (Maybe a)+noteOn o ch val vel t = do+ let evt = (t, \t' -> makeEvent 0x90 val ch vel t')+ sendEvent o evt++noteOff :: Output -> CLong -> CLong -> MIDITime -> IO (Maybe a)+noteOff o ch val t = do+ let evt = (t, \t' -> makeEvent 0x80 val ch 60 t')+ sendEvent o evt++makeCtrl :: Output -> CLong -> ControlChange -> CLong -> MIDITime -> IO (Maybe a)+makeCtrl o ch (CC {midi=midi, range=range}) n t = makeCC o ch (fromIntegral midi) n t+makeCtrl o ch (NRPN {midi=midi, range=range}) n t = makeNRPN o ch (fromIntegral midi) n t++-- This is sending CC+makeCC :: Output -> CLong -> CLong -> CLong -> MIDITime -> IO (Maybe a)+makeCC o ch c n t = do+ let evt = (t, \t' -> makeEvent 0xB0 c ch n t')+ sendEvent o evt++-- This is sending NRPN+makeNRPN :: Output -> CLong -> CLong -> CLong -> MIDITime -> IO (Maybe a)+makeNRPN o ch c n t = do+ let nrpn = makeEvent 0xB0+ evts = [(t, (\t' -> nrpn 0x63 ch (shift (c .&. 0x3F80) (-7)) t')),+ (t, (\t' -> nrpn 0x62 ch (c .&. 0x7F) t')),+ (t, (\t' -> nrpn 0x06 ch (shift (n .&. 0x3F80) (-7)) t')),+ (t, (\t' -> nrpn 0x26 ch (n .&. 0x7F) t'))+ ]+ mapM (sendEvent o) evts+ return Nothing+++-- Port Midi Wrapper++outputDevice :: PM.DeviceID -> Int -> IO (Either Output PM.PMError)+outputDevice deviceID latency = do+ PM.initialize+ now <- getCurrentTime+ result <- PM.openOutput deviceID latency+ bs <- newMVar (0, 0, False)+ case result of+ Left dev ->+ do+ info <- PM.getDeviceInfo deviceID+ putStrLn ("Opened: " ++ show (PM.interface info) ++ ": " ++ show (PM.name info))+ buffer <- newMVar []++ return (Left Output { conn=dev, buffer=buffer, bufferstate=bs })+ Right err -> return (Right err)+++makeEvent :: CLong -> CLong -> CLong -> CLong -> CULong -> PM.PMEvent+makeEvent st n ch v t = PM.PMEvent msg (t)+ where msg = PM.encodeMsg $ PM.PMMsg (encodeChannel ch st) (n) (v)++sendEvent :: Output -> (MIDITime, (CULong -> PM.PMEvent)) -> IO (Maybe a)+sendEvent o evt = do+ let buf = buffer o++ cbuf <- takeMVar buf+ putMVar buf (cbuf ++ [evt])+ return Nothing
+ Sound/Tidal/MIDI/Synth.hs view
@@ -0,0 +1,17 @@+module Sound.Tidal.MIDI.Synth where++import Sound.Tidal.Params+import Sound.Tidal.MIDI.Control++synthController :: ControllerShape+synthController = ControllerShape {+ controls = [+ mCC modwheel_p 1,+ mCC pan_p 10,+ mCC expression_p 11,+ mCC sustainpedal_p 64+ ],+ latency = 0.04+ }++synth = toShape synthController
+ Sound/Tidal/MIDI/SynthParams.hs view
@@ -0,0 +1,46 @@+{- |+Module: SynthParams+Description: Parameters to control synth++In general, synth parameters specify patterns of sounds, and patterns of effects on those sounds. These are the synthesis parameters you can use with the default Dirt synth:+-}+module Sound.Tidal.MIDI.SynthParams (+ sound,+ grp,+ accelerate,+ bandf,+ bandq,+ begin,+ channel,+ coarse,+ crush,+ cut,+ cutoff,+ cutoffegint,+ delay,+ delayfeedback,+ delaytime,+ detune,+ dry,+ end,+ gain,+ hcutoff,+ hresonance,+ loop,+ n,+ nudge,+ offset,+ orbit,+ pan,+ resonance,+ room,+ shape,+ size,+ speed,+ s,+ unit,+ velocity,+ vowel + ) where++import Sound.Tidal.Params
+ Sound/Tidal/MIDI/VolcaBass.hs view
@@ -0,0 +1,27 @@+module Sound.Tidal.MIDI.VolcaBass where++import Sound.Tidal.Params+import Sound.Tidal.MIDI.Control++bassController :: ControllerShape+bassController = ControllerShape { controls = [+ mCC slide_p 5,+ mCC expression_p 11,+ mCC octave_p 40,+ mCC lfo_p 41,+ mCC lfoint_p 42,+ mCC pitch1_p 43,+ mCC pitch2_p 44,+ mCC pitch3_p 45,+ mCC attack_p 46,+ mCC decay_p 47,+ mCC cutoff_p 48,+ mCC gate_p 49+ ],+ --duration = ("dur", 0.05),+ --velocity = ("vel", 0.5),+ latency = 0.01+ }+ +bass = toShape bassController+
+ Sound/Tidal/MIDI/VolcaBeats.hs view
@@ -0,0 +1,35 @@+module Sound.Tidal.MIDI.VolcaBeats where++import Sound.Tidal.Params+import Sound.Tidal.MIDI.Control++beatsController :: ControllerShape+beatsController = ControllerShape { controls = [+ mCC lkick_p 40,+ mCC lsnare_p 41,+ mCC llotom_p 42,+ mCC lhitom_p 43,+ mCC lclhat_p 44,+ mCC lophat_p 45,+ mCC lclap_p 46,+ mCC lclaves_p 47,+ mCC lagogo_p 48,+ mCC lcrash_p 49,+ mCC sclap_p 50,+ mCC sclaves_p 51,+ mCC sagogo_p 52,+ mCC scrash_p 53,+ mCC stuttertime_p 54,+ mCC stutterdepth_p 55,+ mCC tomdecay_p 56,+ mCC clhatdecay_p 57,+ mCC ophatdecay_p 58,+ mCC hatgrain_p 59+ ],+ -- duration = ("dur", 0.05),+ -- velocity = ("vel", 0.5),+ latency = 0.01+ }++-- What is this used for?+beats = toShape beatsController
+ Sound/Tidal/MIDI/VolcaKeys.hs view
@@ -0,0 +1,30 @@+module Sound.Tidal.MIDI.VolcaKeys where++import Sound.Tidal.Params+import Sound.Tidal.MIDI.Control++keysController :: ControllerShape+keysController = ControllerShape { controls = [+ mCC portamento_p 5,+ mCC expression_p 11,+ mCC voice_p 40, -- voi+ mCC octave_p 41, -- oct+ mCC detune_p 42, -- det+ mCC vcoegint_p 43, -- vco+ mCC cutoff_p 44, -- ctf+ mCC vcfegint_p 45, -- vcf+ mCC lfo_p 46,+ mCC lfopitchint_p 47, -- lfop+ mCC lfocutoffint_p 48, -- lfoc+ mCC attack_p 49, -- att+ mCC decay_p 50, -- dec+ mCC sustain_p 51, -- sus+ mCC delaytime_p 52, -- delayt+ mCC delayfeedback_p 53 -- delayfb+ ],+ -- duration = ("dur", 0.05),+ -- velocity = ("vel", 0.5),+ latency = 0.01+ }++keys = toShape keysController
− Sound/Tidal/Rytm.hs
@@ -1,203 +0,0 @@-module Sound.Tidal.Rytm where--import Sound.Tidal.Stream (makeI, makeF)--import Sound.Tidal.MIDI.Control--keys :: ControllerShape-keys = ControllerShape { params = [-- mCC "synth1" 16,- mCC "synth2" 17,- mCC "synth3" 18,- mCC "synth4" 19,- mCC "synth5" 20,- mCC "synth6" 21,- mCC "synth7" 22,- mCC "synth8" 23,-- mCC "revpre" 24,- mCC "revtime" 25,- mCC "revfrq" 26,- mCC "revgain" 27,- mCC "revhpf" 28,- mCC "revlpf" 29,- mCC "revvol" 31,-- mCC "samptune" 24,- mCC "sampfinetune" 25,- mCC "sampbitreduction" 26,- mCC "sampslot" 27,- mCC "sampstart" 28,- mCC "sampend" 29,- mCC "samploop" 30,- mCC "samplevel" 31,-- mCC "machtype" 15,-- mCC "filtatk" 70,- mCC "filtdec" 71,- mCC "filtsus" 72,- mCC "filtrel" 73,- mCC "filtfrq" 74,- mCC "filtres" 75,- mCC "filttyp" 76,- mCC "filtenv" 77,-- mCC "perf1" 35,- mCC "perf2" 36,- mCC "perf3" 37,- mCC "perf4" 39,- mCC "perf5" 40,- mCC "perf6" 41,- mCC "perf7" 42,- mCC "perf8" 43,-- mCC "atk" 78,- mCC "hld" 79,- mCC "dec" 80,- mCC "ovr" 81,- mCC "del" 82,- mCC "amprev" 83,- mCC "amppan" 10,- mCC "vol" 7- ],- duration = ("dur", 0.05),- velocity = ("vel", 0.5),- latency = 0.1- }--oscKeys = toOscShape keys---- note on/off-note = makeI oscKeys "note"-dur = makeF oscKeys "dur"---- standard synth params-synth1 = makeF oscKeys "synth1"-synth2 = makeF oscKeys "synth2"-synth3 = makeF oscKeys "synth3"-synth4 = makeF oscKeys "synth4"-synth5 = makeF oscKeys "synth5"-synth6 = makeF oscKeys "synth6"-synth7 = makeF oscKeys "synth7"-synth8 = makeF oscKeys "synth8"---- machine type (e.g. hard snare, classic snare, hard bd, classic bd, etc)-machtype = makeF oscKeys "machtype"---- generic synth level and tuning-lev = makeF oscKeys "synth1"-tun = makeF oscKeys "synth2"---- generic bd decay and sweep type-bddec = makeF oscKeys "synth3"-bdswt = makeF oscKeys "synth5"---- FM bd params-fmbdfmamt = makeF oscKeys "synth4"-fmbdfmswt = makeF oscKeys "synth6"-fmbdfmdec = makeF oscKeys "synth7"-fmbdfmtun = makeF oscKeys "synth8"---- hard bd params-hardbdhold = makeF oscKeys "synth4"-hardbdsnap = makeF oscKeys "synth6"-hardbdwav = makeF oscKeys "synth7"-hardbdtic = makeF oscKeys "synth8"---- classic bd params-clasbdswd = makeF oscKeys "synth6"-clasbdtra = makeF oscKeys "synth7"-clasbdwav = makeF oscKeys "synth8"---- generic sd params (decay, noise decay, noise level)-sddec = makeF oscKeys "synth3"-sdnod = makeF oscKeys "synth6"-sdnol = makeF oscKeys "synth7"---- hard sd params-hardsdswd = makeF oscKeys "synth4"-hardsdtic = makeF oscKeys "synth5"-hardsdswt = makeF oscKeys "synth8"---- classic sd params-classddet = makeF oscKeys "synth4"-classdsnp = makeF oscKeys "synth5"-classdbal = makeF oscKeys "synth8"---- FM sd params-fmsdfmt = makeF oscKeys "synth4"-fmsdfmd = makeF oscKeys "synth5"-fmsdfma = makeF oscKeys "synth8"---- BT-btdec = makeF oscKeys "synth3"---- CP-cpton = makeF oscKeys "synth2"-cpnod = makeF oscKeys "synth3"-cpnum = makeF oscKeys "synth4"-cprat = makeF oscKeys "synth5"-cpnol = makeF oscKeys "synth6"-cprnd = makeF oscKeys "synth7"-cpcpd = makeF oscKeys "synth8"---- filter params-filtatk = makeF oscKeys "filtatk"-filtdec = makeF oscKeys "filtdec"-filtsus = makeF oscKeys "filtsus"-filtrel = makeF oscKeys "filtrel"-filtfrq = makeF oscKeys "filtfrq"-filtres = makeF oscKeys "filtres"-filttyp = makeF oscKeys "filttyp"-filtenv = makeF oscKeys "filtenv"---- amplitude params-atk = makeF oscKeys "atk"-hld = makeF oscKeys "hld"-dec = makeF oscKeys "dec"-ovr = makeF oscKeys "ovr"-del = makeF oscKeys "del"-amprev = makeF oscKeys "amprev"-amppan = makeF oscKeys "amppan"-vol = makeF oscKeys "vol"---- delay params (only used on FX MIDI channel)-deltime = makeF oscKeys "synth1"-delpingpong = makeF oscKeys "synth2"-delwidth = makeF oscKeys "synth3"-delfeedback = makeF oscKeys "synth4"-delhpf = makeF oscKeys "synth5"-dellpf = makeF oscKeys "synth6"-delrev = makeF oscKeys "synth7"-delvol = makeF oscKeys "synth8"---- reverb params (only used on FX MIDI channel)-revpre = makeF oscKeys "revpre"-revtime = makeF oscKeys "revtime"-revfrq = makeF oscKeys "revfrq"-revgain = makeF oscKeys "revgain"-revhpf = makeF oscKeys "revhpf"-revlpf = makeF oscKeys "revlpf"-revvol = makeF oscKeys "revvol"---- performance-perf1 = makeF oscKeys "perf1"-perf2 = makeF oscKeys "perf2"-perf3 = makeF oscKeys "perf3"-perf4 = makeF oscKeys "perf4"-perf5 = makeF oscKeys "perf5"-perf6 = makeF oscKeys "perf6"-perf7 = makeF oscKeys "perf7"-perf8 = makeF oscKeys "perf8"---- sample-samptune = makeF oscKeys "samptune"-sampfinetune = makeF oscKeys "sampfinetune"-sampbitreduction = makeF oscKeys "sampbitreduction"-sampslot = makeF oscKeys "sampslot"-sampstart = makeF oscKeys "sampstart"-sampend = makeF oscKeys "sampend"-samploop = makeF oscKeys "samploop"-samplevel = makeF oscKeys "samplevel"
− Sound/Tidal/SimpleSynth.hs
@@ -1,26 +0,0 @@-module Sound.Tidal.SimpleSynth where--import Sound.Tidal.Stream (makeI, makeF)--import Sound.Tidal.MIDI.Control--keys :: ControllerShape-keys = ControllerShape {params = [- mCC "modwheel" 1,- mCC "balance" 10,- mCC "expression" 11,- mCC "sustainpedal" 64- ],- duration = ("dur", 0.05),- velocity = ("vel", 0.5),- latency = 0.1}--oscKeys = toOscShape keys--note = makeI oscKeys "note"-dur = makeF oscKeys "dur"-vel = makeF oscKeys "vel"-modwheel = makeF oscKeys "modwheel"-balance = makeF oscKeys "balance"-expression = makeF oscKeys "expression"-sustainpedal = makeF oscKeys "sustainpedal"
− Sound/Tidal/Synthino.hs
@@ -1,52 +0,0 @@-module Sound.Tidal.Synthino where--import Sound.Tidal.Stream (makeI, makeF)--import Sound.Tidal.MIDI.Control--keys :: ControllerShape-keys = ControllerShape { params = [- mCC "attack" 73,- mCC "decay" 75,- mCC "sustain" 79,- mCC "release" 72,- mCC "waveform" 70,- mCC "pitchlforate" 76,- mCC "pitchlfodepth" 1,- mCC "lfowaveform" 12,- mCC "filterlforate" 13,- mCC "filterlfodepth" 91,- mCC "peak" 71,- mCC "kcutoff" 74,- mCC "bpm" 16,- mCC "arplength" 17,- mCC "arptranspose" 18,- mCC "vol" 7,- mCC "off" 123- ],- duration = ("dur", 0.05),- velocity = ("vel", 0.5),- latency = 0.1- }--oscKeys = toOscShape keys--note = makeI oscKeys "note"-dur = makeF oscKeys "dur"-attack = makeF oscKeys "attack"-decay = makeF oscKeys "decay"-sustain = makeF oscKeys "sustain"-release = makeF oscKeys "release"-waveform = makeF oscKeys "waveform"-pitchlforate = makeF oscKeys "pitchlforate"-pitchlfodepth = makeF oscKeys "pitchlfodepth"-lfowaveform = makeF oscKeys "lfowaveform"-filterlforate = makeF oscKeys "filterlforate"-filterlfodepth = makeF oscKeys "filterlfodepth"-peak = makeF oscKeys "peak"-kcutoff = makeF oscKeys "kcutoff"-bpm = makeF oscKeys "bpm"-arplength = makeF oscKeys "arplength"-arptranspose = makeF oscKeys "arptranspose"-vol = makeF oscKeys "vol"-off = makeF oscKeys "off"
− Sound/Tidal/Tetra.hs
@@ -1,530 +0,0 @@-module Sound.Tidal.Tetra where--import Sound.Tidal.Stream (makeI, makeF, (|+|), merge, OscPattern)--import Sound.Tidal.MIDI.Control--import Sound.Tidal.Parse-import Sound.Tidal.Pattern--import Control.Applicative--makeSeqTracks = concat $ map makeSeqTrack [0..3]- where makeSeqTrack t = map (makeSeqStep t) [0..15]- makeSeqStep t s = NRPN (makeName t s) (makeCC t s) (0, 127) 0 passThru- makeName t s = "seq" ++ (show $ t + 1) ++ "step" ++ (show $ s + 1)- makeCC t s = (t * 16) + (s + 120)--polysynth :: ControllerShape-polysynth = ControllerShape { params = ([- mrNRPN "osc1freq" 0 (0, 120) 0.2,- mrNRPN "osc1detune" 1 (0, 100) 0.5,- NRPN "osc1shape" 2 (0, 103) 1 passThru,- mNRPN "osc1glide" 3,- NRPN "osc1kbd" 4 (0, 1) 1 passThru,-- mrNRPN "osc2freq" 5 (0, 120) 0.2,- mrNRPN "osc2detune" 6 (0, 100) 0.5,- NRPN "osc2shape" 7 (0, 103) 1 passThru,- mNRPN "osc2glide" 8,- NRPN "osc2kbd" 9 (0, 1) 1 passThru,-- NRPN "oscsync" 10 (0, 1) 0 passThru,- NRPN "glidemode" 11 (0, 3) 0 passThru,- NRPN "oscslop" 12 (0, 5) 0 passThru,- mrNRPN "oscmix" 13 (0, 127) 0.5,-- mNRPN "noise" 14,- mrNRPN "kcutoff" 15 (0, 164) 1,- mNRPN "kresonance" 16,- mNRPN "kamt" 17,- mNRPN "audiomod" 18,- NRPN "fpoles" 19 (0, 1) 1 passThru,-- -- filter envelope- mrNRPN "famt" 20 (0, 254) 0.5,- mNRPN "fvel" 21,- mNRPN "fdel" 22,- mNRPN "fatk" 23,- mNRPN "fdcy" 24,- mNRPN "fsus" 25,- mNRPN "frel" 26,--- mNRPN "vcavol" 27,- mNRPN "outspread" 28,- mrNRPN "vol" 29 (0, 127) 1, -- max volume by default-- mrNRPN "vamt" 30 (0, 127) 1, -- max vca envelope amount- mNRPN "vvel" 31,- mNRPN "vdel" 32,- mNRPN "vatk" 33,- mrNRPN "vdcy" 34 (0, 127) 0.5,- mrNRPN "vsus" 35 (0, 127) 0.5,- mNRPN "vrel" 36,-- NRPN "lfo1rate" 37 (0, 166) 0 passThru, -- unsynced- -- mrNRPN "lfo1step" 37 (151, 166) 0, -- (bpm / 32) - 16 bpm-cycles- NRPN "lfo1shape" 38 (0, 4) 0 passThru,- mNRPN "lfo1amt" 39,- NRPN "lfo1dest" 40 (0, 43) 0 passThru,- NRPN "lfo1sync" 41 (0, 1) 0 passThru,-- NRPN "lfo2rate" 42 (0, 166) 0 passThru, -- unsynced- -- mrNRPN "lfo2step" 42 (151, 166) 0, -- (bpm / 32) - 16 bpm-cycles- NRPN "lfo2shape" 43 (0, 4) 0 passThru,- mNRPN "lfo2amt" 44,- NRPN "lfo2dest" 45 (0, 43) 0 passThru,- NRPN "lfo2sync" 46 (0, 1) 0 passThru,-- NRPN "lfo3rate" 47 (0, 166) 0 passThru, -- unsynced- -- mrNRPN "lfo3step" 47 (151, 166) 0, -- (bpm / 32) - 16 bpm-cycles- NRPN "lfo3shape" 48 (0, 4) 0 passThru,- mNRPN "lfo3amt" 49,- NRPN "lfo3dest" 50 (0, 43) 0 passThru,- NRPN "lfo3sync" 51 (0, 1) 0 passThru,-- NRPN "lfo4rate" 52 (0, 166) 0 passThru, -- unsynced- -- mrNRPN "lfo4step" 52 (151, 166) 0, -- (bpm / 32) - 16 bpm-cycles- NRPN "lfo4shape" 53 (0, 4) 0 passThru,- mNRPN "lfo4amt" 54,- NRPN "lfo4dest" 55 (0, 43) 0 passThru,- NRPN "lfo4sync" 56 (0, 1) 0 passThru,-- NRPN "emod" 57 (0, 43) 0 passThru,- mrNRPN "eamt" 58 (0, 254) 0.5,- mNRPN "evel" 59,- mNRPN "edel" 60,- mNRPN "eatk" 61,- mNRPN "edcy" 62,- mNRPN "esus" 63,- mNRPN "erel" 64,-- NRPN "mod1src" 65 (0, 20) 0 passThru,- mrNRPN "mod1amt" 66 (0, 254) 0.5,- NRPN "mod1dst" 67 (0, 47) 0 passThru,-- NRPN "mod2src" 68 (0, 20) 0 passThru,- mrNRPN "mod2amt" 69 (0, 254) 0.5,- NRPN "mod2dst" 70 (0, 47) 0 passThru,-- NRPN "mod3src" 71 (0, 20) 0 passThru,- mrNRPN "mod3amt" 72 (0, 254) 0.5,- NRPN "mod3dst" 73 (0, 47) 0 passThru,-- NRPN "mod4src" 74 (0, 20) 0 passThru,- mrNRPN "mod4amt" 75 (0, 254) 0.5,- NRPN "mod4dst" 76 (0, 47) 0 passThru,-- NRPN "seq1dst" 77 (0, 47) 0 passThru,- NRPN "seq2dst" 78 (0, 47) 0 passThru,- NRPN "seq3dst" 79 (0, 47) 0 passThru,- NRPN "seq4dst" 80 (0, 47) 0 passThru,-- mrNRPN "mwhl" 81 (0, 254) 0.5,- NRPN "mwhldst" 82 (0, 47) 0 passThru,-- mrNRPN "aftt" 83 (0, 254) 0.5,- NRPN "afttdst" 84 (0, 47) 0 passThru,-- mrNRPN "breath" 85 (0, 254) 0.5,- NRPN "breathdst" 86 (0, 47) 0 passThru,-- mrNRPN "mvel" 87 (0, 254) 0.5,- NRPN "mveldst" 88 (0, 47) 0 passThru,-- mrNRPN "foot" 89 (0, 254) 0.5,- NRPN "footdst" 90 (0, 47) 0 passThru,-- NRPN "kbpm" 91 (30, 250) 0 passThru,- NRPN "clockdiv" 92 (0, 12) 0 passThru, -- TODO: document values-- NRPN "bendrng" 93 (0, 12) 0 passThru,-- NRPN "sqntrig" 94 (0, 4) 0 passThru, -- TODO: document values- NRPN "unisonkey" 95 (0, 5) 0 passThru, -- TODO: document values- NRPN "unisonmode" 96 (0, 4) 0 passThru, -- TODO: document values- NRPN "arpmode" 97 (0, 14) 0 passThru,-- NRPN "erepeat" 98 (0, 1) 0 passThru,- NRPN "unison" 99 (0, 1) 0 passThru,--- NRPN "arp" 100 (0, 1) 0 passThru,- NRPN "sqn" 101 (0, 1) 0 passThru,-- NRPN "mcr1" 105 (0, 183) 0 passThru,- NRPN "mcr2" 106 (0, 183) 0 passThru,- NRPN "mcr3" 107 (0, 183) 0 passThru,- NRPN "mcr4" 108 (0, 183) 0 passThru,-- mNRPN "fbgain" 110,-- mrNRPN "btnfreq" 111 (0, 127) 0.25,- mrNRPN "btnvel" 112 (0, 127) 1,- NRPN "btnmode" 113 (0, 1) 0 passThru,-- mNRPN "sub1vol" 114,- mNRPN "sub2vol" 115,-- mNRPN "fbvol" 116,-- -- left out: editor byte,-- mrNRPN "ksplitpoint" 118 (0, 127) 0.5,- NRPN "kmode" 119 (0, 2) 0 passThru, -- TODO: document values- mCC "notesoff" 123,- mCC "ccreset" 121,- mCC "damp" 64-- ] ++ makeSeqTracks),- duration = ("dur", 0.2),- velocity = ("vel", 0.5),- latency = 0.04- }--oscPolysynth = toOscShape polysynth--note = makeI oscPolysynth "note"--dur = makeF oscPolysynth "dur"-vel = makeF oscPolysynth "vel"-notesoff = makeF oscPolysynth "notesoff"-ccreset = makeF oscPolysynth "ccreset"-damp = makeF oscPolysynth "damp"---osc1freq = makeF oscPolysynth "osc1freq"-osc1detune = makeF oscPolysynth "osc1detune"-osc1shape = makeF oscPolysynth "osc1shape"-osc1glide = makeF oscPolysynth "osc1glide"-osc1kbd = makeF oscPolysynth "osc1kbd"--osc2freq = makeF oscPolysynth "osc2freq"-osc2detune = makeF oscPolysynth "osc2detune"-osc2shape = makeF oscPolysynth "osc2shape"-osc2glide = makeF oscPolysynth "osc2glide"-osc2kbd = makeF oscPolysynth "osc2kbd"--oscsync = makeF oscPolysynth "oscsync"-glidemode = makeF oscPolysynth "glidemode"-oscslop = makeF oscPolysynth "oscslop"-oscmix = makeF oscPolysynth "oscmix"--noise = makeF oscPolysynth "noise"-kcutoff = makeF oscPolysynth "kcutoff"-kresonance = makeF oscPolysynth "kresonance"-kamt = makeF oscPolysynth "kamt"-audiomod = makeF oscPolysynth "audiomod"-fpoles = makeF oscPolysynth "fpoles"-twopole = fpoles (p "0")-fourpole = fpoles (p "1")---- filter envelope-famt = makeF oscPolysynth "famt"-fvel = makeF oscPolysynth "fvel"-fdel = makeF oscPolysynth "fdel"-fatk = makeF oscPolysynth "fatk"-fdcy = makeF oscPolysynth "fdcy"-fsus = makeF oscPolysynth "fsus"-frel = makeF oscPolysynth "frel"---vcavol = makeF oscPolysynth "vcavol"-outspread = makeF oscPolysynth "outspread"-vol = makeF oscPolysynth "vol"--vamt = makeF oscPolysynth "vamt"-vvel = makeF oscPolysynth "vvel"-vdel = makeF oscPolysynth "vdel"-vatk = makeF oscPolysynth "vatk"-vdcy = makeF oscPolysynth "vdcy"-vsus = makeF oscPolysynth "vsus"-vrel = makeF oscPolysynth "vrel"--lfo1rate = makeF oscPolysynth "lfo1rate"--- lfo1step = makeF oscPolysynth "lfo1step"-lfo1shape = makeF oscPolysynth "lfo1shape"-lfo1amt = makeF oscPolysynth "lfo1amt"-lfo1dest = makeF oscPolysynth "lfo1dest"-lfo1sync = makeF oscPolysynth "lfo1sync"--lfo2rate = makeF oscPolysynth "lfo2rate"--- lfo2step = makeF oscPolysynth "lfo2step"-lfo2shape = makeF oscPolysynth "lfo2shape"-lfo2amt = makeF oscPolysynth "lfo2amt"-lfo2dest = makeF oscPolysynth "lfo2dest"-lfo2sync = makeF oscPolysynth "lfo2sync"--lfo3rate = makeF oscPolysynth "lfo3rate"--- lfo3step = makeF oscPolysynth "lfo3step"-lfo3shape = makeF oscPolysynth "lfo3shape"-lfo3amt = makeF oscPolysynth "lfo3amt"-lfo3dest = makeF oscPolysynth "lfo3dest"-lfo3sync = makeF oscPolysynth "lfo3sync"--lfo4rate = makeF oscPolysynth "lfo4rate"--- lfo4step = makeF oscPolysynth "lfo4step"-lfo4shape = makeF oscPolysynth "lfo4shape"-lfo4amt = makeF oscPolysynth "lfo4amt"-lfo4dest = makeF oscPolysynth "lfo4dest"-lfo4sync = makeF oscPolysynth "lfo4sync"--emod = makeF oscPolysynth "emod"-eamt = makeF oscPolysynth "eamt"-evel = makeF oscPolysynth "evel"-edel = makeF oscPolysynth "edel"-eatk = makeF oscPolysynth "eatk"-edcy = makeF oscPolysynth "edcy"-esus = makeF oscPolysynth "esus"-erel = makeF oscPolysynth "erel"--mod1src = makeF oscPolysynth "mod1src"-mod1amt = makeF oscPolysynth "mod1amt"-mod1dst = makeF oscPolysynth "mod1dst"--mod2src = makeF oscPolysynth "mod2src"-mod2amt = makeF oscPolysynth "mod2amt"-mod2dst = makeF oscPolysynth "mod2dst"--mod3src = makeF oscPolysynth "mod3src"-mod3amt = makeF oscPolysynth "mod3amt"-mod3dst = makeF oscPolysynth "mod3dst"--mod4src = makeF oscPolysynth "mod4src"-mod4amt = makeF oscPolysynth "mod4amt"-mod4dst = makeF oscPolysynth "mod4dst"--seq1dst = makeF oscPolysynth "seq1dst"-seq2dst = makeF oscPolysynth "seq2dst"-seq3dst = makeF oscPolysynth "seq3dst"-seq4dst = makeF oscPolysynth "seq4dst"---mwhl = makeF oscPolysynth "mwhl"-mwhldst = makeF oscPolysynth "mwhldst"--aftt = makeF oscPolysynth "aftt"-afttdst = makeF oscPolysynth "afttdst"--breath = makeF oscPolysynth "breath"-breathdst = makeF oscPolysynth "breathdst"--mvel = makeF oscPolysynth "mvel"-mveldst = makeF oscPolysynth "mveldst"--foot = makeF oscPolysynth "foot"-footdst = makeF oscPolysynth "footdst"--bendrng = makeF oscPolysynth "bendrng"---- left out: modwheel, breath, footctrl, pressure, velocity--kbpm = makeF oscPolysynth "kbpm"-clockdiv = makeF oscPolysynth "clockdiv"---- left out: pitchbend range--sqntrig = makeF oscPolysynth "sqntrig"-unisonkey = makeF oscPolysynth "unisonkey"-unisonmode = makeF oscPolysynth "unisonmode"-arpmode = makeF oscPolysynth "arpmode"--erepeat = makeF oscPolysynth "erepeat"-unison = makeF oscPolysynth "unison"---arp = makeF oscPolysynth "arp"-sqn = makeF oscPolysynth "sqn"--mcr1 = makeF oscPolysynth "mcr1"-mcr2 = makeF oscPolysynth "mcr2"-mcr3 = makeF oscPolysynth "mcr3"-mcr4 = makeF oscPolysynth "mcr4"--fbgain = makeF oscPolysynth "fbgain"--btnfreq = makeF oscPolysynth "btnfreq"-btnvel = makeF oscPolysynth "btnvel"-btnmode = makeF oscPolysynth "btnmode"--sub1vol = makeF oscPolysynth "sub1vol"-sub2vol = makeF oscPolysynth "sub2vol"--fbvol = makeF oscPolysynth "fbvol"--ksplitpoint = makeF oscPolysynth "ksplitpoint"-kmode = makeF oscPolysynth "kmode"-knormal = kmode (p "0")-kstack = kmode (p "0.5")-ksplit = kmode (p "1")---- sequences--seqtrack1 = map (makeF oscPolysynth . (\x -> "seq1step" ++ show x)) [1..16]-seqtrack2 = map (makeF oscPolysynth . (\x -> "seq2step" ++ show x)) [1..16]-seqtrack3 = map (makeF oscPolysynth . (\x -> "seq3step" ++ show x)) [1..16]-seqtrack4 = map (makeF oscPolysynth . (\x -> "seq4step" ++ show x)) [1..16]---seqpatterns p' = map onlyValues events- where arc' = arc p'- events = arc' (0,1)- onlyValues = \(_, _, a) -> p a--sqnp i t p' = foldr (|+|) i (zipWith ($) t patterns)- where patterns = seqpatterns p'--sqnp1 d p' = sqnp (seq1dst $ p $ show d) seqtrack1 p'-sqnp2 d p' = sqnp (seq2dst $ p $ show d) seqtrack2 p'-sqnp3 d p' = sqnp (seq3dst $ p $ show d) seqtrack3 p'-sqnp4 d p' = sqnp (seq4dst $ p $ show d) seqtrack4 p'----- abstractions---- adsr--atk p' = vatk p' |+| fatk p' |+| eatk p'-dcy p' = vdcy p' |+| fdcy p' |+| edcy p'-sus p' = vsus p' |+| fsus p' |+| esus p'-rel p' = vrel p' |+| frel p' |+| erel p'--adsr a d s r = atk a |+| dcy d |+| sus s |+| rel r-asr a d r = atk a |+| dcy d |+| rel r---- lfo--lfotri = doublePattern 0-lforsaw = doublePattern 1-lfosaw = doublePattern 2-lfopulse = doublePattern 3-lforand = doublePattern 4--lrate r = ((min 150) . (max 0)) <$> p r-lstep s = ((min 166) . (max 151) . (+150)) <$> p s--lfo1 s d r a = lfo1shape s |+| lfo1dest d |+| lfo1rate r |+| lfo1amt a-lfo2 s d r a = lfo2shape s |+| lfo2dest d |+| lfo2rate r |+| lfo2amt a-lfo3 s d r a = lfo3shape s |+| lfo3dest d |+| lfo3rate r |+| lfo3amt a-lfo4 s d r a = lfo4shape s |+| lfo4dest d |+| lfo4rate r |+| lfo4amt a----lfo = lfo1---- mod--mod1 s d a = mod1src s |+| mod1dst d |+| mod1amt a-mod2 s d a = mod2src s |+| mod2dst d |+| mod2amt a-mod3 s d a = mod3src s |+| mod3dst d |+| mod3amt a-mod4 s d a = mod4src s |+| mod4dst d |+| mod4amt a---- mod destination--doublePattern d = (p $ show d) :: Pattern Double--dosc1 = doublePattern 1-dosc2 = doublePattern 2-dosc = doublePattern 3-dmix = doublePattern 4-dnoise = doublePattern 5-dpw1 = doublePattern 6-dpw2 = doublePattern 7-dpw = doublePattern 8-dcut = doublePattern 9-dres = doublePattern 10-damod = doublePattern 11-dvca = doublePattern 12-dspread = doublePattern 13--dlfo1f = doublePattern 14-dlfo2f = doublePattern 15-dlfo3f = doublePattern 16-dlfo4f = doublePattern 17-dlfof = doublePattern 18--dlfo1a = doublePattern 19-dlfo2a = doublePattern 20-dlfo3a = doublePattern 21-dlfo4a = doublePattern 22-dlfoa = doublePattern 23--dfamt = doublePattern 24-dvamt = doublePattern 25-deamt = doublePattern 26-damt = doublePattern 27--dfatk = doublePattern 28-dvatk = doublePattern 29-deatk = doublePattern 30-datk = doublePattern 31--dfdcy = doublePattern 32-dvdcy = doublePattern 33-dedcy = doublePattern 34-ddcy = doublePattern 35--dfrel = doublePattern 36-dvrel = doublePattern 37-derel = doublePattern 38-drel = doublePattern 39--dmod1 = doublePattern 40-dmod2 = doublePattern 41-dmod3 = doublePattern 42-dmod4 = doublePattern 43--dfb = doublePattern 44-dsub1 = doublePattern 45-dsub2 = doublePattern 46-dfbgain = doublePattern 47-dslew = doublePattern 48---- mod sources--sseq1 = doublePattern 1-sseq2 = doublePattern 2-sseq3 = doublePattern 3-sseq4 = doublePattern 4--slfo1 = doublePattern 5-slfo2 = doublePattern 6-slfo3 = doublePattern 7-slfo4 = doublePattern 8--sfenv = doublePattern 9-svenv = doublePattern 10-seenv = doublePattern 11--spitchb = doublePattern 12-smodwh = doublePattern 13-saftert = doublePattern 14-sbreath = doublePattern 15-sfoot = doublePattern 16-sexpr = doublePattern 17--svel = doublePattern 18-snote = doublePattern 19-snoise = doublePattern 20--- drums---snare d p' = note p'- |+| osc1shape zero |+| osc1kbd zero- |+| osc2shape zero |+| osc2kbd zero- |+| noise one- |+| vrel d |+| vsus zero |+| vdcy d- |+| kcutoff (p "1")- |+| dur (p "0.01")- where zero = p "0"- one = p "1"---kick blp p' = note p'- |+| fourpole- |+| osc1shape zero |+| osc1kbd zero- |+| osc2shape zero |+| osc2kbd zero- |+| vsus zero |+| vdcy (p "0.95") |+| vrel (p "0.5")- |+| kresonance (p "0.99") |+| kcutoff zero- |+| eamt (p "0.8") |+| emod (p "9") |+| edcy blp- |+| dur (p "0.2")- where zero = p "0"
− Sound/Tidal/VolcaBass.hs
@@ -1,42 +0,0 @@-module Sound.Tidal.VolcaBass where--import Sound.Tidal.Stream (makeI, makeF)--import Sound.Tidal.MIDI.Control--bass :: ControllerShape-bass = ControllerShape { params = [- mCC "slide" 5,- mCC "expression" 11,- mCC "octave" 40,- mCC "lforate" 41,- mCC "lfoint" 42,- mCC "pitch1" 43,- mCC "pitch2" 44,- mCC "pitch3" 45,- mCC "attack" 46,- mCC "decay" 47,- mCC "cutoffegint" 48,- mCC "gate" 49- ],- duration = ("dur", 0.05),- velocity = ("vel", 0.5),- latency = 0.1- }--oscBass = toOscShape bass--note = makeI oscBass "note"-dur = makeF oscBass "dur"-slide = makeF oscBass "slide"-expression = makeF oscBass "expression"-octave = makeF oscBass "octave"-lforate = makeF oscBass "lforate"-lfoint = makeF oscBass "lfoint"-pitch1 = makeF oscBass "pitch1"-pitch2 = makeF oscBass "pitch2"-pitch3 = makeF oscBass "pitch3"-attack = makeF oscBass "attack"-decay = makeF oscBass "decay"-cutoffegint = makeF oscBass "cutoffegint"-gate = makeF oscBass "gate"
− Sound/Tidal/VolcaBeats.hs
@@ -1,72 +0,0 @@-module Sound.Tidal.VolcaBeats where--import Sound.Tidal.Stream (makeI, makeF)--import Sound.Tidal.MIDI.Control-import Control.Applicative--beats :: ControllerShape-beats = ControllerShape { params = [- mCC "lKick" 40,- mCC "lSnare" 41,- mCC "lLoTom" 42,- mCC "lHiTom" 43,- mCC "lClHat" 44,- mCC "lOpHat" 45,- mCC "lClap" 46,- mCC "lClaves" 47,- mCC "lAgogo" 48,- mCC "lCrash" 49,- mCC "sClap" 50,- mCC "sClaves" 51,- mCC "sAgogo" 52,- mCC "sCrash" 53,- mCC "stutterTime" 54,- mCC "stutterDepth" 55,- mCC "tomDecay" 56,- mCC "clHatDecay" 57,- mCC "opHatDecay" 58,- mCC "hatGrain" 59- ],- duration = ("dur", 0.05),- velocity = ("vel", 0.5),- latency = 0.1- }--oscBeats = toOscShape beats--drum = (makeI oscBeats "note") . (noteN <$>)--lbd = makeF oscBeats "lKick"-lsn = makeF oscBeats "lSnare"-llt = makeF oscBeats "lLoTom"-lht = makeF oscBeats "lHiTom"-lch = makeF oscBeats "lClHat"-loh = makeF oscBeats "lOpHat"-lcp = makeF oscBeats "lClap"-lcl = makeF oscBeats "lClaves"-lag = makeF oscBeats "lAgogo"-lcr = makeF oscBeats "lCrash"-scp = makeF oscBeats "sClap"-scl = makeF oscBeats "sClaves"-sag = makeF oscBeats "sAgogo"-scr = makeF oscBeats "sCrash"-stt = makeF oscBeats "stutterTime"-std = makeF oscBeats "stutterDepth"-dt = makeF oscBeats "tomDecay"-dch = makeF oscBeats "clHatDecay"-doh = makeF oscBeats "opHatDecay"-hg = makeF oscBeats "hatGrain"--noteN :: String -> Int-noteN "bd" = 36-noteN "sn" = 38-noteN "lt" = 43-noteN "ht" = 50-noteN "ch" = 42-noteN "oh" = 46-noteN "cp" = 39-noteN "cl" = 75-noteN "ag" = 67-noteN "cr" = 49-noteN _ = 0
− Sound/Tidal/VolcaKeys.hs
@@ -1,50 +0,0 @@-module Sound.Tidal.VolcaKeys where--import Sound.Tidal.Stream (makeI, makeF)--import Sound.Tidal.MIDI.Control--keys :: ControllerShape-keys = ControllerShape { params = [- mCC "portamento" 5,- mCC "expression" 11,- mCC "voice" 40,- mCC "octave" 41,- mCC "detune" 42,- mCC "vcoegint" 43,- mCC "kcutoff" 44,- mCC "vcfegint" 45,- mCC "lforate" 46,- mCC "lfopitchint" 47,- mCC "lfocutoffint" 48,- mCC "attack" 49,- mCC "decay" 50,- mCC "sustain" 51,- mCC "dtime" 52,- mCC "dfeedback" 53- ],- duration = ("dur", 0.05),- velocity = ("vel", 0.5),- latency = 0.1- }--oscKeys = toOscShape keys--note = makeI oscKeys "note"-dur = makeF oscKeys "dur"-por = makeF oscKeys "portamento"-expr = makeF oscKeys "expression"-oct = makeF oscKeys "octave"-voi = makeF oscKeys "voice"-det = makeF oscKeys "detune"-vco = makeF oscKeys "vcoegint"-ctf = makeF oscKeys "kcutoff"-vcf = makeF oscKeys "vcfegint"-lfo = makeF oscKeys "lforate"-lfop = makeF oscKeys "lfopitchint"-lfoc = makeF oscKeys "lfocutoffint"-att = makeF oscKeys "attack"-dec = makeF oscKeys "decay"-sus = makeF oscKeys "sustain"-dt = makeF oscKeys "dtime"-df = makeF oscKeys "dfeedback"
tidal-midi.cabal view
@@ -1,5 +1,5 @@ name: tidal-midi-version: 0.6+version: 0.8 synopsis: MIDI support for tidal -- description: homepage: http://tidal.lurk.org/@@ -16,17 +16,14 @@ Description: MIDI support for Tidal. Supports Volca Keys, Bass and Beats and other synths. Interface is likely to change significantly. library- Exposed-modules: Sound.Tidal.MIDI.Output- Sound.Tidal.MIDI.Device+ Exposed-modules: Sound.Tidal.MIDI.Context+ Sound.Tidal.MIDI.VolcaBeats+ Sound.Tidal.MIDI.VolcaBass+ Sound.Tidal.MIDI.VolcaKeys Sound.Tidal.MIDI.Control- Sound.Tidal.SimpleSynth- Sound.Tidal.VolcaKeys- Sound.Tidal.VolcaBass- Sound.Tidal.VolcaBeats- Sound.Tidal.Blofeld- Sound.Tidal.Tetra- Sound.Tidal.Rytm- Sound.Tidal.Synthino- Sound.Tidal.MBase01-- Build-depends: base < 5, tidal <= 0.6, PortMidi == 0.1.5.2, process, hashable, containers, hosc, time, bytestring+ Sound.Tidal.MIDI.Device+ Sound.Tidal.MIDI.Stream+ Sound.Tidal.MIDI.Synth+ Sound.Tidal.MIDI.SynthParams+ + Build-depends: base < 5, tidal == 0.8, PortMidi == 0.1.6.0, time, containers, transformers