Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix for squeezejoin #950

Merged
merged 3 commits into from
Sep 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions bench/Memory/Tidal/UIB.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ module Tidal.UIB where

import Weigh
import Tidal.Inputs
import Sound.Tidal.UI
import Sound.Tidal.Core
import Sound.Tidal.Context

fixB :: Weigh ()
fixB =
Expand Down
3 changes: 1 addition & 2 deletions bench/Speed/Tidal/UIB.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ module Tidal.UIB where

import Criterion.Main
import Tidal.Inputs
import Sound.Tidal.Core
import Sound.Tidal.UI
import Sound.Tidal.Context

fixB :: [Benchmark]
fixB =
Expand Down
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 = (cyclePos 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
3 changes: 3 additions & 0 deletions test/Sound/Tidal/PatternTest.hs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ run =
(Event (Context []) (Just $ Arc (2 % 3) (5 % 6)) (Arc (2 % 3) (5 % 6)) "d"),
(Event (Context []) (Just $ Arc (5 % 6) (1 % 1)) (Arc (5 % 6) (1 % 1)) "e")
]
it "preserves cycle number of inner patterns" $ do
(map value $ queryArc (squeezeJoin (pure $ struct "1" $ (sig $ id))) (Arc 3 4))
`shouldBe` [3.5]

describe ">>=" $ do
it "can apply functions to patterns" $ do
Expand Down