# サンプルパック

注: このセクションは外部サンプルのある巨大なディレクトリを扱う際の高度なトピックを扱っています。あなたがサンプルパックをダウンロードしたり購入したりして、それをSonic Piから使いたい場合が当てはまるでしょう。

内蔵サンプルで問題なければ、このセクションは飛ばしても構いませんよ。

外部サンプルのある大きなフォルダを扱う際に、個々のサンプルを再生する度にパス全体をタイプするのは、面倒かもしれません。

例えば、次のようなフォルダがあなたのマシンにあるとします。

    /path/to/my/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`

例えばピアノのサンプルを再生したい場合、次のようなフルパスでの指定が可能です。

    sample "/path/to/my/samples/120_Bb_piano1.wav"

次にギターのサンプルを再生したい場合、また同じようにフルパスでの指定が可能です。

    sample "/path/to/my/samples/120_Bb_guit.wav"

しかしながら、これらのどちらのサンプルの呼び出しでも、ディレクトリ内のファイル名を知っている必要があります。もしサンプルを順番に聴いて行きたい場合どうしたら良いでしょう？

## サンプルパックのインデックス

もしディレクトリの1番目のサンプルを再生したい場合、必要なことは次のように`sample`にディレクトリ名と’0’のインデックスを渡すだけです。

    sample "/path/to/my/samples/", 0

さらにディレクトリ名は変数を使ってショートカットを作ることも可能です。

    samps = "/path/to/my/samples/"
    sample samps, 0

次に、ディレクトリの2番目のサンプルを再生したい場合、先ほどのインデックスに1を追加すれば出来ます。

    samps = "/path/to/my/samples/"
    sample samps, 1

もはやディレクトリ内のサンプルの名前を知る必要がないことに注意してください。必要なのはディレクトリそのもの（もしくはそのショートカット）を知っていることです。もしディレクトリ内のサンプルの数より大きい値をインデックスに指定した場合、リングのように単純に先頭に戻ります。したがって、どのような数字もディレクトリ内のどれかのサンプルを取得することが保証されているのです。

## サンプルパックのフィルタ

インデックスは機能的には十分かもしれませんが、サンプルを分類するもっと強力な方法が必要になるかもしれません。幸いにして、いくつかのサンプルパックではファイル名に意味のある情報を付加してくれています。ディレクトリ内のファイル名を別な観点から見てみましょう。

- `100_A#_melody1.wav`
- `100_A#_melody2.wav`
- `100_A#_melody3.wav`
- `120_A#_melody4.wav`
- `120_Bb_guit1.wav`
- `120_Bb_piano1.wav`

これらのファイル名はかなりの情報を持っていることに注目してください。最初にサンプルのBPM（beats per minute）があります。ピアノのサンプルはBPMが120で最初の3つのメロディーはBPMが100であることが分かると思います。また、サンプルのファイル名はキーを含んでいます。ギターのサンプルはキーがBbでメロディーのキーはA#です。この情報は我々の他のコードと組み合わせるのにとても役立ちます。例えば、ピアノのサンプルをBPM120でBbのキーのソースコードとしか使えないことが分かると思います。

サンプルの特定の命名規則を使って、我々が必要とするファイルをフィルタできることが分かりました。例えば、BPM120で演奏している場合に、`"120"`という文字列を含む全てのサンプルを次のようにフィルタできます。

    samps = "/path/to/my/samples/"
    sample samps, "120"

これは最初にマッチしたものを再生します。もし2番目にマッチしたものを再生したい場合には、インデックスを使用します。

    samps = "/path/to/my/samples/"
    sample samps, "120", 1

さらに複数のフィルタを使うこともできます。例えば、”120”と”A#”をファイル名に含むサンプルが必要な場合、次のような簡単なコードで実現できます。

    samps = "/path/to/my/samples/"
    sample samps, "120", "A#"

最後に、フィルタを使用した場合にも`sample`で通常使用されるオプションをそのまま自由に追加できます。

    samps = "/path/to/my/samples/"
    sample samps, "120", "Bb", 1, lpf: 70, amp: 2

## ソース

サンプルフィルタの引数前の処理システムは、ソースとフィルタという2つタイプの情報を認識します。ソースは、候補となる可能性のあるサンプルのリストを作成するのに使われる情報です。ソースは次の2つの形式を取ることができます。

1. “/path/to/samples” - 有効なディレクトリを表す文字列
2. “/path/to/samples/foo.wav” - サンプルへの有効なパスを表す文字列

`sample`関数は、最初に全てのソースを集めてサンプルの候補の巨大なリストを作成します。このリストは最初に全ての有効なパスを追加した後、次にディレクトリ内にある全ての有効な`.flac`, `.aif`, `.aiff`, `.wav`, `.wave`ファイルを追加します。

例として、次のコードを見てください。

    samps = "/path/to/my/samples/"
    samps2 = "/path/to/my/samples2/"
    path = "/path/to/my/samples3/foo.wav"
    sample samps, samps2, path, 0

ここでは、2つのディレクトリの内容と1つの特定のサンプルを組み合わせています。もし`"/path/to/my/samples/"`に3つのサンプルがあり、`"/path/to/my/samples2/"`に12個のサンプルがあるとすると、インデックスやフィルタ可能となるサンプルは16(3 + 12 + 1)になります。

デフォルトでは、ディレクトリ内のサンプルファイルのみが候補リストに集められますが、ときにはネストした数多くのフォルダ内のサンプルを検索したりフィルタしたりしたいことがあるかもしれません。その場合には、次のように`**`をパスの最後に付けることで、全てのサブディレクトリ内のサンプルを再帰的に検索することができます。

    samps = "/path/to/nested/samples/**"
    sample samps, 0

とても大きなフォルダのセットを検索するのは、長い時間が掛かるかもしれないことに気をつけてください。しかし、フォルダーのソースの内容は全てキャッシュされるので、この遅延は一度目しか発生しません。

最後に、ソースの指定は「必ず先頭に」付けるようにしてください。もし何もソースが指定されない場合、内蔵サンプルのセットが候補リストして選択されます。

## フィルタ

候補リストを取得した後、選択肢を減らすために次のようなフィルタのタイプを使うことができます。

- `"foo"`という文字列は、（ディレクトリパスと拡張子を除いた）ファイル名の部分一致を抽出します。
- `/fo[oO]/`という正規表現は、（ディレクトリパスと拡張子を除いた）ファイル名のパターンマッチを抽出します。
- `:foo`というキーワードは、（ディレクトリパスと拡張子を除いた）ファイル名の完全一致を抽出します。
- `lambda{|a| ... }`という1つの引数を伴ったProc（手続きオブジェクト）は、候補リストのフィルタまたは生成する関数として扱われます。この関数は、現在の候補リストが引数として渡され、新しい候補リスト（サンプルの有効なパスのリスト）を返却する必要があります。
- `1`のような数値は、インデックス（必要があればリングのように先頭に戻る）で、候補から選択します。

例として、あるディレクトリから`"foo"`の文字列を含むサンプルを抽出し、そのうちの最初のものを半分のレートで再生するには、次のように書きます。

    sample "/path/to/samples", "foo", rate: 0.5

詳細な使用例は`sample`のヘルプを参照してください。また、フィルタの順序が尊重されることに注意してください。

## 複合

最後に、ソースまたはフィルタを配置することが可能な位置であればどこでもリストを使用することができます。リストは自動的に平坦化され、正規のソースとフィルタとして扱われます。したがって、次に示す`sample`の呼び出しは意味的には全て同じものになります。

    sample "/path/to/dir", "100", "C#"
    sample ["/path/to/dir", "100", "C#"]
    sample "/path/to/dir", ["100", "C#"]
    sample ["/path/to/dir", ["100", ["C#"]]]

## まとめ

このセクションでは、サンプルパックを操作・使用する強力な方法を必要とする人のための高度な内容を紹介しました。このセクションの大部分があまり意味があるように思えなかったとしても心配しないでください。それは、これらの機能のどれもまだあなたが必要としていないというだけだと思います。しかし、サンプルの巨大なディレクトリを扱うことになり、これらの機能が必要なことが分かったときに、またこのセクションに戻って読み直すことができるでしょう。