# 2.4 Playing Samples There are currently two special-case Synths in FoxDot for playing back audio stored in a file; `play` and `loop`. Here we will look at these in some depth: ## The `play` synth ### Basics The very basics of the play synth has been covered briefly in the [player object intro](./player-object-intro.md) section but will be revisited here. Unlike other synths in FoxDot, the first argument should be a string of characters as opposed to numbers. This allows more information to be encoded in the string. Each character refers to a set of samples such as kick drums, hi-hats, snares, and other sounds. The most basic sequence you create is a disco drum beat: ``` python p1 >> play("x-o-") ``` You can use different types of brackets to add more information to the sequence. Putting two or more characters in round brackets will alternate which sound to play on each loop through the sequence: ``` python # Simple pattern p1 >> play("(x-)(-x)o-") # Nested brackets for more variety p1 >> play("(x-)(-(xo))o-") ``` Putting multiple characters in square brackets will play them successively in the space of one step: ``` python # Plays a triplet on the fourth steps p1 >> play("x-o[---]", dur=1) # Can be used in the round brackets p1 >> play("(x-)(-[-x])o-") # Can contain round brackets p1 >> play("x-o[-(xo)]") ``` You can also use curly braces to pick a sample at random and add some variety to your sequence: ``` python # Randomly pick a sample on the fourth step p1 >> play("x-o{-ox}") # Can contain [square brackets] p1 >> play("x-o{[--]ox}") # Can be put inside square brackets p1 >> play("x-o[-{ox}]") ``` ### The `sample` Keyword Each character relates to a folder of files arranged in alphabetical order. To select a different file, use the sample keyword. ``` python p1 >> play("x-o-", sample=1) ``` Like with any other keyword argument, this can be a list, or even a tuple, of values. ``` python p1 >> play("x-o-", sample=[0, 1, 2]) p1 >> play("x-o-", sample=(0, 3)) ``` The sample for an individual character can be specified from within the string itself by surrounding the character with a `"|"` and the specific number like so: ``` python # Plays sample=2 for the 'o' character p1 >> play("x-|o2|-") # Will override the sample keyword p1 >> play("x-|o2|-", sample=3) ``` This syntax can contain any of the brackets used before on the character and on the numbers: ``` python # Alternate the sample number p1 >> play("x-|o(12)|-") # Alternate the sample character p1 >> play("x-|(o*)2|-") # Play multiple different samples in one step p1 >> play("x-|o[23]|-") # Play random sample selection p1 >> play("x-|o{1[23]}|-") ``` ### Layering sequences You can also use less than and greater than signs to layer multiple sequences simultaneously. Let’s start with two separate sequences and then put them together in a single line of code. ``` python p1 >> play("x-o-") p2 >> play(" + + [ +]") ``` We can put each sequence between `"<>"` characters in a single sequence and have them play at the same time: ``` python # "Layers" the two sequences p1 >> play("< + + [ +]>") # Equivalent to: p1 >> play(P["x-o-"].zip(P[" + + [ +]"])) ``` Each 'layer' relates to the index of a group such that, for a group of values given to a player object, each 'layer' is affected only by one of those given values. This is best demonstrated by an example: ``` python # Hard pan each sequence to left and right channels p1 >> play("< + + [ +]>", pan=(-1, 1)) # Change the sample used in the first layer p1 >> play("< + + [ +]>", sample=(2, 0)) ``` Be careful when combining multiple layers with some functions like `offadd` as that creates new layers if they don’t exist, or affects them if they do. The following code will only affect the second layer and, so, the first layer is unaffected: ``` python p1 >> play("< + + [ +]>", sample=(2, 0)).every(4, "sample.offadd", 2) ``` ## The `loop` synth This is still a fairly experimental feature of FoxDot and is definitely subject to change but let’s have a look at the basics. The loop synth is designed to let you play longer audio files (>1 sec) and manipulate them. To get started, just supply the filename you want to play and the duration you want to play in beats: ``` python p1 >> loop("path/to/my/my_file.wav", dur=32) ``` You can put files in a special folder located in FoxDot/snd/_loop_/ which can be opened by going to "Help & Settings" and then "Open Samples Folder" from the FoxDot menu. You don’t need to supply the full path (or extension) for files in this folder: ``` python p1 >> loop("my_file", dur=4) ``` To see all the files in this folder, run `print(Samples.loops)`. If you want to play with the play back order, you can supply a position argument after the file name that FoxDot will iterate through based on the duration. ``` python # Play the first 4 beats of audio in order p1 >> loop("my_file", P[:4], dur=1) # Play the first 4 beats in random order p1 >> loop("my_file", P[:4].shuffle(), dur=1) ``` If you know the bpm of the audio file and wish to play it at the current tempo, you can supply the player with a `tempo` argument. For example, my_file could be a drum beat at 135 bpm but the current tempo is 120, I can fit the tempo of my_file to the clock like so: ``` python # First 4 beats in 1 beat steps p1 >> loop("my_file", P[:4], dur=1, tempo=135) # First 4 beats in 1/2 beat steps p1 >> loop("my_file", P[:8]/2, dur=1/2, tempo=135) ``` You can play the entire file at the current tempo by supplying a `beat_stretch` argument with a non-zero value (such as 1 or True) and you don’t need to know the tempo beforehand. ``` python p1 >> loop("my_file", dur=4, beat_stretch=True) ``` Time stretching the audio in this fashion will change the pitch, so if the audio is pitched, you may wish the time-stretch it without losing that information. This is possible using the `striate` argument. This cuts the file into lots of small segments and plays them back spread out over the course of the duration value – this will play the entire audio file. The larger the audio file, the larger the number you will probably want to use. Using the example above, you may want to use a `striate` value of 100-200 for a smoother playback: ``` python # Stretch the file using 100 segments p1 >> loop("my_file", dur=4, striate=100) # Stretch it using 10 segments - listen to the difference p1 >> loop("my_file", dur=4, striate=10) ``` _Please note_: you may experience changes in pitch at faster tempos. All FoxDot [Player effects](./player-effects.md) can be used with the loop synth, so experiment and find out what works best for your audio. For example, using `slide` with negative values can recreate the "dj scratching" effect from old school hip-hop as it slows the playback rate to 0 then back again: ``` python p1 >> loop("my_file", P[:8]/2, dur=1/2, slide=[0,0,-2]) ``` ## The `stretch` synth This recent addition to FoxDot allows you to beat stretch an entire audio file without losing any pitch information – regardless if the tempo is faster or slower. Simply supply the filename in the same way as the loop synth and set the duration you wish to play the file over and away you go: ``` python # Play back the whole file in 4 beats p1 >> stretch("my_file", dur=4) ```