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

pattern weights for chooseby functions #1173

Merged
merged 6 commits into from
Feb 22, 2025
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
14 changes: 7 additions & 7 deletions tidal-core/src/Sound/Tidal/UI.hs
Original file line number Diff line number Diff line change
Expand Up @@ -291,19 +291,19 @@ chooseBy f xs = (xs !!!) . floor <$> range 0 (fromIntegral $ length xs) f
-- play as the "e" note, and half as likely to play as the "g" note.
--
-- > wchoose = 'wchooseBy' 'rand'
wchoose :: [(a, Double)] -> Pattern a
wchoose :: [(a, Pattern Double)] -> Pattern a
wchoose = wchooseBy rand

-- | Given a pattern of probabilities and a list of @(value, weight)@ pairs,
-- @wchooseBy@ creates a @'Pattern' value@ by choosing values based on those
-- probabilities and weighted appropriately by the weights in the list of pairs.
wchooseBy :: Pattern Double -> [(a, Double)] -> Pattern a
wchooseBy pat pairs = match <$> pat
wchooseBy :: Pattern Double -> [(a, Pattern Double)] -> Pattern a
wchooseBy pat pairs = match <$> pat <* cweightpat <* totalpat
where
match r = values !! head (findIndices (> (r * total)) cweights)
cweights = scanl1 (+) (map snd pairs)
match r cweights total = values !! head (findIndices (> (r * total)) cweights)
cweightpat = sequence $ scanl1 (+) (map snd pairs)
values = map fst pairs
total = sum $ map snd pairs
totalpat = sum $ map snd pairs

-- | @randcat ps@: does a @slowcat@ on the list of patterns @ps@ but
-- randomises the order in which they are played.
Expand All @@ -319,7 +319,7 @@ randcat ps = spread' rotL (_segment 1 $ (% 1) . fromIntegral <$> (_irand (length
-- > d1 $ sound
-- > $ wrandcat
-- > [ ("bd*2 sn", 5), ("jvbass*3", 2), ("drum*2", 2), ("ht mt", 1) ]
wrandcat :: [(Pattern a, Double)] -> Pattern a
wrandcat :: [(Pattern a, Pattern Double)] -> Pattern a
wrandcat ps = unwrap $ wchooseBy (segment 1 rand) ps

-- | @degrade@ randomly removes events from a pattern 50% of the time:
Expand Down
2 changes: 1 addition & 1 deletion tidal-core/tidal-core.cabal
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cabal-version: 2.0

name: tidal-core
version: 1.9.6
version: 1.10

license: GPL-3
copyright: (c) Alex McLean and other contributors, 2025
Expand Down
2 changes: 1 addition & 1 deletion tidal-listener/tidal-listener.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ library
deepseq,
optparse-applicative,
tidal >= 1.10 && < 1.11,
tidal-core,
tidal-core >= 1.10 && < 1.11,
hosc >= 0.21 && < 0.22,
hint,
network
Expand Down
34 changes: 19 additions & 15 deletions tidal-parse/src/Sound/Tidal/Parse.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

module Sound.Tidal.Parse (parseTidal) where

import Control.Applicative
import Control.Monad.Except
import Data.Bifunctor
import Data.Char
import Control.Applicative (Alternative (empty, (<|>)))
import Control.Monad.Except (MonadError (throwError))
import Data.Bifunctor (Bifunctor (bimap))
import Data.Char (isSpace)
import Data.List (dropWhileEnd)
import qualified Data.Text
import Language.Haskellish as Haskellish
Expand All @@ -18,17 +18,21 @@ import Sound.Tidal.Control as T
import Sound.Tidal.Core as T
import Sound.Tidal.Params as T
import Sound.Tidal.Parse.TH
( fromHaskell,
fromTidal,
fromTidalList,
)
import Sound.Tidal.ParseBP (Enumerable, Parseable, parseBP)
import Sound.Tidal.Pattern as T
import Sound.Tidal.Scales as T
import Sound.Tidal.Simple as T
import Sound.Tidal.Scales as T (scale)
import Sound.Tidal.Simple as T (silent)
import Sound.Tidal.UI as T

type H = Haskellish ()

-- This is depended upon by Estuary, and changes to its type will cause problems downstream for Estuary.
parseTidal :: String -> Either String ControlPattern
parseTidal x = if x' == [] then (return silence) else r
parseTidal x = if null x' then return silence else r
where
x' = dropWhileEnd isSpace $ dropWhile isSpace $ Haskellish.removeComments x
r = bimap showSyntaxError fst $ Haskellish.parseAndRun parser () x
Expand Down Expand Up @@ -164,12 +168,12 @@ genericPatternExpressions =
(parser :: H (Pattern a -> Pattern a)) <*!> parser
<|> (parser :: H ([a] -> Pattern a)) <*!> parser
<|> (parser :: H ([Pattern a] -> Pattern a)) <*!> parser
<|> (parser :: H ([(Pattern a, Double)] -> Pattern a)) <*!> parser
<|> (parser :: H ([(Pattern a, Pattern Double)] -> Pattern a)) <*!> parser
<|> (parser :: H ([Pattern a -> Pattern a] -> Pattern a)) <*!> parser
<|> (parser :: H ([(Time, Pattern a)] -> Pattern a)) <*!> parser
<|> pInt_p <*!> parser
<|> list_p <*!> parser
<|> tupleADouble_p <*!> parser
<|> tupleApDouble_p <*!> parser
<|> listTupleStringTransformation_p <*!> parser
<|> parseSilence

Expand Down Expand Up @@ -423,7 +427,7 @@ instance Parse ([Pattern a] -> Pattern a) where
<|> (parser :: H (Pattern Int -> [Pattern a] -> Pattern a)) <*!> parser
<|> a_patternB

instance Parse ([(Pattern a, Double)] -> Pattern a) where
instance Parse ([(Pattern a, Pattern Double)] -> Pattern a) where
parser =
$(fromTidal "wrandcat")
<|> a_patternB
Expand Down Expand Up @@ -551,10 +555,10 @@ list_p :: (Parse a) => H ([a] -> Pattern a)
list_p = pDouble_list_p <*!> parser

-- note: mising a_patternB pathway
tupleADouble_p :: (Parse a) => H ([(a, Double)] -> Pattern a)
tupleADouble_p =
tupleApDouble_p :: (Parse a) => H ([(a, Pattern Double)] -> Pattern a)
tupleApDouble_p =
$(fromTidal "wchoose")
<|> pDouble_tupleADouble_p <*!> parser
<|> pDouble_tupleApDouble_p <*!> parser

instance Parse ([(Time, Pattern a)] -> Pattern a) where
parser = $(fromTidal "timeCat") <|> $(fromTidal "timecat")
Expand Down Expand Up @@ -903,8 +907,8 @@ pAB_pA_pB = pTime_pAB_pA_pB <*!> parser
pDouble_list_p :: (Parse a) => H (Pattern Double -> [a] -> Pattern a)
pDouble_list_p = $(fromTidal "chooseBy")

pDouble_tupleADouble_p :: (Parse a) => H (Pattern Double -> [(a, Double)] -> Pattern a)
pDouble_tupleADouble_p = $(fromTidal "wchooseBy")
pDouble_tupleApDouble_p :: (Parse a) => H (Pattern Double -> [(a, Pattern Double)] -> Pattern a)
pDouble_tupleApDouble_p = $(fromTidal "wchooseBy")

instance Parse (String -> String -> Pattern String) where
parser = $(fromTidal "sseq")
Expand Down
2 changes: 1 addition & 1 deletion tidal-parse/tidal-parse.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ library

Build-depends:
base >=4.8 && <5
, tidal-core
, tidal-core == 1.10
, transformers >= 0.5 && < 0.7
, template-haskell
, haskellish >= 0.3.2 && < 0.4
Expand Down
2 changes: 1 addition & 1 deletion tidal.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ library
, exceptions < 0.11
, mtl >= 2.2 && < 2.4
, tidal-link >= 1.1 && < 1.2
, tidal-core == 1.9.6
, tidal-core == 1.10

test-suite tests
type: exitcode-stdio-1.0
Expand Down
Loading