Рандомизация

Отличный способ сделать вашу музыку несколько более интересной - это использовать случайные числа. В Sonic Pi есть замечательная функция добавления случайности в музыку, но прежде, чем мы начнем, нужно усвоить неприятную истину: в Sonic Pi случайности не являются по-настоящему случайными. Что же, спрашивается, это значит? Давайте разберёмся.

Повторяемость

Очень полезная случайная функция называется rrand. Она вернет случайное значение в диапазоне двух чисел - минимума и максимума (rrand это сокращение от “ранжированный генератор случайных чисел”). Попробуем проиграть какую-нибудь случайную ноту:

play rrand(50, 95)

Ого, получился неожиданный звук. Он воспроизвел ноту 83.7527. Прекрасная случайная нота в промежутке между 50 и 95. Постойте-ка, я только что точно предсказал случайную ноту, которая и у вас получилась? Что-то тут нечисто. Попробуем снова. Что? Он снова выбрал 83.7527? Это явно не случайно!

Правда в том, что выбор не случаен, он псевдо-случаен. Sonic Pi выдаёт повторяющиеся псевдо-случайные числа, чтобы быть уверенным, что музыка, которую вы создаёте на своей машине, будет звучать точно так же на всех других машинах. Это очень полезное свойство, даже если вы добавляете совсем немного случайности в свои композиции.

Конечно же, в конкретном музыкальном произведении, если бы 83.7527 “случайно” выбиралась каждый раз, это было бы не очень интересно. Но все-таки этого не происходит. Попробуйте следующее:

loop do
  play rrand(50, 95)
  sleep 0.5
end 

Ура! Наконец-то это звучит случайно. В течение одного запуска, последующие вызовы функции генератора случайных чисел будут возвращать случайные значения. Однако, следующий прогон создаст точно такую же последовательность случайных чисел и будет звучать идентично. Это как если бы код Sonic Pi всякий раз возвращался назад во времени в тот момент, когда нажимается кнопка Run. Это День Сурка для музыкального синтеза!

Колокола с привидениями

Прекрасной иллюстрацией случайности в действии является пример колоколов, в которые как будто вселились призраки. Он повторяет пример :perc_bell , выбирая случайную скорость и задержку между звуками:

loop do
  sample :perc_bell, rate: (rrand 0.125, 1.5)
  sleep rrand(0.2, 2)
end

Случайная частота среза фильтра нижних частот

Еще один забавный пример рандомизации - управление частотой среза фильтра синта случайным образом. Отличный синт, на котором можно это попробовать, - это эмулятор :tb303:

use_synth :tb303
loop do
  play 50, release: 0.1, cutoff: rrand(60, 120)
  sleep 0.125
end

Начальные точки для генерации случайных чисел

Что, если вам не нравится последовательность случайных чисел, сгенерированная Sonic Pi? Ну, очень легко выбрать другую начальную точку, если использовать use_random_seed.Начальная точка по умолчанию равна 0, так что для другого случайного результата выбирайте другую точку!

Сравните следующее:

5.times do
  play rrand(50, 100)
  sleep 0.5
end

Каждый раз, когда этот код выполняется, вы будете слышать одну и ту же последовательность из 5 нот. Чтобы получить другой порядок просто поменяйте начальную точку:

use_random_seed 40
5.times do
  play rrand(50, 100)
  sleep 0.5
end

В итоге получится другая последовательность из 5 нот. Изменяя начальную точку и слушая результат, можно выбрать что-тона свой вкус. Потом, когда вы поделитесь результатом с другими, они услышат в точности то же самое, что и вы.

Давайте познакомимся с некоторыми другими случайными функциями.

choose

Очень часто приходится выбирать что-то из списка случайным образом. Например, мне бы могло захотеться проиграть одну ноту из набора: 60, 65 и 72. Я могу достичь этого с помощью функции choose, которая позволяет мне выбрать элемент из списка. Вначале, надо добавить мои числа в список, что достигается заключением их в квадратные скобки и разделением запятыми: [60, 65, 72]. Затем, надо просто передать их choose:

choose([60, 65, 72])

Послушаем, как это звучит:

loop do
  play choose([60, 65, 72])
  sleep 1
end

rrand

Мы уже видели rrand, но пробежимся по ней вновь. Она возвращает случайную величину в промежутке двух чисел, не включая границы. Это значит, что никогда не будет выбрано самое большое или самое маленькое значение - всегда нечто между ними. Число всегда будет дробным, то есть не целым. Примеры дробных чисел, возвращаемых rrand(20, 110):

rrand_i

Время от времени вам может понадобится получить целое случайное число, а не дробное. Тут-то и придёт на помощь rrand_i. Она работает так же, как rrand, но включает граничные значения (то есть она может выбирать минимальные и максимальные числа). Примеры, полученные из rrand_i(20, 110):

случайный

Вернет случайное дробное число от 0 (включительно), до максимального указанного вами. По умолчанию числа лежат в промежутке от 0 до 1. Такая функция полезна для выбора случайного усиления:

loop do
  play 60, amp: rand
  sleep 0.25
end

rand_i

Относится к rrand_i, как rrand_i к rrand. То есть она выбирает случайное целое число в диапазоне от 0 до максимального значение, которое вы укажете.

игральная кость

Иногда нужно изобразить бросание игральных костей - это частный случай rrand_i, когда минимальное значение всегда 1. В вызов dice требуется передать количество сторон кости. Стандартная игральная кость имеет 6 сторон, так что dice(6) будет работать очень похожим образом - возвращать 1, 2, 3, 4, 5 или 6. Однако, прямо как в ролевых играх в стиле фэнтези, пользу может принести и кость с 4 сторонами, и с 12 сторонами или с 20 сторонами. Может даже потребуется кость со 120 гранями!

one_in

Наконец, может потребоваться сымитировать вероятность выпадания наибольшей из граней игральной кости, например, 6 для обычной кости. Функция one_in возвращает истину с вероятностью один к числу сторон кости. Следовательно, для one_in(6) шанс получить истину составит 1 к 5. В остальных 5 из 6 случаев вернётся ложь. Истинные и ложные значения очень полезны для логических выражений if, которые мы рассмотрим в одной из следующих глав нашего учебника.

А теперь, пришла пора добавить немного неразберихи в вашу музыку за счет случайностей!