# Sharing custom functions

Hi all!

I watched this excellent video (1st video below) by @kindohm and have been feeling pretty inspired by the plyWith function. To that end, I started looking into custom functions to save some time writing code. @kindohm also has a super informative tutorial on writing custom functions (2nd video below) that I used to make the following:

``````let plyCato num amt = plyWith num (|* legato amt)
plyDown num amt = plyWith num (|* gain amt)
``````

Here's a tldr/tldw for each function:
plyCato takes a sound and repeats it in increasing/decreasing increments determined by amt. In short, it creates a stuttery repeat trail for a sound.
plyDown does the same as plyCato but reduces/increases the gain instead of playback length.

I'd love to use this thread to share functions and help each other find new shortcuts to interesting sounds!

9 Likes

Here's an example of both functions in action:

5 Likes

I love this idea of sharing custom functions.

I made a few modulation functions that kind of behave like zenith plugin (little window wave functions) to modulate parameters.

``````let parabolamod = listToPat([x^2 | x<-[0.1,0.12..0.5]])
recparabola = listToPat([1/x^2 | x<-[0.1,0.12..0.5]])
linmod = listToPat([0.4*x+0.4 | x<-[0.1,0.12..0.4]])
sinemod = listToPat([sin(0.4*x+0.4) | x<-[0.1,0.12..0.4]])
cosmod = listToPat([cos(0.4*x+0.4) | x<-[0.1,0.12..0.4]])
downstairs = listToPat([x | x<-[1 ,1, 0.8 ,0.8 ,0.6, 0.6, 0.4, 0.4, 0.2, 0.2, 0, 0 ]])
``````

I wanted make the setbuilder notation dynamic and add the ability to control the set size, but I don't know how to pass a size parameter to the setbuilder notation without getting an error.
math-wise:

``````let    cosmod  n = listToPat([cos(0.4*x+0.4) | x<-[0.1,0.2..(n*0.1)]])

``````

I also made a couple of more melodic examples:

``````let odds y = listToPat([2*x+1 | x<-[1,2..y]]) -- odd numbers
evens y = listToPat([2*x | x<-[1,2..y]]) -- even numbers
``````

If you have those supersynths installed:

``````d4 \$ plyWith 2 (# n (odds 4)) \$ n ( evens 16) # s "gabor cyclo supergong" # accelerate "0 0.2 0.8" # gain downstairs
``````
4 Likes

These ones i use frequently:

Oscillators: Just to livecode faster

``````let sinosc  min max frq = (fast frq \$ range min max sine)
triosc  min max frq = (fast frq \$ range min max tri)
sqrosc  min max frq = (fast frq \$ range min max square)
sawosc  min max frq = (fast frq \$ range min max saw)
randosc min max = (range min max rand)
-- Usage
d1 \$ s "bd*8" # gain (sinosc 0.4 1 1)
``````

Get random notes in a scale

``````let randscale sc n f = (|+ note (scale sc (irand n))) f
-- Usage
d1 \$ randscale "phryigian" 7 \$ s "arpy(9,16,12)"
``````

``````let invnote n = 0-n
invnote' axis x = (2*axis)-n
-- Usage
d1 \$ note (invnote' "<5 7>/4" "<c'maj7(5,8) d'm11(<3 [3 5]>,8)>") # s "superpiano" # room 0.5 # velocity 0.8
``````
8 Likes

Thanks, this could open a whole new door for me, I think! Two questions: could I put these in my BootTidal.hs so that they are ready to go? Or somewhere else? And, is it necessary to write type declarations to go with them?

Yes you could place them at the end of your BootTidal.hs. I'm assuming you're talking about Haskell's type declaration, using `::` and `->`. If I recall correctly that's not needed, the compiler will do the work for you, and since these are a small number of functions it shouldn't be a problem at all.

These are great! Thanks!

I tried downstairs modulating speed along with plyCato and got some sweet results! Thanks for sharing!

1 Like

These are fun! Thank you.
I'll try to share my functions as well.

Apply oscillators to arp in a scale

``````let roundy p =  (fromIntegral . round) <\$> p
stepr n r1 r2 f = segment n \$ range r1 r2 \$ f
stepr' n r1 r2 f = roundy \$ stepr n r1 r2 f
myarp sc r2 f = scale sc (stepr' 32 0 r2 f)
-- ex.)
setcps 0.2
d1 \$ note (myarp "major" 7 sine) # s "superpiano"
d1 \$ note (myarp "locrian" 12 (fast 2 \$ isaw)) # s "superpiano"
d1 \$ note (myarp "dorian" 12 (fast 8 \$ (perlin*isaw**2))) # s "superpiano"``````
6 Likes

Hi all!

A small helper function that you may utilize to make panning less jarring if you're working on phones:

`smallpan wave = pan (range 0.3 0.7 wave)`

Just treat it like you would a normal pan parameter and you'll get a less drastic outcome.

really nice! (also, you don't have to highlight your whole entire block to evaluate it. if you just hit ctrl-enter, it'll grab everything for you.)

1 Like

Atom doesn't work for me that way, but I've been kinda eager to fix it! Do you use atom as well?

i do! i've got it loaded on both PC and Mac and ctrl-enter works for both. let me see if i can look up a fix.

found this in my keybindings pane under settings.

Thanks! I found it as well; appreciate it.

Two functions I wrote those days:

``````rslice x p = slice x (segment (toTime <\$> x) \$ ((>>= irand) x)) \$ p
rsplice x p = splice x (segment (toTime <\$> x) \$ ((>>= irand) x)) \$ p
``````

they are two shorthands for:

``````slice x (segment x \$ irand x)
splice x (segment x \$ irand x)
``````
3 Likes

Hi folks!

[Edit:] I completely overlooked that there is already the `up` function. However I have made this for using and customizing the live pitch-shifting of an input signal. So this could be helpfully anyway, I think.

I made my own function that converts the speed ratio parameter into notes. For this I wrote a speed' function which I am currently experimenting with:

``````-- Calculating the n'th root of a value
nroot :: (Integral a, Floating b) => a -> b -> b
n `nroot` x = x ** (1 / fromIntegral n)

-- Calculates the n'th root of all pattern values in p and use the function f (like speed)
nrootFuncs :: Pattern Double -> (Pattern Double -> ControlPattern) -> ControlPattern
nrootFuncs p f = f (fmap (12 `nroot` 2 **) (p))

-- Define custom speed function
speed' :: Pattern Double -> ControlPattern
speed' p = nrootFuncs p speed
``````

To demonstrate this I have created a short video for you:

The video also contains the function `psrate` and `psrate'`. Unfortunately, you can't reproduce the `in` stuff with `psrate` at the moment, because there is a small bug in SuperDirt (but it's fixed and waits for the approval)

Sharing a post from another thread, this is some WIP on rhythm structure 