tidal 1.9.2 → 1.9.3
raw patch · 22 files changed
+437/−354 lines, 22 filesdep ~hoscdep ~primitivePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: hosc, primitive
API changes (from Hackage documentation)
- Sound.Tidal.Control: reset :: Show a => a -> Pattern b -> Pattern b
- Sound.Tidal.Core: _fast :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Core: _slow :: Time -> Pattern a -> Pattern a
- Sound.Tidal.Core: density :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Core: fast :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Core: fastSqueeze :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Core: rev :: Pattern a -> Pattern a
- Sound.Tidal.Core: silence :: Pattern a
- Sound.Tidal.Core: slow :: Pattern Time -> Pattern a -> Pattern a
- Sound.Tidal.Params: acceleraterecv :: Pattern Int -> ControlPattern
- Sound.Tidal.Params: beginrecv :: Pattern Int -> ControlPattern
- Sound.Tidal.Tempo: ResetCycles :: TempoAction
- Sound.Tidal.Tempo: [nowEnd] :: State -> Micros
- Sound.Tidal.Tempo: instance GHC.Show.Show Sound.OSC.Transport.FD.UDP.UDP
- Sound.Tidal.Tempo: resetCycles :: MVar [TempoAction] -> IO ()
+ Sound.Tidal.Chords: minorMajor7 :: Num a => [a]
+ Sound.Tidal.Control: mt :: Int -> Pattern a -> Pattern a
+ Sound.Tidal.Control: mtrigger :: Int -> Pattern a -> Pattern a
+ Sound.Tidal.Pattern: _fast :: Time -> Pattern a -> Pattern a
+ Sound.Tidal.Pattern: _slow :: Time -> Pattern a -> Pattern a
+ Sound.Tidal.Pattern: density :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.Pattern: fast :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.Pattern: fastSqueeze :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.Pattern: focusArc :: Arc -> Pattern a -> Pattern a
+ Sound.Tidal.Pattern: rev :: Pattern a -> Pattern a
+ Sound.Tidal.Pattern: silence :: Pattern a
+ Sound.Tidal.Pattern: slow :: Pattern Time -> Pattern a -> Pattern a
+ Sound.Tidal.Pattern: withQueryControls :: (ValueMap -> ValueMap) -> Pattern a -> Pattern a
+ Sound.Tidal.Tempo: SetCycle :: Time -> TempoAction
+ Sound.Tidal.Tempo: instance GHC.Show.Show Sound.Osc.Transport.Fd.Udp.Udp
+ Sound.Tidal.Tempo: setCycle :: Time -> MVar [TempoAction] -> IO ()
+ Sound.Tidal.UI: ghostWith :: Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
- Sound.Tidal.Control: ctrigger :: Show a => a -> Pattern b -> Pattern b
+ Sound.Tidal.Control: ctrigger :: Pattern a -> Pattern a
- Sound.Tidal.Control: ftrigger :: Show a => a -> Pattern b -> Pattern b
+ Sound.Tidal.Control: ftrigger :: Pattern a -> Pattern a
- Sound.Tidal.Control: qt :: Show a => a -> Pattern b -> Pattern b
+ Sound.Tidal.Control: qt :: Pattern a -> Pattern a
- Sound.Tidal.Control: qtrigger :: Show a => a -> Pattern b -> Pattern b
+ Sound.Tidal.Control: qtrigger :: Pattern a -> Pattern a
- Sound.Tidal.Control: rtrigger :: Show a => a -> Pattern b -> Pattern b
+ Sound.Tidal.Control: rtrigger :: Pattern a -> Pattern a
- Sound.Tidal.Control: trigger :: Show a => a -> Pattern b -> Pattern b
+ Sound.Tidal.Control: trigger :: Pattern a -> Pattern a
- Sound.Tidal.Control: triggerWith :: Show a => (Time -> Time) -> a -> Pattern b -> Pattern b
+ Sound.Tidal.Control: triggerWith :: (Time -> Time) -> Pattern a -> Pattern a
- Sound.Tidal.Tempo: ActionHandler :: (TickState -> LinkOperations -> ValueMap -> IO ValueMap) -> (LinkOperations -> ValueMap -> ControlPattern -> IO ValueMap) -> (ID -> ControlPattern -> IO ()) -> ActionHandler
+ Sound.Tidal.Tempo: ActionHandler :: (TickState -> LinkOperations -> ValueMap -> IO ValueMap) -> (LinkOperations -> ValueMap -> ControlPattern -> IO ValueMap) -> (ID -> Time -> ControlPattern -> IO ()) -> ActionHandler
- Sound.Tidal.Tempo: State :: Int64 -> Micros -> Micros -> Arc -> Double -> State
+ Sound.Tidal.Tempo: State :: Int64 -> Micros -> Arc -> Double -> State
- Sound.Tidal.Tempo: [updatePattern] :: ActionHandler -> ID -> ControlPattern -> IO ()
+ Sound.Tidal.Tempo: [updatePattern] :: ActionHandler -> ID -> Time -> ControlPattern -> IO ()
Files
- BootTidal.hs +1/−0
- CHANGELOG.md +135/−165
- bench/Memory/Tidal/UIB.hs +1/−2
- bench/Speed/Tidal/UIB.hs +1/−2
- src/Sound/Tidal/Chords.hs +5/−0
- src/Sound/Tidal/Control.hs +54/−23
- src/Sound/Tidal/Core.hs +0/−57
- src/Sound/Tidal/Params.hs +39/−18
- src/Sound/Tidal/ParseBP.hs +5/−5
- src/Sound/Tidal/Pattern.hs +94/−3
- src/Sound/Tidal/Safe/Boot.hs +2/−1
- src/Sound/Tidal/Safe/Context.hs +2/−0
- src/Sound/Tidal/Simple.hs +2/−2
- src/Sound/Tidal/Stream.hs +31/−24
- src/Sound/Tidal/Tempo.hs +25/−26
- src/Sound/Tidal/Time.hs +24/−17
- src/Sound/Tidal/UI.hs +7/−3
- src/Sound/Tidal/Version.hs +1/−1
- test/Sound/Tidal/PatternTest.hs +3/−0
- test/Sound/Tidal/StreamTest.hs +1/−1
- tidal.cabal +3/−3
- tidal.el +1/−1
BootTidal.hs view
@@ -27,6 +27,7 @@ nudgeAll = streamNudgeAll tidal all = streamAll tidal resetCycles = streamResetCycles tidal+ setCycle = streamSetCycle tidal setcps = asap . cps getcps = streamGetcps tidal getnow = streamGetnow tidal
CHANGELOG.md view
@@ -1,19 +1,17 @@ # TidalCycles log of changes -## 1.9.2-+## 1.9.2 - Siteswap c Same with 1.9.1, but now with new tidal-link version 1.0.1 -## 1.9.1-+## 1.9.1 - Siteswap b A quick release to set specific tidal-link version 1.0 in tidal.cabal. Stack seems to want this. -## 1.9.0+## 1.9.0 - Siteswap -## What's Changed+### What's Changed -### General enhancements+#### General enhancements * Rename linux binary name by @ndr-brt in https://github.com/tidalcycles/Tidal/pull/911 * Fix echo by @ndr-brt in https://github.com/tidalcycles/Tidal/pull/910 * If first argument of euclid is negative, apply euclidInv by @polymorphicengine in https://github.com/tidalcycles/Tidal/pull/916@@ -21,39 +19,37 @@ * Make chunk reverse direction with negative number by @ndr-brt in https://github.com/tidalcycles/Tidal/pull/918 * overhaul of the chord parser by @polymorphicengine in https://github.com/tidalcycles/Tidal/pull/931 -### New ableton link support+#### New ableton link support * Use ableton link for scheduling by @Zalastax in https://github.com/tidalcycles/Tidal/pull/898 * tidal-link: add link source files to extra-source-files, fixes #924 by @yaxu in https://github.com/tidalcycles/Tidal/pull/925 * Use target latency in all send modes by @Zalastax in https://github.com/tidalcycles/Tidal/pull/927 * Rename cCyclesPerBeat -> cBeatsPerCycle by @Zalastax in https://github.com/tidalcycles/Tidal/pull/939 -### Emacs plugin updates+#### Emacs plugin updates * formatting fixes in tidal.el by @zzkt in https://github.com/tidalcycles/Tidal/pull/932 * a window-excursion for tidal.el by @zzkt in https://github.com/tidalcycles/Tidal/pull/933 * autoloads for tidal.el by @zzkt in https://github.com/tidalcycles/Tidal/pull/934 * avoid race in loading bootscript during restart by @zzkt in https://github.com/tidalcycles/Tidal/pull/937 -### Tidal-parse (estuary) updates+#### Tidal-parse (estuary) updates * Various updates to tidal-parse by @dktr0 in https://github.com/tidalcycles/Tidal/pull/913 and https://github.com/tidalcycles/Tidal/pull/941 -### Maintenance+#### Maintenance * Increase upper bounds of text dependency by @yaxu in https://github.com/tidalcycles/Tidal/pull/948 * Use system-cxx-std-lib by @Zalastax in https://github.com/tidalcycles/Tidal/pull/944 * Use c++ extra library for MacOS by @giuseppelillo in https://github.com/tidalcycles/Tidal/pull/946 -## New Contributors+### New Contributors * @Zalastax made their first contribution in https://github.com/tidalcycles/Tidal/pull/898 * @zzkt made their first contribution in https://github.com/tidalcycles/Tidal/pull/932 * @giuseppelillo made their first contribution in https://github.com/tidalcycles/Tidal/pull/946 **Full Changelog**: https://github.com/tidalcycles/Tidal/compare/v1.8.0...v1.9.0 -## 1.8.1-+## 1.8.1 - Sanquhar b * Removed executable from tidal.cabal file (while latest ghc on windows fails to build it) ## 1.8.0 - Sanquhar- * move tidal-listener code by @polymorphicengine in #885 * Fix a typo incurred (I assume) by a filename change. by @JeffreyBenjaminBrown in #886 * Hide contexts from Events per default by @polymorphicengine in #887@@ -68,7 +64,6 @@ Commit list: https://github.com/tidalcycles/Tidal/compare/1.7.10...v1.8.0 ## 1.7.10 - Tama b- * Derive RealFrac for Note by @ndr-brt in https://github.com/tidalcycles/Tidal/pull/876 * Add timescale and timewin control params by @yaxu in https://github.com/tidalcycles/Tidal/pull/878 * deriving typeclass memberships for ID by @polymorphicengine in https://github.com/tidalcycles/Tidal/pull/879@@ -112,152 +107,149 @@ **Full Changelog**: https://github.com/tidalcycles/Tidal/compare/1.7.8...1.7.9 ## 1.7.8 - Ayatakedai- * Add pattern id to patterns as _id_, and send it with /code/highlights+* Add pattern id to patterns as _id_, and send it with /code/highlights ## 1.7.7 - Caramel wafer- * Support hosc 0.19 in test suite @yaxu+* Support hosc 0.19 in test suite @yaxu ## 1.7.6 - Tunnocks- * Fix dot shorthand in int patterns so floating point numbers raise an error @ndr-brt- * Support factors in ratio shorthand for rational patterns @ndr-brt- * support hosc 0.19 @yaxu+* Fix dot shorthand in int patterns so floating point numbers raise an error @ndr-brt+* Support factors in ratio shorthand for rational patterns @ndr-brt+* support hosc 0.19 @yaxu ## 1.7.5 - Dalbeattie- * Minor change to _splice so that it respects if the speed parameter was already declared @onthepeakofnormal- * Some tests for chords @cleary- * Remove direct semigroups dependency @yaxu- * Derive functor for pattern @yaxu- * Handle negative ratio shorthands for rationals @ndr_brt- * drawLine - draw non-events with periods @yaxu- * Parse chord without root note @yaxu- * Fix clock sharing between tidal processes @yaxu+* Minor change to _splice so that it respects if the speed parameter was already declared @onthepeakofnormal+* Some tests for chords @cleary+* Remove direct semigroups dependency @yaxu+* Derive functor for pattern @yaxu+* Handle negative ratio shorthands for rationals @ndr_brt+* drawLine - draw non-events with periods @yaxu+* Parse chord without root note @yaxu+* Fix clock sharing between tidal processes @yaxu ## 1.7.4 - Symonds Yat b- * Fixes for bipolar waveforms (sine2, etc) @mindofmatthew- * More playback controls for OSC API @mindofmatthew- * Disable bus variants for MIDI controls @mindofmatthew+* Fixes for bipolar waveforms (sine2, etc) @mindofmatthew+* More playback controls for OSC API @mindofmatthew+* Disable bus variants for MIDI controls @mindofmatthew ## 1.7.3 - Symonds Yat- * Signed ratio shorthands now supported @ndr_brt- * OSC API - mute/unmute stream @mindofmatthew- * improve performance of playFor/seqP @yaxu- * Expand tests with autodiscovered laws @RSWilli- * Add `getState` to BootTidal @mindofmatthew- * add fadeTime / fadeInTime / fadeOutTime params for grain envelopes @yaxu- * Fix for nrpnn and nrpnv params @yaxu- * Disable busses for MIDI parameters @mindofmatthew+* Signed ratio shorthands now supported @ndr_brt+* OSC API - mute/unmute stream @mindofmatthew+* improve performance of playFor/seqP @yaxu+* Expand tests with autodiscovered laws @RSWilli+* Add `getState` to BootTidal @mindofmatthew+* add fadeTime / fadeInTime / fadeOutTime params for grain envelopes @yaxu+* Fix for nrpnn and nrpnv params @yaxu+* Disable busses for MIDI parameters @mindofmatthew ## 1.7.2 - IKLECTIK c- * tidal-parse additions and improved errors, haskellish dependency fix @dktr0- * spring cleaning and delinting, recreated Time.hs, renamed ControlMap toValueMAp @yaxu- * start of [major refactoring of chords](https://club.tidalcycles.org/t/rfc-working-on-making-chord-naming-chordlist-more-consistent/2717/56) @cleary- * fix `.` mininotation operator @zudov- * stateful event parameters, for counting @yaxu- * Move some stuff from BootTidal.hs to the tidal library, to reduce dependencies there @yaxu+* tidal-parse additions and improved errors, haskellish dependency fix @dktr0+* spring cleaning and delinting, recreated Time.hs, renamed ControlMap toValueMAp @yaxu+* start of [major refactoring of chords](https://club.tidalcycles.org/t/rfc-working-on-making-chord-naming-chordlist-more-consistent/2717/56) @cleary+* fix `.` mininotation operator @zudov+* stateful event parameters, for counting @yaxu+* Move some stuff from BootTidal.hs to the tidal library, to reduce dependencies there @yaxu ## 1.7.1 - IKLECTIK b- * Fix stack build @yaxu- * Add tidal_status command @yaxu- * Add cVerbose config setting (default on) @yaxu- * Fix for emacs plugin @jwaldmann- * Snowball bugfix @yaxu- * Migrate to github actions, tested against additional ghc versions @ndr_brt- * Fix mininotation bug - allow leading/trailing spaces @ndr_brt- * Make linger work with negative numbers (to linger on end of cycle rather than start) @yaxu- * Friendlier startup messages @yaxu- * Compatibility with ghc 9.0.1 @yaxu+* Fix stack build @yaxu+* Add tidal_status command @yaxu+* Add cVerbose config setting (default on) @yaxu+* Fix for emacs plugin @jwaldmann+* Snowball bugfix @yaxu+* Migrate to github actions, tested against additional ghc versions @ndr_brt+* Fix mininotation bug - allow leading/trailing spaces @ndr_brt+* Make linger work with negative numbers (to linger on end of cycle rather than start) @yaxu+* Friendlier startup messages @yaxu+* Compatibility with ghc 9.0.1 @yaxu ## 1.7 - IKLECTIK- * Added drum aliases from GM2 percussion spec to `drum` function @lvm- * `getcps` helper function now in BootTidal.hs @yaxu- * `getnow` helper function back in BootTidal.hs (returns current cycle) @bgold-cosmos- * Developments towards tidal api, @yaxu et al- * `coarse` parameter is now floating point @lwlsn- * `irand` parameter now patternable @ndr-brt- * `note` now produces its own type to avoid conflicts between parsing note names and duration shorthands @ndr-brt- * Numerous tidal-parse improvements and additions @dktr0 et al- * `grain` function for combining begin and end (in terms of begin and duration) @khoparzi- * Added missing pB and pR functions @thgrund- * Emacs plugin bugfixes @jwaldmann- * `binaryN` parameters now fully patternable @ndr-brt- * `press` and `pressBy` functions for syncopation @yaxu- * `bite`'s first parameter is now patternable @ndr-brt- * Most SuperDirt control/effect parameters can now be modified while a sound is playing, using 'bus' functions. @telefon + @yaxu- * Sound.Tidal.Params is now generated by a script in bin/generate-params.hs @yaxu- * `qtrigger` is now an alias for `ctrigger`, which now quantises to the _next_ cycle (via ceiling) @thgund / @yaxu- * There is now also `ftrigger` and `rtrigger` for floor (previous) and round (nearest) cycle- * `whenmod`'s first two parameters are now rationals, and patternable. @th-four / @yaxu- * `brand` and `brandBy` for continuous patterns of boolean values @yaxu- * Two-way protocol between Tidal and SuperDirt, initially to receive available busses @telefon / @yaxu- * bipolar waveforms - sine2, square2, tri2, saw2, cosine2 @yaxu+* Added drum aliases from GM2 percussion spec to `drum` function @lvm+* `getcps` helper function now in BootTidal.hs @yaxu+* `getnow` helper function back in BootTidal.hs (returns current cycle) @bgold-cosmos+* Developments towards tidal api, @yaxu et al+* `coarse` parameter is now floating point @lwlsn+* `irand` parameter now patternable @ndr-brt+* `note` now produces its own type to avoid conflicts between parsing note names and duration shorthands @ndr-brt+* Numerous tidal-parse improvements and additions @dktr0 et al+* `grain` function for combining begin and end (in terms of begin and duration) @khoparzi+* Added missing pB and pR functions @thgrund+* Emacs plugin bugfixes @jwaldmann+* `binaryN` parameters now fully patternable @ndr-brt+* `press` and `pressBy` functions for syncopation @yaxu+* `bite`'s first parameter is now patternable @ndr-brt+* Most SuperDirt control/effect parameters can now be modified while a sound is playing, using 'bus' functions. @telefon + @yaxu+* Sound.Tidal.Params is now generated by a script in bin/generate-params.hs @yaxu+* `qtrigger` is now an alias for `ctrigger`, which now quantises to the _next_ cycle (via ceiling) @thgund / @yaxu+* There is now also `ftrigger` and `rtrigger` for floor (previous) and round (nearest) cycle+* `whenmod`'s first two parameters are now rationals, and patternable. @th-four / @yaxu+* `brand` and `brandBy` for continuous patterns of boolean values @yaxu+* Two-way protocol between Tidal and SuperDirt, initially to receive available busses @telefon / @yaxu+* bipolar waveforms - sine2, square2, tri2, saw2, cosine2 @yaxu ## 1.6.1 - We are not DJs- * Patternise first parameter of chunk @lwlsn- * Patternise fit parameter @bgold-cosmos- * Increase upper bounds of random @yaxu- * Switch travis to ubuntu bionic @yaxu+* Patternise first parameter of chunk @lwlsn+* Patternise fit parameter @bgold-cosmos+* Increase upper bounds of random @yaxu+* Switch travis to ubuntu bionic @yaxu ## 1.6.0 - Keep live coding live- * Rollback to previous pattern on parse error @jwaldmann- * Increased strictness to catch parse errors earlier @jwaldmann @yaxu- * Support for superdirt 'panic' @yaxu- * Increase hosc upper bounds to admin 0.18- * New function 'splat' @yaxu- * `quantise` now uses round, add qfloor, qceiling variants and qround alis @lwlsn- * Add ghc 8.8.3 to travis @jwaldmann- * Switch `substruct` to use binary pattern @yaxu+* Rollback to previous pattern on parse error @jwaldmann+* Increased strictness to catch parse errors earlier @jwaldmann @yaxu+* Support for superdirt 'panic' @yaxu+* Increase hosc upper bounds to admin 0.18+* New function 'splat' @yaxu+* `quantise` now uses round, add qfloor, qceiling variants and qround alis @lwlsn+* Add ghc 8.8.3 to travis @jwaldmann+* Switch `substruct` to use binary pattern @yaxu ## 1.5.2 - Rivelin- * Fix streamAll+* Fix streamAll ## 1.5.1 - Blacka Moor- * Bugfix splice+* Bugfix splice ## 1.5.0 - Active travel- * Export drawLineSz @mxmxyz- * tidal-parse additions (bite, splice, pickF, select, squeeze; fixed slice) @dktr0- * New, more efficient pseudorandom number generator @dktr0- * Pattern first someCyclesBy param @bgold-cosmos- * Refactored, more flexible OSC targetting @yaxu- * Simplify tidal-boot-script in tidal.el @jamagin- * Support state substitution in mininotation #530 @yaxu- * Pattern first parameter of splice #656 @yaxu- * Pattern first parameter of chew @yaxu- * add 'x' fraction alias for 1/6 @yaxu- * add dfb alias for delayfeedback param, dt for delaytime @yaxu- * add unmuteAll and only to BootTidal.hs @yaxu+* Export drawLineSz @mxmxyz+* tidal-parse additions (bite, splice, pickF, select, squeeze; fixed slice) @dktr0+* New, more efficient pseudorandom number generator @dktr0+* Pattern first someCyclesBy param @bgold-cosmos+* Refactored, more flexible OSC targetting @yaxu+* Simplify tidal-boot-script in tidal.el @jamagin+* Support state substitution in mininotation #530 @yaxu+* Pattern first parameter of splice #656 @yaxu+* Pattern first parameter of chew @yaxu+* add 'x' fraction alias for 1/6 @yaxu+* add dfb alias for delayfeedback param, dt for delaytime @yaxu+* add unmuteAll and only to BootTidal.hs @yaxu ## 1.4.9 - Housebound spirit- * Simplify 'show'ing of patterns @yaxu- * New `draw` function for drawing a pattern of single characters as a text-based diagram,- with friends `drawLine` and `drawLineSz` for drawing multiple cycles @yaxu- * Fixes and expansions of ratio aliases - s should be a sixteenth @mxmxyz, w is now 1, f is now 0.2- * Simplify definition of `accumulate` using scanl @benjwadams- * The first parameter of `someCyclesBy` is now patternable @bgold-cosmos+* Simplify 'show'ing of patterns @yaxu+* New `draw` function for drawing a pattern of single characters as a text-based diagram, with friends `drawLine` and `drawLineSz` for drawing multiple cycles @yaxu+* Fixes and expansions of ratio aliases - s should be a sixteenth @mxmxyz, w is now 1, f is now 0.2+* Simplify definition of `accumulate` using scanl @benjwadams+* The first parameter of `someCyclesBy` is now patternable @bgold-cosmos ## 1.4.8 - Limerick- * Add ratio shorthand to floating point patterns @yaxu- * Support fractional scales, add Arabic scales @quakehead- * Additions to tidal-parse including support from overgain, overshape adn rot @dktr0- * Move prompt-cont setting to end of BootTidal.hs (older versions of Haskell crash out at this point) @ndr-brt-## 1.4.7 - Bleep+* Add ratio shorthand to floating point patterns @yaxu+* Support fractional scales, add Arabic scales @quakehead+* Additions to tidal-parse including support from overgain, overshape adn rot @dktr0+* Move prompt-cont setting to end of BootTidal.hs (older versions of Haskell crash out at this point) @ndr-brt - * Fix BootTidal.hs - make loadable in atom @bgold-cosmos- * More additions to tidal-parse @dktr0+## 1.4.7 - Bleep+* Fix BootTidal.hs - make loadable in atom @bgold-cosmos+* More additions to tidal-parse @dktr0 ## 1.4.6 - Megatron-- * Experimental ratio shorthand ref #573 @yaxu- * Store mininotation source location(s) in events ref #245 @yaxu- * Add more things to tidal-parse @dktr0 @yaxu- * Separate out haskell parser from tidal-parse into new hackage module called 'haskellish' @dktr0- * Support patterning polyrhythmic % steps in mininotation @yaxu- * Fixes to emacs plugin (tidal.el) @xmacex- * New parameters for freq, overgain, overshape, and missing midi params including the new nrpn ones @yaxu+* Experimental ratio shorthand ref #573 @yaxu+* Store mininotation source location(s) in events ref #245 @yaxu+* Add more things to tidal-parse @dktr0 @yaxu+* Separate out haskell parser from tidal-parse into new hackage module called 'haskellish' @dktr0+* Support patterning polyrhythmic % steps in mininotation @yaxu+* Fixes to emacs plugin (tidal.el) @xmacex+* New parameters for freq, overgain, overshape, and missing midi params including the new nrpn ones @yaxu ## 1.4.5 - Porter Brook- * Mini notation - `@` (and its alias `_`) now accepts rational relative durations. E.g. `a b@0.5 c d` to make `b` have a half step (that would be the same as `a@2 b c@2 c@d`). This can also be patterned `a b@<0.5 2> c d` @yaxu #435 * Experimental `reset` function - stick in a pattern so it acts as though the cycle number was reset to 0, from the next cycle @yaxu * Bugfix for setR in BootTidal.hs @yaxu@@ -270,7 +262,6 @@ * Many tidal-parse updates @dktr0 ## 1.4.4 - Chee Dale- * wrandcat (weighted randcat) @yaxu * MIDI Sysex support #558 @yaxu * Elements in an Open Sound Control path address can now be patterned #557@@ -280,39 +271,31 @@ * Add power pattern operators |**, **| and |**| @yaxu ## 1.4.3 - Stanage Edge- * Fix for xfade / xfadein transition * New function plyWith ## 1.4.2 - Higger Tor- * Fix for 'nudge' ## 1.4.1 - Carl Wark- * improvements to handling of cps changes @yaxu #501 * fix for parameter patterning in 'range' @yaxu #547 ## 1.4.0 - Padley Gorge- * fix representation to handle continuous and analog events properly @yaxu ## 1.3.0 - rolled back to 1.1.2 ## 1.2.0 - Hunters Bar- * Simplify <* and *>, removing any distinction between analogue and digital patterns ## 1.1.2 - Eccy Road- * Usability fix for `binary` / `binaryN` (use squeezeJoin on input pattern) ## 1.1.1 - Chelsea Park- * Usability fixes for `binary` / `binaryN` / `ascii` @yaxu ## 1.1.0 - Brincliffe Edge- * `binary` and `ascii` functions for playing with bit patterns @yaxu * support chord inversions in chord parser @bgold-cosmos * skip ticks when system clock jumps @yaxu@@ -331,7 +314,6 @@ * minitidal refactor, support for parsing more of tidal, tests @dktr0 ## 1.0.14 - IICON- * 'chew' - like bite, but speeds playback rate up and down * variable probability for ? in mini notation * chooseBy takes modulo of index to avoid out of bounds errors@@ -339,32 +321,29 @@ * Fix dependencies for parsec/colour ## 1.0.13 - 🐝⌛️🦋 #2- * Simplify espgrid support - @yaxu ## 1.0.12 - 🐝⌛️🦋- * Fix ESPGrid support - @dktr0 * Add 'snowball' function - @XiNNiW ## 1.0.11 - Cros Bríde- 2019-04-17 Alex McLean <alex@slab.org>- * Add `bite` function for slicing patterns (rather than samples)- * Tweak tidal.el to attempt to infer location of default BootTidal.hs- * Skip time (forward or backward) if the reference clock jumps suddenly- * Fix `fit` - @bgold-cosmos- * Remove 'asap'- * Add cB for boolean control input- * `pickF` for choosing between functions with a pattern of integers- * `select` for choosing between list of patterns with a floating point pattern- * `squeeze` for choosing between list of patterns with a pattern of integers, where patterns are squeezed into the integer event duration- * `splice` for choosing between slices of a pattern, where the slices are squeezed into event duration- * Ord and Eq instances for value type @bgold-cosmos- * `trigger` - support for resetting envelopes on evaluation- * Support for rational event values- * Tweak how `*>` and `<*` deal with analog patterns- * Caribiner link bridge support+* Add `bite` function for slicing patterns (rather than samples)+* Tweak tidal.el to attempt to infer location of default BootTidal.hs+* Skip time (forward or backward) if the reference clock jumps suddenly+* Fix `fit` - @bgold-cosmos+* Remove 'asap'+* Add cB for boolean control input+* `pickF` for choosing between functions with a pattern of integers+* `select` for choosing between list of patterns with a floating point pattern+* `squeeze` for choosing between list of patterns with a pattern of integers, where patterns are squeezed into the integer event duration+* `splice` for choosing between slices of a pattern, where the slices are squeezed into event duration+* Ord and Eq instances for value type @bgold-cosmos+* `trigger` - support for resetting envelopes on evaluation+* Support for rational event values+* Tweak how `*>` and `<*` deal with analog patterns+* Caribiner link bridge support ## 1.0.10 - This machine also kills fascists * Add exports to Sound.Tidal.Scales for `getScale` and `scaleTable`@@ -378,10 +357,8 @@ * `djf` control ready for new superdirt dj filter @yaxu * `getScale` for handrolling/adding scales to `scale` function * Add `djf` control for upcoming superdirt dj filter @yaxu -## 1.0.8 (trying to get back to doing these, -## see also https://tidalcycles.org/index.php/Changes_in_Tidal_1.0.x -## for earlier stuff)-+## 1.0.8 (trying to get back to doing these)+**See also https://tidalcycles.org/index.php/Changes_in_Tidal_1.0.x for earlier stuff)** * Add 'to', 'toArg' and 'from' controls for new superdirt routing experiments - @telephon * Fixes for squeezeJoin (nee unwrap') - @bgold-cosmos * Simplify `cycleChoose`, it is now properly discrete (one event per cycle) - @yaxu@@ -398,7 +375,6 @@ * fix for `sometimesBy` - @yaxu ## 0.9.10 (and earlier missing versions from this log)- * arpg, a function to arpeggiate * within', an alternate within with a different approach to time, following discussion here https://github.com/tidalcycles/Tidal/issues/313 * sine et al are now generalised so can be used as double or rational patterns@@ -415,7 +391,6 @@ ## 0.9.7 ### Enhancements- * The `note` pattern parameter is no longer an alias for `midinote`, but an independent parameter for supercollider to handle (in a manner similar to `up`)@@ -423,14 +398,12 @@ ## 0.9.6 ### Enhancements- * Added `chord` for chord patterns and `scaleP` for scale patterns * The `n` pattern parameter is now floating point ## 0.9.5 ### Enhancements- * Added `hurry` which both speeds up the sound and the pattern by the given amount. * Added `stripe` which repeats a pattern a given number of times per cycle, with random but contiguous durations.@@ -444,14 +417,12 @@ ## 0.9.4 ### Fixes- * Swapped `-` for `..` in ranges as quick fix for issue with parsing negative numbers * Removed overloaded list thingie for now, unsure whether it's worth the dependency ## 0.9.3 ### Enhancements- * The sequence parser can now expand ranges, e.g. `"0-3 4-2"` is equivalent to `"[0 1 2 3] [4 3 2]"` * Sequences can now be described using list syntax, for example `sound ["bd", "sn"]` is equivalent to `sound "bd sn"`. They *aren't* lists though, so you can't for example do `sound (["bd", "sn"] ++ ["arpy", "cp"])` -- but can do `sound (append ["bd", "sn"] ["arpy", "cp"])`@@ -462,6 +433,5 @@ * The start of automatic testing for a holy bug-free future ### Fixes- * Fixed bug that was causing events to double up or get lost, e.g. where `rev` was combined with certain other functions.
bench/Memory/Tidal/UIB.hs view
@@ -2,8 +2,7 @@ import Weigh import Tidal.Inputs -import Sound.Tidal.UI-import Sound.Tidal.Core+import Sound.Tidal.Context fixB :: Weigh () fixB =
bench/Speed/Tidal/UIB.hs view
@@ -4,8 +4,7 @@ import Criterion.Main import Tidal.Inputs-import Sound.Tidal.Core-import Sound.Tidal.UI +import Sound.Tidal.Context fixB :: [Benchmark] fixB =
src/Sound/Tidal/Chords.hs view
@@ -95,6 +95,8 @@ minor11 = [0,3,7,10,14,17] minor13 :: Num a => [a] minor13 = [0,3,7,10,14,17,21]+minorMajor7 :: Num a => [a]+minorMajor7 = [0,3,7,11] -- other chords one :: Num a => [a] one = [0]@@ -233,6 +235,9 @@ ("minor13", minor13), ("min13", minor13), ("m13", minor13),+ ("minorMajor7", minorMajor7),+ ("minMaj7", minorMajor7),+ ("mmaj7", minorMajor7), ("one", one), ("1", one), ("five", five),
src/Sound/Tidal/Control.hs view
@@ -29,6 +29,7 @@ import Sound.Tidal.Pattern import Sound.Tidal.Core+import Sound.Tidal.Stream (patternTimeID) import Sound.Tidal.UI import qualified Sound.Tidal.Params as P import Sound.Tidal.Utils@@ -412,38 +413,68 @@ msec :: Fractional a => Pattern a -> Pattern a msec p = (realToFrac . (/1000) <$> cF 1 "_cps") *| p -triggerWith :: Show a => (Time -> Time) -> a -> Pattern b -> Pattern b-triggerWith f k pat = pat {query = q}- where q st = query (rotR (offset st) pat) st- offset st = fromMaybe 0 $ do v <- Map.lookup ctrl (controls st)- return (f $ fromMaybe 0 $ getR v)- ctrl = "_t_" ++ show k--trigger :: Show a => a -> Pattern b -> Pattern b+-- | Align the start of a pattern with the time a pattern is evaluated,+-- rather than the global start time. Because of this, the pattern will+-- probably not be aligned to the pattern grid.+trigger :: Pattern a -> Pattern a trigger = triggerWith id -ctrigger :: Show a => a -> Pattern b -> Pattern b-ctrigger = triggerWith $ (fromIntegral :: Int -> Rational) . ceiling--qtrigger :: Show a => a -> Pattern b -> Pattern b+-- | (Alias @__qt__@) Quantise trigger. Aligns the start of the pattern+-- with the next cycle boundary. For example, this pattern will fade in+-- starting with the next cycle after the pattern is evaluated:+-- +-- @+-- d1 $ qtrigger $ s "hh(5, 8)" # amp envL+-- @+-- +-- Note that the pattern will start playing immediately. The /start/ of the+-- pattern aligns with the next cycle boundary, but events will play before+-- if the pattern has events at negative timestamps (which most loops do).+-- These events can be filtered out, for example:+-- +-- @+-- d1 $ qtrigger $ filterWhen (>= 0) $ s "hh(5, 8)"+-- @+qtrigger :: Pattern a -> Pattern a qtrigger = ctrigger -rtrigger :: Show a => a -> Pattern b -> Pattern b+qt :: Pattern a -> Pattern a+qt = qtrigger++-- | Ceiling trigger. Aligns the start of a pattern to the next cycle+-- boundary, just like 'qtrigger'.+ctrigger :: Pattern a -> Pattern a+ctrigger = triggerWith $ (fromIntegral :: Int -> Rational) . ceiling++-- | Rounded trigger. Aligns the start of a pattern to the nearest cycle+-- boundary, either next or previous.+rtrigger :: Pattern a -> Pattern a rtrigger = triggerWith $ (fromIntegral :: Int -> Rational) . round -ftrigger :: Show a => a -> Pattern b -> Pattern b+-- | Floor trigger. Aligns the start of a pattern to the previous cycle+-- boundary.+ftrigger :: Pattern a -> Pattern a ftrigger = triggerWith $ (fromIntegral :: Int -> Rational) . floor -qt :: Show a => a -> Pattern b -> Pattern b-qt = qtrigger+-- | (Alias @__mt__@) Mod trigger. Aligns the start of a pattern to the+-- next cycle boundary where the cycle is evenly divisible by a given+-- number. 'qtrigger' is equivalent to @mtrigger 1@.+mtrigger :: Int -> Pattern a -> Pattern a+mtrigger n = triggerWith $ fromIntegral . nextMod+ where nextMod t = n * ceiling (t / (fromIntegral n)) -reset :: Show a => a -> Pattern b -> Pattern b-reset k pat = pat {query = q}- where q st = query (rotR (offset st) $ when (<=0) (const silence) pat) st- f = (fromIntegral :: Int -> Rational) . floor- offset st = fromMaybe 0 $ do p <- Map.lookup ctrl (controls st)- return (f $ fromMaybe 0 $ getR p)- ctrl = "_t_" ++ show k+mt :: Int -> Pattern a -> Pattern a+mt = mtrigger++-- | This aligns the start of a pattern to some value relative to the+-- time the pattern is evaluated. The provided function maps the evaluation+-- time (on the global cycle clock) to a new time, and then @triggerWith@+-- aligns the pattern's start to the time that's returned.+triggerWith :: (Time -> Time) -> Pattern a -> Pattern a+triggerWith f pat = pat {query = q}+ where q st = query (rotR (offset st) pat) st+ offset st = fromMaybe 0 $ f+ <$> (Map.lookup patternTimeID (controls st) >>= getR) splat :: Pattern Int -> ControlPattern -> ControlPattern -> ControlPattern splat slices epat pat = chop slices pat # bite 1 (const 0 <$> pat) epat
src/Sound/Tidal/Core.hs view
@@ -29,10 +29,6 @@ -- ** 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@@ -347,67 +343,14 @@ (~>) :: 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 slowSqueeze = tParamSqueeze _slow -- | An alias for @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:
src/Sound/Tidal/Params.hs view
@@ -73,24 +73,49 @@ pX :: String -> Pattern [Word8] -> ControlPattern pX name = fmap (Map.singleton name . VX) -pStateF :: String -> String -> (Maybe Double -> Double) -> ControlPattern-pStateF name sName update = pure $ Map.singleton name $ VState statef+pStateF ::+ String -> -- ^ A parameter, e.g. `note`; a+ -- `String` recognizable by a `ValueMap`.+ String -> -- ^ Identifies the cycling state pattern.+ -- Can be anything the user wants.+ (Maybe Double -> Double) ->+ ControlPattern+pStateF name sName update =+ pure $ Map.singleton name $ VState statef where statef :: ValueMap -> (ValueMap, Value)- statef sMap = (Map.insert sName v sMap, v) - where v = VF $ update $ (Map.lookup sName sMap) >>= getF+ statef sMap = (Map.insert sName v sMap, v)+ where v = VF $ update+ $ Map.lookup sName sMap >>= getF -pStateList :: String -> String -> [Value] -> ControlPattern-pStateList name sName xs = pure $ Map.singleton name $ VState statef- where statef :: ValueMap -> (ValueMap, Value)- statef sMap = (Map.insert sName (VList $ tail looped) sMap, head looped) - where xs' = fromMaybe xs ((Map.lookup sName sMap) >>= getList)- -- do this instead of a cycle, so it can get updated with the a list- looped | null xs' = xs- | otherwise = xs'+-- | `pStateList` is made with cyclic lists in mind,+-- but it can even "cycle" through infinite lists.+pStateList ::+ String -> -- ^ A parameter, e.g. `note`; a+ -- `String` recognizable by a `ValueMap`.+ String -> -- ^ Identifies the cycling state pattern.+ -- Can be anything the user wants.+ [Value] -> -- ^ The list to cycle through.+ ControlPattern+pStateList name sName xs =+ pure $ Map.singleton name $ VState statef+ where+ statef :: ValueMap -> (ValueMap, Value)+ statef sMap = ( Map.insert sName+ (VList $ tail looped) sMap+ , head looped)+ where xs' = fromMaybe xs+ $ Map.lookup sName sMap >>= getList+ -- do this instead of a cycle, so it can get updated with the a list+ looped | null xs' = xs+ | otherwise = xs' +-- | A wrapper for `pStateList` that accepts a `[Double]`+-- rather than a `[Value]`. pStateListF :: String -> String -> [Double] -> ControlPattern pStateListF name sName = pStateList name sName . map VF +-- | A wrapper for `pStateList` that accepts a `[String]`+-- rather than a `[Value]`. pStateListS :: String -> String -> [String] -> ControlPattern pStateListS name sName = pStateList name sName . map VS @@ -200,9 +225,7 @@ accelerateCountTo name ipat = innerJoin $ (\i -> pStateF "accelerate" name (maybe 0 ((`mod'` i) . (+1)))) <$> ipat acceleratebus :: Pattern Int -> Pattern Double -> ControlPattern-acceleratebus busid pat = (pF "accelerate" pat) # (pI "^accelerate" busid)-acceleraterecv :: Pattern Int -> ControlPattern-acceleraterecv busid = pI "^accelerate" busid+acceleratebus _ _ = error $ "Control parameter 'accelerate' can't be sent to a bus." -- | like @gain@, but linear. amp :: Pattern Double -> ControlPattern@@ -283,9 +306,7 @@ beginCountTo name ipat = innerJoin $ (\i -> pStateF "begin" name (maybe 0 ((`mod'` i) . (+1)))) <$> ipat beginbus :: Pattern Int -> Pattern Double -> ControlPattern-beginbus busid pat = (pF "begin" pat) # (pI "^begin" busid)-beginrecv :: Pattern Int -> ControlPattern-beginrecv busid = pI "^begin" busid+beginbus _ _ = error $ "Control parameter 'begin' can't be sent to a bus." -- | Spectral binshift binshift :: Pattern Double -> ControlPattern
src/Sound/Tidal/ParseBP.hs view
@@ -519,20 +519,20 @@ parseChord :: (Enum a, Num a) => MyParser [a] parseChord = do char '\'' name <- many1 $ letter <|> digit- let chord = fromMaybe [0] $ lookup name chordTable+ let foundChord = fromMaybe [0] $ lookup name chordTable do char '\'' notFollowedBy space <?> "chord range or 'i' or 'o'"- let n = length chord+ let n = length foundChord i <- option n (fromIntegral <$> integer) j <- length <$> many (char 'i') o <- length <$> many (char 'o')- let chord' = take i $ drop j $ concatMap (\x -> map (+ x) chord) [0,12..]+ let chord' = take i $ drop j $ concatMap (\x -> map (+ x) foundChord) [0,12..] -- open voiced chords let chordo' = if o > 0 && n > 2 then [ (chord' !! 0 - 12), (chord' !! 2 - 12), (chord' !! 1) ] ++ reverse (take (length chord' - 3) (reverse chord')) else chord' return chordo'- <|> return chord+ <|> return foundChord parseNote :: Num a => MyParser a parseNote = do n <- notenum@@ -684,7 +684,7 @@ parseModOpen = char 'o' >> return Open parseModRange :: MyParser Modifier-parseModRange = parseIntNote >>= \i -> return $ Range $ fromIntegral i+parseModRange = parseIntNote >>= \i -> return $ Range $ fromIntegral (i :: Integer) parseModifiers :: MyParser [Modifier] parseModifiers = (many1 parseModOpen) <|> parseModDrop <|> (fmap pure parseModRange) <|> try parseModInvNum <|> (many1 parseModInv) <?> "modifier"
src/Sound/Tidal/Pattern.hs view
@@ -67,8 +67,36 @@ instance Applicative Pattern where -- | Repeat the given value once per cycle, forever pure v = Pattern $ \(State a _) ->- map (\a' -> Event (Context []) (Just a') (sect a a') v) $ cycleArcsInArc a+ map (\a' -> Event+ (Context [])+ (Just a')+ (sect a a')+ v)+ $ cycleArcsInArc a + -- | In each of `a <*> b`, `a <* b` and `a *> b`+ -- (using the definitions from this module, not the Prelude),+ -- the time structure of the result+ -- depends on the structures of both `a` and `b`.+ -- They all result in `Event`s with identical `part`s and `value`s.+ -- However, their `whole`s are different.+ --+ -- For instance, `listToPat [(+1), (+2)] <*> "0 10 100"`+ -- gives the following 4-`Event` cycle:+ -- > (0>⅓)|1+ -- > (⅓>½)|11+ -- > (½>⅔)|12+ -- > (⅔>1)|102+ -- If we use `<*` instead, we get this:+ -- > (0>⅓)-½|1+ -- > 0-(⅓>½)|11+ -- > (½>⅔)-1|12+ -- > ½-(⅔>1)|102+ -- And if we use `*>`, we get this:+ -- > (0>⅓)|1+ -- > (⅓>½)-⅔|11+ -- > ⅓-(½>⅔)|12+ -- > (⅔>1)|102 (<*>) = applyPatToPatBoth -- | Like <*>, but the 'wholes' come from the left@@ -199,7 +227,7 @@ 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) =@@ -342,11 +370,14 @@ 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 @@ -375,6 +406,10 @@ withQueryTime :: (Time -> Time) -> Pattern a -> Pattern a withQueryTime f pat = withQueryArc (\(Arc s e) -> Arc (f s) (f e)) pat +-- | Apply a function to the control values of the query+withQueryControls :: (ValueMap -> ValueMap) -> Pattern a -> Pattern a+withQueryControls f pat = pat { query = query pat . (\(State a m) -> State a (f m))}+ -- | @withEvent f p@ returns a new @Pattern@ with each event mapped over -- function @f@. withEvent :: (Event a -> Event b) -> Pattern a -> Pattern b@@ -427,6 +462,35 @@ 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 $@@ -448,6 +512,33 @@ 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.
src/Sound/Tidal/Safe/Boot.hs view
@@ -19,6 +19,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. -} +{-# OPTIONS_GHC -Wno-missing-signatures #-} {-# language NoMonomorphismRestriction #-} module Sound.Tidal.Safe.Boot where@@ -52,7 +53,7 @@ jumpIn i t = transition True (Sound.Tidal.Transition.jumpIn t) i jumpIn' i t = transition True (Sound.Tidal.Transition.jumpIn' t) i jumpMod i t = transition True (Sound.Tidal.Transition.jumpMod t) i-mortal i lifespan release = transition True (Sound.Tidal.Transition.mortal lifespan release) i+mortal i lifespan releaseTime = transition True (Sound.Tidal.Transition.mortal lifespan releaseTime) i interpolate i = transition True (Sound.Tidal.Transition.interpolate) i interpolateIn i t = transition True (Sound.Tidal.Transition.interpolateIn t) i clutch i = transition True (Sound.Tidal.Transition.clutch) i
src/Sound/Tidal/Safe/Context.hs view
@@ -21,6 +21,8 @@ {-# language GeneralizedNewtypeDeriving #-} {-# language NoMonomorphismRestriction #-}+{-# OPTIONS_GHC -Wno-missing-signatures #-}+{-# OPTIONS_GHC -Wno-unused-top-binds #-} module Sound.Tidal.Safe.Context ( Op () -- do not export constructor,
src/Sound/Tidal/Simple.hs view
@@ -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
src/Sound/Tidal/Stream.hs view
@@ -34,18 +34,18 @@ import Foreign.C.Types import System.IO (hPutStrLn, stderr) -import qualified Sound.OSC.FD as O+import qualified Sound.Osc.Fd as O+import qualified Sound.Osc.Time.Timeout 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) import Sound.Tidal.Pattern import qualified Sound.Tidal.Tempo as T import Sound.Tidal.Utils ((!!!))--- import qualified Sound.OSC.Datum as O import Data.List (sortOn) import System.Random (getStdRandom, randomR) import Sound.Tidal.Show ()@@ -59,7 +59,7 @@ sStateMV :: MVar ValueMap, -- sOutput :: MVar ControlPattern, sLink :: Link.AbletonLink,- sListen :: Maybe O.UDP,+ sListen :: Maybe O.Udp, sPMapMV :: MVar PlayMap, sActionsMV :: MVar [T.TempoAction], sGlobalFMV :: MVar (ControlPattern -> ControlPattern),@@ -67,7 +67,7 @@ } data Cx = Cx {cxTarget :: Target,- cxUDP :: O.UDP,+ cxUDP :: O.Udp, cxOSCs :: [OSC], cxAddr :: N.AddrInfo, cxBusAddr :: Maybe N.AddrInfo@@ -256,13 +256,13 @@ else hPutStrLn stderr "Can't handshake with SuperCollider without control port." -sendO :: Bool -> (Maybe O.UDP) -> Cx -> O.Message -> IO ()+sendO :: Bool -> (Maybe O.Udp) -> Cx -> O.Message -> IO () sendO isBusMsg (Just listen) cx msg = O.sendTo listen (O.Packet_Message msg) (N.addrAddress addr) where addr | isBusMsg && isJust (cxBusAddr cx) = fromJust $ cxBusAddr cx | otherwise = cxAddr cx sendO _ Nothing cx msg = O.sendMessage (cxUDP cx) msg -sendBndl :: Bool -> (Maybe O.UDP) -> Cx -> O.Bundle -> IO ()+sendBndl :: Bool -> (Maybe O.Udp) -> Cx -> O.Bundle -> IO () sendBndl isBusMsg (Just listen) cx bndl = O.sendTo listen (O.Packet_Bundle bndl) (N.addrAddress addr) where addr | isBusMsg && isJust (cxBusAddr cx) = fromJust $ cxBusAddr cx | otherwise = cxAddr cx@@ -332,11 +332,10 @@ defaultValue _ = Nothing playStack :: PlayMap -> ControlPattern-playStack pMap = stack $ map pattern active- where active = filter (\pState -> if hasSolo pMap- then solo pState- else not (mute pState)- ) $ Map.elems pMap+playStack pMap = stack . (map pattern) . (filter active) . Map.elems $ pMap+ where active pState = if hasSolo pMap+ then solo pState+ else not (mute pState) toOSC :: [Int] -> ProcessedEvent -> OSC -> [(Double, Bool, O.Message)] toOSC busses pe osc@(OSC _ _)@@ -400,16 +399,21 @@ ident = fromMaybe "unknown" $ Map.lookup "_id_" (value $ peEvent pe) >>= getS ts = (peOnWholeOrPartOsc pe) + nudge -- + latency +patternTimeID :: String+patternTimeID = "_t_pattern"+ -- Used for Tempo callback-updatePattern :: Stream -> ID -> ControlPattern -> IO ()-updatePattern stream k pat = do+updatePattern :: Stream -> ID -> Time -> ControlPattern -> IO ()+updatePattern stream k !t pat = do let x = queryArc pat (Arc 0 0) pMap <- seq x $ takeMVar (sPMapMV stream) let playState = updatePS $ Map.lookup (fromID k) pMap putMVar (sPMapMV stream) $ Map.insert (fromID k) playState pMap where updatePS (Just playState) = do playState {pattern = pat', history = pat:(history playState)} updatePS Nothing = PlayState pat' False False [pat']- pat' = pat # pS "_id_" (pure $ fromID k)+ patControls = Map.singleton patternTimeID (VR t)+ pat' = withQueryControls (Map.union patControls)+ $ pat # pS "_id_" (pure $ fromID k) processCps :: T.LinkOperations -> [Event ValueMap] -> IO [ProcessedEvent] processCps ops = mapM processEvent@@ -542,7 +546,7 @@ -- Send events early using timestamp in the OSC bundle - used by Superdirt -- Send events early by adding timestamp to the OSC message - used by Dirt -- Send events live by delaying the thread-send :: Maybe O.UDP -> Cx -> Double -> Double -> (Double, Bool, O.Message) -> IO ()+send :: Maybe O.Udp -> Cx -> Double -> Double -> (Double, Bool, O.Message) -> IO () send listen cx latency extraLatency (time, isBusMsg, m) | oSchedule target == Pre BundleStamp = sendBndl isBusMsg listen cx $ O.Bundle timeWithLatency [m] | oSchedule target == Pre MessageStamp = sendO isBusMsg listen cx $ addtime m@@ -551,7 +555,7 @@ sendO isBusMsg listen cx m return () where addtime (O.Message mpath params) = O.Message mpath ((O.int32 sec):((O.int32 usec):params))- ut = O.ntpr_to_ut timeWithLatency+ ut = O.ntpr_to_posix timeWithLatency sec :: Int sec = floor ut usec :: Int@@ -565,8 +569,11 @@ streamNudgeAll s nudge = T.setNudge (sActionsMV s) nudge streamResetCycles :: Stream -> IO ()-streamResetCycles s =T.resetCycles (sActionsMV s)+streamResetCycles s = streamSetCycle s 0 +streamSetCycle :: Stream -> Time -> IO ()+streamSetCycle s cyc = T.setCycle cyc (sActionsMV s)+ hasSolo :: Map.Map k PlayState -> Bool hasSolo = (>= 1) . length . filter solo . Map.elems @@ -652,7 +659,7 @@ streamSetR :: Stream -> String -> Pattern Rational -> IO () streamSetR = streamSet -openListener :: Config -> IO (Maybe O.UDP)+openListener :: Config -> IO (Maybe O.Udp) openListener c | cCtrlListen c = catchAny run (\_ -> do verbose c "That port isn't available, perhaps another Tidal instance is already listening on that port?" return Nothing@@ -686,16 +693,16 @@ return () where bufferIndices [] = []- bufferIndices (x:xs') | x == (O.ASCII_String $ O.ascii "&controlBusIndices") = catMaybes $ takeWhile isJust $ map O.datum_integral xs'+ bufferIndices (x:xs') | x == (O.AsciiString $ O.ascii "&controlBusIndices") = catMaybes $ takeWhile isJust $ map O.datum_integral xs' | otherwise = bufferIndices xs' -- External controller commands act (O.Message "/ctrl" (O.Int32 k:v:[])) = act (O.Message "/ctrl" [O.string $ show k,v])- act (O.Message "/ctrl" (O.ASCII_String k:v@(O.Float _):[]))+ act (O.Message "/ctrl" (O.AsciiString k:v@(O.Float _):[])) = add (O.ascii_to_string k) (VF (fromJust $ O.datum_floating v))- act (O.Message "/ctrl" (O.ASCII_String k:O.ASCII_String v:[]))+ act (O.Message "/ctrl" (O.AsciiString k:O.AsciiString v:[])) = add (O.ascii_to_string k) (VS (O.ascii_to_string v))- act (O.Message "/ctrl" (O.ASCII_String k:O.Int32 v:[]))+ act (O.Message "/ctrl" (O.AsciiString k:O.Int32 v:[])) = add (O.ascii_to_string k) (VI (fromIntegral v)) -- Stream playback commands act (O.Message "/mute" (k:[]))@@ -722,7 +729,7 @@ putMVar (sStateMV stream) $ Map.insert k v sMap return () withID :: O.Datum -> (ID -> IO ()) -> IO ()- withID (O.ASCII_String k) func = func $ (ID . O.ascii_to_string) k+ withID (O.AsciiString k) func = func $ (ID . O.ascii_to_string) k withID (O.Int32 k) func = func $ (ID . show) k withID _ _ = return () ctrlResponder _ _ _ = return ()
src/Sound/Tidal/Tempo.hs view
@@ -6,7 +6,7 @@ import Control.Concurrent.MVar import qualified Sound.Tidal.Pattern as P-import qualified Sound.OSC.FD as O+import qualified Sound.Osc.Fd as O import Control.Concurrent (forkIO, ThreadId, threadDelay) import Control.Monad (when) import qualified Data.Map.Strict as Map@@ -20,7 +20,6 @@ import Data.Int(Int64) import Sound.Tidal.StreamTypes-import Sound.Tidal.Core (silence) {- Tempo.hs - Tidal's scheduler@@ -40,13 +39,13 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. -} -instance Show O.UDP where+instance Show O.Udp where show _ = "-unshowable-" type TransitionMapper = P.Time -> [P.ControlPattern] -> P.ControlPattern data TempoAction =- ResetCycles+ SetCycle P.Time | SingleTick P.ControlPattern | SetNudge Double | StreamReplace ID P.ControlPattern@@ -54,7 +53,6 @@ data State = State {ticks :: Int64, start :: Link.Micros,- nowEnd :: Link.Micros, nowArc :: P.Arc, nudged :: Double }@@ -64,7 +62,7 @@ ActionHandler { onTick :: TickState -> LinkOperations -> P.ValueMap -> IO P.ValueMap, onSingleTick :: LinkOperations -> P.ValueMap -> P.ControlPattern -> IO P.ValueMap,- updatePattern :: ID -> P.ControlPattern -> IO ()+ updatePattern :: ID -> P.Time -> P.ControlPattern -> IO () } data LinkOperations =@@ -78,8 +76,8 @@ cyclesToBeat :: CDouble -> CDouble } -resetCycles :: MVar [TempoAction] -> IO ()-resetCycles actionsMV = modifyMVar_ actionsMV (\actions -> return $ ResetCycles : actions)+setCycle :: P.Time -> MVar [TempoAction] -> IO ()+setCycle cyc actionsMV = modifyMVar_ actionsMV (\actions -> return $ SetCycle cyc : actions) setNudge :: MVar [TempoAction] -> Double -> IO () setNudge actionsMV nudge = modifyMVar_ actionsMV (\actions -> return $ SetNudge nudge : actions)@@ -89,6 +87,7 @@ beat <- Link.beatAtTime ss time (cQuantum config) return $! (toRational beat) / (toRational (cBeatsPerCycle config)) +-- At what time does the cycle occur according to Link? cyclesToTime :: Config -> Link.SessionState -> P.Time -> IO Link.Micros cyclesToTime config ss cyc = do let beat = (fromRational cyc) * (cBeatsPerCycle config)@@ -117,11 +116,10 @@ now <- Link.clock abletonLink let startAt = now + processAhead Link.requestBeatAtTime sessionState 0 startAt quantum- Link.commitAppSessionState abletonLink sessionState+ Link.commitAndDestroyAppSessionState abletonLink sessionState putMVar actionsMV [] let st = State {ticks = 0, start = now,- nowEnd = logicalTime now 1, nowArc = P.Arc 0 0, nudged = 0 }@@ -178,9 +176,7 @@ startCycle = P.stop $ nowArc st sessionState <- Link.createAndCaptureAppSessionState abletonLink endCycle <- timeToCycles' config sessionState logicalEnd- let st' = st {nowArc = P.Arc startCycle endCycle,- nowEnd = logicalEnd- }+ let st' = st {nowArc = P.Arc startCycle endCycle} nowOsc <- O.time nowLink <- Link.clock abletonLink let ops = LinkOperations {@@ -213,19 +209,24 @@ return $! st' handleActions :: State -> [TempoAction] -> P.ValueMap -> IO (State, P.ValueMap) handleActions st [] streamState = return (st, streamState)- handleActions st (ResetCycles : otherActions) streamState =+ handleActions st (SetCycle cyc : otherActions) streamState = do (st', streamState') <- handleActions st otherActions streamState sessionState <- Link.createAndCaptureAppSessionState abletonLink - let logicalEnd = logicalTime (start st') $ ticks st' + 1- st'' = st' {- nowArc = P.Arc 0 0,- nowEnd = logicalEnd + frameTimespan- } now <- Link.clock abletonLink- Link.requestBeatAtTime sessionState 0 now quantum+ let startAt = now + processAhead+ beat = (fromRational cyc) * (cBeatsPerCycle config)+ Link.requestBeatAtTime sessionState beat startAt quantum Link.commitAndDestroyAppSessionState abletonLink sessionState++ + let st'' = st' {+ ticks = 0,+ start = now,+ nowArc = P.Arc cyc cyc+ }+ return (st'', streamState') handleActions st (SingleTick pat : otherActions) streamState = do@@ -269,10 +270,8 @@ sessionState <- Link.createAndCaptureAppSessionState abletonLink cyc <- timeToCycles' config sessionState now Link.destroySessionState sessionState- -- put pattern id and change time in control input- let streamState'' = Map.insert ("_t_all") (P.VR $! cyc) $ Map.insert ("_t_" ++ fromID k) (P.VR $! cyc) streamState'- (updatePattern ac) k pat- return (st', streamState'')+ (updatePattern ac) k cyc pat+ return (st', streamState') ) (\(e :: E.SomeException) -> do hPutStrLn stderr $ "Error in pattern: " ++ show e@@ -284,10 +283,10 @@ 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
src/Sound/Tidal/Time.hs view
@@ -38,16 +38,16 @@ -- Utility functions - Time --- | The 'sam' (start of cycle) for the given time value.+-- | The @sam@ (start of cycle) for the given time value. -- Cycles have duration 1, so every integer Time value divides two cycles. sam :: Time -> Time sam = fromIntegral . (floor :: Time -> Int) --- | Turns a number into a (rational) time value. An alias for 'toRational'.+-- | Turns a number into a (rational) time value. An alias for @toRational@. toTime :: Real a => a -> Rational toTime = toRational --- | Turns a (rational) time value into another number. An alias for 'fromRational'.+-- | Turns a (rational) time value into another number. An alias for @fromRational@. fromTime :: Fractional a => Time -> a fromTime = fromRational @@ -102,29 +102,36 @@ cycleArc :: Arc -> Arc cycleArc (Arc s e) = Arc (cyclePos s) (cyclePos s + (e-s)) --- | Returns the numbers of the cycles that the input Arc overlaps--- (excluding the input Arc's endpoint, unless it has duration 0 --+-- | Returns the numbers of the cycles that the input @Arc@ overlaps+-- (excluding the input @Arc@'s endpoint, unless it has duration 0 -- -- see "Edge cases" below).--- The "cycle number" of an Arc is equal to its start value.--- Thus, for instance, `cyclesInArc (Arc 0 1.5) == [0,1]`.--- * Edge cases:--- `cyclesInArc $ Arc 0 1.0001 == [0,1]`--- `cyclesInArc $ Arc 0 1 == [0]` -- the endpoint is excluded--- `cyclesInArc $ Arc 1 1 == [1]` -- unless the Arc has duration 0+-- (The "cycle number" of an @Arc@ is equal to its start value.+-- Thus, for instance, @cyclesInArc (Arc 0 1.5) == [0,1]@.)+--+-- Edge cases:+-- > cyclesInArc $ Arc 0 1.0001 == [0,1]+-- > cyclesInArc $ Arc 0 1 == [0] -- the endpoint is excluded+-- > cyclesInArc $ Arc 1 1 == [1] -- unless the Arc has duration 0+--+-- PITFALL: Don't be fooled by the name. The output cycles+-- are not necessarily completely contained in the input @Arc@,+-- but they definitely overlap it,+-- and they include every cycle that overlaps it. cyclesInArc :: Integral a => Arc -> [a] cyclesInArc (Arc s e) | s > e = [] | s == e = [floor s] | otherwise = [floor s .. ceiling e-1] --- | The whole cycles that overlap the input Arc,--- (excluding its endpoint, unless it has duration 0,--- similarly to `cyclesInArc` ----- see that function's description for details).+-- | This provides exactly the same information as @cyclesInArc@,+-- except that this represents its output as @Arc@s,+-- whereas @cyclesInArc@ represents the same information as integral indices.+-- (The @Arc@ from 0 to 1 corresponds to the index 0,+-- the one from 1 to 2 has index 1, etc.) cycleArcsInArc :: Arc -> [Arc] cycleArcsInArc = map (timeToCycleArc . (toTime :: Int -> Time)) . cyclesInArc --- | Splits the given 'Arc' into a list of 'Arc's, at cycle boundaries.+-- | Splits the given @Arc@ into a list of @Arc@s, at cycle boundaries. arcCycles :: Arc -> [Arc] arcCycles (Arc s e) | s >= e = [] | sam s == sam e = [Arc s e]@@ -135,7 +142,7 @@ arcCyclesZW (Arc s e) | s == e = [Arc s e] | otherwise = arcCycles (Arc s e) --- | Similar to 'fmap' but time is relative to the cycle (i.e. the+-- | Similar to @fmap@ but time is relative to the cycle (i.e. the -- sam of the start of the arc) mapCycle :: (Time -> Time) -> Arc -> Arc mapCycle f (Arc s e) = Arc (sam' + f (s - sam')) (sam' + f (e - sam'))
src/Sound/Tidal/UI.hs view
@@ -800,7 +800,7 @@ distrib' (True:a) (x:b) = x : distrib' a b distrib' (False:a) b = False : distrib' a b layers = map bjorklund . (zip<*>tail)- boolsToPat a b' = flip const <$> filterValues (== True) (fastFromList a) <*> b'+ boolsToPat a b' = flip const <$> filterValues (== True) (fastFromList a) <* b' {- | `euclidInv` fills in the blanks left by `e` -@@ -1728,11 +1728,15 @@ | otherwise = silence +-- ghost'' is kept for backwards compatibility ghost'' :: Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a-ghost'' a f p = superimpose (((a*2.5) `rotR`) . f) $ superimpose (((a*1.5) `rotR`) . f) p+ghost'' = ghostWith +ghostWith :: Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a+ghostWith a f p = superimpose (((a*2.5) `rotR`) . f) $ superimpose (((a*1.5) `rotR`) . f) p+ ghost' :: Time -> Pattern ValueMap -> Pattern ValueMap-ghost' a p = ghost'' a ((|*| P.gain (pure 0.7)) . (|> P.end (pure 0.2)) . (|*| P.speed (pure 1.25))) p+ghost' a p = ghostWith a ((|*| P.gain (pure 0.7)) . (|> P.end (pure 0.2)) . (|*| P.speed (pure 1.25))) p ghost :: Pattern ValueMap -> Pattern ValueMap ghost = ghost' 0.125
src/Sound/Tidal/Version.hs view
@@ -21,7 +21,7 @@ -} tidal_version :: String-tidal_version = "1.9.2"+tidal_version = "1.9.3" tidal_status :: IO () tidal_status = tidal_status_string >>= putStrLn
test/Sound/Tidal/PatternTest.hs view
@@ -207,6 +207,9 @@ (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
test/Sound/Tidal/StreamTest.hs view
@@ -5,7 +5,7 @@ import Test.Microspec import Sound.Tidal.Stream import Sound.Tidal.Pattern-import qualified Sound.OSC.FD as O+import qualified Sound.Osc.Fd as O import qualified Data.Map.Strict as M run :: Microspec ()
tidal.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.0 name: tidal-version: 1.9.2+version: 1.9.3 synopsis: Pattern language for improvised music description: Tidal is a domain specific language for live coding patterns. homepage: http://tidalcycles.org/@@ -55,7 +55,7 @@ base >=4.8 && <5 , containers < 0.7 , colour < 2.4- , hosc >= 0.17 && < 0.20+ , hosc >= 0.20 && < 0.21 , text < 2.1 , parsec >= 3.1.12 && < 3.2 , network < 3.2@@ -90,7 +90,7 @@ build-depends: base ==4.* , microspec >= 0.2.0.1- , hosc >= 0.17 && < 0.20+ , hosc >= 0.20 && < 0.21 , containers , parsec , tidal
tidal.el view
@@ -228,7 +228,7 @@ ,(format "Send %s $ silence as a single line." name) (interactive) (tidal-send-string ":{")- (tidal-send-string " mapM_ ($ silence) [,name]")+ (tidal-send-string (concat " mapM_ ($ silence) [" ,name "]")) (tidal-send-string ":}")))) (defun tidal-create-runner (name)