1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
|
3.7 Sample Packs
# Sample Packs
**Note: this section of the tutorial covers the advanced topic of
working with large directories of your own samples. This will be the
case if you've downloaded or bought your own sample packs and wish to
use them within Sonic Pi.**
**Feel free to skip this if you're happy working with the built-in
samples.**
When working with large folders of external samples it can be cumbersome
to have to type the whole path every time to trigger an individual
sample.
For example, say you have the following folder on your machine:
```
/path/to/my/samples/
```
When we look inside that folder we find the following samples:
* `100_A#_melody1.wav`
* `100_A#_melody2.wav`
* `100_A#_melody3.wav`
* `120_A#_melody4.wav`
* `120_Bb_guit1.wav`
* `120_Bb_piano1.wav`
Typically in order to play the piano sample we can use the full path:
```
sample "/path/to/my/samples/120_Bb_piano1.wav"
```
If we want to then play the guitar sample we can use its full path too:
```
sample "/path/to/my/samples/120_Bb_guit.wav"
```
However, both of these calls to sample requires us to *know* the names
of the samples within our directory. What if we just want to listen to
each sample in turn quickly?
## Indexing Sample Packs
If we want to play the first sample in a directory we just need to pass
the directory's name to `sample` and the index `0` as follows:
```
sample "/path/to/my/samples/", 0
```
We can even make a shortcut to our directory path using a variable:
```
samps = "/path/to/my/samples/"
sample samps, 0
```
Now, if we want to play the second sample in our directory, we just need
to add 1 to our index:
```
samps = "/path/to/my/samples/"
sample samps, 1
```
Notice that we no longer need to know the names of the samples in the
directory - we just need to know the directory itself (or have a
shortcut to it). If we ask for an index which is larger than the number
of samples, it simply wraps round just like Rings. Therefore, whatever
number we use we're guaranteed to get one of the samples in that
directory.
## Filtering Sample Packs
Usually indexing is enough, but sometimes we need more power to sort
and organise our samples. Luckily many sample packs add useful
information in the filenames. Let's take another look at the sample file
names in our directory:
* `100_A#_melody1.wav`
* `100_A#_melody2.wav`
* `100_A#_melody3.wav`
* `120_A#_melody4.wav`
* `120_Bb_guit1.wav`
* `120_Bb_piano1.wav`
Notice that in these filenames we have quite a bit of
information. Firstly, we have the BPM of the sample (beats per minute)
at the start. So, the piano sample is at 120 BPM and our first three
melodies are at 100 BPM. Also, our sample names contain the key. So the
guitar sample is in Bb and the melodies are in A#. This information is
very useful for mixing in these samples with our other code. For
example, we know we can only play the piano sample with code that's in
120 BPM and in the key of Bb.
It turns out that we can use this particular naming convention of our
sample sets in the code to help us filter out the ones we want. For
example, if we're working at 120 BPM, we can filter down to all the
samples that contain the string `"120"` with the following:
```
samps = "/path/to/my/samples/"
sample samps, "120"
```
This will play us the first match. If we want the second match we just
need to use the index:
```
samps = "/path/to/my/samples/"
sample samps, "120", 1
```
We can even use multiple filters at the same time. For example, if we
want a sample whose filename contains both the substrings `"120"` and `"A#"`
we can find it easily with the following code:
```
samps = "/path/to/my/samples/"
sample samps, "120", "A#"
```
Finally, we're still free to add our usual opts to the call to `sample`:
```
samps = "/path/to/my/samples/"
sample samps, "120", "Bb", 1, lpf: 70, amp: 2
```
## Sources
The sample filter pre-arg system understands two types of information:
*sources* and *filters*. Sources are information used to create the list
of potential candidates. A source can take two forms:
1. `"/path/to/samples"` - a string representing a valid path to a directory
2. `"/path/to/samples/foo.wav"` - a string representing a valid path to a sample
The `sample` fn will first gather all sources and use them to create a
large list of candidates. This list is constructed by first adding all
valid paths and then by adding all the valid `.flac`, `.aif`, `.aiff`,
`.wav`, `.wave` files contained within the directories.
For example, take a look at the following code:
```
samps = "/path/to/my/samples/"
samps2 = "/path/to/my/samples2/"
path = "/path/to/my/samples3/foo.wav"
sample samps, samps2, path, 0
```
Here, we're combining the contents of the samples within two directories
and adding a specific sample. If `"/path/to/my/samples/"` contained 3
samples and `"/path/to/my/samples2/"` contained 12, we'd have 16
potential samples to index and filter (3 + 12 + 1).
By default, only the sample files within a directory are gathered into
the candidate list. Sometimes you might have a number of nested folders of
samples you wish to search and filter within. You can therefore do a
recursive search for all samples within all subfolders of a particular
folder by adding `**` to the end of the path:
```
samps = "/path/to/nested/samples/**"
sample samps, 0
```
Take care though as searching through a very large set of folders may
take a long time. However, the contents of all folder sources are
cached, so the delay will only happen the first time.
Finally, note that the sources *must go first*. If no source is given,
then the set of built-in samples will be selected as the default list of
candidates to work with.
## Filters
Once you have a list of candidates you may use the following filtering
types to further reduce the selection:
* `"foo"` Strings will filter on substring occurrence within file name (minus directory path and extension).
* `/fo[oO]/` Regular Expressions will filter on pattern matching of file name (minus directory path and extension).
* `:foo` - Keywords will filter candidates on whether the keyword is a direct match of the filename (minus directory path and extension).
* `lambda{|a| ... }` - Procs with one argument will be treated as a candidate filter or generator function. It will be passed the list of current candidates and must return a new list of candidates (a list of valid paths to sample files).
* `1` - Numbers will select the candidate with that index (wrapping round like a ring if necessary).
For example, we can filter over all the samples in a directory
containing the string `"foo"` and play the first matching sample at half
speed:
```
sample "/path/to/samples", "foo", rate: 0.5
```
See the help for `sample` for many detailed usage examples. Note that
the ordering of the filters is honoured.
## Composites
Finally, you may use lists wherever you may place a source or
filter. The list will be automatically flattened and the contents will
be treated as regular sources and filters. Therefore the following calls
to `sample` are semantically equivalent:
```
sample "/path/to/dir", "100", "C#"
sample ["/path/to/dir", "100", "C#"]
sample "/path/to/dir", ["100", "C#"]
sample ["/path/to/dir", ["100", ["C#"]]]
```
## Wrapping Up
This was an advanced section for people that need real power to
manipulate and use sample packs. If most of this section didn't make too
much sense, don't worry. It's likely you don't need any of this
functionality just yet. However, you'll know when you do need it and you
can come back and re-read this when you start working with large
directories of samples.
|