This project is now read-only. It was fun while it lasted! But it was made obsolete by the release of
wags@1.0.0
. Perhaps in the future some of these ideas will be brought back to life, but many of them existed to try to bend a rendering loop into something it wasn't, andwags@1.0.0
novel approach to events makes a lot of this machinery unnecessary. Check out the new wags for ideas and inspiration!
Collaborative interactive music-making using purescript-wags
.
Practice makes perfect! To try this repo out:
purs ide
. This includes, but is probably not limited to, VSCode, emacs and IntelliJ.nix-shell
by running nix-shell
in the root directory of this project. Then, run npm install --no-optional && npm start
. Make sure to open your editor from the command line (ie if you're using code by invoking code .
) in order to pick up on the nix
environment.nix-shell
and run npm install && npm start
.localhost:8080
in Chrome or Firefox and click on Start Audio.src/LiveCodeHere/Wagged.purs
. Start editing & save the file to render (ie change the empty ""
to "bassdm"
). You should hear some beats! If not, file an issue on this repo.cookbook/
. All examples from the cookbook can be pasted into src/LiveCodeHere/Wagged.purs
- just make sure to keep the module's name as WAGSI.LiveCodeHere.Wagged
when pasting.Wagsi implements a subset of the tidal API + a couple additional bells and whistles.
When you start, the top-level file has the following code:
module WAGSI.LiveCodeHere.Wagged where
import WAGS.Lib.Tidal.Tidal (make, s)
import WAGS.Lib.Tidal.Types (AFuture)
wag :: AFuture
wag = make 1.0
{ earth: s ""
, title: "i m a k e n o i s e"
}
Here's an example that uses mini-notation.
module WAGSI.LiveCodeHere.Wagged where
import WAGS.Lib.Tidal.Types (AFuture)
import WAGS.Lib.Tidal.Tidal (make, s)
wag :: AFuture
wag = make 2.0
{ earth: s "bassdm hh27 [bassdm:2 bassdm:2] hh27 , <[~ gab ~ gab] ~>"
}
Wagsi tidal supports the following mini-notation. A big thanks to whoever wrote the Tidal documentation, which was dutifully copied.
Symbol | Description | Example |
---|---|---|
hh27 |
A single note. | bassdm hh27 bassdm hh27 |
~ |
A rest. | bassdm ~ bassdm hh27 |
[ ] |
Create a pattern grouping. | [bassdm kick] hh27 |
, |
Play multiple patterns at the same time. | bassdm hh27 , cr cr cr cr |
< > |
Alternate between patterns. | [hh hh hh] [hh27 gab hh27 <gab cr>] |
A full list is here. Enjoy!
You can also use PureScript terms to create notation. Here is the same example above using PureScript terms.
module WAGSI.LiveCodeHere.Wagged where
import Prelude
import WAGS.Lib.Tidal.Types (AFuture)
import WAGS.Lib.Tidal.Cycle (r)
import WAGS.Lib.Tidal.Tidal (make, parse, s, i, b, x)
bassdm = parse "bassdm"
bassdm_2 = parse "bassdm:2"
hh27 = parse "hh27"
gab = parse "gab"
wag :: AFuture
wag = make 2.0
-- "bassdm hh27 [bassdm:2 bassdm:2] hh27 , <[~ gab ~ gab] ~>"
{ earth: s $ x (i bassdm [ hh27, i bassdm_2 [ bassdm_2 ], hh27 ]) [ b (i r [ gab, r, gab ]) [ r ] ]
}
Symbol | Description | Example |
---|---|---|
hh |
A single note. | i bassdm [hh27, kick, hh27] |
r |
A rest. | i bassdm [r, kick, hh27] |
i _ [ ] |
Create a pattern grouping. | i (i bassdm [kick]) [hh27] |
x _ [ ] |
Play multiple patterns at the same time. | x (i bassdm [hh27]) [i cr [cr, cr, cr]] |
b _ [ ] |
Alternate between patterns. | i (i cr [cr, cr]) [i hh27 [gab, hh27, b gab [cr]]] |
It's often useful to create an initial beat with a string and then modify it using PureScript functions. To do this, you can use parse
. This will give you low-level access to the underlying notes, which we'll take advantage of in the examples below.
module WAGSI.LiveCodeHere.Wagged where
import Prelude
import WAGS.Lib.Tidal.Types (AFuture)
import WAGS.Lib.Tidal.Tidal (make, parse, plainly, rend)
wag :: AFuture
wag = make 2.0
{ earth: map plainly $ rend $ parse "bassdm hh27 [bassdm:2 bassdm:2] hh27 , <[~ gab ~ gab] ~>"
}
You can manipulate the pitch and volume of notes. Let's pitch-shift everything up a fifth:
module WAGSI.LiveCodeHere.Wagged where
import Prelude
import WAGS.Lib.Tidal.Types (AFuture)
import Data.Lens (set, traversed)
import WAGS.Lib.Tidal.Tidal (lnr, make, parse, s)
wag :: AFuture
wag = make 2.0
{ earth: s
$ (set (traversed <<< traversed <<< lnr) (const 1.5))
$ parse "bassdm hh27 [bassdm:2 bassdm:2] hh27 , <[~ gab ~ gab] ~>"
}
The same works on individual notes. Let's drop the first bassdm down an octave.
module WAGSI.LiveCodeHere.Wagged where
import Prelude
import WAGS.Lib.Tidal.Types (AFuture)
import Data.Lens (set, traversed)
import WAGS.Lib.Tidal.Cycle (r)
import WAGS.Lib.Tidal.Tidal (parse, i, b, changeRate, make, s, x)
bassdm = parse "bassdm"
hh27 = parse "hh27"
gab = parse "gab"
wag :: AFuture
wag = make 2.0
{ earth: s
$ x
( i (map (changeRate (const 0.5)) bassdm)
[ hh27, i bassdm [ bassdm ], hh27 ]
)
[ b (i r [ gab, r, gab ]) [ r ] ]
}
The same can been achieved using the string syntax, like this:
module WAGSI.LiveCodeHere.Wagged where
import Prelude
import Data.Lens (set, traversed, view)
import Data.Variant.Either (hush)
import Data.Newtype (wrap)
import WAGS.Lib.Tidal.Types (AFuture)
import WAGS.Lib.Tidal.Tidal (focus, lnr, lns, make, parse, s)
wag :: AFuture
wag = make 2.0
{ earth: s
$ set
(traversed <<< traversed <<< focus (eq (pure (wrap "gab:0")) <<< hush <<< view lns) <<< lnr)
(const 1.5)
$ parse "bassdm hh27 [bassdm:2 bassdm:2] hh27 , <[~ gab ~ gab] ~>"
}
Link to the first wagsi jam session
If you're attending a wagsi Jam session, please make sure to follow these instructions.
#music
channel of PureScript Discord. You can join right from the browser without installing VSCode. However, you'll still need a GitHub account.#music
channel of PureScript Discord from a different device than the one making the music you're listening to. For example, you can use your computer to render the audio and the phone for joining the meetup or vice versa. It's generally a good idea to use headphones.