Skip to content

Commit

Permalink
fix for squeezejoin (ref tidalcycles/strudel#216), moving some suppor…
Browse files Browse the repository at this point in the history
…ting functions up to the pattern module
  • Loading branch information
yaxu committed Sep 23, 2022
1 parent b4de72e commit 82d29af
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 65 deletions.
57 changes: 0 additions & 57 deletions src/Sound/Tidal/Core.hs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ import Sound.Tidal.Pattern

-- ** Elemental patterns

-- | An empty pattern
silence :: Pattern a
silence = empty

-- | Takes a function from time to values, and turns it into a 'Pattern'.
sig :: (Time -> a) -> Pattern a
sig f = Pattern q
Expand Down Expand Up @@ -347,31 +343,6 @@ stack = foldr overlay silence
(~>) :: Pattern Time -> Pattern a -> Pattern a
(~>) = tParam rotR

-- | Speed up a pattern by the given time pattern
fast :: Pattern Time -> Pattern a -> Pattern a
fast = tParam _fast

-- | Slow down a pattern by the factors in the given time pattern, 'squeezing'
-- the pattern to fit the slot given in the time pattern
fastSqueeze :: Pattern Time -> Pattern a -> Pattern a
fastSqueeze = tParamSqueeze _fast

-- | An alias for @fast@
density :: Pattern Time -> Pattern a -> Pattern a
density = fast

_fast :: Time -> Pattern a -> Pattern a
_fast rate pat | rate == 0 = silence
| rate < 0 = rev $ _fast (negate rate) pat
| otherwise = withResultTime (/ rate) $ withQueryTime (* rate) pat

-- | Slow down a pattern by the given time pattern
slow :: Pattern Time -> Pattern a -> Pattern a
slow = tParam _slow
_slow :: Time -> Pattern a -> Pattern a
_slow 0 _ = silence
_slow r p = _fast (1/r) p

-- | Slow down a pattern by the factors in the given time pattern, 'squeezing'
-- the pattern to fit the slot given in the time pattern
slowSqueeze :: Pattern Time -> Pattern a -> Pattern a
Expand All @@ -381,34 +352,6 @@ slowSqueeze = tParamSqueeze _slow
sparsity :: Pattern Time -> Pattern a -> Pattern a
sparsity = slow

-- | @rev p@ returns @p@ with the event positions in each cycle
-- reversed (or mirrored).
rev :: Pattern a -> Pattern a
rev p =
splitQueries $ p {
query = \st -> map makeWholeAbsolute $
mapParts (mirrorArc (midCycle $ arc st)) $
map makeWholeRelative
(query p st
{arc = mirrorArc (midCycle $ arc st) (arc st)
})
}
where makeWholeRelative :: Event a -> Event a
makeWholeRelative e@Event {whole = Nothing} = e
makeWholeRelative (Event c (Just (Arc s e)) p'@(Arc s' e') v) =
Event c (Just $ Arc (s'-s) (e-e')) p' v
makeWholeAbsolute :: Event a -> Event a
makeWholeAbsolute e@Event {whole = Nothing} = e
makeWholeAbsolute (Event c (Just (Arc s e)) p'@(Arc s' e') v) =
Event c (Just $ Arc (s'-e) (e'+s)) p' v
midCycle :: Arc -> Time
midCycle (Arc s _) = sam s + 0.5
mapParts :: (Arc -> Arc) -> [Event a] -> [Event a]
mapParts f es = (\(Event c w p' v) -> Event c w (f p') v) <$> es
-- | Returns the `mirror image' of a 'Arc' around the given point in time
mirrorArc :: Time -> Arc -> Arc
mirrorArc mid' (Arc s e) = Arc (mid' - (e-mid')) (mid'+(mid'-s))

{- | Plays a portion of a pattern, specified by a time arc (start and end time).
The new resulting pattern is played over the time period of the original pattern:
Expand Down
63 changes: 61 additions & 2 deletions src/Sound/Tidal/Pattern.hs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ squeezeJoin :: Pattern (Pattern a) -> Pattern a
squeezeJoin pp = pp {query = q}
where q st = concatMap
(\e@(Event c w p v) ->
mapMaybe (munge c w p) $ query (compressArc (cycleArc $ wholeOrPart e) v) st {arc = p}
mapMaybe (munge c w p) $ query (focusArc (wholeOrPart e) v) st {arc = p}
)
(query pp st)
munge oContext oWhole oPart (Event iContext iWhole iPart v) =
Expand Down Expand Up @@ -342,11 +342,14 @@ instance Floating ValueMap
atanh _ = noOv "atanh"

------------------------------------------------------------------------
-- * Internal functions
-- * Internal/fundamental functions

empty :: Pattern a
empty = Pattern {query = const []}

silence :: Pattern a
silence = empty

queryArc :: Pattern a -> Arc -> [Event a]
queryArc p a = query p $ State a Map.empty

Expand Down Expand Up @@ -427,6 +430,35 @@ compressArc (Arc s e) p | s > e = empty
compressArcTo :: Arc -> Pattern a -> Pattern a
compressArcTo (Arc s e) = compressArc (Arc (cyclePos s) (e - sam s))

focusArc :: Arc -> Pattern a -> Pattern a
focusArc (Arc s e) p = s `rotR` (_fast (1/(e-s)) p)


-- | Speed up a pattern by the given time pattern
fast :: Pattern Time -> Pattern a -> Pattern a
fast = tParam _fast

-- | Slow down a pattern by the factors in the given time pattern, 'squeezing'
-- the pattern to fit the slot given in the time pattern
fastSqueeze :: Pattern Time -> Pattern a -> Pattern a
fastSqueeze = tParamSqueeze _fast

-- | An alias for @fast@
density :: Pattern Time -> Pattern a -> Pattern a
density = fast

_fast :: Time -> Pattern a -> Pattern a
_fast rate pat | rate == 0 = silence
| rate < 0 = rev $ _fast (negate rate) pat
| otherwise = withResultTime (/ rate) $ withQueryTime (* rate) pat

-- | Slow down a pattern by the given time pattern
slow :: Pattern Time -> Pattern a -> Pattern a
slow = tParam _slow
_slow :: Time -> Pattern a -> Pattern a
_slow 0 _ = silence
_slow r p = _fast (1/r) p

_fastGap :: Time -> Pattern a -> Pattern a
_fastGap 0 _ = empty
_fastGap r p = splitQueries $
Expand All @@ -448,6 +480,33 @@ rotL t p = withResultTime (subtract t) $ withQueryTime (+ t) p
rotR :: Time -> Pattern a -> Pattern a
rotR t = rotL (negate t)

-- | @rev p@ returns @p@ with the event positions in each cycle
-- reversed (or mirrored).
rev :: Pattern a -> Pattern a
rev p =
splitQueries $ p {
query = \st -> map makeWholeAbsolute $
mapParts (mirrorArc (midCycle $ arc st)) $
map makeWholeRelative
(query p st
{arc = mirrorArc (midCycle $ arc st) (arc st)
})
}
where makeWholeRelative :: Event a -> Event a
makeWholeRelative e@Event {whole = Nothing} = e
makeWholeRelative (Event c (Just (Arc s e)) p'@(Arc s' e') v) =
Event c (Just $ Arc (s'-s) (e-e')) p' v
makeWholeAbsolute :: Event a -> Event a
makeWholeAbsolute e@Event {whole = Nothing} = e
makeWholeAbsolute (Event c (Just (Arc s e)) p'@(Arc s' e') v) =
Event c (Just $ Arc (s'-e) (e'+s)) p' v
midCycle :: Arc -> Time
midCycle (Arc s _) = sam s + 0.5
mapParts :: (Arc -> Arc) -> [Event a] -> [Event a]
mapParts f es = (\(Event c w p' v) -> Event c w (f p') v) <$> es
-- | Returns the `mirror image' of a 'Arc' around the given point in time
mirrorArc :: Time -> Arc -> Arc
mirrorArc mid' (Arc s e) = Arc (mid' - (e-mid')) (mid'+(mid'-s))

-- | Mark values in the first pattern which match with at least one
-- value in the second pattern.
Expand Down
4 changes: 2 additions & 2 deletions src/Sound/Tidal/Simple.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@
module Sound.Tidal.Simple where

import Sound.Tidal.Control (chop, hurry)
import Sound.Tidal.Core ((#), (|*), (<~), silence, rev)
import Sound.Tidal.Core ((#), (|*), (<~))
import Sound.Tidal.Params (crush, gain, pan, speed, s)
import Sound.Tidal.ParseBP (parseBP_E)
import Sound.Tidal.Pattern (ControlPattern)
import Sound.Tidal.Pattern (ControlPattern, silence, rev)
import GHC.Exts ( IsString(..) )

instance {-# OVERLAPPING #-} IsString ControlPattern where
Expand Down
2 changes: 1 addition & 1 deletion src/Sound/Tidal/Stream.hs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import qualified Sound.OSC.FD as O
import qualified Network.Socket as N

import Sound.Tidal.Config
import Sound.Tidal.Core (stack, silence, (#))
import Sound.Tidal.Core (stack, (#))
import Sound.Tidal.ID
import qualified Sound.Tidal.Link as Link
import Sound.Tidal.Params (pS)
Expand Down
5 changes: 2 additions & 3 deletions src/Sound/Tidal/Tempo.hs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import System.IO (hPutStrLn, stderr)
import Data.Int(Int64)

import Sound.Tidal.StreamTypes
import Sound.Tidal.Core (silence)

{-
Tempo.hs - Tidal's scheduler
Expand Down Expand Up @@ -284,10 +283,10 @@ clocked config stateMV mapMV actionsMV ac abletonLink
let
appendPat flag = if flag then (pat:) else id
updatePS (Just playState) = playState {history = (appendPat historyFlag) (history playState)}
updatePS Nothing = PlayState {pattern = silence,
updatePS Nothing = PlayState {pattern = P.silence,
mute = False,
solo = False,
history = (appendPat historyFlag) (silence:[])
history = (appendPat historyFlag) (P.silence:[])
}
transition' pat' = do now <- Link.clock abletonLink
ss <- Link.createAndCaptureAppSessionState abletonLink
Expand Down

0 comments on commit 82d29af

Please sign in to comment.