Выравнивание Pattern 🌀 Bulka

Выравнивание и комбинирование Pattern

Одним из ключевых аспектов Strudel, унаследованным от Tidal, является гибкий способ комбинирования patterns независимо от их структуры. Его декларативный подход означает, что live coder не нужно думать о деталях того, как это делается, только о том, что должно быть сделано.

В качестве простого примера рассмотрим два числовых pattern "0 [1 2] 3" и "10 20". Первый имеет три непрерывных шага равной длины, где второй шаг разбит на два подшага, давая четыре события в общей сложности. Существует очень большое количество способов, которыми можно комбинировать структуру этих двух patterns, но метод по умолчанию как в Strudel, так и в Tidal заключается в выравнивании cycles двух patterns, а затем взятии событий из первого pattern и их сопоставлении с событиями второго pattern. Поэтому следующие две строки эквивалентны:

'0 [1 2] 3'.add('10 20');
('10 [11 22] 23');

Когда события частично перекрываются, они рассматриваются как фрагменты события из первого pattern. Это немного сложно концептуализировать, но давайте начнем со сравнения двух patterns в следующем примере:

'0 1 2'.add('10 20');
('10 [11 21] 22');

Они похожи на предыдущий пример тем, что число 1 разделено на два, и к его двум половинам добавлены 10 и 20 соответственно. Однако 11 ‘помнит’, что это фрагмент исходного события 1, и поэтому рассматривается как имеющий длительность в треть cycle, несмотря на то, что активен только в течение шестой части cycle. Аналогично, 21 также является фрагментом исходного события 1, но фрагментом его второй половины. Поскольку начало его события отсутствует, оно фактически не вызовет звук (если только не подвергнется дальнейшим трансформациям/комбинациям pattern).

На практике эффект этого неявного метода по умолчанию для комбинирования двух patterns заключается в том, что второй pattern добавляется в первый, и действительно это можно сделать явным:

'0 1 2'.add.in('10 20');

Это открывает путь для других способов выравнивания pattern, и несколько уже определены, в частности:

  • in - как объяснено выше, выравнивает cycles и применяет значения из pattern справа в pattern слева.
  • out - как с in, но значения применяются из pattern слева (т.е. в тот, что справа).
  • mix - структуры из обоих patterns комбинируются, так что новые события не являются фрагментами, а создаются на пересечениях событий с обеих сторон.
  • squeeze - cycles из pattern справа сжимаются в события слева. Так что, например, "0 1 2".add.squeeze("10 20") эквивалентно "[10 20] [11 21] [12 22]".
  • squeezeout - как с squeeze, но cycles слева сжимаются в события справа. Так, "0 1 2".add.squeezeout("10 20") эквивалентно [10 11 12] [20 21 22].
  • reset похож на squeezeout в том, что cycles справа выравниваются с событиями слева. Однако эти cycles не ‘сжимаются’, а усекаются, чтобы соответствовать событию. Так "0 1 2 3 4 5 6 7".add.reset("10 [20 30]") будет эквивалентно 10 11 12 13 20 21 30 31. По сути, события справа ‘сбрасывают’ cycles слева.
  • restart похож на reset, но pattern ‘перезапускается’ с самого первого cycle, а не с текущего cycle. reset и restart поэтому дают разные результаты только там, где самый левый pattern отличается от одного cycle к другому.

Мы сохраним более глубокое изучение фона, дизайна и практических аспектов этих функций выравнивания для будущих публикаций. Однако в следующем разделе мы рассмотрим их в качестве кейса для изучения различных возможностей дизайна, предлагаемых Haskell для Tidal и JavaScript для Strudel.

Итак, как же Strudel и Tidal соотносятся?