Once you understand the basic Sardine model, you can start thinking about musical patterns at different scales. You can think of patterns in the context of the Sardine pattern language or Ziffers pattern language. You can also think about patterns of these patterns, and so on. In this section, you will learn how to generate musical structures by controlling how your functions are looping, when your functions are looping, etc… There are some functions that apply globally to patterns. These functions can be accessed using keyword arguments. They can help you to shape your improvisation, to master repetition and cyclical constructs.
The span argument can be used with Players in order to control the flow of time. The
span argument will compress or extend the duration of your pattern. Think of it as a pattern level event-based time-strecthing method :).
The following patterns are identic. However, note the use of
span. The first pattern is 1.5 times longer compared to the version without
span. The second one, on the other hand, is 50% shorter:
Pa >> d('voodoo voodoo:4 linnhats:(rand*20)!4', span=1.5, p=0.5) Pb >> d('voodoo voodoo:4 linnhats:(rand*20)!4', span=0.5, p=0.5, speed=2)
Try to add or remove the
span argument and listen to the difference.
Play carefully with it as you might sometimes end up with weird rhythmical results, especially if you are already playing complex rhythms with
snap is an additional argument for the
snap will time-shift the beginning of your pattern around the first beat of the measure:
snap=1will start the pattern one beat after the beginning of the bar.
snap=-0.5will start the pattern half a beat before the beginning of the next bar.
It is a useful function for shifting things around and for synchronising Sardine in some scenarios (recording, etc..).
until argument can also be used in the
@swim decorator for swimming functions and as a regular arguemnt for players. As its name suggests, this argument will loop the function
n times and stop. This is a very useful trick to use for solos or one-shots events during your sessions:
@swim(until=10) def baba(p=0.5, i=0): D('sid:2', legato=0.9, speed=0.5, lpf='[5000:200,400]', i=i ) print(i) again(baba, p=P('[1:0.1,0.1]', i), i=i+1)
You can also pair it with the
snap argument if you wish to!
Here is the bouncing ball example from above written using the Players syntax:
Pa >> d('sid:2', until=10, legato=0.9, speed=0.5, lpf=['5000:200,400'], p='[1:0.1,0.1]')
on arguments can be used in your senders to determine if the pattern should play on a given bar or not. In the following diagram, each
- represents one bar.:
loaf argument will cut slices of time, just like if you were cutting with a knife in a
loaf of bread:
-------------------------- (time) ---- (loaf=4)
on argument, you can now select which of these slices your pattern is going to be played on:
-------------------------- (time) ---- (loaf=4) - - (on=(1, 3))
Note that the
on argument can be given as an integer or as a integer-based tuple for targetting multiple bars in your
loaf! In code, the above example would look like:
Pa >> d('bd', loaf=4, on=(1,3))
You can create extremely complex rhythmic structures using these two arguments in conjunction with complex patterns!
on can also be used alone!
Just like in the Sardine Pattern Language, you can compose euclidian rhythms. This time, these euclidian rhythms will not be composed of single events but of entire bars! This is an extremely funny way to compose complex evolving structures spanning over multiple bars.
Pa >> d('(eu bd 5 8)', p=.5, euclid=(5, 8)) Pb >> d('linnhats', p=.25) Pc >> d('(eu cp 3 8', p=.5, euclid=(4, 8))
euclid is the regular euclidian rhythm function while
neuclid will play the opposite version of that pattern.
binary is another argument similar to
neuclid. Using it, you can declare a boolean structure that will determine if a bar is to be played or not. Use it like so:
Pa >> d('voodoo:[1:10]', binary=[1, 0, 0, 1, 1, 0])
This pattern will be played on bars
5. It will cycle every 6 bars and restart :)
This is a port of the TidalCycles
sometimes family of functions:
These functions represent a likelihood for an event to be played. In order to use these functions, please use the
chance keyword in any of your patterns:
Pa >> d('linnhats', p=.25, chance="almostAlways")